@vetta-org/plugin-cli 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +10 -0
- package/dist/agents-template.d.ts +15 -0
- package/dist/agents-template.d.ts.map +1 -1
- package/dist/cli.js +187 -96
- package/dist/command.d.ts +16 -0
- package/dist/command.d.ts.map +1 -1
- package/dist/hub-template.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +190 -97
- package/dist/init.d.ts +14 -1
- package/dist/init.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@vetta-org/plugin-cli` are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.6] — 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **`init --refresh-guide` 不再覆盖手写的 `AGENTS.md`**。此前它无条件重写,而 `docs` 又把「没有
|
|
10
|
+
版本戳」判成过期并给出这条命令——两者合起来是在引导用户删掉自己的文件。已知造成一个能力市场
|
|
11
|
+
仓库根部 443 行手写市场规范被整份替换。
|
|
12
|
+
|
|
13
|
+
没有 `vetta-guide-revision` 标记的文件现在一律拒绝覆盖(退出码 7),要覆盖得显式 `--force`;
|
|
14
|
+
新增 `--dry-run` 把新模板打到 stdout 供人工合并。`docs` 对无标记文件改口为「看起来是手写的,
|
|
15
|
+
请手动合并」,只有**带标记且落后**的才会被称作 stale 并给出刷新命令。
|
|
16
|
+
|
|
17
|
+
- 说明书标题不再印出未解析的本地化占位符。`plugin.json` 的 `name` 写成 `%plugin.name%` 时,按
|
|
18
|
+
`defaultLocale` 从 `locales/` 解析;解析不到退回插件 id。
|
|
19
|
+
|
|
20
|
+
- 说明书的命令清单改为读 `package.json` 的 `scripts`,只列真实存在的。老工程和自定义工程未必有
|
|
21
|
+
`dev` / `install:vetta`,照着跑只会得到一句 "Missing script";没有 `install:vetta` 时改列
|
|
22
|
+
`vetta-plugin-cli add .`。
|
|
23
|
+
|
|
24
|
+
- 更正 hub `AGENTS.md` 对 `sync` 的两处描述:`marketplaceVersion` 只在 semver 或纯整数时才推得动
|
|
25
|
+
(`YYYY.MM.DD-NN` 这类会报出来要手改),`config.api_version` / `permissions` / `commands`
|
|
26
|
+
**不回填**——宿主用 `plugin.json` 整个重算 `config`,`sync` 只在副本与真源不符时提醒删掉。
|
|
27
|
+
|
|
28
|
+
## [0.1.5] — 2026-09-14
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **脚手架的 `AGENTS.md` 削薄成纯指引**:原先写在里面的「不可违反的几条」(Tailwind-only、
|
|
33
|
+
错误必须 notify、最小权限、MF 顶层 JSX、`agent_mode` 已废弃、依赖用发布版本、`dist/` 进
|
|
34
|
+
版本库)全部移进手册的 `README.md#不可违反的红线`。写进说明书的规则会在所有存量工程里就地
|
|
35
|
+
凝固——它是 `init` 当天的快照,之后既不自更新、用户也没有理由回头看它。规则放进手册才能
|
|
36
|
+
随 SDK 升级一起到位;说明书越薄,需要回头迁移老仓库的理由就越少。
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- `AGENTS.md` 带版本戳(`<!-- vetta-guide-revision: N -->`),`docs` 每次比对并在落后时打印
|
|
41
|
+
`This brief is stale ... npx @vetta-org/plugin-cli init --refresh-guide`。此前「说明书旧了」
|
|
42
|
+
只能靠人记得,而这正是它凝固的原因。没有 `AGENTS.md` 的工程不提示——「没有」不是「旧」。
|
|
43
|
+
|
|
5
44
|
## [0.1.4] — 2026-09-14
|
|
6
45
|
|
|
7
46
|
### Added
|
package/README.md
CHANGED
|
@@ -28,6 +28,16 @@ is purely derived and holds no user content — leaving source, manifest and con
|
|
|
28
28
|
the id and display name from the `plugin.json` already on disk. At a marketplace root it rewrites the
|
|
29
29
|
hub brief instead.
|
|
30
30
|
|
|
31
|
+
It refuses to overwrite a brief that carries no `vetta-guide-revision` marker — that file is
|
|
32
|
+
indistinguishable from a hand-written one, and a marketplace root often holds a hand-written spec.
|
|
33
|
+
Use `--dry-run` to print the current template for manual merging, or `--force` to replace the file
|
|
34
|
+
outright.
|
|
35
|
+
|
|
36
|
+
You will rarely have to remember this: the brief carries a revision stamp, and `docs` compares it on
|
|
37
|
+
every run and says outright when it is behind. The brief itself holds no rules — those live in the
|
|
38
|
+
manual, which travels with the SDK — so it changes seldom, and a project that refreshes once keeps
|
|
39
|
+
itself current from then on.
|
|
40
|
+
|
|
31
41
|
## Remove a plugin
|
|
32
42
|
|
|
33
43
|
```bash
|
|
@@ -7,10 +7,25 @@
|
|
|
7
7
|
* 因此任何 Agent(Claude Code、Cursor、Vetta 自己)在任何陌生目录都能自举,而且读到的
|
|
8
8
|
* 永远是这个工程实际编译所针对的那份合同。
|
|
9
9
|
*
|
|
10
|
+
* **这里刻意只留指引,不留知识。** 写进这个文件的每一条规则都会在所有存量工程里就地凝固:
|
|
11
|
+
* 它是 `init` 当天的快照,之后既不会自更新,用户也没有理由回来看它。规则属于手册——手册
|
|
12
|
+
* 随 SDK 升级一起到位。这个文件越薄,需要回头迁移老仓库的理由就越少。
|
|
13
|
+
*
|
|
10
14
|
* 单位是插件目录本身:外面是能力市场仓库、是单插件仓库、还是一堆别的东西,都不影响这里。
|
|
11
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* 说明书的版本戳。
|
|
18
|
+
*
|
|
19
|
+
* `docs` 读它来判断一份说明书是不是旧的——没有这个戳,「该不该刷新」就只能靠人记得,而这
|
|
20
|
+
* 恰恰是它凝固的原因。**改动模板内容时必须一并推进它**,否则存量工程不会收到提示。
|
|
21
|
+
*/
|
|
22
|
+
export declare const AGENTS_GUIDE_REVISION = 3;
|
|
23
|
+
/** 从一份 AGENTS.md 正文里读出版本戳;不是本模板生成的(或早于版本戳)时返回 undefined。 */
|
|
24
|
+
export declare function readAgentsGuideRevision(content: string): number | undefined;
|
|
12
25
|
export declare function renderAgentsGuide(input: {
|
|
13
26
|
pluginId: string;
|
|
14
27
|
displayName: string;
|
|
28
|
+
/** 工程 package.json 里实际存在的 script 名;缺省按脚手架的那套算。 */
|
|
29
|
+
scripts?: readonly string[];
|
|
15
30
|
}): string;
|
|
16
31
|
//# sourceMappingURL=agents-template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-template.d.ts","sourceRoot":"","sources":["../src/agents-template.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents-template.d.ts","sourceRoot":"","sources":["../src/agents-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,4HAA4D;AAC5D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI3E;AA4BD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,4FAAkD;IAClD,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,GAAG,MAAM,CAiDT","sourcesContent":["/**\n * 随脚手架落地的 Agent 说明书。\n *\n * 它替代的是「把开发知识写死在工作台插件的 skill 里」那套做法:那份 skill 只有 Vetta\n * 自己的 Agent 读得到,而且每加一个能力就要改一次、还要等 App 发版才到用户手里。这里\n * 反过来——工程自带说明书,说明书只说「去哪读手册」,手册随 SDK 版本进 node_modules。\n * 因此任何 Agent(Claude Code、Cursor、Vetta 自己)在任何陌生目录都能自举,而且读到的\n * 永远是这个工程实际编译所针对的那份合同。\n *\n * **这里刻意只留指引,不留知识。** 写进这个文件的每一条规则都会在所有存量工程里就地凝固:\n * 它是 `init` 当天的快照,之后既不会自更新,用户也没有理由回来看它。规则属于手册——手册\n * 随 SDK 升级一起到位。这个文件越薄,需要回头迁移老仓库的理由就越少。\n *\n * 单位是插件目录本身:外面是能力市场仓库、是单插件仓库、还是一堆别的东西,都不影响这里。\n */\n\n/**\n * 说明书的版本戳。\n *\n * `docs` 读它来判断一份说明书是不是旧的——没有这个戳,「该不该刷新」就只能靠人记得,而这\n * 恰恰是它凝固的原因。**改动模板内容时必须一并推进它**,否则存量工程不会收到提示。\n */\nexport const AGENTS_GUIDE_REVISION = 3;\n\n/** 从一份 AGENTS.md 正文里读出版本戳;不是本模板生成的(或早于版本戳)时返回 undefined。 */\nexport function readAgentsGuideRevision(content: string): number | undefined {\n\tconst match = /<!--\\s*vetta-guide-revision:\\s*(\\d+)\\s*-->/.exec(content);\n\tif (!match) return undefined;\n\treturn Number(match[1]);\n}\n\n/**\n * 渲染常用命令块。\n *\n * 只列工程真有的 script:模板写死 `npm run dev` / `install:vetta`,老工程和自定义工程未必有,\n * 照着跑就是一句 \"Missing script\"。读不到 package.json 时退回 CLI 直连命令——它们不依赖工程脚本。\n */\nfunction renderCommands(pluginId: string, scripts: readonly string[]): string {\n\tconst known: readonly (readonly [string, string])[] = [\n\t\t[\"dev\", \"npm run dev # 开发服务器\"],\n\t\t[\"build\", \"npm run build # 产出 dist/\"],\n\t\t[\"install:vetta\", \"npm run install:vetta # 打包并装进正在运行的 Vetta(需要 Vetta 已启动)\"],\n\t];\n\tconst lines = known.filter(([name]) => scripts.includes(name)).map(([, line]) => line);\n\tif (!scripts.includes(\"install:vetta\")) {\n\t\tlines.push(\"npx vetta-plugin-cli add . # 打包并装进正在运行的 Vetta\");\n\t}\n\treturn [\n\t\t...lines,\n\t\t\"\",\n\t\t\"npx vetta-plugin-cli watch # 热更新:宿主改从本工程目录加载,改完即生效\",\n\t\t`npx vetta-plugin-cli reload ${pluginId} # 装完提示有 pending 版本时用它`,\n\t\t\"npx vetta-plugin-cli uninstall # 卸载(省略 id 即本工程对应的插件)\",\n\t\t\"npx vetta-plugin-cli sync # 在 hub 仓库根上跑:把索引与各能力目录对账\",\n\t].join(\"\\n\");\n}\n\nexport function renderAgentsGuide(input: {\n\tpluginId: string;\n\tdisplayName: string;\n\t/** 工程 package.json 里实际存在的 script 名;缺省按脚手架的那套算。 */\n\tscripts?: readonly string[];\n}): string {\n\treturn `<!-- vetta-guide-revision: ${AGENTS_GUIDE_REVISION} -->\n# ${input.displayName}\n\nVetta 桌面插件工程(插件 id:\\`${input.pluginId}\\`)。\n\n**本文件不讲规则,只告诉你去哪读。** 规则在手册里,手册随 SDK 升级;写在这里的任何一条都会\n停在这个工程创建那天。两者冲突时一律以手册为准。\n\n## 第一步:装依赖,找到手册\n\n\\`\\`\\`bash\nnpm install\nnpx vetta-plugin-cli docs --check-latest\n\\`\\`\\`\n\n\\`npm install\\` 必须先跑:\\`vetta-plugin-cli\\` 是 \\`@vetta-org/plugin-cli\\` 的命令名,装完才在\n\\`node_modules/.bin\\` 里。还没装就想跑,用全名 \\`npx @vetta-org/plugin-cli docs\\`。\n\n它打印手册目录的**绝对路径**、手册对应的 SDK 版本,以及本工程与所属 hub 的位置。\n**不要硬编码这个路径**:工作区可能把依赖提升到仓库根,一仓多插件时各插件还可能钉不同版本。\n\n输出里出现 \\`Manual is behind\\` 或 \\`This brief is stale\\` 就按它给的命令升级,再重跑一次。\n\n## 第二步:按顺序读手册\n\n| 顺序 | 文件 | 何时读 |\n| --- | --- | --- |\n| 1 | \\`README.md\\` | **总是先读**:能力矩阵、信任模型、**不可违反的红线**、导航 |\n| 2 | \\`getting-started.md\\` | 首次写代码、构建、安装调试 |\n| 3 | \\`manifest.md\\` | 写/改 \\`plugin.json\\`、贡献智能体与团队 |\n| 4 | \\`permissions.md\\` | 选定权限列表之前 |\n| 5 | 按扩展点选读 | \\`ui-slots.md\\` / \\`conversation-and-agent.md\\` / \\`message-cards.md\\` / \\`mcp.md\\` / \\`ai.md\\` / \\`browser.md\\` / \\`app-actions.md\\` / \\`styling-and-pitfalls.md\\` |\n\n实现任一扩展点**之前**再读对应那章,不要凭记忆写 SDK API——这套合同变化很快。\n\n## 常用命令\n\n\\`\\`\\`bash\n${renderCommands(input.pluginId, input.scripts ?? [\"dev\", \"build\", \"install:vetta\"])}\n\\`\\`\\`\n\n细节都在 \\`getting-started.md\\`。\\`docs\\` 打印了 \\`Marketplace index:\\` 就说明这个目录之上有能力\n市场索引,改完 \\`version\\` / \\`permissions\\` / \\`pluginApiVersion\\` 后要回仓库根跑 \\`sync\\`。\n\n## 信息不足时\n\n插件 id、展示名、要用哪些权限、功能边界、是否立刻安装——**问用户**,不要自己假定。\n`;\n}\n"]}
|
package/dist/cli.js
CHANGED
|
@@ -3647,7 +3647,7 @@ var require_npa = __commonJS((exports, module) => {
|
|
|
3647
3647
|
});
|
|
3648
3648
|
|
|
3649
3649
|
// src/command.ts
|
|
3650
|
-
import { existsSync as existsSync4, statSync as statSync2 } from "node:fs";
|
|
3650
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
3651
3651
|
import { join as join6, resolve as resolve5 } from "node:path";
|
|
3652
3652
|
import { parseArgs } from "node:util";
|
|
3653
3653
|
|
|
@@ -15419,7 +15419,9 @@ var PluginAgentTeamMemberManifestSchema = Type.Object({
|
|
|
15419
15419
|
agent: Type.Optional(NonWhitespaceStringSchema),
|
|
15420
15420
|
role: Type.Optional(PluginAgentRoleSchema),
|
|
15421
15421
|
responsibility: Type.String({ maxLength: 2000 }),
|
|
15422
|
-
optional: Type.Optional(Type.Boolean())
|
|
15422
|
+
optional: Type.Optional(Type.Boolean()),
|
|
15423
|
+
instructions: Type.Optional(Type.String({ maxLength: 64000 })),
|
|
15424
|
+
instructionsPath: Type.Optional(NonWhitespaceStringSchema)
|
|
15423
15425
|
}, { additionalProperties: false });
|
|
15424
15426
|
var PluginAgentTeamManifestSchema = Type.Object({
|
|
15425
15427
|
id: Type.String({ pattern: "^[a-z0-9][a-z0-9-]{0,63}$" }),
|
|
@@ -18920,107 +18922,93 @@ async function resolveNpmPluginArchive(packageSpec, pack = runNpmPack) {
|
|
|
18920
18922
|
}
|
|
18921
18923
|
}
|
|
18922
18924
|
|
|
18923
|
-
// src/init.ts
|
|
18924
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
18925
|
-
import { dirname, join as join3, resolve as resolve2 } from "node:path";
|
|
18926
|
-
|
|
18927
18925
|
// src/agents-template.ts
|
|
18926
|
+
var AGENTS_GUIDE_REVISION = 3;
|
|
18927
|
+
function readAgentsGuideRevision(content) {
|
|
18928
|
+
const match2 = /<!--\s*vetta-guide-revision:\s*(\d+)\s*-->/.exec(content);
|
|
18929
|
+
if (!match2)
|
|
18930
|
+
return;
|
|
18931
|
+
return Number(match2[1]);
|
|
18932
|
+
}
|
|
18933
|
+
function renderCommands(pluginId, scripts) {
|
|
18934
|
+
const known = [
|
|
18935
|
+
["dev", "npm run dev # 开发服务器"],
|
|
18936
|
+
["build", "npm run build # 产出 dist/"],
|
|
18937
|
+
["install:vetta", "npm run install:vetta # 打包并装进正在运行的 Vetta(需要 Vetta 已启动)"]
|
|
18938
|
+
];
|
|
18939
|
+
const lines = known.filter(([name]) => scripts.includes(name)).map(([, line]) => line);
|
|
18940
|
+
if (!scripts.includes("install:vetta")) {
|
|
18941
|
+
lines.push("npx vetta-plugin-cli add . # 打包并装进正在运行的 Vetta");
|
|
18942
|
+
}
|
|
18943
|
+
return [
|
|
18944
|
+
...lines,
|
|
18945
|
+
"",
|
|
18946
|
+
"npx vetta-plugin-cli watch # 热更新:宿主改从本工程目录加载,改完即生效",
|
|
18947
|
+
`npx vetta-plugin-cli reload ${pluginId} # 装完提示有 pending 版本时用它`,
|
|
18948
|
+
"npx vetta-plugin-cli uninstall # 卸载(省略 id 即本工程对应的插件)",
|
|
18949
|
+
"npx vetta-plugin-cli sync # 在 hub 仓库根上跑:把索引与各能力目录对账"
|
|
18950
|
+
].join(`
|
|
18951
|
+
`);
|
|
18952
|
+
}
|
|
18928
18953
|
function renderAgentsGuide(input) {
|
|
18929
|
-
return
|
|
18954
|
+
return `<!-- vetta-guide-revision: ${AGENTS_GUIDE_REVISION} -->
|
|
18955
|
+
# ${input.displayName}
|
|
18930
18956
|
|
|
18931
|
-
Vetta
|
|
18957
|
+
Vetta 桌面插件工程(插件 id:\`${input.pluginId}\`)。
|
|
18932
18958
|
|
|
18933
|
-
|
|
18959
|
+
**本文件不讲规则,只告诉你去哪读。** 规则在手册里,手册随 SDK 升级;写在这里的任何一条都会
|
|
18960
|
+
停在这个工程创建那天。两者冲突时一律以手册为准。
|
|
18961
|
+
|
|
18962
|
+
## 第一步:装依赖,找到手册
|
|
18934
18963
|
|
|
18935
18964
|
\`\`\`bash
|
|
18936
18965
|
npm install
|
|
18937
|
-
npx vetta-plugin-cli docs
|
|
18966
|
+
npx vetta-plugin-cli docs --check-latest
|
|
18938
18967
|
\`\`\`
|
|
18939
18968
|
|
|
18940
18969
|
\`npm install\` 必须先跑:\`vetta-plugin-cli\` 是 \`@vetta-org/plugin-cli\` 的命令名,装完才在
|
|
18941
18970
|
\`node_modules/.bin\` 里。还没装就想跑,用全名 \`npx @vetta-org/plugin-cli docs\`。
|
|
18942
18971
|
|
|
18943
|
-
|
|
18944
|
-
|
|
18945
|
-
|
|
18946
|
-
\`\`\`bash
|
|
18947
|
-
npx vetta-plugin-cli docs --check-latest
|
|
18948
|
-
\`\`\`
|
|
18949
|
-
|
|
18950
|
-
落后就按它打印的命令升级 SDK 再重读手册。\`docs\` 的输出永远比本文件新(\`npx\` 默认取最新的
|
|
18951
|
-
CLI),**两者冲突时以它为准**。
|
|
18972
|
+
它打印手册目录的**绝对路径**、手册对应的 SDK 版本,以及本工程与所属 hub 的位置。
|
|
18973
|
+
**不要硬编码这个路径**:工作区可能把依赖提升到仓库根,一仓多插件时各插件还可能钉不同版本。
|
|
18952
18974
|
|
|
18953
|
-
|
|
18954
|
-
这份手册对应的 SDK 版本。**不要硬编码这个路径**:工作区可能把依赖提升到仓库根,一仓多插件
|
|
18955
|
-
时各插件还可能钉不同的 SDK 版本。
|
|
18975
|
+
输出里出现 \`Manual is behind\` 或 \`This brief is stale\` 就按它给的命令升级,再重跑一次。
|
|
18956
18976
|
|
|
18957
|
-
|
|
18977
|
+
## 第二步:按顺序读手册
|
|
18958
18978
|
|
|
18959
18979
|
| 顺序 | 文件 | 何时读 |
|
|
18960
18980
|
| --- | --- | --- |
|
|
18961
|
-
| 1 | \`README.md\` |
|
|
18981
|
+
| 1 | \`README.md\` | **总是先读**:能力矩阵、信任模型、**不可违反的红线**、导航 |
|
|
18962
18982
|
| 2 | \`getting-started.md\` | 首次写代码、构建、安装调试 |
|
|
18963
18983
|
| 3 | \`manifest.md\` | 写/改 \`plugin.json\`、贡献智能体与团队 |
|
|
18964
18984
|
| 4 | \`permissions.md\` | 选定权限列表之前 |
|
|
18965
|
-
| 5 | 按扩展点选读 | \`ui-slots.md\` / \`conversation-and-agent.md\` / \`message-cards.md\` / \`mcp.md\` / \`ai.md\` / \`browser.md\` / \`app-actions.md\` |
|
|
18985
|
+
| 5 | 按扩展点选读 | \`ui-slots.md\` / \`conversation-and-agent.md\` / \`message-cards.md\` / \`mcp.md\` / \`ai.md\` / \`browser.md\` / \`app-actions.md\` / \`styling-and-pitfalls.md\` |
|
|
18966
18986
|
|
|
18967
|
-
|
|
18987
|
+
实现任一扩展点**之前**再读对应那章,不要凭记忆写 SDK API——这套合同变化很快。
|
|
18968
18988
|
|
|
18969
|
-
##
|
|
18989
|
+
## 常用命令
|
|
18970
18990
|
|
|
18971
18991
|
\`\`\`bash
|
|
18972
|
-
|
|
18973
|
-
npm run build # 产出 dist/
|
|
18974
|
-
npm run install:vetta # 打包并装进正在运行的 Vetta(需要 Vetta 已启动)
|
|
18975
|
-
npx vetta-plugin-cli watch # 开热更新:宿主改从本工程目录加载,改完即生效
|
|
18976
|
-
npx vetta-plugin-cli uninstall # 卸载(省略 id 即本工程对应的插件)
|
|
18992
|
+
${renderCommands(input.pluginId, input.scripts ?? ["dev", "build", "install:vetta"])}
|
|
18977
18993
|
\`\`\`
|
|
18978
18994
|
|
|
18979
|
-
\`
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
装完若提示有 pending 版本,用 \`npx vetta-plugin-cli reload ${input.pluginId}\` 让宿主应用它。
|
|
18995
|
+
细节都在 \`getting-started.md\`。\`docs\` 打印了 \`Marketplace index:\` 就说明这个目录之上有能力
|
|
18996
|
+
市场索引,改完 \`version\` / \`permissions\` / \`pluginApiVersion\` 后要回仓库根跑 \`sync\`。
|
|
18983
18997
|
|
|
18984
|
-
开发期建议开热更新(\`watch\`):之后改源码即时生效,不用每次重新打包安装。改 \`plugin.json\`
|
|
18985
|
-
的权限或命令声明时仍需重新安装一次,让宿主把授权落盘。\`watch --stop\` 关闭。
|
|
18986
|
-
|
|
18987
|
-
## 如果这个目录之上有能力市场索引
|
|
18988
|
-
|
|
18989
|
-
\`vetta-plugin-cli docs\` 会告诉你有没有(它会打印 \`Marketplace index:\`)。有的话,**改完
|
|
18990
|
-
\`version\` / \`permissions\` / \`pluginApiVersion\` 之后要回仓库根跑一次**:
|
|
18991
|
-
|
|
18992
|
-
\`\`\`bash
|
|
18993
|
-
npx @vetta-org/plugin-cli sync # 从各能力目录回填索引,并推进 marketplaceVersion
|
|
18994
|
-
npx @vetta-org/plugin-cli sync --check # 只报不写,CI 用
|
|
18995
|
-
\`\`\`
|
|
18996
|
-
|
|
18997
|
-
索引里的 \`version\` 与 \`plugin.json\` 的 \`version\` 必须**完全相等**,否则宿主同步直接失败;
|
|
18998
|
-
而内容变了却不换 \`marketplaceVersion\` 时,客户端既不报错也不更新——用户只是永远收不到。
|
|
18999
|
-
\`add .\` 装完若检测到索引还停在旧版本,会当场提醒你。
|
|
19000
|
-
|
|
19001
|
-
## 不可违反的几条
|
|
19002
|
-
|
|
19003
|
-
- **样式只用 Tailwind \`className\`**。禁止新建业务 CSS、禁止在 \`style.css\` 里写 \`button\`/\`div\`/\`*\`
|
|
19004
|
-
这类选择器——插件与宿主共享同一个页面,全局选择器会污染整个 UI。
|
|
19005
|
-
- **可能失败的路径必须上报**:读文件、解析、网络、外部库的 catch 里调用
|
|
19006
|
-
\`ctx.ui.notify({ message, error })\`(无需权限)。禁止只写死「失败」文案并丢掉原始 error。
|
|
19007
|
-
- **权限按需最小声明**。构建期会校验产物用到的能力与 \`plugin.json\` 的声明是否匹配,缺了直接
|
|
19008
|
-
构建失败。但 UI 槽位不在这条校验里——那类缺权限在运行时只是静默跳过,所以对着手册核对。
|
|
19009
|
-
- **不要写 \`agent_mode\`**(已废弃,无运行时语义)。想收窄某个工具的使用场景,把「何时不该用它 +
|
|
19010
|
-
替代做法」写进该工具 description 的反向触发段。
|
|
19011
|
-
- **顶层不要出现依赖共享 React 的 JSX**,放进组件或 \`activate\` 内(Module Federation 的加载时序)。
|
|
19012
|
-
- 依赖用 registry 上已发布的 semver,不要 \`workspace:*\`。
|
|
19013
|
-
- **\`dist/\` 要进版本库**。插件通过仓库目录分发时,宿主直接读 \`plugin.json\` 指向的 \`entry\`
|
|
19014
|
-
与 \`styles\`,它不会替你构建——目录里没有构建产物就装不上。
|
|
19015
18998
|
## 信息不足时
|
|
19016
18999
|
|
|
19017
19000
|
插件 id、展示名、要用哪些权限、功能边界、是否立刻安装——**问用户**,不要自己假定。
|
|
19018
19001
|
`;
|
|
19019
19002
|
}
|
|
19020
19003
|
|
|
19004
|
+
// src/init.ts
|
|
19005
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
19006
|
+
import { dirname, join as join3, resolve as resolve2 } from "node:path";
|
|
19007
|
+
|
|
19021
19008
|
// src/hub-template.ts
|
|
19022
19009
|
function renderHubAgentsGuide(input) {
|
|
19023
|
-
return
|
|
19010
|
+
return `<!-- vetta-guide-revision: ${AGENTS_GUIDE_REVISION} -->
|
|
19011
|
+
# ${input.name}
|
|
19024
19012
|
|
|
19025
19013
|
Vetta 能力市场仓库。本仓库索引若干**能力**(plugin / mcp / skill / scene / bundle),
|
|
19026
19014
|
每个能力是 \`abilities/\` 下的一个自包含目录。
|
|
@@ -19054,16 +19042,25 @@ npx @vetta-org/plugin-cli init --id <slug> --name "<Display Name>" abilities/plu
|
|
|
19054
19042
|
|
|
19055
19043
|
## 索引由工具对账,不要手改派生字段
|
|
19056
19044
|
|
|
19057
|
-
|
|
19058
|
-
\`config.commands\` 全都是从能力包推导出来的。改完能力后:
|
|
19045
|
+
改完能力后:
|
|
19059
19046
|
|
|
19060
19047
|
\`\`\`bash
|
|
19061
|
-
npx @vetta-org/plugin-cli sync #
|
|
19048
|
+
npx @vetta-org/plugin-cli sync # 对账并回填,看输出
|
|
19062
19049
|
npx @vetta-org/plugin-cli sync --check # 只报不写,非零退出(CI 用)
|
|
19063
19050
|
\`\`\`
|
|
19064
19051
|
|
|
19052
|
+
\`sync\` 到底做什么,分三档看清楚——它不是万能的:
|
|
19053
|
+
|
|
19054
|
+
| 字段 | \`sync\` 的行为 |
|
|
19055
|
+
| --- | --- |
|
|
19056
|
+
| 条目 \`version\` | **回填**成能力包里的版本 |
|
|
19057
|
+
| \`marketplaceVersion\` | 内容有变化时**尝试**推进。只认 semver(\`1.2.3\`)和纯整数;\`YYYY.MM.DD-NN\` 之类的格式推不动,会报出来要你手改 |
|
|
19058
|
+
| \`config.api_version\` / \`config.permissions\` / \`config.commands\` | **不写**。宿主建目录时用 \`plugin.json\` 整个重算 \`config\`,索引里的副本读都不读。已经存在且与真源不符时 \`sync\` 会提醒你删掉或改对 |
|
|
19059
|
+
|
|
19060
|
+
所以 \`sync\` 跑完要看输出:它报出来的问题(尤其是推不动的 \`marketplaceVersion\`)没人会替你处理。
|
|
19061
|
+
|
|
19065
19062
|
要**手写**的只有身份与展示:\`slug\`、\`name\`、\`description\`、\`source.path\`、\`category\`、\`tags\`、
|
|
19066
|
-
\`detail
|
|
19063
|
+
\`detail\`。新能力上架时手动加一条这样的条目。
|
|
19067
19064
|
|
|
19068
19065
|
三条容易踩的约束,\`sync --check\` 会替你守住:
|
|
19069
19066
|
|
|
@@ -19073,7 +19070,7 @@ npx @vetta-org/plugin-cli sync --check # 只报不写,非零退出(CI 用
|
|
|
19073
19070
|
| \`plugin.json\` 的 \`entry\` / \`styles\` 必须在已发布目录里真实存在 | 本地能装,市场上装不了 |
|
|
19074
19071
|
| 改了任何内容必须换 \`marketplaceVersion\` | 客户端不报错、也不更新,用户永远收不到 |
|
|
19075
19072
|
|
|
19076
|
-
|
|
19073
|
+
第三条最阴险——它不报错。\`sync\` 只在版本号是 semver 或整数时才推得动,其余格式要你自己换。
|
|
19077
19074
|
|
|
19078
19075
|
## 为什么插件目录里要提交 \`dist/\`
|
|
19079
19076
|
|
|
@@ -19241,26 +19238,80 @@ node_modules/
|
|
|
19241
19238
|
}
|
|
19242
19239
|
return { root, pluginId: input.pluginId, files: Object.keys(files).sort() };
|
|
19243
19240
|
}
|
|
19244
|
-
function refreshAgentsGuide(targetDir) {
|
|
19241
|
+
function refreshAgentsGuide(targetDir, options = {}) {
|
|
19245
19242
|
const root = resolve2(targetDir);
|
|
19243
|
+
const file = join3(root, "AGENTS.md");
|
|
19246
19244
|
const manifestPath = join3(root, "plugin.json");
|
|
19245
|
+
const hubManifestPath = join3(root, ".vetta", "marketplace.json");
|
|
19246
|
+
let kind;
|
|
19247
|
+
let content;
|
|
19247
19248
|
if (existsSync(manifestPath)) {
|
|
19248
19249
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
19249
19250
|
const pluginId = typeof manifest.id === "string" ? manifest.id : undefined;
|
|
19250
19251
|
if (!pluginId)
|
|
19251
19252
|
throw new Error(`plugin.json at ${root} has no id`);
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19253
|
+
kind = "plugin";
|
|
19254
|
+
content = renderAgentsGuide({
|
|
19255
|
+
pluginId,
|
|
19256
|
+
displayName: resolveManifestText(manifest.name, root, pluginId),
|
|
19257
|
+
scripts: readPackageScripts(root)
|
|
19258
|
+
});
|
|
19259
|
+
} else if (existsSync(hubManifestPath)) {
|
|
19260
|
+
const manifest = JSON.parse(readFileSync(hubManifestPath, "utf8"));
|
|
19261
|
+
kind = "hub";
|
|
19262
|
+
content = renderHubAgentsGuide({
|
|
19263
|
+
name: typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : "marketplace"
|
|
19264
|
+
});
|
|
19265
|
+
} else {
|
|
19266
|
+
throw new Error(`Not a plugin project or marketplace repository: ${root}`);
|
|
19255
19267
|
}
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19268
|
+
if (!options.dryRun)
|
|
19269
|
+
assertSafeToOverwrite(file, options.force === true);
|
|
19270
|
+
if (options.dryRun)
|
|
19271
|
+
return { root, kind, file, content, written: false };
|
|
19272
|
+
writeFileSync(file, content, "utf8");
|
|
19273
|
+
return { root, kind, file, content, written: true };
|
|
19274
|
+
}
|
|
19275
|
+
function assertSafeToOverwrite(file, force) {
|
|
19276
|
+
if (force || !existsSync(file))
|
|
19277
|
+
return;
|
|
19278
|
+
if (readAgentsGuideRevision(readFileSync(file, "utf8")) !== undefined)
|
|
19279
|
+
return;
|
|
19280
|
+
throw new Error(`${file} has no vetta-guide-revision marker, so it looks hand-written rather than scaffolded. ` + "Refusing to overwrite it. Review the new template with `--dry-run`, merge what you want by hand, " + "or pass `--force` to replace the file.");
|
|
19281
|
+
}
|
|
19282
|
+
function resolveManifestText(raw2, root, fallback) {
|
|
19283
|
+
if (typeof raw2 !== "string" || raw2.length === 0)
|
|
19284
|
+
return fallback;
|
|
19285
|
+
const match2 = /^%([^%]+)%$/.exec(raw2);
|
|
19286
|
+
if (!match2)
|
|
19287
|
+
return raw2;
|
|
19288
|
+
const key = match2[1];
|
|
19289
|
+
const pluginManifest = readJsonFile(join3(root, "plugin.json"));
|
|
19290
|
+
const locale = typeof pluginManifest?.defaultLocale === "string" ? pluginManifest.defaultLocale : "zh";
|
|
19291
|
+
for (const candidate of [locale, "zh", "en"]) {
|
|
19292
|
+
const table = readJsonFile(join3(root, "locales", `${candidate}.json`));
|
|
19293
|
+
const value = table?.[key];
|
|
19294
|
+
if (typeof value === "string" && value.length > 0)
|
|
19295
|
+
return value;
|
|
19296
|
+
}
|
|
19297
|
+
return fallback;
|
|
19298
|
+
}
|
|
19299
|
+
function readPackageScripts(root) {
|
|
19300
|
+
const pkg = readJsonFile(join3(root, "package.json"));
|
|
19301
|
+
const scripts = pkg?.scripts;
|
|
19302
|
+
if (typeof scripts !== "object" || scripts === null || Array.isArray(scripts))
|
|
19303
|
+
return [];
|
|
19304
|
+
return Object.keys(scripts);
|
|
19305
|
+
}
|
|
19306
|
+
function readJsonFile(path) {
|
|
19307
|
+
if (!existsSync(path))
|
|
19308
|
+
return;
|
|
19309
|
+
try {
|
|
19310
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
19311
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
|
|
19312
|
+
} catch {
|
|
19313
|
+
return;
|
|
19262
19314
|
}
|
|
19263
|
-
throw new Error(`Not a plugin project or marketplace repository: ${root}`);
|
|
19264
19315
|
}
|
|
19265
19316
|
var HUB_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
19266
19317
|
var APP_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -19320,7 +19371,7 @@ function detectJsonIndent(source) {
|
|
|
19320
19371
|
const match2 = /\n([ \t]+)\S/.exec(source);
|
|
19321
19372
|
return match2?.[1] ?? "\t";
|
|
19322
19373
|
}
|
|
19323
|
-
function
|
|
19374
|
+
function readJsonFile2(path) {
|
|
19324
19375
|
try {
|
|
19325
19376
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
19326
19377
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
@@ -19364,7 +19415,7 @@ function nextMarketplaceVersion(current) {
|
|
|
19364
19415
|
return;
|
|
19365
19416
|
}
|
|
19366
19417
|
function syncMarketplaceIndex(input) {
|
|
19367
|
-
const manifest =
|
|
19418
|
+
const manifest = readJsonFile2(input.manifestPath);
|
|
19368
19419
|
if (!manifest)
|
|
19369
19420
|
throw new Error(`Malformed marketplace manifest: ${input.manifestPath}`);
|
|
19370
19421
|
const abilities = Array.isArray(manifest.abilities) ? manifest.abilities : [];
|
|
@@ -19433,7 +19484,7 @@ function syncMarketplaceIndex(input) {
|
|
|
19433
19484
|
}
|
|
19434
19485
|
function reconcilePlugin(context) {
|
|
19435
19486
|
const { entry, slug, abilityDir, changes, problems } = context;
|
|
19436
|
-
const manifest =
|
|
19487
|
+
const manifest = readJsonFile2(join4(abilityDir, "plugin.json"));
|
|
19437
19488
|
if (!manifest) {
|
|
19438
19489
|
problems.push({ slug, message: "plugin.json is missing or malformed" });
|
|
19439
19490
|
return;
|
|
@@ -19474,7 +19525,7 @@ function reconcilePlugin(context) {
|
|
|
19474
19525
|
}
|
|
19475
19526
|
function reconcileIdentityFile(context) {
|
|
19476
19527
|
const { entry, slug, abilityDir, fileName, changes, problems } = context;
|
|
19477
|
-
const identity =
|
|
19528
|
+
const identity = readJsonFile2(join4(abilityDir, fileName));
|
|
19478
19529
|
if (!identity) {
|
|
19479
19530
|
problems.push({ slug, message: `${fileName} is missing or malformed` });
|
|
19480
19531
|
return;
|
|
@@ -19517,7 +19568,7 @@ function findAbilityDirectories(hubRoot) {
|
|
|
19517
19568
|
return found.sort();
|
|
19518
19569
|
}
|
|
19519
19570
|
function describeIndexDrift(input) {
|
|
19520
|
-
const manifest =
|
|
19571
|
+
const manifest = readJsonFile2(input.manifestPath);
|
|
19521
19572
|
if (!manifest || !Array.isArray(manifest.abilities))
|
|
19522
19573
|
return;
|
|
19523
19574
|
const entry = manifest.abilities.find((item) => typeof item === "object" && item !== null && !Array.isArray(item) && item.slug === input.slug);
|
|
@@ -19607,7 +19658,7 @@ Usage:
|
|
|
19607
19658
|
vetta-plugin-cli reload <plugin-id> [--json]
|
|
19608
19659
|
vetta-plugin-cli docs [--check-latest] [--json]
|
|
19609
19660
|
vetta-plugin-cli init --id <plugin-id> [--name <display>] [dir] [--json]
|
|
19610
|
-
vetta-plugin-cli init --refresh-guide [dir] [--json]
|
|
19661
|
+
vetta-plugin-cli init --refresh-guide [dir] [--dry-run] [--force] [--json]
|
|
19611
19662
|
vetta-plugin-cli init hub --name <slug> --repository <url> --min-app-version <x.y.z> [dir]
|
|
19612
19663
|
vetta-plugin-cli watch [dir] [--stop] [--json]
|
|
19613
19664
|
vetta-plugin-cli uninstall [plugin-id] [--json]
|
|
@@ -19708,7 +19759,9 @@ function parsePluginInitCommand(argv) {
|
|
|
19708
19759
|
id: { type: "string" },
|
|
19709
19760
|
name: { type: "string" },
|
|
19710
19761
|
json: { type: "boolean" },
|
|
19711
|
-
"refresh-guide": { type: "boolean" }
|
|
19762
|
+
"refresh-guide": { type: "boolean" },
|
|
19763
|
+
force: { type: "boolean" },
|
|
19764
|
+
"dry-run": { type: "boolean" }
|
|
19712
19765
|
}
|
|
19713
19766
|
});
|
|
19714
19767
|
} catch (error) {
|
|
@@ -19718,7 +19771,13 @@ function parsePluginInitCommand(argv) {
|
|
|
19718
19771
|
const [dir, extra] = parsed.positionals;
|
|
19719
19772
|
if (extra)
|
|
19720
19773
|
return { type: "error", message: `Unexpected argument: ${extra}` };
|
|
19721
|
-
return {
|
|
19774
|
+
return {
|
|
19775
|
+
type: "refresh-guide",
|
|
19776
|
+
...dir ? { targetDir: dir } : {},
|
|
19777
|
+
json: parsed.values.json === true,
|
|
19778
|
+
force: parsed.values.force === true,
|
|
19779
|
+
dryRun: parsed.values["dry-run"] === true
|
|
19780
|
+
};
|
|
19722
19781
|
}
|
|
19723
19782
|
const pluginId = parsed.values.id;
|
|
19724
19783
|
if (typeof pluginId !== "string" || pluginId.length === 0) {
|
|
@@ -20061,6 +20120,7 @@ async function runDocsCommand(command, dependencies) {
|
|
|
20061
20120
|
const sdkVersion = readManualSdkVersion(manualDir);
|
|
20062
20121
|
const latestVersion = command.checkLatest ? await dependencies.readLatestSdkVersion?.() : undefined;
|
|
20063
20122
|
const outdated = sdkVersion !== undefined && latestVersion !== undefined && compareSemver(sdkVersion, latestVersion) < 0;
|
|
20123
|
+
const guide = inspectAgentsGuide(project?.root ?? hub?.root ?? cwd);
|
|
20064
20124
|
if (command.json) {
|
|
20065
20125
|
dependencies.writeStdout(`${JSON.stringify({
|
|
20066
20126
|
ok: true,
|
|
@@ -20068,6 +20128,7 @@ async function runDocsCommand(command, dependencies) {
|
|
|
20068
20128
|
entry: join6(manualDir, "README.md"),
|
|
20069
20129
|
sdkVersion,
|
|
20070
20130
|
refreshCommand: SDK_REFRESH_COMMAND,
|
|
20131
|
+
guide,
|
|
20071
20132
|
...command.checkLatest ? { latestVersion, outdated } : {},
|
|
20072
20133
|
project: project ? { root: project.root, pluginId: project.pluginId, version: project.version } : undefined,
|
|
20073
20134
|
hub: hub ? {
|
|
@@ -20093,6 +20154,11 @@ async function runDocsCommand(command, dependencies) {
|
|
|
20093
20154
|
} else {
|
|
20094
20155
|
lines.push(`Manual follows the installed SDK. To refresh it: ${SDK_REFRESH_COMMAND}`);
|
|
20095
20156
|
}
|
|
20157
|
+
if (guide.stale) {
|
|
20158
|
+
lines.push(`This brief is stale (AGENTS.md revision ${guide.revision} < ${AGENTS_GUIDE_REVISION}). Refresh it with: ${GUIDE_REFRESH_COMMAND}`);
|
|
20159
|
+
} else if (guide.unstamped) {
|
|
20160
|
+
lines.push(`AGENTS.md has no revision marker, so it looks hand-written. Review the current template with \`${GUIDE_REFRESH_COMMAND} --dry-run\` and merge by hand; do not overwrite it blindly.`);
|
|
20161
|
+
}
|
|
20096
20162
|
if (hub) {
|
|
20097
20163
|
lines.push(`Marketplace index: ${hub.manifestPath}`);
|
|
20098
20164
|
lines.push("After changing version/permissions, run `vetta-plugin-cli sync` at the repository root.");
|
|
@@ -20103,6 +20169,24 @@ async function runDocsCommand(command, dependencies) {
|
|
|
20103
20169
|
return 0;
|
|
20104
20170
|
}
|
|
20105
20171
|
var SDK_REFRESH_COMMAND = "npm i -D @vetta-org/plugin-sdk@latest && npx vetta-plugin-cli docs";
|
|
20172
|
+
var GUIDE_REFRESH_COMMAND = "npx @vetta-org/plugin-cli init --refresh-guide";
|
|
20173
|
+
function inspectAgentsGuide(root) {
|
|
20174
|
+
const path = join6(root, "AGENTS.md");
|
|
20175
|
+
if (!existsSync4(path))
|
|
20176
|
+
return { present: false, stale: false, unstamped: false };
|
|
20177
|
+
let revision;
|
|
20178
|
+
try {
|
|
20179
|
+
revision = readAgentsGuideRevision(readFileSync4(path, "utf8"));
|
|
20180
|
+
} catch {
|
|
20181
|
+
return { present: true, stale: false, unstamped: false };
|
|
20182
|
+
}
|
|
20183
|
+
return {
|
|
20184
|
+
present: true,
|
|
20185
|
+
...revision === undefined ? {} : { revision },
|
|
20186
|
+
stale: revision !== undefined && revision < AGENTS_GUIDE_REVISION,
|
|
20187
|
+
unstamped: revision === undefined
|
|
20188
|
+
};
|
|
20189
|
+
}
|
|
20106
20190
|
function compareSemver(left, right) {
|
|
20107
20191
|
const parse2 = (value) => {
|
|
20108
20192
|
const match2 = /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(value.trim());
|
|
@@ -20123,11 +20207,18 @@ function compareSemver(left, right) {
|
|
|
20123
20207
|
function runRefreshGuideCommand(command, dependencies) {
|
|
20124
20208
|
const cwd = dependencies.cwd?.() ?? process.cwd();
|
|
20125
20209
|
try {
|
|
20126
|
-
const result = refreshAgentsGuide(resolve5(cwd, command.targetDir ?? ".")
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20210
|
+
const result = refreshAgentsGuide(resolve5(cwd, command.targetDir ?? "."), {
|
|
20211
|
+
force: command.force,
|
|
20212
|
+
dryRun: command.dryRun
|
|
20213
|
+
});
|
|
20214
|
+
if (command.json) {
|
|
20215
|
+
dependencies.writeStdout(`${JSON.stringify({ ok: true, ...result })}
|
|
20130
20216
|
`);
|
|
20217
|
+
return 0;
|
|
20218
|
+
}
|
|
20219
|
+
dependencies.writeStdout(result.written ? `Rewrote ${result.file}
|
|
20220
|
+
Next: npx vetta-plugin-cli docs --check-latest
|
|
20221
|
+
` : `${result.content}`);
|
|
20131
20222
|
return 0;
|
|
20132
20223
|
} catch (error) {
|
|
20133
20224
|
const message = error instanceof Error ? error.message : String(error);
|
package/dist/command.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ export type PluginInitCommand = {
|
|
|
44
44
|
type: "refresh-guide";
|
|
45
45
|
targetDir?: string;
|
|
46
46
|
json: boolean;
|
|
47
|
+
force: boolean;
|
|
48
|
+
dryRun: boolean;
|
|
47
49
|
} | {
|
|
48
50
|
type: "init-hub";
|
|
49
51
|
targetDir?: string;
|
|
@@ -104,5 +106,19 @@ export declare function parsePluginUninstallCommand(argv: string[]): PluginUnins
|
|
|
104
106
|
export declare function parsePluginSyncCommand(argv: string[]): PluginSyncCommand | undefined;
|
|
105
107
|
export declare function runPluginAddCommand(command: PluginAddCommand, dependencies?: PluginAddCommandDependencies): Promise<number>;
|
|
106
108
|
export declare function runPluginCommand(command: PluginCommand, dependencies?: PluginCommandDependencies): Promise<number>;
|
|
109
|
+
export interface AgentsGuideStatus {
|
|
110
|
+
/** 本工程有没有 AGENTS.md。 */
|
|
111
|
+
readonly present: boolean;
|
|
112
|
+
/** 读到的版本戳;没有戳(模板早于版本戳,或是手写的)时缺省。 */
|
|
113
|
+
readonly revision?: number;
|
|
114
|
+
/**
|
|
115
|
+
* **带戳**且落后于当前 CLI 的模板——只有这一档能安全地一键重写。
|
|
116
|
+
*
|
|
117
|
+
* 没有 AGENTS.md 时为 false(那是「没有」,不是「旧」);没有戳时也为 false,见 {@link unstamped}。
|
|
118
|
+
*/
|
|
119
|
+
readonly stale: boolean;
|
|
120
|
+
/** 有文件但没有版本戳:可能是手写的,也可能是版本戳之前的模板,无从区分。 */
|
|
121
|
+
readonly unstamped: boolean;
|
|
122
|
+
}
|
|
107
123
|
export declare function runPluginCli(argv: string[]): Promise<number>;
|
|
108
124
|
//# sourceMappingURL=command.d.ts.map
|