diff --git a/CONVENTIONS.md b/CONVENTIONS.md
index 1a9269c..6cc4981 100644
--- a/CONVENTIONS.md
+++ b/CONVENTIONS.md
@@ -72,6 +72,42 @@ validation in every shipped build. The client dropped them from its schema first
(`.passthrough()` meant it ignored the ones still arriving), and only then did the
payload stop carrying them.
+## Bypassing a check means owning what it was doing
+
+Workflow files (`.amphi-workflow`) are offered for download from two tutorials.
+The obvious spelling — a markdown link to a file sitting next to the page —
+fails the build, and the error is actively misleading:
+
+```
+Found dead link ./downloads/%E4%B8%8A%E6%8A%A5...amphi-workflow
+[vitepress] 3 dead link(s) found.
+```
+
+The files were **committed and present**. VitePress resolves a markdown link
+against its page routes unless the extension is one it treats as an asset;
+`.amphi-workflow` is not, so each link was read as a route, matched no page, and
+`ignoreDeadLinks: false` turned that into a failed build. Reproduced by creating
+the files and building: identical errors. Reading "dead link" as "file missing"
+sends you looking in the wrong place — the fix is the *link*, not the file.
+
+What works: the file in `docs/public/` (copied to the site root untouched, no
+pipeline to confuse), linked with a raw `` tag, carrying `download` — the
+server recognises no extension here and sends an empty `Content-Type`, so a
+browser may otherwise render the bytes instead of saving them.
+
+The part worth generalising is what raw HTML costs. The dead-link check only
+parses markdown link syntax, so switching to `` gets the build passing by
+**opting out of the check**, not by satisfying it. That trade is usually invisible
+and always one-way: a typo in that href would now build clean, deploy clean, and
+404 on click — strictly worse than the failure it replaced, which at least
+announced itself. So `check:api` re-imposes the guarantee: every
+`href="/downloads/..."` must exist under `docs/public` and must carry `download`.
+
+**When you route around a check, you inherit its job.** Three of this repo's
+checks now exist for exactly that reason — links hardcoded in `config.ts`, pages
+absent from the payload, and these download links — each one covering a place the
+framework stopped looking.
+
## The languages are allowed to diverge
Both languages live under a prefix (`/zh/`, `/en/`) instead of one at the root, so
diff --git a/README.md b/README.md
index 69ad77d..13b7d76 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,38 @@ renders it so you can preview, `bun run build` drops it, and `check:api` does no
ask for a payload entry. The reverse is enforced too: an entry may not point at a
draft, since that would be a card leading to a 404. Rename when it is ready.
+## Offering a file for download
+
+For anything the reader downloads rather than views — an exported
+`.amphi-workflow`, a sample dataset — follow this exactly. The obvious way does
+not work, and fails in a way that is easy to misread:
+
+1. Put the file in `docs/public/downloads/`, with an **ASCII name**.
+2. Link it with a raw `` tag and the `download` attribute:
+ ```html
+ 上报开发任务
+ ```
+3. `bun run check:api`
+
+Why each part, since none of it is guessable:
+
+- **`docs/public/`** is copied to the site root untouched. Under `docs/` the file
+ goes through the asset pipeline, which only recognises extensions it knows.
+- **Raw ``, not `[text](link)`** — VitePress resolves a markdown link against
+ its *page routes* unless the extension is a known asset type. An unknown one is
+ read as a route, matches no page, and `ignoreDeadLinks: false` fails the build
+ **even though the file is right there**. The error says "dead link", which reads
+ like the file is missing; it is not.
+- **`download`** — the server recognises no extension here and sends an empty
+ `Content-Type`, so without it a browser may render the bytes instead of saving
+ a file.
+- **ASCII name** — a name with spaces or CJK does resolve once encoded, but the
+ emitted `href` carries the raw characters, and an unencoded request 404s.
+
+Raw HTML buys its way past the dead-link check, so `check:api` re-imposes it:
+every `href="/downloads/..."` must exist under `docs/public` and carry
+`download`. Otherwise a typo would build clean, deploy clean, and 404 on click.
+
## Bilingual contract
Both languages sit under a prefix (`/zh/`, `/en/`) rather than one at the root, so
diff --git a/docs/public/api/workflows.zh.json b/docs/public/api/workflows.zh.json
index ecf964b..dc463e0 100644
--- a/docs/public/api/workflows.zh.json
+++ b/docs/public/api/workflows.zh.json
@@ -12,7 +12,7 @@
{
"id": "e-commerce-product-scraper",
"name": "天猫超市商品抓取教程",
- "desc": "演示从天猫超市抓取某一类商品信息并自动化下载商品图片",
+ "desc": "演示从天猫超市抓取某一类商品信息、自动化下载商品图片并批量存入excel文件中",
"domain": "浏览器自动化",
"status": "verified",
"path": "zh/workflows/e-commerce-product-scraper"
diff --git a/docs/public/downloads/bug-analysis-report.amphi-workflow b/docs/public/downloads/bug-analysis-report.amphi-workflow
new file mode 100644
index 0000000..f94fcbb
Binary files /dev/null and b/docs/public/downloads/bug-analysis-report.amphi-workflow differ
diff --git a/docs/public/downloads/report-dev-task.amphi-workflow b/docs/public/downloads/report-dev-task.amphi-workflow
new file mode 100644
index 0000000..a0bb283
Binary files /dev/null and b/docs/public/downloads/report-dev-task.amphi-workflow differ
diff --git a/docs/public/downloads/tmall-snack-scraper.amphi-workflow b/docs/public/downloads/tmall-snack-scraper.amphi-workflow
new file mode 100644
index 0000000..4e3492a
Binary files /dev/null and b/docs/public/downloads/tmall-snack-scraper.amphi-workflow differ
diff --git a/docs/zh/workflows/e-commerce-images/check-condition-1.webp b/docs/zh/workflows/e-commerce-images/check-condition-1.webp
index 11c740f..5c529ea 100644
Binary files a/docs/zh/workflows/e-commerce-images/check-condition-1.webp and b/docs/zh/workflows/e-commerce-images/check-condition-1.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/check-condition-2.webp b/docs/zh/workflows/e-commerce-images/check-condition-2.webp
index e756233..2aae09c 100644
Binary files a/docs/zh/workflows/e-commerce-images/check-condition-2.webp and b/docs/zh/workflows/e-commerce-images/check-condition-2.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/clarify-1.webp b/docs/zh/workflows/e-commerce-images/clarify-1.webp
index b9c0949..583a433 100644
Binary files a/docs/zh/workflows/e-commerce-images/clarify-1.webp and b/docs/zh/workflows/e-commerce-images/clarify-1.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/clarify-2.webp b/docs/zh/workflows/e-commerce-images/clarify-2.webp
index 626d7ca..0b2129f 100644
Binary files a/docs/zh/workflows/e-commerce-images/clarify-2.webp and b/docs/zh/workflows/e-commerce-images/clarify-2.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/clarify-3.webp b/docs/zh/workflows/e-commerce-images/clarify-3.webp
index 0039c51..0d568c5 100644
Binary files a/docs/zh/workflows/e-commerce-images/clarify-3.webp and b/docs/zh/workflows/e-commerce-images/clarify-3.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/clarify-4.webp b/docs/zh/workflows/e-commerce-images/clarify-4.webp
new file mode 100644
index 0000000..e45aa76
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/clarify-4.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/clarify-5.webp b/docs/zh/workflows/e-commerce-images/clarify-5.webp
new file mode 100644
index 0000000..d1fd073
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/clarify-5.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/login-page.webp b/docs/zh/workflows/e-commerce-images/login-page.webp
index a096b6b..105dc46 100644
Binary files a/docs/zh/workflows/e-commerce-images/login-page.webp and b/docs/zh/workflows/e-commerce-images/login-page.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/login-prompt.webp b/docs/zh/workflows/e-commerce-images/login-prompt.webp
index b9f4015..cf78464 100644
Binary files a/docs/zh/workflows/e-commerce-images/login-prompt.webp and b/docs/zh/workflows/e-commerce-images/login-prompt.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/login-submit.webp b/docs/zh/workflows/e-commerce-images/login-submit.webp
index f1b08a1..db6d859 100644
Binary files a/docs/zh/workflows/e-commerce-images/login-submit.webp and b/docs/zh/workflows/e-commerce-images/login-submit.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/new-task.webp b/docs/zh/workflows/e-commerce-images/new-task.webp
index b111f6b..d9a8b8d 100644
Binary files a/docs/zh/workflows/e-commerce-images/new-task.webp and b/docs/zh/workflows/e-commerce-images/new-task.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/running-1.webp b/docs/zh/workflows/e-commerce-images/running-1.webp
new file mode 100644
index 0000000..e48f437
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/running-1.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/running-excel.webp b/docs/zh/workflows/e-commerce-images/running-excel.webp
new file mode 100644
index 0000000..0889642
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/running-excel.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/running-result.webp b/docs/zh/workflows/e-commerce-images/running-result.webp
new file mode 100644
index 0000000..e31269f
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/running-result.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/running-success.webp b/docs/zh/workflows/e-commerce-images/running-success.webp
new file mode 100644
index 0000000..7949d51
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/running-success.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/task-req-1.webp b/docs/zh/workflows/e-commerce-images/task-req-1.webp
index 46849cf..a9972f5 100644
Binary files a/docs/zh/workflows/e-commerce-images/task-req-1.webp and b/docs/zh/workflows/e-commerce-images/task-req-1.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/task-req-2.webp b/docs/zh/workflows/e-commerce-images/task-req-2.webp
index 0cb756f..f9c6847 100644
Binary files a/docs/zh/workflows/e-commerce-images/task-req-2.webp and b/docs/zh/workflows/e-commerce-images/task-req-2.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/task-req-second.webp b/docs/zh/workflows/e-commerce-images/task-req-second.webp
new file mode 100644
index 0000000..54b0551
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/task-req-second.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/workflow-card.webp b/docs/zh/workflows/e-commerce-images/workflow-card.webp
new file mode 100644
index 0000000..d51178f
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/workflow-card.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/workflow-created.webp b/docs/zh/workflows/e-commerce-images/workflow-created.webp
new file mode 100644
index 0000000..e20b9a5
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/workflow-created.webp differ
diff --git a/docs/zh/workflows/e-commerce-images/workflow-naming.webp b/docs/zh/workflows/e-commerce-images/workflow-naming.webp
new file mode 100644
index 0000000..8f39474
Binary files /dev/null and b/docs/zh/workflows/e-commerce-images/workflow-naming.webp differ
diff --git a/docs/zh/workflows/e-commerce-product-scraper.md b/docs/zh/workflows/e-commerce-product-scraper.md
index 18969b6..9c33a9a 100644
--- a/docs/zh/workflows/e-commerce-product-scraper.md
+++ b/docs/zh/workflows/e-commerce-product-scraper.md
@@ -1,10 +1,26 @@
-# 【教程】自动采集天猫超市商品信息 (WIP)
+# 【教程】自动采集天猫超市商品信息
-本教程介绍如何使用Bridgic Agent构建自动化工作流,从天猫超市抓取某一类的商品信息,包括自动化获取商品图片。
+本教程介绍如何使用Bridgic Agent构建自动化工作流,从天猫超市抓取某一类的商品信息(包括自动化获取商品图片),批量存入excel文件中。
本教程详细记录了该工作流的构建过程和运行过程。
## 成品展示
+在本教程结束后,你将会看到一个成功构建的工作流:
+
+
+
+该工作流可直接下载并导入进你的Bridgic Agent,作为参考:
+
+
+
+**注意**:由于每个人的电脑桌面运行环境不同,这个工作流未必能在导入后直接运行。仅作为参考,你可以参考它们制作自己真正需要的工作流。
+如果你一定要运行这个工作流,可以在运行碰到问题后,要求Bridgic Agent根据你的实际运行环境修复它即可。
+
+你还会看到,运行该工作后产出的excel文件(里面存放着从天猫超市采集到的商品信息列表):
+
+
## 工作流构建教程
@@ -28,6 +44,8 @@ Bridgic Agent对于需求中不明确的描述会主动和你确认(需求澄

+
+
Bridgic Agent会提示你选择或确认任务的验收标准:

@@ -56,15 +74,48 @@ Bridgic Agent发现天猫超市需要用户登录,所以弹框告知用户来

+Bridgic Agent在运行过程中又发现了一个需求澄清的点:
+
+
+
+需求澄清后,Bridgic Agent会引导你第二次确认任务说明书的变动:
+
+
+
+构建工作流的最后一步:给工作流取个名字。
+
+
+
+工作流创建成功!
+
+
+
+这个新创建的工作流,以后你随时可以在工作流页面中找到它。工作流卡片如下:
+
+
+
### 运行工作流
+
-### 调度工作流
+
+
+点击“查看结果”,可以看到刚才工作流的运行结果:
+
+
+可以把最后的excel表格下载出来,里面存放着从天猫超市采集到的商品信息列表(该示例批次为50个商品):
+
+
+### 调度工作流
+如果需要定期采集,可以使用Bridgic Agent提供的“调度”功能,来设置定时执行。此处略。
## 注意事项
-修改工作流
+- 由于电脑本地的执行环境不同,你的构建过程可能也会碰到很多差异,未必跟以上记录的过程完全相同。具体的过程体验取决于环境和模型能力;建议使用好的模型来构建工作流,然后可以使用次一级的模型来运行它。
+- 构建过程中如果发生意外情况,不要慌张,可以随时向agent提问,请它提供更多信息或者让它给建议。在中间过程可以把碰到的问题/疑问都抛给Bridgic Agent。
+- Bridgic Agent对于工作流的构建,成功率非常高。只要需求描述清晰且可行,通常能够一次性成功。但偶尔出现失败的情况,也不要紧,可以让Bridgic Agent修复工作流。修复时告诉它你碰到的异常情况。
+- 工作流构建出来之后,并非一成不变,Bridgic Agent提供了强大的工作流修改能力。如果你需求有所变动,随时告诉Bridgic Agent:“修改 @XXX工作流,我要XXXX”。你可以不断优化自己的工作流,让它越来越精细,也越来越贴近你的需求。
diff --git a/docs/zh/workflows/github-trending/new-task-1.png b/docs/zh/workflows/github-trending/new-task-1.png
new file mode 100644
index 0000000..6a9d593
Binary files /dev/null and b/docs/zh/workflows/github-trending/new-task-1.png differ
diff --git a/docs/zh/workflows/github-trending/new-task-2.png b/docs/zh/workflows/github-trending/new-task-2.png
new file mode 100644
index 0000000..55e6464
Binary files /dev/null and b/docs/zh/workflows/github-trending/new-task-2.png differ
diff --git a/docs/zh/workflows/project-management-automation.md b/docs/zh/workflows/project-management-automation.md
index 211c800..33b9afe 100644
--- a/docs/zh/workflows/project-management-automation.md
+++ b/docs/zh/workflows/project-management-automation.md
@@ -16,6 +16,18 @@

+本教程产出的这两个自动化工作流,可直接下载并导入进Bridgic Agent,作为参考:
+
+
+
+**注意**:由于每个人的电脑桌面运行环境不同,这两个工作流未必能在导入后直接运行。仅作为参考,你可以参考它们制作自己真正需要的工作流。
+如果你一定要运行这两个工作流,可以在运行碰到问题后,要求Bridgic Agent根据你的实际运行环境修复它们即可。
+
还有一个定时调度任务:

@@ -32,7 +44,9 @@
### 准备工作
-准备你自己的飞书账号,创建一个多维表格出来,用来保存和展示开发任务(新特性开发或Bug记录)。如下:
+准备你自己的飞书账号,创建一个多维表格出来,用来保存和展示开发任务(新特性开发或Bug记录)。
+
+注:创建多维表格其实也可以让Bridgic Agent来做,当因为初次连接飞书表格可能会有些麻烦,并且这是个一次性的操作,这里建议先用手工创建这个多维表格。如下:

@@ -187,7 +201,7 @@ Bridgic Agent提示你选择任务的验收标准:
## 注意事项
-- 用户本地的环境不同,构建过程可能也会碰到很多差异。可能需要根据具体情况来合理处理。尤其是这个工作流底层需要的lark-cli的安装和配置过程,具体的过程体验取决于环境和模型能力。建议使用好模型来构建工作流,然后可以使用次一些的模型来运行它。
+- 由于电脑本地的执行环境不同,你的构建过程可能也会碰到很多差异,未必跟以上记录的过程完全相同。你需要根据具体情况来合理处理,尤其是这个工作流底层需要的lark-cli的安装和配置过程,其具体的过程体验取决于环境和模型能力。建议使用好的模型来构建工作流,然后可以使用次一级的模型来运行它。
- 构建过程中如果发生意外情况,不要慌张,可以随时向agent提问,请它提供更多信息或者让它给建议。在中间过程可以把碰到的问题/疑问都抛给Bridgic Agent。
- Bridgic Agent对于工作流的构建,成功率非常高。只要需求描述清晰且可行,通常能够一次性成功。但偶尔出现失败的情况,也不要紧,可以让Bridgic Agent修复工作流。修复时告诉它你碰到的异常情况。
-- 工作流构建出来之后,并非一成不变,Bridgic Agent提供了强大的工作流修改能力。如果你需求有所变动,随时告诉Bridgic Agent:“修复 @XXX工作流,我要XXXX”。
+- 工作流构建出来之后,并非一成不变,Bridgic Agent提供了强大的工作流修改能力。如果你需求有所变动,随时告诉Bridgic Agent:“修改 @XXX工作流,我要XXXX”。你可以不断优化自己的工作流,让它越来越精细,也越来越贴近你的需求。
diff --git a/scripts/check-api.ts b/scripts/check-api.ts
index c998847..53f1833 100644
--- a/scripts/check-api.ts
+++ b/scripts/check-api.ts
@@ -159,6 +159,35 @@ for (const link of configLinks) {
}
}
+// --- download links in raw HTML point at files that exist -------------------
+// The same blind spot, one step further. A workflow file has to be linked with a
+// raw `` tag: VitePress resolves markdown links against its page routes, and
+// `.amphi-workflow` is not an extension it treats as an asset, so the markdown
+// form is reported as a dead link and fails the build even when the file is
+// right there. Raw HTML sidesteps that check -- and with it, every guarantee it
+// was providing. A typo here would build clean, deploy clean, and 404 on click.
+function checkDownloadLinks(lang: string): number {
+ const dir = join(DOCS, lang, 'workflows')
+ if (!existsSync(dir)) return 0
+ let count = 0
+ for (const name of readdirSync(dir)) {
+ if (!name.endsWith('.md')) continue
+ const source = readFileSync(join(dir, name), 'utf8')
+ for (const m of source.matchAll(/href="(\/downloads\/[^"]+)"/g)) {
+ count++
+ const href = m[1] as string
+ if (!existsSync(join(DOCS, 'public', href.replace(/^\//, '')))) {
+ fail(`${lang}/workflows/${name} links to '${href}', which does not exist under docs/public`)
+ }
+ if (!/download(\s|=|>)/.test(source.slice(m.index ?? 0, (m.index ?? 0) + 200))) {
+ fail(`${lang}/workflows/${name}: '${href}' needs the \`download\` attribute -- the server sends no Content-Type for this extension`)
+ }
+ }
+ }
+ return count
+}
+const downloads = checkDownloadLinks('zh') + checkDownloadLinks('en')
+
// --- every workflow page is reachable from its own payload ------------------
// checkEntry already covers the other direction (an entry whose `path` points at
// nothing). This catches the opposite slip: overwriting an entry when meaning to
@@ -190,5 +219,5 @@ if (errors.length > 0) {
console.log(
`check-api: ok -- ${zh.length} zh / ${en.length} en workflows, ` +
`${zhPages.length} zh / ${enPages.length} en pages all listed, ` +
- `${seenLinks.size} config links resolve`,
+ `${seenLinks.size} config links resolve, ${downloads} download links resolve`,
)