@vetta-org/plugin-cli 0.1.5 → 0.1.7
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 +33 -0
- package/README.md +16 -4
- package/dist/agents-template.d.ts +3 -1
- package/dist/agents-template.d.ts.map +1 -1
- package/dist/cli.js +292 -54
- package/dist/command.d.ts +9 -1
- package/dist/command.d.ts.map +1 -1
- package/dist/hub-template.d.ts.map +1 -1
- package/dist/index.js +292 -54
- package/dist/init.d.ts +14 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11905,6 +11905,18 @@ var agentExperimentalSettingsUpdateType = Type.Object({
|
|
|
11905
11905
|
promptPrediction: Type.Optional(Type.Boolean()),
|
|
11906
11906
|
agentSkills: Type.Optional(Type.Boolean())
|
|
11907
11907
|
}, { additionalProperties: false, minProperties: 1 });
|
|
11908
|
+
var imageGenerationSettingsType = Type.Object({
|
|
11909
|
+
textToImageProviderId: Type.Optional(Type.String({ minLength: 1, maxLength: 129 })),
|
|
11910
|
+
textToImageModelId: Type.Optional(Type.String({ minLength: 1, maxLength: 256 })),
|
|
11911
|
+
imageToImageProviderId: Type.Optional(Type.String({ minLength: 1, maxLength: 129 })),
|
|
11912
|
+
imageToImageModelId: Type.Optional(Type.String({ minLength: 1, maxLength: 256 }))
|
|
11913
|
+
}, { additionalProperties: false });
|
|
11914
|
+
var imageGenerationSettingsUpdateType = Type.Object({
|
|
11915
|
+
textToImageProviderId: Type.Optional(Type.Union([Type.String({ minLength: 1, maxLength: 129 }), Type.Null()])),
|
|
11916
|
+
textToImageModelId: Type.Optional(Type.Union([Type.String({ minLength: 1, maxLength: 256 }), Type.Null()])),
|
|
11917
|
+
imageToImageProviderId: Type.Optional(Type.Union([Type.String({ minLength: 1, maxLength: 129 }), Type.Null()])),
|
|
11918
|
+
imageToImageModelId: Type.Optional(Type.Union([Type.String({ minLength: 1, maxLength: 256 }), Type.Null()]))
|
|
11919
|
+
}, { additionalProperties: false, minProperties: 1 });
|
|
11908
11920
|
var agentSettingsEmptyInputSchema = defineCapabilityInputSchema(agentSettingsEmptyInputType);
|
|
11909
11921
|
var agentExperimentalSettingsSchema = defineCapabilityOutputSchema(agentExperimentalSettingsType, { clean: true });
|
|
11910
11922
|
var agentExperimentalSettingsUpdateSchema = defineCapabilityInputSchema(agentExperimentalSettingsUpdateType);
|
|
@@ -11924,6 +11936,22 @@ var DOMAIN_AGENT_SETTINGS_CAPABILITIES = {
|
|
|
11924
11936
|
version: 1,
|
|
11925
11937
|
input: agentExperimentalSettingsUpdateSchema,
|
|
11926
11938
|
output: agentExperimentalSettingsSchema
|
|
11939
|
+
}),
|
|
11940
|
+
GET_IMAGE_GENERATION: defineCapability({
|
|
11941
|
+
id: "cap.domain.vetta.agent-settings.image-generation.get",
|
|
11942
|
+
kind: "query",
|
|
11943
|
+
layer: CAPABILITY_LAYERS.DOMAIN,
|
|
11944
|
+
version: 1,
|
|
11945
|
+
input: agentSettingsEmptyInputSchema,
|
|
11946
|
+
output: defineCapabilityOutputSchema(imageGenerationSettingsType, { clean: true })
|
|
11947
|
+
}),
|
|
11948
|
+
SET_IMAGE_GENERATION: defineCapability({
|
|
11949
|
+
id: "cap.domain.vetta.agent-settings.image-generation.set",
|
|
11950
|
+
kind: "command",
|
|
11951
|
+
layer: CAPABILITY_LAYERS.DOMAIN,
|
|
11952
|
+
version: 1,
|
|
11953
|
+
input: defineCapabilityInputSchema(imageGenerationSettingsUpdateType),
|
|
11954
|
+
output: defineCapabilityOutputSchema(imageGenerationSettingsType, { clean: true })
|
|
11927
11955
|
})
|
|
11928
11956
|
};
|
|
11929
11957
|
var DOMAIN_AGENT_SETTINGS_CAPABILITY_CATALOG = createCapabilityCatalog(Object.values(DOMAIN_AGENT_SETTINGS_CAPABILITIES));
|
|
@@ -13029,7 +13057,7 @@ var FOUNDATION_JOB_CAPABILITIES = {
|
|
|
13029
13057
|
var FOUNDATION_JOB_CAPABILITY_CATALOG = createCapabilityCatalog(Object.values(FOUNDATION_JOB_CAPABILITIES));
|
|
13030
13058
|
|
|
13031
13059
|
// ../../capability-sdk/dist/domain/media.js
|
|
13032
|
-
var MEDIA_PROTOCOL_VERSION =
|
|
13060
|
+
var MEDIA_PROTOCOL_VERSION = 5;
|
|
13033
13061
|
var MEDIA_OPERATIONS = {
|
|
13034
13062
|
GENERATE: "generate",
|
|
13035
13063
|
COMPOSE: "compose",
|
|
@@ -13128,6 +13156,16 @@ var mediaGenerationModeCapabilityType = Type.Object({
|
|
|
13128
13156
|
aspectRatioPolicy: Type.Optional(Type.Union([Type.Literal("configurable"), Type.Literal("input-derived")])),
|
|
13129
13157
|
audioGeneration: Type.Optional(Type.Union([Type.Literal("none"), Type.Literal("always"), Type.Literal("optional")]))
|
|
13130
13158
|
}, { additionalProperties: false });
|
|
13159
|
+
var mediaGenerationModelDescriptorType = Type.Object({
|
|
13160
|
+
id: requiredStringType2,
|
|
13161
|
+
displayName: Type.Optional(Type.String({ minLength: 1, maxLength: 128 })),
|
|
13162
|
+
sourceId: Type.Optional(requiredStringType2),
|
|
13163
|
+
sourceDisplayName: Type.Optional(Type.String({ minLength: 1, maxLength: 128 })),
|
|
13164
|
+
modes: Type.Array(mediaGenerationModeType, { minItems: 1 }),
|
|
13165
|
+
aspectRatios: Type.Optional(Type.Array(requiredStringType2)),
|
|
13166
|
+
resolutions: Type.Optional(Type.Array(requiredStringType2)),
|
|
13167
|
+
defaultResolution: Type.Optional(requiredStringType2)
|
|
13168
|
+
}, { additionalProperties: false });
|
|
13131
13169
|
var mediaGenerateCapabilityType = Type.Object({
|
|
13132
13170
|
operation: Type.Literal(MEDIA_OPERATIONS.GENERATE),
|
|
13133
13171
|
kind: mediaGenerationKindType,
|
|
@@ -13135,6 +13173,8 @@ var mediaGenerateCapabilityType = Type.Object({
|
|
|
13135
13173
|
aspectRatios: Type.Optional(Type.Array(requiredStringType2)),
|
|
13136
13174
|
resolutions: Type.Optional(Type.Array(requiredStringType2)),
|
|
13137
13175
|
defaultResolution: Type.Optional(requiredStringType2),
|
|
13176
|
+
models: Type.Optional(Type.Array(mediaGenerationModelDescriptorType, { minItems: 1 })),
|
|
13177
|
+
defaultModelId: Type.Optional(requiredStringType2),
|
|
13138
13178
|
durationsSeconds: Type.Optional(Type.Array(Type.Number({ exclusiveMinimum: 0 }))),
|
|
13139
13179
|
modeCapabilities: Type.Optional(Type.Array(mediaGenerationModeCapabilityType))
|
|
13140
13180
|
}, { additionalProperties: false });
|
|
@@ -13318,6 +13358,8 @@ var modelProviderUpsertModelType = Type.Object({
|
|
|
13318
13358
|
name: Type.Optional(Type.String()),
|
|
13319
13359
|
api: Type.Optional(Type.String()),
|
|
13320
13360
|
reasoning: Type.Optional(Type.Boolean()),
|
|
13361
|
+
reasoningLevels: modelDefinitionDetailType.properties.reasoningLevels,
|
|
13362
|
+
defaultReasoningLevel: modelDefinitionDetailType.properties.defaultReasoningLevel,
|
|
13321
13363
|
contextWindow: Type.Optional(Type.Number()),
|
|
13322
13364
|
maxTokens: Type.Optional(Type.Number())
|
|
13323
13365
|
}, { additionalProperties: false });
|
|
@@ -15419,7 +15461,9 @@ var PluginAgentTeamMemberManifestSchema = Type.Object({
|
|
|
15419
15461
|
agent: Type.Optional(NonWhitespaceStringSchema),
|
|
15420
15462
|
role: Type.Optional(PluginAgentRoleSchema),
|
|
15421
15463
|
responsibility: Type.String({ maxLength: 2000 }),
|
|
15422
|
-
optional: Type.Optional(Type.Boolean())
|
|
15464
|
+
optional: Type.Optional(Type.Boolean()),
|
|
15465
|
+
instructions: Type.Optional(Type.String({ maxLength: 64000 })),
|
|
15466
|
+
instructionsPath: Type.Optional(NonWhitespaceStringSchema)
|
|
15423
15467
|
}, { additionalProperties: false });
|
|
15424
15468
|
var PluginAgentTeamManifestSchema = Type.Object({
|
|
15425
15469
|
id: Type.String({ pattern: "^[a-z0-9][a-z0-9-]{0,63}$" }),
|
|
@@ -18921,13 +18965,33 @@ async function resolveNpmPluginArchive(packageSpec, pack = runNpmPack) {
|
|
|
18921
18965
|
}
|
|
18922
18966
|
|
|
18923
18967
|
// src/agents-template.ts
|
|
18924
|
-
var AGENTS_GUIDE_REVISION =
|
|
18968
|
+
var AGENTS_GUIDE_REVISION = 3;
|
|
18925
18969
|
function readAgentsGuideRevision(content) {
|
|
18926
18970
|
const match2 = /<!--\s*vetta-guide-revision:\s*(\d+)\s*-->/.exec(content);
|
|
18927
18971
|
if (!match2)
|
|
18928
18972
|
return;
|
|
18929
18973
|
return Number(match2[1]);
|
|
18930
18974
|
}
|
|
18975
|
+
function renderCommands(pluginId, scripts) {
|
|
18976
|
+
const known = [
|
|
18977
|
+
["dev", "npm run dev # 开发服务器"],
|
|
18978
|
+
["build", "npm run build # 产出 dist/"],
|
|
18979
|
+
["install:vetta", "npm run install:vetta # 打包并装进正在运行的 Vetta(需要 Vetta 已启动)"]
|
|
18980
|
+
];
|
|
18981
|
+
const lines = known.filter(([name]) => scripts.includes(name)).map(([, line]) => line);
|
|
18982
|
+
if (!scripts.includes("install:vetta")) {
|
|
18983
|
+
lines.push("npx vetta-plugin-cli add . # 打包并装进正在运行的 Vetta");
|
|
18984
|
+
}
|
|
18985
|
+
return [
|
|
18986
|
+
...lines,
|
|
18987
|
+
"",
|
|
18988
|
+
"npx vetta-plugin-cli watch # 热更新:宿主改从本工程目录加载,改完即生效",
|
|
18989
|
+
`npx vetta-plugin-cli reload ${pluginId} # 装完提示有 pending 版本时用它`,
|
|
18990
|
+
"npx vetta-plugin-cli uninstall # 卸载(省略 id 即本工程对应的插件)",
|
|
18991
|
+
"npx vetta-plugin-cli sync # 在 hub 仓库根上跑:把索引与各能力目录对账"
|
|
18992
|
+
].join(`
|
|
18993
|
+
`);
|
|
18994
|
+
}
|
|
18931
18995
|
function renderAgentsGuide(input) {
|
|
18932
18996
|
return `<!-- vetta-guide-revision: ${AGENTS_GUIDE_REVISION} -->
|
|
18933
18997
|
# ${input.displayName}
|
|
@@ -18967,14 +19031,7 @@ npx vetta-plugin-cli docs --check-latest
|
|
|
18967
19031
|
## 常用命令
|
|
18968
19032
|
|
|
18969
19033
|
\`\`\`bash
|
|
18970
|
-
|
|
18971
|
-
npm run build # 产出 dist/
|
|
18972
|
-
npm run install:vetta # 打包并装进正在运行的 Vetta(需要 Vetta 已启动)
|
|
18973
|
-
|
|
18974
|
-
npx vetta-plugin-cli watch # 热更新:宿主改从本工程目录加载,改完即生效
|
|
18975
|
-
npx vetta-plugin-cli reload ${input.pluginId} # 装完提示有 pending 版本时用它
|
|
18976
|
-
npx vetta-plugin-cli uninstall # 卸载(省略 id 即本工程对应的插件)
|
|
18977
|
-
npx vetta-plugin-cli sync # 在 hub 仓库根上跑:把索引与各能力目录对账
|
|
19034
|
+
${renderCommands(input.pluginId, input.scripts ?? ["dev", "build", "install:vetta"])}
|
|
18978
19035
|
\`\`\`
|
|
18979
19036
|
|
|
18980
19037
|
细节都在 \`getting-started.md\`。\`docs\` 打印了 \`Marketplace index:\` 就说明这个目录之上有能力
|
|
@@ -19027,16 +19084,25 @@ npx @vetta-org/plugin-cli init --id <slug> --name "<Display Name>" abilities/plu
|
|
|
19027
19084
|
|
|
19028
19085
|
## 索引由工具对账,不要手改派生字段
|
|
19029
19086
|
|
|
19030
|
-
|
|
19031
|
-
\`config.commands\` 全都是从能力包推导出来的。改完能力后:
|
|
19087
|
+
改完能力后:
|
|
19032
19088
|
|
|
19033
19089
|
\`\`\`bash
|
|
19034
|
-
npx @vetta-org/plugin-cli sync #
|
|
19090
|
+
npx @vetta-org/plugin-cli sync # 对账并回填,看输出
|
|
19035
19091
|
npx @vetta-org/plugin-cli sync --check # 只报不写,非零退出(CI 用)
|
|
19036
19092
|
\`\`\`
|
|
19037
19093
|
|
|
19094
|
+
\`sync\` 到底做什么,分三档看清楚——它不是万能的:
|
|
19095
|
+
|
|
19096
|
+
| 字段 | \`sync\` 的行为 |
|
|
19097
|
+
| --- | --- |
|
|
19098
|
+
| 条目 \`version\` | **回填**成能力包里的版本 |
|
|
19099
|
+
| \`marketplaceVersion\` | 内容有变化时**尝试**推进。只认 semver(\`1.2.3\`)和纯整数;\`YYYY.MM.DD-NN\` 之类的格式推不动,会报出来要你手改 |
|
|
19100
|
+
| \`config.api_version\` / \`config.permissions\` / \`config.commands\` | **不写**。宿主建目录时用 \`plugin.json\` 整个重算 \`config\`,索引里的副本读都不读。已经存在且与真源不符时 \`sync\` 会提醒你删掉或改对 |
|
|
19101
|
+
|
|
19102
|
+
所以 \`sync\` 跑完要看输出:它报出来的问题(尤其是推不动的 \`marketplaceVersion\`)没人会替你处理。
|
|
19103
|
+
|
|
19038
19104
|
要**手写**的只有身份与展示:\`slug\`、\`name\`、\`description\`、\`source.path\`、\`category\`、\`tags\`、
|
|
19039
|
-
\`detail
|
|
19105
|
+
\`detail\`。新能力上架时手动加一条这样的条目。
|
|
19040
19106
|
|
|
19041
19107
|
三条容易踩的约束,\`sync --check\` 会替你守住:
|
|
19042
19108
|
|
|
@@ -19046,7 +19112,7 @@ npx @vetta-org/plugin-cli sync --check # 只报不写,非零退出(CI 用
|
|
|
19046
19112
|
| \`plugin.json\` 的 \`entry\` / \`styles\` 必须在已发布目录里真实存在 | 本地能装,市场上装不了 |
|
|
19047
19113
|
| 改了任何内容必须换 \`marketplaceVersion\` | 客户端不报错、也不更新,用户永远收不到 |
|
|
19048
19114
|
|
|
19049
|
-
|
|
19115
|
+
第三条最阴险——它不报错。\`sync\` 只在版本号是 semver 或整数时才推得动,其余格式要你自己换。
|
|
19050
19116
|
|
|
19051
19117
|
## 为什么插件目录里要提交 \`dist/\`
|
|
19052
19118
|
|
|
@@ -19214,26 +19280,80 @@ node_modules/
|
|
|
19214
19280
|
}
|
|
19215
19281
|
return { root, pluginId: input.pluginId, files: Object.keys(files).sort() };
|
|
19216
19282
|
}
|
|
19217
|
-
function refreshAgentsGuide(targetDir) {
|
|
19283
|
+
function refreshAgentsGuide(targetDir, options = {}) {
|
|
19218
19284
|
const root = resolve2(targetDir);
|
|
19285
|
+
const file = join3(root, "AGENTS.md");
|
|
19219
19286
|
const manifestPath = join3(root, "plugin.json");
|
|
19287
|
+
const hubManifestPath = join3(root, ".vetta", "marketplace.json");
|
|
19288
|
+
let kind;
|
|
19289
|
+
let content;
|
|
19220
19290
|
if (existsSync(manifestPath)) {
|
|
19221
19291
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
19222
19292
|
const pluginId = typeof manifest.id === "string" ? manifest.id : undefined;
|
|
19223
19293
|
if (!pluginId)
|
|
19224
19294
|
throw new Error(`plugin.json at ${root} has no id`);
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19295
|
+
kind = "plugin";
|
|
19296
|
+
content = renderAgentsGuide({
|
|
19297
|
+
pluginId,
|
|
19298
|
+
displayName: resolveManifestText(manifest.name, root, pluginId),
|
|
19299
|
+
scripts: readPackageScripts(root)
|
|
19300
|
+
});
|
|
19301
|
+
} else if (existsSync(hubManifestPath)) {
|
|
19302
|
+
const manifest = JSON.parse(readFileSync(hubManifestPath, "utf8"));
|
|
19303
|
+
kind = "hub";
|
|
19304
|
+
content = renderHubAgentsGuide({
|
|
19305
|
+
name: typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : "marketplace"
|
|
19306
|
+
});
|
|
19307
|
+
} else {
|
|
19308
|
+
throw new Error(`Not a plugin project or marketplace repository: ${root}`);
|
|
19309
|
+
}
|
|
19310
|
+
if (!options.dryRun)
|
|
19311
|
+
assertSafeToOverwrite(file, options.force === true);
|
|
19312
|
+
if (options.dryRun)
|
|
19313
|
+
return { root, kind, file, content, written: false };
|
|
19314
|
+
writeFileSync(file, content, "utf8");
|
|
19315
|
+
return { root, kind, file, content, written: true };
|
|
19316
|
+
}
|
|
19317
|
+
function assertSafeToOverwrite(file, force) {
|
|
19318
|
+
if (force || !existsSync(file))
|
|
19319
|
+
return;
|
|
19320
|
+
if (readAgentsGuideRevision(readFileSync(file, "utf8")) !== undefined)
|
|
19321
|
+
return;
|
|
19322
|
+
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.");
|
|
19323
|
+
}
|
|
19324
|
+
function resolveManifestText(raw2, root, fallback) {
|
|
19325
|
+
if (typeof raw2 !== "string" || raw2.length === 0)
|
|
19326
|
+
return fallback;
|
|
19327
|
+
const match2 = /^%([^%]+)%$/.exec(raw2);
|
|
19328
|
+
if (!match2)
|
|
19329
|
+
return raw2;
|
|
19330
|
+
const key = match2[1];
|
|
19331
|
+
const pluginManifest = readJsonFile(join3(root, "plugin.json"));
|
|
19332
|
+
const locale = typeof pluginManifest?.defaultLocale === "string" ? pluginManifest.defaultLocale : "zh";
|
|
19333
|
+
for (const candidate of [locale, "zh", "en"]) {
|
|
19334
|
+
const table = readJsonFile(join3(root, "locales", `${candidate}.json`));
|
|
19335
|
+
const value = table?.[key];
|
|
19336
|
+
if (typeof value === "string" && value.length > 0)
|
|
19337
|
+
return value;
|
|
19228
19338
|
}
|
|
19229
|
-
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19339
|
+
return fallback;
|
|
19340
|
+
}
|
|
19341
|
+
function readPackageScripts(root) {
|
|
19342
|
+
const pkg = readJsonFile(join3(root, "package.json"));
|
|
19343
|
+
const scripts = pkg?.scripts;
|
|
19344
|
+
if (typeof scripts !== "object" || scripts === null || Array.isArray(scripts))
|
|
19345
|
+
return [];
|
|
19346
|
+
return Object.keys(scripts);
|
|
19347
|
+
}
|
|
19348
|
+
function readJsonFile(path) {
|
|
19349
|
+
if (!existsSync(path))
|
|
19350
|
+
return;
|
|
19351
|
+
try {
|
|
19352
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
19353
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
|
|
19354
|
+
} catch {
|
|
19355
|
+
return;
|
|
19235
19356
|
}
|
|
19236
|
-
throw new Error(`Not a plugin project or marketplace repository: ${root}`);
|
|
19237
19357
|
}
|
|
19238
19358
|
var HUB_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
19239
19359
|
var APP_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -19293,7 +19413,7 @@ function detectJsonIndent(source) {
|
|
|
19293
19413
|
const match2 = /\n([ \t]+)\S/.exec(source);
|
|
19294
19414
|
return match2?.[1] ?? "\t";
|
|
19295
19415
|
}
|
|
19296
|
-
function
|
|
19416
|
+
function readJsonFile2(path) {
|
|
19297
19417
|
try {
|
|
19298
19418
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
19299
19419
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
@@ -19337,7 +19457,7 @@ function nextMarketplaceVersion(current) {
|
|
|
19337
19457
|
return;
|
|
19338
19458
|
}
|
|
19339
19459
|
function syncMarketplaceIndex(input) {
|
|
19340
|
-
const manifest =
|
|
19460
|
+
const manifest = readJsonFile2(input.manifestPath);
|
|
19341
19461
|
if (!manifest)
|
|
19342
19462
|
throw new Error(`Malformed marketplace manifest: ${input.manifestPath}`);
|
|
19343
19463
|
const abilities = Array.isArray(manifest.abilities) ? manifest.abilities : [];
|
|
@@ -19355,13 +19475,31 @@ function syncMarketplaceIndex(input) {
|
|
|
19355
19475
|
for (const member of Array.isArray(bundleConfig?.members) ? bundleConfig.members : []) {
|
|
19356
19476
|
if (typeof member !== "object" || member === null || Array.isArray(member))
|
|
19357
19477
|
continue;
|
|
19358
|
-
const
|
|
19478
|
+
const memberEntry = member;
|
|
19479
|
+
const memberSource = memberEntry.source;
|
|
19359
19480
|
const memberPath = typeof memberSource === "object" && memberSource !== null && !Array.isArray(memberSource) ? memberSource.path : undefined;
|
|
19360
19481
|
if (typeof memberPath !== "string")
|
|
19361
19482
|
continue;
|
|
19362
19483
|
const dir = resolveAbilityDir(input.hubRoot, memberPath);
|
|
19363
|
-
if (dir)
|
|
19484
|
+
if (dir) {
|
|
19364
19485
|
listedDirs.add(dir);
|
|
19486
|
+
if (manifest.schemaVersion === 3 && memberEntry.type === "plugin") {
|
|
19487
|
+
const descriptor2 = readJsonFile2(join4(dir, "ability.json"));
|
|
19488
|
+
const memberChanges = [];
|
|
19489
|
+
reconcilePlugin({
|
|
19490
|
+
entry: { ...memberEntry, version: descriptor2?.version },
|
|
19491
|
+
slug: typeof memberEntry.slug === "string" ? memberEntry.slug : "(unnamed)",
|
|
19492
|
+
abilityDir: dir,
|
|
19493
|
+
schemaVersion: manifest.schemaVersion,
|
|
19494
|
+
minAppVersion: manifest.minAppVersion,
|
|
19495
|
+
changes: memberChanges,
|
|
19496
|
+
problems
|
|
19497
|
+
});
|
|
19498
|
+
for (const change of memberChanges) {
|
|
19499
|
+
problems.push({ slug: change.slug, message: `ability.json version does not match latest release: ${change.to}` });
|
|
19500
|
+
}
|
|
19501
|
+
}
|
|
19502
|
+
}
|
|
19365
19503
|
}
|
|
19366
19504
|
continue;
|
|
19367
19505
|
}
|
|
@@ -19378,7 +19516,7 @@ function syncMarketplaceIndex(input) {
|
|
|
19378
19516
|
}
|
|
19379
19517
|
listedDirs.add(abilityDir);
|
|
19380
19518
|
if (type === "plugin")
|
|
19381
|
-
reconcilePlugin({ entry, slug, abilityDir, changes, problems });
|
|
19519
|
+
reconcilePlugin({ entry, slug, abilityDir, schemaVersion: manifest.schemaVersion, minAppVersion: manifest.minAppVersion, changes, problems });
|
|
19382
19520
|
else if (type === "mcp")
|
|
19383
19521
|
reconcileIdentityFile({ entry, slug, abilityDir, fileName: "mcp.json", changes, problems });
|
|
19384
19522
|
}
|
|
@@ -19405,8 +19543,78 @@ function syncMarketplaceIndex(input) {
|
|
|
19405
19543
|
return { manifestPath: input.manifestPath, changes, problems, unlisted, written };
|
|
19406
19544
|
}
|
|
19407
19545
|
function reconcilePlugin(context) {
|
|
19408
|
-
const { entry, slug, abilityDir, changes, problems } = context;
|
|
19409
|
-
|
|
19546
|
+
const { entry, slug, abilityDir, schemaVersion, minAppVersion, changes, problems } = context;
|
|
19547
|
+
if (schemaVersion === 3 && !("releases" in entry)) {
|
|
19548
|
+
problems.push({ slug, message: "schemaVersion 3 plugin requires versioned releases" });
|
|
19549
|
+
return;
|
|
19550
|
+
}
|
|
19551
|
+
if ("releases" in entry) {
|
|
19552
|
+
if (schemaVersion !== 3) {
|
|
19553
|
+
problems.push({ slug, message: "versioned plugin releases require marketplace schemaVersion 3" });
|
|
19554
|
+
return;
|
|
19555
|
+
}
|
|
19556
|
+
const releases = entry.releases;
|
|
19557
|
+
if (!Array.isArray(releases) || releases.length === 0) {
|
|
19558
|
+
problems.push({ slug, message: "plugin releases must be a nonempty array" });
|
|
19559
|
+
return;
|
|
19560
|
+
}
|
|
19561
|
+
let latest;
|
|
19562
|
+
const seen = new Set;
|
|
19563
|
+
for (const raw2 of releases) {
|
|
19564
|
+
if (typeof raw2 !== "object" || raw2 === null || Array.isArray(raw2)) {
|
|
19565
|
+
problems.push({ slug, message: "plugin release must be an object" });
|
|
19566
|
+
continue;
|
|
19567
|
+
}
|
|
19568
|
+
const release = raw2;
|
|
19569
|
+
const match2 = typeof release.version === "string" ? /^(\d+)\.(\d+)\.(\d+)$/.exec(release.version) : null;
|
|
19570
|
+
if (!match2 || seen.has(release.version)) {
|
|
19571
|
+
problems.push({ slug, message: `invalid or duplicate plugin release version: ${String(release.version)}` });
|
|
19572
|
+
continue;
|
|
19573
|
+
}
|
|
19574
|
+
seen.add(release.version);
|
|
19575
|
+
const minimum = typeof release.minAppVersion === "string" ? /^(\d+)\.(\d+)\.(\d+)$/.exec(release.minAppVersion) : null;
|
|
19576
|
+
if (!minimum || typeof minAppVersion !== "string" || !/^(\d+)\.(\d+)\.(\d+)$/.test(minAppVersion)) {
|
|
19577
|
+
problems.push({ slug, message: `release ${release.version} has an invalid minAppVersion` });
|
|
19578
|
+
} else {
|
|
19579
|
+
const marketMinimum = /^(\d+)\.(\d+)\.(\d+)$/.exec(minAppVersion);
|
|
19580
|
+
if (marketMinimum && compareVersionParts(minimum.slice(1).map(Number), marketMinimum.slice(1).map(Number)) < 0) {
|
|
19581
|
+
problems.push({ slug, message: `release ${release.version} requires an app older than the marketplace` });
|
|
19582
|
+
}
|
|
19583
|
+
}
|
|
19584
|
+
if (typeof release.pluginApiVersion !== "string" || !/^\^\d+\.\d+\.\d+$/.test(release.pluginApiVersion)) {
|
|
19585
|
+
problems.push({ slug, message: `release ${release.version} has an invalid pluginApiVersion` });
|
|
19586
|
+
}
|
|
19587
|
+
for (const field of ["permissions", "commands"]) {
|
|
19588
|
+
if (release[field] !== undefined && !stringArray(release[field])) {
|
|
19589
|
+
problems.push({ slug, message: `release ${release.version} has invalid ${field}` });
|
|
19590
|
+
}
|
|
19591
|
+
}
|
|
19592
|
+
const parts = [Number(match2[1]), Number(match2[2]), Number(match2[3])];
|
|
19593
|
+
if (!latest || compareVersionParts(parts, latest.parts) > 0) {
|
|
19594
|
+
latest = { version: release.version, parts };
|
|
19595
|
+
}
|
|
19596
|
+
const artifact = release.artifact;
|
|
19597
|
+
if (typeof artifact !== "object" || artifact === null || Array.isArray(artifact)) {
|
|
19598
|
+
problems.push({ slug, message: `release ${release.version} has no artifact` });
|
|
19599
|
+
continue;
|
|
19600
|
+
}
|
|
19601
|
+
const { url, sha256 } = artifact;
|
|
19602
|
+
let validUrl = false;
|
|
19603
|
+
try {
|
|
19604
|
+
const parsed = new URL(String(url));
|
|
19605
|
+
validUrl = parsed.protocol === "https:" && !parsed.username && !parsed.password && !parsed.hash;
|
|
19606
|
+
} catch {}
|
|
19607
|
+
if (!validUrl || typeof sha256 !== "string" || !/^[a-f0-9]{64}$/.test(sha256)) {
|
|
19608
|
+
problems.push({ slug, message: `release ${release.version} has an invalid HTTPS artifact or SHA-256` });
|
|
19609
|
+
}
|
|
19610
|
+
}
|
|
19611
|
+
if (latest && entry.version !== latest.version) {
|
|
19612
|
+
changes.push({ slug, field: "version", from: entry.version, to: latest.version });
|
|
19613
|
+
entry.version = latest.version;
|
|
19614
|
+
}
|
|
19615
|
+
return;
|
|
19616
|
+
}
|
|
19617
|
+
const manifest = readJsonFile2(join4(abilityDir, "plugin.json"));
|
|
19410
19618
|
if (!manifest) {
|
|
19411
19619
|
problems.push({ slug, message: "plugin.json is missing or malformed" });
|
|
19412
19620
|
return;
|
|
@@ -19445,9 +19653,16 @@ function reconcilePlugin(context) {
|
|
|
19445
19653
|
}
|
|
19446
19654
|
}
|
|
19447
19655
|
}
|
|
19656
|
+
function compareVersionParts(left, right) {
|
|
19657
|
+
for (let index = 0;index < 3; index += 1) {
|
|
19658
|
+
if (left[index] !== right[index])
|
|
19659
|
+
return (left[index] ?? 0) - (right[index] ?? 0);
|
|
19660
|
+
}
|
|
19661
|
+
return 0;
|
|
19662
|
+
}
|
|
19448
19663
|
function reconcileIdentityFile(context) {
|
|
19449
19664
|
const { entry, slug, abilityDir, fileName, changes, problems } = context;
|
|
19450
|
-
const identity =
|
|
19665
|
+
const identity = readJsonFile2(join4(abilityDir, fileName));
|
|
19451
19666
|
if (!identity) {
|
|
19452
19667
|
problems.push({ slug, message: `${fileName} is missing or malformed` });
|
|
19453
19668
|
return;
|
|
@@ -19490,7 +19705,7 @@ function findAbilityDirectories(hubRoot) {
|
|
|
19490
19705
|
return found.sort();
|
|
19491
19706
|
}
|
|
19492
19707
|
function describeIndexDrift(input) {
|
|
19493
|
-
const manifest =
|
|
19708
|
+
const manifest = readJsonFile2(input.manifestPath);
|
|
19494
19709
|
if (!manifest || !Array.isArray(manifest.abilities))
|
|
19495
19710
|
return;
|
|
19496
19711
|
const entry = manifest.abilities.find((item) => typeof item === "object" && item !== null && !Array.isArray(item) && item.slug === input.slug);
|
|
@@ -19576,11 +19791,11 @@ function readManualSdkVersion(manualDir) {
|
|
|
19576
19791
|
var HELP_TEXT = `Vetta plugin manager
|
|
19577
19792
|
|
|
19578
19793
|
Usage:
|
|
19579
|
-
vetta-plugin-cli add <npm-package|
|
|
19794
|
+
vetta-plugin-cli add <npm-package|package-path|http-url> [--json]
|
|
19580
19795
|
vetta-plugin-cli reload <plugin-id> [--json]
|
|
19581
19796
|
vetta-plugin-cli docs [--check-latest] [--json]
|
|
19582
19797
|
vetta-plugin-cli init --id <plugin-id> [--name <display>] [dir] [--json]
|
|
19583
|
-
vetta-plugin-cli init --refresh-guide [dir] [--json]
|
|
19798
|
+
vetta-plugin-cli init --refresh-guide [dir] [--dry-run] [--force] [--json]
|
|
19584
19799
|
vetta-plugin-cli init hub --name <slug> --repository <url> --min-app-version <x.y.z> [dir]
|
|
19585
19800
|
vetta-plugin-cli watch [dir] [--stop] [--json]
|
|
19586
19801
|
vetta-plugin-cli uninstall [plugin-id] [--json]
|
|
@@ -19590,7 +19805,7 @@ Examples:
|
|
|
19590
19805
|
npx @vetta-org/plugin-cli add @example/vetta-plugin-demo
|
|
19591
19806
|
npx @vetta-org/plugin-cli add @example/vetta-plugin-demo@1.2.0
|
|
19592
19807
|
npx @vetta-org/plugin-cli add . # 当前插件工程(先 pack)
|
|
19593
|
-
npx @vetta-org/plugin-cli add ./release/demo-1.2.0.
|
|
19808
|
+
npx @vetta-org/plugin-cli add ./release/demo-1.2.0.vettapkg
|
|
19594
19809
|
npx @vetta-org/plugin-cli reload demo
|
|
19595
19810
|
npx @vetta-org/plugin-cli docs
|
|
19596
19811
|
npx @vetta-org/plugin-cli init --id my-plugin --name "My Plugin"
|
|
@@ -19616,7 +19831,7 @@ function parsePluginAddCommand(argv) {
|
|
|
19616
19831
|
}
|
|
19617
19832
|
const [source, unexpected] = parsed.positionals;
|
|
19618
19833
|
if (!source)
|
|
19619
|
-
return { type: "error", message: "Missing <npm-package|
|
|
19834
|
+
return { type: "error", message: "Missing <npm-package|package-path|http-url>" };
|
|
19620
19835
|
if (unexpected)
|
|
19621
19836
|
return { type: "error", message: `Unexpected argument: ${unexpected}` };
|
|
19622
19837
|
return { type: "add", source, json: parsed.values.json === true };
|
|
@@ -19681,7 +19896,9 @@ function parsePluginInitCommand(argv) {
|
|
|
19681
19896
|
id: { type: "string" },
|
|
19682
19897
|
name: { type: "string" },
|
|
19683
19898
|
json: { type: "boolean" },
|
|
19684
|
-
"refresh-guide": { type: "boolean" }
|
|
19899
|
+
"refresh-guide": { type: "boolean" },
|
|
19900
|
+
force: { type: "boolean" },
|
|
19901
|
+
"dry-run": { type: "boolean" }
|
|
19685
19902
|
}
|
|
19686
19903
|
});
|
|
19687
19904
|
} catch (error) {
|
|
@@ -19691,7 +19908,13 @@ function parsePluginInitCommand(argv) {
|
|
|
19691
19908
|
const [dir, extra] = parsed.positionals;
|
|
19692
19909
|
if (extra)
|
|
19693
19910
|
return { type: "error", message: `Unexpected argument: ${extra}` };
|
|
19694
|
-
return {
|
|
19911
|
+
return {
|
|
19912
|
+
type: "refresh-guide",
|
|
19913
|
+
...dir ? { targetDir: dir } : {},
|
|
19914
|
+
json: parsed.values.json === true,
|
|
19915
|
+
force: parsed.values.force === true,
|
|
19916
|
+
dryRun: parsed.values["dry-run"] === true
|
|
19917
|
+
};
|
|
19695
19918
|
}
|
|
19696
19919
|
const pluginId = parsed.values.id;
|
|
19697
19920
|
if (typeof pluginId !== "string" || pluginId.length === 0) {
|
|
@@ -19839,8 +20062,9 @@ function isHttpUrl(source) {
|
|
|
19839
20062
|
return false;
|
|
19840
20063
|
}
|
|
19841
20064
|
}
|
|
19842
|
-
function
|
|
19843
|
-
|
|
20065
|
+
function isLocalPackage(source) {
|
|
20066
|
+
const lower = source.toLowerCase();
|
|
20067
|
+
if (lower.endsWith(".vettapkg") || lower.endsWith(".zip"))
|
|
19844
20068
|
return true;
|
|
19845
20069
|
const path = resolve5(source);
|
|
19846
20070
|
return existsSync4(path) && !statSync2(path).isDirectory();
|
|
@@ -19859,7 +20083,7 @@ function resolveProjectArchive(source) {
|
|
|
19859
20083
|
}
|
|
19860
20084
|
throw new Error(`No plugin.json found in ${from} or any parent directory.`);
|
|
19861
20085
|
}
|
|
19862
|
-
const archivePath = join6(project.root, "release", `${project.pluginId}-${project.version}.
|
|
20086
|
+
const archivePath = join6(project.root, "release", `${project.pluginId}-${project.version}.vettapkg`);
|
|
19863
20087
|
if (!existsSync4(archivePath)) {
|
|
19864
20088
|
throw new Error(`Packaged archive not found: ${archivePath}
|
|
19865
20089
|
Build it first: npm run build && npx vetta-plugin pack`);
|
|
@@ -19880,6 +20104,7 @@ function indexDriftHint(project) {
|
|
|
19880
20104
|
function npmInstallInput(resolved) {
|
|
19881
20105
|
return {
|
|
19882
20106
|
operation: "install-from-path",
|
|
20107
|
+
initiator: "plugin-cli",
|
|
19883
20108
|
path: resolved.archivePath,
|
|
19884
20109
|
enable: true,
|
|
19885
20110
|
source: "npm",
|
|
@@ -19973,19 +20198,22 @@ async function runPluginCommand(command, dependencies = defaultDependencies) {
|
|
|
19973
20198
|
} else if (isHttpUrl(command.source)) {
|
|
19974
20199
|
result = await dependencies.runAction("plugins.manage", {
|
|
19975
20200
|
operation: "install-from-url",
|
|
20201
|
+
initiator: "plugin-cli",
|
|
19976
20202
|
url: command.source
|
|
19977
20203
|
});
|
|
19978
20204
|
} else if (isDirectorySource(command.source)) {
|
|
19979
20205
|
const { archivePath, project } = resolveProjectArchive(command.source);
|
|
19980
20206
|
result = await dependencies.runAction("plugins.manage", {
|
|
19981
20207
|
operation: "install-from-path",
|
|
20208
|
+
initiator: "plugin-cli",
|
|
19982
20209
|
path: archivePath,
|
|
19983
20210
|
enable: true
|
|
19984
20211
|
});
|
|
19985
20212
|
driftHint = indexDriftHint(project);
|
|
19986
|
-
} else if (
|
|
20213
|
+
} else if (isLocalPackage(command.source)) {
|
|
19987
20214
|
result = await dependencies.runAction("plugins.manage", {
|
|
19988
20215
|
operation: "install-from-path",
|
|
20216
|
+
initiator: "plugin-cli",
|
|
19989
20217
|
path: resolve5(command.source),
|
|
19990
20218
|
enable: true
|
|
19991
20219
|
});
|
|
@@ -20069,7 +20297,9 @@ async function runDocsCommand(command, dependencies) {
|
|
|
20069
20297
|
lines.push(`Manual follows the installed SDK. To refresh it: ${SDK_REFRESH_COMMAND}`);
|
|
20070
20298
|
}
|
|
20071
20299
|
if (guide.stale) {
|
|
20072
|
-
lines.push(`This brief is stale (AGENTS.md revision ${guide.revision
|
|
20300
|
+
lines.push(`This brief is stale (AGENTS.md revision ${guide.revision} < ${AGENTS_GUIDE_REVISION}). Refresh it with: ${GUIDE_REFRESH_COMMAND}`);
|
|
20301
|
+
} else if (guide.unstamped) {
|
|
20302
|
+
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.`);
|
|
20073
20303
|
}
|
|
20074
20304
|
if (hub) {
|
|
20075
20305
|
lines.push(`Marketplace index: ${hub.manifestPath}`);
|
|
@@ -20085,17 +20315,18 @@ var GUIDE_REFRESH_COMMAND = "npx @vetta-org/plugin-cli init --refresh-guide";
|
|
|
20085
20315
|
function inspectAgentsGuide(root) {
|
|
20086
20316
|
const path = join6(root, "AGENTS.md");
|
|
20087
20317
|
if (!existsSync4(path))
|
|
20088
|
-
return { present: false, stale: false };
|
|
20318
|
+
return { present: false, stale: false, unstamped: false };
|
|
20089
20319
|
let revision;
|
|
20090
20320
|
try {
|
|
20091
20321
|
revision = readAgentsGuideRevision(readFileSync4(path, "utf8"));
|
|
20092
20322
|
} catch {
|
|
20093
|
-
return { present: true, stale: false };
|
|
20323
|
+
return { present: true, stale: false, unstamped: false };
|
|
20094
20324
|
}
|
|
20095
20325
|
return {
|
|
20096
20326
|
present: true,
|
|
20097
20327
|
...revision === undefined ? {} : { revision },
|
|
20098
|
-
stale: revision
|
|
20328
|
+
stale: revision !== undefined && revision < AGENTS_GUIDE_REVISION,
|
|
20329
|
+
unstamped: revision === undefined
|
|
20099
20330
|
};
|
|
20100
20331
|
}
|
|
20101
20332
|
function compareSemver(left, right) {
|
|
@@ -20118,11 +20349,18 @@ function compareSemver(left, right) {
|
|
|
20118
20349
|
function runRefreshGuideCommand(command, dependencies) {
|
|
20119
20350
|
const cwd = dependencies.cwd?.() ?? process.cwd();
|
|
20120
20351
|
try {
|
|
20121
|
-
const result = refreshAgentsGuide(resolve5(cwd, command.targetDir ?? ".")
|
|
20122
|
-
|
|
20123
|
-
|
|
20124
|
-
|
|
20352
|
+
const result = refreshAgentsGuide(resolve5(cwd, command.targetDir ?? "."), {
|
|
20353
|
+
force: command.force,
|
|
20354
|
+
dryRun: command.dryRun
|
|
20355
|
+
});
|
|
20356
|
+
if (command.json) {
|
|
20357
|
+
dependencies.writeStdout(`${JSON.stringify({ ok: true, ...result })}
|
|
20125
20358
|
`);
|
|
20359
|
+
return 0;
|
|
20360
|
+
}
|
|
20361
|
+
dependencies.writeStdout(result.written ? `Rewrote ${result.file}
|
|
20362
|
+
Next: npx vetta-plugin-cli docs --check-latest
|
|
20363
|
+
` : `${result.content}`);
|
|
20126
20364
|
return 0;
|
|
20127
20365
|
} catch (error) {
|
|
20128
20366
|
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;
|
|
@@ -109,8 +111,14 @@ export interface AgentsGuideStatus {
|
|
|
109
111
|
readonly present: boolean;
|
|
110
112
|
/** 读到的版本戳;没有戳(模板早于版本戳,或是手写的)时缺省。 */
|
|
111
113
|
readonly revision?: number;
|
|
112
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* **带戳**且落后于当前 CLI 的模板——只有这一档能安全地一键重写。
|
|
116
|
+
*
|
|
117
|
+
* 没有 AGENTS.md 时为 false(那是「没有」,不是「旧」);没有戳时也为 false,见 {@link unstamped}。
|
|
118
|
+
*/
|
|
113
119
|
readonly stale: boolean;
|
|
120
|
+
/** 有文件但没有版本戳:可能是手写的,也可能是版本戳之前的模板,无从区分。 */
|
|
121
|
+
readonly unstamped: boolean;
|
|
114
122
|
}
|
|
115
123
|
export declare function runPluginCli(argv: string[]): Promise<number>;
|
|
116
124
|
//# sourceMappingURL=command.d.ts.map
|