mano-coding 0.1.33 → 0.1.34

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.
Files changed (2) hide show
  1. package/dist/bin.js +467 -262
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -3404,17 +3404,19 @@ var init_zh = __esm({
3404
3404
  "version.description": "\u663E\u793A CLI \u7248\u672C",
3405
3405
  // create.ts
3406
3406
  "create.description": "\u5411\u6307\u5B9A\u76EE\u5F55\u521B\u5EFA\u5DE5\u7A0B\u5E76\u5B89\u88C5 AI Coding \u8D44\u4EA7",
3407
- "create.argPackageSpec": "\u6269\u5C55\u5305\u89C4\u683C\u6216\u9879\u76EE\u76EE\u5F55",
3407
+ "create.argTemplateSpec": "\u6A21\u677F\u89C4\u683C\uFF08\u672A\u6307\u5B9A\u65F6\u5728\u4EA4\u4E92\u7EC8\u7AEF\u4E2D\u9009\u62E9\uFF09",
3408
3408
  "create.argDirectory": "\u9879\u76EE\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09",
3409
- "create.optionPackage": "\u6269\u5C55\u5305\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF0C\u6240\u6709\u5305\u6309\u540C\u540D\u751F\u547D\u5468\u671F\u4E32\u884C\u6267\u884C\uFF09",
3410
- "create.optionTemplate": "\u6269\u5C55\u5305\u89C4\u683C\uFF08\u5411\u540E\u517C\u5BB9\u522B\u540D\uFF0C\u5EFA\u8BAE\u4F7F\u7528 --package\uFF09",
3411
- "create.optionAddon": "\u6269\u5C55\u5305\u89C4\u683C\uFF08\u5411\u540E\u517C\u5BB9\u522B\u540D\uFF0C\u5EFA\u8BAE\u4F7F\u7528 --package\uFF09",
3412
- "create.templateRequired": "\u975E\u4EA4\u4E92\u73AF\u5883\u5FC5\u987B\u901A\u8FC7\u53C2\u6570\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u6269\u5C55\u5305\u89C4\u683C",
3413
- "create.registryIndexUnsupported": "\u5F53\u524D Registry \u5BA2\u6237\u7AEF\u4E0D\u652F\u6301\u5305\u7D22\u5F15",
3414
- "create.chooseTemplate": "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u6269\u5C55\u5305",
3415
- "create.templateSelectionCancelled": "\u6269\u5C55\u5305\u9009\u62E9\u5DF2\u53D6\u6D88",
3416
- "create.packageKindMismatch": "\u5305 {0} \u7684\u5185\u5BB9\u4E0D\u7B26\u5408 create \u547D\u4EE4\u8981\u6C42",
3417
- "create.addonKindMismatch": "\u5305 {0} \u7684\u5185\u5BB9\u4E0D\u7B26\u5408\u8981\u6C42",
3409
+ "create.optionTemplate": "\u6A21\u677F\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF0C\u652F\u6301\u4E00\u6B21\u6027\u6307\u5B9A\u591A\u4E2A\u6A21\u677F\uFF09",
3410
+ "create.templateRequired": "\u975E\u4EA4\u4E92\u73AF\u5883\u5FC5\u987B\u901A\u8FC7\u53C2\u6570\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u6A21\u677F\u89C4\u683C",
3411
+ "create.registryIndexUnsupported": "\u5F53\u524D Registry \u5BA2\u6237\u7AEF\u4E0D\u652F\u6301\u6A21\u677F\u7D22\u5F15",
3412
+ "create.chooseTemplate": "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u6A21\u677F",
3413
+ "create.templateSelectionCancelled": "\u6A21\u677F\u9009\u62E9\u5DF2\u53D6\u6D88",
3414
+ "create.templateKindMismatch": "\u6A21\u677F {0} \u7684\u5185\u5BB9\u4E0D\u7B26\u5408 create \u547D\u4EE4\u8981\u6C42",
3415
+ "create.filterUnsupported": "create \u547D\u4EE4\u4E0D\u652F\u6301 --only / --skip \u8D44\u4EA7\u8FC7\u6EE4\uFF0C\u4EE5\u4FDD\u8BC1\u6A21\u677F\u5B8C\u6574\u4EA4\u4ED8\u3002\u5982\u9700\u5B9A\u5236\u53D7\u7BA1\u8D44\u4EA7\u8BF7\u4F7F\u7528 apply \u547D\u4EE4\u3002",
3416
+ "create.templateAlreadyInstalled": "\u6A21\u677F '{0}' \u5DF2\u7ECF\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D\u3002\u4E0D\u80FD\u901A\u8FC7 create \u91CD\u65B0\u5B89\u88C5\u3002\u5982\u9700\u66F4\u65B0\u914D\u7F6E\u6216\u540C\u6B65\u8D44\u4EA7\u8BF7\u4F7F\u7528 'apply'\u3001'sync' \u6216 'upgrade' \u547D\u4EE4\u3002",
3417
+ "create.missingTaskInputs": "\u6A21\u677F '{0}' \u7F3A\u5C11\u521D\u59CB\u5316\u53C2\u6570: {1}\uFF0C\u8BF7\u4F7F\u7528\uFF1A\n{2}",
3418
+ "create.promptTaskInput": "[{0}] \u8BF7\u8F93\u5165\u521D\u59CB\u5316\u53C2\u6570 '{1}':",
3419
+ "create.taskValidationFailed": "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
3418
3420
  "create.missingInputs": "\u7F3A\u5C11\u5FC5\u586B\u8F93\u5165\uFF1A{0}",
3419
3421
  "create.missingInputsHint": "\u7F3A\u5C11\u5FC5\u586B\u8F93\u5165\uFF1A{0}\u3002\u8BF7\u901A\u8FC7 --input <name>=<value> \u63D0\u4F9B",
3420
3422
  "create.chooseTargets": "\u9009\u62E9\u8981\u521D\u59CB\u5316\u7684 IDE \u76EE\u6807",
@@ -3425,7 +3427,7 @@ var init_zh = __esm({
3425
3427
  "create.userDeclined": "\u7528\u6237\u62D2\u7EDD\u4E86 Plan \u786E\u8BA4",
3426
3428
  "create.executionFailed": "\u6267\u884C\u5931\u8D25\uFF1B\u5DF2\u5C1D\u8BD5\u56DE\u6EDA",
3427
3429
  "create.executionFailedShort": "\u6267\u884C\u5931\u8D25",
3428
- "create.projectExtensionFailed": "\u5DE5\u7A0B\u6269\u5C55 create \u5931\u8D25\uFF1A{0}",
3430
+ "create.projectExtensionFailed": "\u5DE5\u7A0B\u6A21\u677F create \u5931\u8D25\uFF1A{0}",
3429
3431
  "create.createdProject": "\u9879\u76EE\u5DF2\u521B\u5EFA\u5728 {0}",
3430
3432
  "create.lockFile": "Lock \u6587\u4EF6\uFF1A{0}",
3431
3433
  "create.enterInput": "\u8F93\u5165 {0}",
@@ -3434,23 +3436,46 @@ var init_zh = __esm({
3434
3436
  "create.initializingWorkspace": "\u6B63\u5728\u521D\u59CB\u5316\u5DE5\u7A0B\u5DE5\u4F5C\u533A\u2026\n",
3435
3437
  "create.workspaceInitialized": "\u2713 \u5DE5\u7A0B\u5DE5\u4F5C\u533A\u521D\u59CB\u5316\u5B8C\u6210\uFF08{0}\uFF09\n",
3436
3438
  "create.installingUserTools": "\u6B63\u5728\u5B89\u88C5\u7528\u6237\u7EA7\u5DE5\u5177\uFF08{0} \u9879\uFF09\u2026\n",
3437
- "create.userToolsInstalled": "\u2713 \u7528\u6237\u7EA7\u5DE5\u5177\u5B89\u88C5\u5B8C\u6210\uFF08{0}\uFF09\n",
3439
+ "create.computingPlan": "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
3440
+ "create.planReady": "\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 {0} \u9879\u8D44\u6E90\u53D8\u66F4)",
3441
+ "create.planFailed": "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25",
3438
3442
  "create.installing": "\u6B63\u5728\u5B89\u88C5\uFF1A{0}\n",
3439
3443
  "create.installed": "\u2713 \u5DF2\u5B89\u88C5\uFF1A{0}\n",
3440
3444
  "create.reused": "\u2713 \u5DF2\u590D\u7528\uFF1A{0}\n",
3441
3445
  "create.skipped": "- \u65E0\u9700\u5B89\u88C5\uFF1A{0}\n",
3446
+ "common.seconds": "{0} \u79D2",
3447
+ // 模板通用解析文案
3448
+ "template.resolving": "\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6A21\u677F ({0})...",
3449
+ "template.resolved": "\u2714 \u6A21\u677F\u89E3\u6790\u5B8C\u6210: {0} (v{1})",
3450
+ "template.resolveFailed": "\u2716 \u6A21\u677F\u89E3\u6790\u5931\u8D25: {0}",
3451
+ // 任务通用执行文案
3452
+ "task.runningBeforeCreate": "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u521B\u5EFA\u4EFB\u52A1 (before:create) [{0}/{1}] ({2}):",
3453
+ "task.runningAfterCreate": "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u521B\u5EFA\u4EFB\u52A1 (after:create) [{0}/{1}] ({2}):",
3454
+ "task.runningBeforeApply": "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u5E94\u7528\u4EFB\u52A1 (before:apply) [{0}/{1}] ({2}):",
3455
+ "task.runningAfterApply": "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u5E94\u7528\u4EFB\u52A1 (after:apply) [{0}/{1}] ({2}):",
3456
+ "task.runningBeforeRemove": "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u79FB\u9664\u4EFB\u52A1 (before:remove) [{0}/{1}] ({2}):",
3457
+ "task.runningAfterRemove": "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u79FB\u9664\u4EFB\u52A1 (after:remove) [{0}/{1}] ({2}):",
3458
+ "task.runningBeforeSync": "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u540C\u6B65\u4EFB\u52A1 (before:sync) [{0}/{1}] ({2}):",
3459
+ "task.runningAfterSync": "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u540C\u6B65\u4EFB\u52A1 (after:sync) [{0}/{1}] ({2}):",
3442
3460
  // apply.ts
3443
3461
  "apply.description": "\u5411\u6307\u5B9A\u76EE\u5F55\u589E\u52A0 AI Coding \u77E5\u8BC6\u8D44\u4EA7\u6216\u672C\u5730 MCP",
3444
- "apply.argPackageSpec": "\u8981\u5E94\u7528\u7684\u6A21\u677F\u89C4\u683C\uFF08\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u6A21\u677F\uFF09",
3445
- "apply.packageRequired": "apply \u547D\u4EE4\u5FC5\u987B\u663E\u5F0F\u6307\u5B9A\u81F3\u5C11\u4E00\u4E2A\u6A21\u677F",
3462
+ "apply.argTemplateSpec": "\u8981\u5E94\u7528\u7684\u6A21\u677F\u89C4\u683C\uFF08\u672A\u6307\u5B9A\u65F6\u5728\u4EA4\u4E92\u7EC8\u7AEF\u4E2D\u9009\u62E9\uFF09",
3463
+ "apply.optionTemplate": "\u8981\u5E94\u7528\u7684\u6A21\u677F\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF0C\u6240\u6709\u6A21\u677F\u6309\u540C\u540D\u751F\u547D\u5468\u671F\u4E32\u884C\u6267\u884C\uFF09",
3464
+ "apply.templateRequired": "\u975E\u4EA4\u4E92\u73AF\u5883\u5FC5\u987B\u663E\u5F0F\u6307\u5B9A\u81F3\u5C11\u4E00\u4E2A\u6A21\u677F",
3465
+ "apply.chooseTemplate": "\u9009\u62E9\u8981\u5E94\u7528\u7684\u6A21\u677F",
3466
+ "apply.templateSelectionCancelled": "\u6A21\u677F\u9009\u62E9\u5DF2\u53D6\u6D88",
3467
+ "apply.chooseTargets": "\u9009\u62E9\u8981\u5E94\u7528\u7684 IDE \u76EE\u6807",
3468
+ "apply.targetSelectionCancelled": "\u76EE\u6807\u9009\u62E9\u5DF2\u53D6\u6D88",
3469
+ "apply.targetRequired": "\u7F3A\u5C11\u76EE\u6807 IDE \u53C2\u6570\uFF0C\u8BF7\u4F7F\u7528 --target <ide...>",
3470
+ "apply.noAvailableTemplates": "\u6CA1\u6709\u53EF\u4F9B\u5B89\u88C5\u7684\u65B0\u6A21\u677F\u6216\u5168\u90E8\u5019\u9009\u6A21\u677F\u5DF2\u5B89\u88C5",
3446
3471
  "apply.optionOnly": "\u4EC5\u5B89\u88C5\u6307\u5B9A\u7684\u53D7\u7BA1\u77E5\u8BC6\u8D44\u4EA7\u7C7B\u578B\uFF08\u9017\u53F7\u5206\u9694\uFF1Askills,rules,subagents,mcp,agents-md\uFF09",
3447
3472
  "apply.optionSkip": "\u8DF3\u8FC7\u6307\u5B9A\u7684\u53D7\u7BA1\u77E5\u8BC6\u8D44\u4EA7\u7C7B\u578B\uFF08\u9017\u53F7\u5206\u9694\uFF1Askills,rules,subagents,mcp,agents-md\uFF09",
3448
3473
  "apply.onlySkipExclusive": "--only \u4E0E --skip \u53C2\u6570\u4E92\u65A5\uFF0C\u4E0D\u80FD\u540C\u65F6\u4F7F\u7528",
3449
3474
  "apply.invalidAssetType": "\u65E0\u6548\u7684\u8D44\u4EA7\u7C7B\u578B '{0}'\uFF0C\u4EC5\u652F\u6301: skills, rules, subagents, mcp, agents-md",
3450
- "apply.emptyAfterFilter": "\u8FC7\u6EE4\u540E\u65E0\u53EF\u4EA4\u4ED8\u7684\u6838\u5FC3\u53D7\u7BA1\u8D44\u4EA7\u4E14\u5305\u4E0D\u5305\u542B apply \u751F\u547D\u5468\u671F\u4EFB\u52A1",
3475
+ "apply.emptyAfterFilter": "\u8FC7\u6EE4\u540E\u65E0\u53EF\u4EA4\u4ED8\u7684\u6838\u5FC3\u53D7\u7BA1\u8D44\u4EA7\u4E14\u6A21\u677F\u4E0D\u5305\u542B apply \u751F\u547D\u5468\u671F\u4EFB\u52A1",
3451
3476
  "apply.driftDetected": "\u53D7\u7BA1\u8D44\u6E90\u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD apply\uFF1B\u8BF7\u5148\u8FD0\u884C sync --drift restore \u6216 accept",
3452
- "apply.packageSpecRequired": "\u9879\u76EE\u65E0 lock \u6587\u4EF6\u65F6 apply \u9700\u8981 <package-spec>\u3002\u4F7F\u7528 --dry-run \u9884\u89C8\u3002",
3453
- "apply.addonKindMismatch": "\u5305 {0} \u7684\u7C7B\u578B\u4E3A '{1}'\uFF0C\u671F\u671B '\u6A21\u677F'",
3477
+ "apply.packageSpecRequired": "\u9879\u76EE\u65E0 lock \u6587\u4EF6\u65F6 apply \u9700\u8981\u6307\u5B9A\u6A21\u677F\u3002\u4F7F\u7528 --dry-run \u9884\u89C8\u3002",
3478
+ "apply.templateKindMismatch": "\u6A21\u677F {0} \u7684\u7C7B\u578B\u4E3A '{1}'\uFF0C\u671F\u671B 'template'",
3454
3479
  "apply.missingInputs": "\u7F3A\u5C11\u5FC5\u586B\u8F93\u5165\uFF1A{0}\u3002\u901A\u8FC7 --set \u63D0\u4F9B\u3002",
3455
3480
  "apply.planConflict": "Plan \u5B58\u5728\u51B2\u7A81",
3456
3481
  "apply.needsConfirmation": "\u6267\u884C Plan \u9700\u8981 --yes\u3002\u4F7F\u7528 --dry-run \u9884\u89C8\u3002",
@@ -3460,8 +3485,18 @@ var init_zh = __esm({
3460
3485
  "apply.projectExtensionFailed": "\u6A21\u677F {0} \u7684\u5DE5\u7A0B\u6269\u5C55 apply \u5931\u8D25\uFF1A{1}",
3461
3486
  "apply.applied": "\u5DF2\u5C06\u6A21\u677F\u5E94\u7528\u5230 {0}",
3462
3487
  "apply.lockFile": "Lock \u6587\u4EF6\uFF1A{0}",
3488
+ "apply.alreadyUpToDate": "\u5DF2\u5E94\u7528\uFF0C\u65E0\u53D8\u5316",
3489
+ "apply.computingPlan": "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
3490
+ "apply.planReady": "\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 {0} \u9879\u8D44\u6E90\u53D8\u66F4)",
3491
+ "apply.planFailed": "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25",
3492
+ "apply.resourceConflict": "\u8D44\u6E90 '{0}' \u4E0E\u5DF2\u6709\u6A21\u677F\u8D44\u6E90\u5B58\u5728\u51B2\u7A81",
3493
+ "apply.lockedConfigLoaded": "\u2714 \u5DF2\u52A0\u8F7D\u9501\u5B9A\u914D\u7F6E",
3494
+ "apply.skippedCreateTasks": "- \u5DF2\u8DF3\u8FC7 {0} \u4E2A create \u751F\u547D\u5468\u671F\u94A9\u5B50\u4EFB\u52A1\uFF08apply \u8BED\u4E49\u4E0D\u6267\u884C before:create / after:create \u94A9\u5B50\uFF09\n",
3495
+ "apply.templateUpdatedNeedsUpgrade": "\u6A21\u677F '{0}' \u7248\u672C\u76F8\u540C\u4F46\u5185\u5BB9\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u4F7F\u7528 upgrade \u547D\u4EE4\u8FDB\u884C\u66F4\u65B0",
3463
3496
  // sync.ts
3464
3497
  "sync.description": "\u4ECE lock \u6587\u4EF6\u6062\u590D\u9879\u76EE\u72B6\u6001\uFF08\u4E0D\u89E3\u6790\u7248\u672C\uFF09",
3498
+ "sync.optionTemplate": "\u4EC5\u540C\u6B65\u6307\u5B9A\u7684\u5DF2\u5B89\u88C5\u6A21\u677F",
3499
+ "sync.templateNotFound": "\u672A\u5728 Lock \u6587\u4EF6\u4E2D\u627E\u5230\u6A21\u677F '{0}'\u3002\u8BE5\u6A21\u677F\u672A\u5B89\u88C5\u6216\u65E0\u6CD5\u540C\u6B65\u3002",
3465
3500
  "sync.lockNotFound": "\u5728 {0} \u672A\u627E\u5230 lock \u6587\u4EF6\u3002\u8BF7\u5148\u4F7F\u7528 create \u6216 apply\u3002",
3466
3501
  "sync.acceptMissing": "sync --drift accept \u4E0D\u5141\u8BB8 missing \u8D44\u6E90\uFF1B\u8BF7\u5148\u6062\u590D\u6216\u4F7F\u7528 remove \u91CA\u653E\uFF1A{0}",
3467
3502
  "sync.driftDetected": "\u68C0\u6D4B\u5230 {0} \u9879\u8D44\u6E90\u6F02\u79FB\uFF1B\u4F7F\u7528 --drift restore \u6062\u590D\u6216 --drift accept \u63A5\u7EB3",
@@ -3475,35 +3510,41 @@ var init_zh = __esm({
3475
3510
  "sync.lockFile": "Lock \u6587\u4EF6\uFF1A{0}",
3476
3511
  "sync.locateDriftFailed": "\u65E0\u6CD5\u5B9A\u4F4D\u6F02\u79FB\u8D44\u6E90 {0}",
3477
3512
  // remove.ts
3478
- "remove.description": "\u4ECE\u9879\u76EE\u4E2D\u79FB\u9664\u5305\u6216\u5168\u90E8\u53D7\u7BA1\u5185\u5BB9",
3479
- "remove.optionPackage": "\u8981\u79FB\u9664\u7684\u5305 ID\uFF08\u5355\u4E2A\uFF09",
3480
- "remove.lockNotFound": "\u5728 {0} \u672A\u627E\u5230 lock \u6587\u4EF6\u3002\u65E0\u5185\u5BB9\u53EF\u79FB\u9664\u3002",
3481
- "remove.packageNotInLock": "\u5305 {0} \u4E0D\u5728\u9879\u76EE lock \u4E2D\u3002\u53EF\u7528\uFF1A{1}",
3513
+ "remove.description": "\u4ECE\u9879\u76EE\u4E2D\u79FB\u9664\u6307\u5B9A\u7684\u6A21\u677F\u6216\u5168\u90E8\u53D7\u7BA1\u5185\u5BB9",
3514
+ "remove.argTemplate": "\u8981\u79FB\u9664\u7684\u6A21\u677F ID\uFF08\u53EF\u9009\uFF0C\u672A\u6307\u5B9A\u65F6\u79FB\u9664\u5168\u90E8\uFF09",
3515
+ "remove.optionTemplate": "\u8981\u79FB\u9664\u7684\u6A21\u677F ID\uFF08\u5355\u4E2A\uFF09",
3516
+ "remove.chooseTemplate": "\u9009\u62E9\u8981\u79FB\u9664\u7684\u6A21\u677F",
3517
+ "remove.templateSelectionCancelled": "\u6A21\u677F\u79FB\u9664\u9009\u62E9\u5DF2\u53D6\u6D88",
3518
+ "remove.lockNotFound": "\u5728 {0} \u672A\u627E\u5230 lock \u6587\u4EF6\u3002\u65E0\u6A21\u677F\u53EF\u79FB\u9664\u3002",
3519
+ "remove.templateNotInLock": "\u6A21\u677F {0} \u4E0D\u5728\u9879\u76EE lock \u4E2D\u3002\u5F53\u524D\u53EF\u7528\u6A21\u677F\uFF1A{1}",
3520
+ "remove.bootstrapTemplateCannotBeRemoved": "\u6A21\u677F '{0}' \u662F\u9879\u76EE\u7684\u521D\u59CB\u5DE5\u7A0B\u6A21\u677F (bootstrap-only)\uFF0C\u4E0D\u5305\u542B\u53D7\u7BA1\u77E5\u8BC6\u8D44\u4EA7\uFF0C\u65E0\u6CD5\u88AB remove\u3002\u82E5\u9700\u5220\u9664\u6574\u4E2A\u9879\u76EE\uFF0C\u8BF7\u76F4\u63A5\u5220\u9664\u9879\u76EE\u76EE\u5F55\u3002",
3482
3521
  "remove.driftDetected": "\u68C0\u6D4B\u5230 {0} \u9879\u8D44\u6E90\u6F02\u79FB\uFF1B\u5982\u786E\u8BA4\u5220\u9664\u5DF2\u4FEE\u6539\u5185\u5BB9\uFF0C\u8BF7\u4F7F\u7528 --drift accept",
3483
3522
  "remove.needsConfirmation": "\u6267\u884C Remove \u9700\u8981 --yes\u3002\u4F7F\u7528 --dry-run \u9884\u89C8\u3002",
3484
3523
  "remove.userDeclined": "\u7528\u6237\u62D2\u7EDD\u4E86 Plan \u786E\u8BA4",
3485
3524
  "remove.executionFailed": "\u6267\u884C\u5931\u8D25\uFF1B\u5DF2\u5C1D\u8BD5\u56DE\u6EDA",
3486
3525
  "remove.executionFailedShort": "\u6267\u884C\u5931\u8D25",
3487
- "remove.removed": "\u5DF2\u4ECE {1} \u79FB\u9664 {0}",
3488
- "remove.allPackages": "\u6240\u6709\u5305",
3526
+ "remove.removed": "\u5DF2\u4ECE {1} \u79FB\u9664\u6A21\u677F {0}",
3527
+ "remove.allTemplates": "\u6240\u6709\u6A21\u677F",
3489
3528
  "remove.lockRemoved": "Lock \u6587\u4EF6\u5DF2\u79FB\u9664\u3002",
3490
3529
  "remove.lockUpdated": "Lock \u6587\u4EF6\u5DF2\u66F4\u65B0\u3002",
3491
3530
  "remove.userReferenceFailed": "\u79FB\u9664 {0}/{1}@{2} \u7684\u7528\u6237\u7EA7\u5F15\u7528\u5931\u8D25\uFF1A{3}",
3492
3531
  // upgrade.ts
3493
3532
  "upgrade.description": "\u5C06 Capability \u5347\u7EA7\u5230\u65B0\u7248\u672C\u5E76\u5207\u6362\u9879\u76EE\u5F15\u7528",
3494
3533
  "upgrade.optionProject": "\u9879\u76EE\u6839\u76EE\u5F55",
3495
- "upgrade.optionPackage": "Capability \u7684\u5305 ID",
3534
+ "upgrade.optionTemplate": "Capability \u6240\u5C5E\u7684\u6A21\u677F ID",
3496
3535
  "upgrade.optionCapability": "\u8981\u5347\u7EA7\u7684 Capability ID",
3497
3536
  "upgrade.optionVersion": "\u76EE\u6807\u5347\u7EA7\u7248\u672C",
3498
3537
  "upgrade.optionDryRun": "\u4EC5\u9884\u89C8\uFF0C\u4E0D\u6267\u884C",
3499
3538
  "upgrade.optionYes": "\u65E0\u9700\u786E\u8BA4\u5373\u6279\u51C6",
3500
3539
  "upgrade.optionAllow": "\u6388\u6743\u9AD8\u98CE\u9669\u64CD\u4F5C\uFF08\u53EF\u91CD\u590D\uFF09",
3501
- "upgrade.missingOptions": "upgrade \u9700\u8981 --package\u3001--capability \u548C --version",
3540
+ "upgrade.missingOptions": "upgrade \u9700\u8981 --template\u3001--capability \u548C --version",
3541
+ "upgrade.missingTemplate": "\u8BF7\u901A\u8FC7 --template <template-id> \u6307\u5B9A\u9700\u8981\u5347\u7EA7\u7684\u6A21\u677F\u3002",
3542
+ "upgrade.planSummary": "\u5347\u7EA7\u8BA1\u5212\uFF1A\n \u6A21\u677F\uFF1A{0}\n \u5F53\u524D\uFF1A{1}\n \u76EE\u6807\uFF1A{2}\n \u9879\u76EE\uFF1A{3}\n",
3502
3543
  "upgrade.lockNotFound": "\u5728 {0} \u672A\u627E\u5230 lock \u6587\u4EF6\u3002\u8BF7\u5148\u4F7F\u7528 create \u6216 apply\u3002",
3503
3544
  "upgrade.driftDetected": "\u53D7\u7BA1\u8D44\u6E90\u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u5347\u7EA7",
3504
- "upgrade.packageNotInLock": "\u5728 lock \u6587\u4EF6\u7684 template \u4E2D\u672A\u627E\u5230\u5305 {0}",
3545
+ "upgrade.templateNotInLock": "\u5728 lock \u6587\u4EF6\u7684 template \u4E2D\u672A\u627E\u5230\u6A21\u677F {0}",
3505
3546
  "upgrade.alreadyAtVersion": "\u5DF2\u5904\u4E8E\u7248\u672C {0}\uFF0C\u65E0\u9700\u5347\u7EA7",
3506
- "upgrade.noDesiredTemplate": "\u5305 {0} \u6CA1\u6709 desired template \u6761\u76EE",
3547
+ "upgrade.noDesiredTemplate": "\u6A21\u677F {0} \u6CA1\u6709 desired template \u6761\u76EE",
3507
3548
  "upgrade.resolveFailed": "\u65E0\u6CD5\u89E3\u6790\u6A21\u677F {0}@{1}\uFF1A{2}",
3508
3549
  "upgrade.resolveInvalid": "\u65E0\u6CD5\u89E3\u6790\u6A21\u677F {0}@{1}",
3509
3550
  "upgrade.capabilityAbsent": "Capability {0}/{1} \u5728 {2} \u4E2D\u4E0D\u5B58\u5728",
@@ -3513,6 +3554,9 @@ var init_zh = __esm({
3513
3554
  "upgrade.upgraded": "\u5DF2\u5347\u7EA7 {0}/{1}\uFF1A{2} -> {3}",
3514
3555
  "upgrade.dryRunPlan": "CLI \u5347\u7EA7\u8BA1\u5212\uFF1A\n current: {0}\n target: {1}\n integrity: {2}\n manager: {3}\n bin: {4}\n",
3515
3556
  "upgrade.alreadyCurrent": "aicoding \u5DF2\u662F {0}\u3002",
3557
+ // 任务通用执行文案 (upgrade)
3558
+ "task.runningBeforeUpgrade": "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u5347\u7EA7\u4EFB\u52A1 (before:upgrade) ({0}):",
3559
+ "task.runningAfterUpgrade": "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u5347\u7EA7\u4EFB\u52A1 (after:upgrade) ({0}):",
3516
3560
  // self-upgrade.ts
3517
3561
  "selfUpgrade.description": "\u68C0\u67E5\u6216\u5347\u7EA7\u7531 npm/pnpm \u5B89\u88C5\u7684 mano-coding CLI",
3518
3562
  "selfUpgrade.optionCheck": "\u4EC5\u5237\u65B0\u7248\u672C\u4FE1\u606F",
@@ -3615,7 +3659,8 @@ var init_zh = __esm({
3615
3659
  // launch.ts
3616
3660
  "launch.description": "\u9690\u85CF\u542F\u52A8\u547D\u4EE4 - \u542F\u52A8\u7CBE\u786E\u5B89\u88C5\uFF08\u8BF7\u52FF\u76F4\u63A5\u4F7F\u7528\uFF09",
3617
3661
  "launch.optionKind": "\u6240\u6709\u8005\u7C7B\u578B\uFF08project|capability|plugin\uFF09",
3618
- "launch.optionPackage": "\u5305 ID",
3662
+ "launch.optionTemplate": "\u6A21\u677F ID",
3663
+ "launch.optionPackage": "\u6A21\u677F ID",
3619
3664
  "launch.optionId": "\u6240\u6709\u8005 ID",
3620
3665
  "launch.optionVersion": "\u7CBE\u786E\u7248\u672C",
3621
3666
  "launch.optionCommand": "\u547D\u4EE4\u540D\u79F0\uFF08\u53EA\u6709\u4E00\u4E2A\u547D\u4EE4\u65F6\u53EF\u9009\uFF09",
@@ -3644,17 +3689,37 @@ var init_zh = __esm({
3644
3689
  // extension commands
3645
3690
  "extension.create.description": "\u521D\u59CB\u5316\u6807\u51C6\u6269\u5C55/\u6A21\u677F\u5DE5\u7A0B",
3646
3691
  "extension.create.argDirectory": "\u76EE\u6807\u5DE5\u7A0B\u76EE\u5F55",
3647
- "extension.create.optionName": "\u6269\u5C55\u5305 ID (package-id)",
3648
- "extension.create.optionCategory": "\u6269\u5C55\u5206\u7C7B",
3649
- "extension.create.optionWithProject": "\u662F\u5426\u5305\u542B\u5DE5\u7A0B\u6A21\u677F",
3692
+ "extension.create.optionName": "\u6A21\u677F ID (template-id)",
3693
+ "extension.create.optionTemplateName": "\u6A21\u677F\u663E\u793A\u540D\u79F0 (name)",
3694
+ "extension.create.optionDescription": "\u6A21\u677F\u63CF\u8FF0",
3695
+ "extension.create.optionCategory": "\u6A21\u677F\u5206\u7C7B",
3696
+ "extension.create.optionWithProject": "\u662F\u5426\u5305\u542B\u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6 (project/)",
3697
+ "extension.create.optionWithTasks": "\u662F\u5426\u751F\u6210\u521D\u59CB\u5316\u4EFB\u52A1\u793A\u4F8B",
3650
3698
  "extension.create.optionWithCapability": "\u5305\u542B\u7684\u80FD\u529B\u7279\u6027",
3651
3699
  "extension.create.optionWithPipeline": "\u662F\u5426\u751F\u6210 GitLab CI/CD \u81EA\u52A8\u540C\u6B65\u6D41\u6C34\u7EBF\u914D\u7F6E (.gitlab-ci.yml)",
3652
3700
  "extension.create.optionYes": "\u8DF3\u8FC7\u4EA4\u4E92\u786E\u8BA4\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C",
3653
3701
  "extension.create.directoryNotEmpty": "\u76EE\u6807\u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\uFF1A{0}",
3654
- "extension.pipeline.description": "\u751F\u6210\u6216\u66F4\u65B0\u6269\u5C55\u5305\u7684 GitLab CI/CD \u81EA\u52A8\u540C\u6B65\u6D41\u6C34\u7EBF\u914D\u7F6E (.gitlab-ci.yml)",
3655
- "extension.pipeline.argDirectory": "\u6269\u5C55\u5305\u5DE5\u7A0B\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09",
3702
+ "extension.create.promptName": "\u8BF7\u8F93\u5165\u6A21\u677F ID (Template ID):",
3703
+ "extension.create.promptTemplateName": "\u8BF7\u8F93\u5165\u6A21\u677F\u540D\u79F0 (Name):",
3704
+ "extension.create.promptDescription": "\u8BF7\u8F93\u5165\u6A21\u677F\u7B80\u8981\u63CF\u8FF0 (Description):",
3705
+ "extension.create.promptWithTasks": "\u662F\u5426\u5305\u542B\u9879\u76EE\u811A\u624B\u67B6\u521D\u59CB\u5316\u4EFB\u52A1 (Tasks) \u793A\u4F8B\uFF1F",
3706
+ "extension.create.promptWithProject": "\u662F\u5426\u751F\u6210\u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6\u76EE\u5F55 (project/)\uFF1F",
3707
+ "extension.create.promptWithPipeline": "\u662F\u5426\u751F\u6210 GitLab CI/CD \u81EA\u52A8\u540C\u6B65\u6D41\u6C34\u7EBF\u914D\u7F6E (.gitlab-ci.yml)\uFF1F",
3708
+ "extension.create.created": "\u6A21\u677F\u5DE5\u7A0B\u5DF2\u521B\u5EFA\u5728\uFF1A{0}",
3709
+ "extension.create.success": "\u2713 \u6210\u529F\u521D\u59CB\u5316\u6A21\u677F\u5DE5\u7A0B: {0}",
3710
+ "extension.create.generatedFiles": "\u5DF2\u751F\u6210\u6587\u4EF6\u6E05\u5355:",
3711
+ "extension.pipeline.description": "\u751F\u6210\u6216\u66F4\u65B0\u6A21\u677F\u5DE5\u7A0B\u7684 GitLab CI/CD \u81EA\u52A8\u540C\u6B65\u6D41\u6C34\u7EBF\u914D\u7F6E (.gitlab-ci.yml)",
3712
+ "extension.pipeline.argDirectory": "\u6A21\u677F\u5DE5\u7A0B\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09",
3656
3713
  "extension.pipeline.optionForce": "\u82E5\u5DF2\u5B58\u5728 .gitlab-ci.yml \u5219\u5F3A\u5236\u8986\u76D6",
3657
- "extension.pipeline.optionPackageId": "\u6269\u5C55\u5305 ID\uFF08\u9ED8\u8BA4\u4ECE manifest.yaml \u6216 package.json \u89E3\u6790\uFF09"
3714
+ "extension.pipeline.optionTemplateId": "\u6A21\u677F ID\uFF08\u9ED8\u8BA4\u4ECE manifest.yaml \u6216 package.json \u89E3\u6790\uFF09",
3715
+ "extension.pipeline.optionYes": "\u8DF3\u8FC7\u4EA4\u4E92\u786E\u8BA4",
3716
+ "extension.pipeline.idNotFound": "\u672A\u80FD\u81EA\u52A8\u8BC6\u522B\u6A21\u677F ID\u3002\u8BF7\u786E\u4FDD\u5F53\u524D\u76EE\u5F55\u4E0B\u5B58\u5728\u6709\u6548\u7684 manifest.yaml \u6216 package.json\uFF0C\u6216\u4F7F\u7528 --template-id \u663E\u5F0F\u4F20\u5165\u3002",
3717
+ "extension.pipeline.overwritePrompt": "\u68C0\u6D4B\u5230\u5F53\u524D\u76EE\u5F55\u5DF2\u5B58\u5728 .gitlab-ci.yml\uFF0C\u662F\u5426\u8986\u76D6\uFF1F",
3718
+ "extension.pipeline.cancelled": "\u64CD\u4F5C\u5DF2\u53D6\u6D88\uFF0C\u672A\u4FEE\u6539\u73B0\u6709\u6D41\u6C34\u7EBF\u914D\u7F6E\u3002",
3719
+ "extension.pipeline.alreadyExists": "\u5F53\u524D\u76EE\u5F55\u5DF2\u5B58\u5728 .gitlab-ci.yml\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u9012 --force \u53C2\u6570\u3002",
3720
+ "extension.pipeline.success": "\u2713 \u6210\u529F\u751F\u6210 CI/CD \u6D41\u6C34\u7EBF\u914D\u7F6E: {0}",
3721
+ "extension.pipeline.addedReleaseScript": '\u2713 \u5DF2\u5728 package.json \u7684 scripts \u4E2D\u6DFB\u52A0\u53D1\u7248\u547D\u4EE4: "release": "npm version patch"',
3722
+ "extension.pipeline.gitlabNotice": '\n\u2699\uFE0F GitLab \u9879\u76EE\u914D\u7F6E\u63D0\u793A:\n \u8BF7\u5728\u5F53\u524D\u6A21\u677F\u4ED3\u5E93\u7684\u3010Settings -> CI/CD -> Variables\u3011\u4E2D\u914D\u7F6E\u4EE5\u4E0B\u73AF\u5883\u53D8\u91CF\uFF1A\n - REGISTRY_TRIGGER_TOKEN: Registry \u4ED3\u5E93\u751F\u6210\u7684 Pipeline Trigger Token\n - REGISTRY_PROJECT_ID: Registry \u4ED3\u5E93\u5728 GitLab \u4E0A\u7684\u9879\u76EE ID\n\n\u{1F680} \u65E5\u5E38\u53D1\u7248\u5DE5\u4F5C\u6D41:\n 1. \u63D0\u4EA4\u4EE3\u7801: git add . && git commit -m "feat: xxx"\n 2. \u4E00\u952E\u63D0\u5347\u7248\u672C\u5E76\u6253 Tag: npm run release\n 3. \u63A8\u9001\u5230\u8FDC\u7A0B\u89E6\u53D1\u81EA\u52A8\u5408\u5E76: git push --follow-tags origin main\n\n'
3658
3723
  };
3659
3724
  }
3660
3725
  });
@@ -23353,10 +23418,10 @@ async function persistGitCheckout(workDir, targetDir) {
23353
23418
  return targetDir;
23354
23419
  }
23355
23420
  async function copyGitCheckout(src, dest) {
23356
- const { readdir: readdir11, mkdir: mkdir20, copyFile: copyFile2 } = await import("node:fs/promises");
23421
+ const { readdir: readdir12, mkdir: mkdir20, copyFile: copyFile2 } = await import("node:fs/promises");
23357
23422
  const { join: joinPath } = await import("node:path");
23358
23423
  await mkdir20(dest, { recursive: true });
23359
- const entries = await readdir11(src, { withFileTypes: true });
23424
+ const entries = await readdir12(src, { withFileTypes: true });
23360
23425
  for (const entry of entries) {
23361
23426
  if (entry.name === ".git") continue;
23362
23427
  const srcPath = joinPath(src, entry.name);
@@ -23549,8 +23614,8 @@ var init_git_resolver = __esm({
23549
23614
  }
23550
23615
  const cacheBase = join6(cacheRoot, "git", encodePackageId(packageId));
23551
23616
  try {
23552
- const { readdir: readdir11 } = await import("node:fs/promises");
23553
- const commits = await readdir11(cacheBase, { withFileTypes: true });
23617
+ const { readdir: readdir12 } = await import("node:fs/promises");
23618
+ const commits = await readdir12(cacheBase, { withFileTypes: true });
23554
23619
  for (const entry of commits) {
23555
23620
  if (!entry.isDirectory()) continue;
23556
23621
  const cacheDir = join6(cacheBase, entry.name);
@@ -26935,10 +27000,10 @@ var init_tarball_loader = __esm({
26935
27000
  return targetDir;
26936
27001
  }
26937
27002
  async copyDirRecursive(src, dest) {
26938
- const { readdir: readdir11, mkdir: mkdir20, copyFile: copyFile2 } = await import("node:fs/promises");
27003
+ const { readdir: readdir12, mkdir: mkdir20, copyFile: copyFile2 } = await import("node:fs/promises");
26939
27004
  const { join: joinPath } = await import("node:path");
26940
27005
  await mkdir20(dest, { recursive: true });
26941
- const entries = await readdir11(src, { withFileTypes: true });
27006
+ const entries = await readdir12(src, { withFileTypes: true });
26942
27007
  for (const entry of entries) {
26943
27008
  const srcPath = joinPath(src, entry.name);
26944
27009
  const destPath = joinPath(dest, entry.name);
@@ -27001,14 +27066,14 @@ var init_tarball_loader = __esm({
27001
27066
  return readFile34(join7(packageRoot, "manifest.yaml"), "utf-8");
27002
27067
  }
27003
27068
  async findPackageRoot(workDir, packageId, version) {
27004
- const { access: access12, readdir: readdir11 } = await import("node:fs/promises");
27069
+ const { access: access12, readdir: readdir12 } = await import("node:fs/promises");
27005
27070
  const { resolve: resolvePath10 } = await import("node:path");
27006
27071
  const candidates = [
27007
27072
  resolvePath10(workDir),
27008
27073
  resolvePath10(workDir, "package")
27009
27074
  ];
27010
27075
  try {
27011
- const entries = await readdir11(workDir, { withFileTypes: true });
27076
+ const entries = await readdir12(workDir, { withFileTypes: true });
27012
27077
  for (const entry of entries) {
27013
27078
  if (entry.isDirectory()) {
27014
27079
  candidates.push(resolvePath10(workDir, entry.name));
@@ -30530,10 +30595,27 @@ var init_toml_editor = __esm({
30530
30595
  });
30531
30596
 
30532
30597
  // packages/core/src/execute/executor.ts
30533
- import { readFile as readFile17, writeFile as writeFile5, unlink as unlink7, mkdir as mkdir12, access as access9, rename as rename4, rm as rm4, mkdtemp as mkdtemp4, chmod } from "node:fs/promises";
30598
+ import { readFile as readFile17, writeFile as writeFile5, unlink as unlink7, mkdir as mkdir12, access as access9, rename as rename4, rm as rm4, mkdtemp as mkdtemp4, chmod, readdir as readdir5, rmdir } from "node:fs/promises";
30534
30599
  import { resolve as resolvePath7, dirname as dirname11, join as join12 } from "node:path";
30535
30600
  import { tmpdir as tmpdir4 } from "node:os";
30536
30601
  import { createHash as createHash9 } from "node:crypto";
30602
+ async function cleanEmptyParentDirs(startDir, rootDir) {
30603
+ let current = resolvePath7(startDir);
30604
+ const normalizedRoot = resolvePath7(rootDir);
30605
+ while (current !== normalizedRoot && current.startsWith(normalizedRoot)) {
30606
+ try {
30607
+ const files = await readdir5(current);
30608
+ if (files.length === 0) {
30609
+ await rmdir(current);
30610
+ current = dirname11(current);
30611
+ } else {
30612
+ break;
30613
+ }
30614
+ } catch {
30615
+ break;
30616
+ }
30617
+ }
30618
+ }
30537
30619
  async function getTmpBase() {
30538
30620
  return mkdtemp4(join12(tmpdir4(), "aicoding-tx-"));
30539
30621
  }
@@ -30931,6 +31013,7 @@ var init_executor = __esm({
30931
31013
  throw err;
30932
31014
  }
30933
31015
  });
31016
+ await cleanEmptyParentDirs(dirname11(absPath), projectRoot);
30934
31017
  addFileRollback(absPath, backupPath, rollbackActions, `\u6062\u590D\u5DF2\u5220\u9664\u7684\u6587\u4EF6 ${intent.path}`);
30935
31018
  } else if (intent.type === "config-entry") {
30936
31019
  await removeConfigEntry(absPath, intent.selector, intent.format, backupDir, rollbackActions, intent.path);
@@ -31831,7 +31914,7 @@ var init_task_runner = __esm({
31831
31914
  });
31832
31915
 
31833
31916
  // packages/core/src/execute/template-contract.ts
31834
- import { readFile as readFile19, readdir as readdir5 } from "node:fs/promises";
31917
+ import { readFile as readFile19, readdir as readdir6 } from "node:fs/promises";
31835
31918
  import { join as join14, relative as relative6 } from "node:path";
31836
31919
  function validateMcpConfig(rawConfig) {
31837
31920
  if (typeof rawConfig !== "object" || rawConfig === null) {
@@ -31974,7 +32057,7 @@ async function scanTemplateDirectoryContract(options) {
31974
32057
  if (shouldIncludeAssetType("skills", filter)) {
31975
32058
  const skillsDir = join14(templateDir, "skills");
31976
32059
  try {
31977
- const skillEntries = await readdir5(skillsDir, { withFileTypes: true });
32060
+ const skillEntries = await readdir6(skillsDir, { withFileTypes: true });
31978
32061
  for (const skillEntry of skillEntries) {
31979
32062
  if (!skillEntry.isDirectory()) continue;
31980
32063
  const skillId = skillEntry.name;
@@ -32001,7 +32084,7 @@ async function scanTemplateDirectoryContract(options) {
32001
32084
  if (shouldIncludeAssetType("rules", filter)) {
32002
32085
  const rulesDir = join14(templateDir, "rules");
32003
32086
  try {
32004
- const ruleIdeEntries = await readdir5(rulesDir, { withFileTypes: true });
32087
+ const ruleIdeEntries = await readdir6(rulesDir, { withFileTypes: true });
32005
32088
  for (const ideEntry of ruleIdeEntries) {
32006
32089
  if (!ideEntry.isDirectory()) continue;
32007
32090
  const ide = ideEntry.name;
@@ -32027,7 +32110,7 @@ async function scanTemplateDirectoryContract(options) {
32027
32110
  if (shouldIncludeAssetType("subagents", filter)) {
32028
32111
  const subagentsDir = join14(templateDir, "subagents");
32029
32112
  try {
32030
- const agentIdeEntries = await readdir5(subagentsDir, { withFileTypes: true });
32113
+ const agentIdeEntries = await readdir6(subagentsDir, { withFileTypes: true });
32031
32114
  for (const ideEntry of agentIdeEntries) {
32032
32115
  if (!ideEntry.isDirectory()) continue;
32033
32116
  const ide = ideEntry.name;
@@ -32075,12 +32158,30 @@ async function scanTemplateDirectoryContract(options) {
32075
32158
  }
32076
32159
  }
32077
32160
  }
32161
+ if (!filter?.skipProjectDir) {
32162
+ const projectDir = join14(templateDir, "project");
32163
+ try {
32164
+ const allProjectFiles = await listAllFilesRecursive(projectDir);
32165
+ for (const relFile of allProjectFiles) {
32166
+ const fileContent = await readFile19(join14(projectDir, relFile));
32167
+ const normalizedRel = relFile.replaceAll("\\", "/");
32168
+ intents.push({
32169
+ action: "upsert",
32170
+ type: "file",
32171
+ path: normalizedRel,
32172
+ content: fileContent,
32173
+ assetType: "project-seed"
32174
+ });
32175
+ }
32176
+ } catch {
32177
+ }
32178
+ }
32078
32179
  return intents;
32079
32180
  }
32080
32181
  async function listAllFilesRecursive(dir, baseDir = dir) {
32081
32182
  const files = [];
32082
32183
  try {
32083
- const entries = await readdir5(dir, { withFileTypes: true });
32184
+ const entries = await readdir6(dir, { withFileTypes: true });
32084
32185
  for (const entry of entries) {
32085
32186
  const full = join14(dir, entry.name);
32086
32187
  if (entry.isDirectory()) {
@@ -32109,7 +32210,7 @@ var init_template_contract = __esm({
32109
32210
  });
32110
32211
 
32111
32212
  // packages/core/src/plugin/plugin-delivery.ts
32112
- import { readFile as readFile20, stat as stat4, readdir as readdir6 } from "node:fs/promises";
32213
+ import { readFile as readFile20, stat as stat4, readdir as readdir7 } from "node:fs/promises";
32113
32214
  import { join as join15, resolve as resolve11 } from "node:path";
32114
32215
  import { createHash as createHash11 } from "node:crypto";
32115
32216
  function isPluginTargetSupported(target) {
@@ -32467,7 +32568,7 @@ function buildSettingsUpdate(plugin, target) {
32467
32568
  }
32468
32569
  async function collectDirectoryCopyIntents(sourceDir, sourceRelPath, destDir, packageRoot, metadata) {
32469
32570
  const intents = [];
32470
- const entries = await readdir6(sourceDir, { withFileTypes: true });
32571
+ const entries = await readdir7(sourceDir, { withFileTypes: true });
32471
32572
  for (const entry of entries) {
32472
32573
  const entrySourcePath = join15(sourceDir, entry.name);
32473
32574
  const entryDestPath = `${destDir}/${entry.name}`;
@@ -32586,7 +32687,7 @@ var init_plugin = __esm({
32586
32687
 
32587
32688
  // packages/core/src/journal.ts
32588
32689
  import { createHash as createHash12, randomUUID as randomUUID3 } from "node:crypto";
32589
- import { chmod as chmod2, cp as cp2, mkdir as mkdir14, open as open4, readdir as readdir7, readFile as readFile21, rename as rename5, rm as rm5, stat as stat5, writeFile as writeFile7 } from "node:fs/promises";
32690
+ import { chmod as chmod2, cp as cp2, mkdir as mkdir14, open as open4, readdir as readdir8, readFile as readFile21, rename as rename5, rm as rm5, stat as stat5, writeFile as writeFile7 } from "node:fs/promises";
32590
32691
  import { dirname as dirname12, join as join16, resolve as resolve12 } from "node:path";
32591
32692
  function projectHash(projectRoot) {
32592
32693
  return createHash12("sha256").update(resolve12(projectRoot)).digest("hex").slice(0, 32);
@@ -32734,7 +32835,7 @@ async function scanJournals(userDataDir, projectRoot) {
32734
32835
  const directory = join16(resolve12(userDataDir), "transactions", projectHash(projectRoot));
32735
32836
  let entries;
32736
32837
  try {
32737
- entries = await readdir7(directory, { withFileTypes: true });
32838
+ entries = await readdir8(directory, { withFileTypes: true });
32738
32839
  } catch (error) {
32739
32840
  if (error.code === "ENOENT") return [];
32740
32841
  throw error;
@@ -33307,7 +33408,7 @@ var init_staging_manager = __esm({
33307
33408
  });
33308
33409
 
33309
33410
  // packages/core/src/orchestrator/staging-scanner.ts
33310
- import { readFile as readFile23, readdir as readdir8, stat as stat6 } from "node:fs/promises";
33411
+ import { readFile as readFile23, readdir as readdir9, stat as stat6 } from "node:fs/promises";
33311
33412
  import { join as join18, relative as relative7 } from "node:path";
33312
33413
  async function scanStagingDirectory(options) {
33313
33414
  const { stagingDir, packageId, ownerKind = "template" } = options;
@@ -33316,7 +33417,7 @@ async function scanStagingDirectory(options) {
33316
33417
  async function walk(currentDir) {
33317
33418
  let entries;
33318
33419
  try {
33319
- entries = await readdir8(currentDir, { withFileTypes: true });
33420
+ entries = await readdir9(currentDir, { withFileTypes: true });
33320
33421
  } catch {
33321
33422
  return;
33322
33423
  }
@@ -43846,9 +43947,9 @@ notify_registry:
43846
43947
  }
43847
43948
  function createExtensionPipelineCommand() {
43848
43949
  const cmd = new Command("pipeline");
43849
- cmd.alias("ci").description(t("extension.pipeline.description")).argument("[directory]", t("extension.pipeline.argDirectory"), ".").option("--package-id <id>", t("extension.pipeline.optionPackageId")).option("--force", t("extension.pipeline.optionForce")).option("--yes", "\u8DF3\u8FC7\u4EA4\u4E92\u786E\u8BA4").option("--json", t("global.json")).option("--no-color", t("global.noColor")).option("--verbose", t("global.verbose")).action(async (directory, opts) => {
43950
+ cmd.alias("ci").description(t("extension.pipeline.description")).argument("[directory]", t("extension.pipeline.argDirectory"), ".").option("--template-id <id>", t("extension.pipeline.optionTemplateId")).option("--force", t("extension.pipeline.optionForce")).option("--yes", t("extension.pipeline.optionYes")).option("--json", t("global.json")).option("--no-color", t("global.noColor")).option("--verbose", t("global.verbose")).action(async (directory, opts) => {
43850
43951
  const options = {
43851
- packageId: opts.packageId,
43952
+ templateId: opts.templateId ?? opts.packageId,
43852
43953
  force: Boolean(opts.force),
43853
43954
  yes: Boolean(opts.yes),
43854
43955
  json: Boolean(opts.json),
@@ -43880,35 +43981,35 @@ async function executeExtensionPipeline(directory, options) {
43880
43981
  const pkgJsonPath = resolve14(targetDir, "package.json");
43881
43982
  const ciFilePath = resolve14(targetDir, ".gitlab-ci.yml");
43882
43983
  const isInteractive = !options.yes && !options.json && Boolean(process.stdin.isTTY);
43883
- let packageId = options.packageId;
43884
- if (!packageId) {
43984
+ let templateId = options.templateId;
43985
+ if (!templateId) {
43885
43986
  if (existsSync5(manifestPath)) {
43886
43987
  try {
43887
43988
  const manifestContent = await readFile24(manifestPath, "utf-8");
43888
43989
  const parsed = import_yaml4.default.parse(manifestContent);
43889
43990
  if (parsed && typeof parsed.id === "string") {
43890
- packageId = parsed.id;
43991
+ templateId = parsed.id;
43891
43992
  }
43892
43993
  } catch {
43893
43994
  }
43894
43995
  }
43895
- if (!packageId && existsSync5(pkgJsonPath)) {
43996
+ if (!templateId && existsSync5(pkgJsonPath)) {
43896
43997
  try {
43897
43998
  const pkgContent = await readFile24(pkgJsonPath, "utf-8");
43898
43999
  const parsed = JSON.parse(pkgContent);
43899
44000
  if (parsed && typeof parsed.name === "string") {
43900
- packageId = parsed.name;
44001
+ templateId = parsed.name;
43901
44002
  }
43902
44003
  } catch {
43903
44004
  }
43904
44005
  }
43905
44006
  }
43906
- if (!packageId) {
43907
- const errorMsg = "\u672A\u80FD\u81EA\u52A8\u8BC6\u522B\u6269\u5C55\u5305 ID\u3002\u8BF7\u786E\u4FDD\u5F53\u524D\u76EE\u5F55\u4E0B\u5B58\u5728\u6709\u6548\u7684 manifest.yaml \u6216 package.json\uFF0C\u6216\u4F7F\u7528 --package-id \u663E\u5F0F\u4F20\u5165\u3002";
44007
+ if (!templateId) {
44008
+ const errorMsg = t("extension.pipeline.idNotFound");
43908
44009
  if (output.json) {
43909
- emitFailureJson("extension pipeline", "PACKAGE_ID_NOT_FOUND", errorMsg);
44010
+ emitFailureJson("extension pipeline", "TEMPLATE_ID_NOT_FOUND", errorMsg);
43910
44011
  } else {
43911
- process.stderr.write(`error: PACKAGE_ID_NOT_FOUND: ${errorMsg}
44012
+ process.stderr.write(`error: TEMPLATE_ID_NOT_FOUND: ${errorMsg}
43912
44013
  `);
43913
44014
  }
43914
44015
  return ExitCode.ResolveFailed;
@@ -43916,15 +44017,16 @@ async function executeExtensionPipeline(directory, options) {
43916
44017
  if (existsSync5(ciFilePath) && !options.force) {
43917
44018
  if (isInteractive) {
43918
44019
  const overwrite = await dist_default5({
43919
- message: "\u68C0\u6D4B\u5230\u5F53\u524D\u76EE\u5F55\u5DF2\u5B58\u5728 .gitlab-ci.yml\uFF0C\u662F\u5426\u8986\u76D6\uFF1F",
44020
+ message: t("extension.pipeline.overwritePrompt"),
43920
44021
  default: false
43921
44022
  });
43922
44023
  if (!overwrite) {
43923
- process.stdout.write("\u64CD\u4F5C\u5DF2\u53D6\u6D88\uFF0C\u672A\u4FEE\u6539\u73B0\u6709\u6D41\u6C34\u7EBF\u914D\u7F6E\u3002\n");
44024
+ process.stdout.write(`${t("extension.pipeline.cancelled")}
44025
+ `);
43924
44026
  return ExitCode.Success;
43925
44027
  }
43926
44028
  } else {
43927
- const errorMsg = "\u5F53\u524D\u76EE\u5F55\u5DF2\u5B58\u5728 .gitlab-ci.yml\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u9012 --force \u53C2\u6570\u3002";
44029
+ const errorMsg = t("extension.pipeline.alreadyExists");
43928
44030
  if (output.json) {
43929
44031
  emitFailureJson("extension pipeline", "FILE_ALREADY_EXISTS", errorMsg);
43930
44032
  } else {
@@ -43934,7 +44036,7 @@ async function executeExtensionPipeline(directory, options) {
43934
44036
  return ExitCode.ConflictOrDrift;
43935
44037
  }
43936
44038
  }
43937
- const ciContent = generateGitlabCiYaml(packageId);
44039
+ const ciContent = generateGitlabCiYaml(templateId);
43938
44040
  await writeFile9(ciFilePath, ciContent, "utf-8");
43939
44041
  let addedReleaseScript = false;
43940
44042
  if (existsSync5(pkgJsonPath)) {
@@ -43953,25 +44055,18 @@ async function executeExtensionPipeline(directory, options) {
43953
44055
  if (output.json) {
43954
44056
  emitSuccessJson("extension pipeline", {
43955
44057
  directory: targetDir,
43956
- packageId,
44058
+ templateId,
43957
44059
  ciFile: ciFilePath,
43958
44060
  addedReleaseScript
43959
44061
  });
43960
44062
  } else {
43961
- process.stdout.write(`\u2713 \u6210\u529F\u751F\u6210 CI/CD \u6D41\u6C34\u7EBF\u914D\u7F6E: ${ciFilePath}
44063
+ process.stdout.write(`${t("extension.pipeline.success", ciFilePath)}
43962
44064
  `);
43963
44065
  if (addedReleaseScript) {
43964
- process.stdout.write(`\u2713 \u5DF2\u5728 package.json \u7684 scripts \u4E2D\u6DFB\u52A0\u53D1\u7248\u547D\u4EE4: "release": "npm version patch"
44066
+ process.stdout.write(`${t("extension.pipeline.addedReleaseScript")}
43965
44067
  `);
43966
44068
  }
43967
- process.stdout.write("\n\u2699\uFE0F GitLab \u9879\u76EE\u914D\u7F6E\u63D0\u793A:\n");
43968
- process.stdout.write(" \u8BF7\u5728\u5F53\u524D\u6269\u5C55\u5305\u4ED3\u5E93\u7684\u3010Settings -> CI/CD -> Variables\u3011\u4E2D\u914D\u7F6E\u4EE5\u4E0B\u73AF\u5883\u53D8\u91CF\uFF1A\n");
43969
- process.stdout.write(" - REGISTRY_TRIGGER_TOKEN: Registry \u4ED3\u5E93\u751F\u6210\u7684 Pipeline Trigger Token\n");
43970
- process.stdout.write(" - REGISTRY_PROJECT_ID: Registry \u4ED3\u5E93\u5728 GitLab \u4E0A\u7684\u9879\u76EE ID\n");
43971
- process.stdout.write("\n\u{1F680} \u65E5\u5E38\u53D1\u7248\u5DE5\u4F5C\u6D41:\n");
43972
- process.stdout.write(' 1. \u63D0\u4EA4\u4EE3\u7801: git add . && git commit -m "feat: xxx"\n');
43973
- process.stdout.write(" 2. \u4E00\u952E\u63D0\u5347\u7248\u672C\u5E76\u6253 Tag: npm run release\n");
43974
- process.stdout.write(" 3. \u63A8\u9001\u5230\u8FDC\u7A0B\u89E6\u53D1\u81EA\u52A8\u5408\u5E76: git push --follow-tags origin main\n\n");
44069
+ process.stdout.write(t("extension.pipeline.gitlabNotice"));
43975
44070
  }
43976
44071
  return ExitCode.Success;
43977
44072
  }
@@ -43988,18 +44083,18 @@ var init_extension_pipeline = __esm({
43988
44083
  });
43989
44084
 
43990
44085
  // packages/cli/src/commands/extension-create.ts
43991
- import { mkdir as mkdir17, writeFile as writeFile10, readdir as readdir9 } from "node:fs/promises";
44086
+ import { mkdir as mkdir17, writeFile as writeFile10, readdir as readdir10 } from "node:fs/promises";
43992
44087
  import { basename as basename4, resolve as resolve15 } from "node:path";
43993
44088
  function createExtensionCreateCommand() {
43994
44089
  const cmd = new Command("create");
43995
- cmd.description(t("extension.create.description")).argument("<directory>", t("extension.create.argDirectory")).option("--name <package-id>", t("extension.create.optionName")).option("--template-name <name>", "\u6A21\u677F\u663E\u793A\u540D\u79F0 (name)").option("--description <description>", "\u6A21\u677F\u63CF\u8FF0").option("--with-tasks", "\u662F\u5426\u751F\u6210\u521D\u59CB\u5316\u4EFB\u52A1\u793A\u4F8B").option("--with-pipeline", t("extension.create.optionWithPipeline")).option("--category <category>", t("extension.create.optionCategory")).option("--with-project", t("extension.create.optionWithProject")).option("--with-capability <type>", t("extension.create.optionWithCapability"), collectCapability, []).option("--yes", t("extension.create.optionYes")).option("--json", t("global.json")).option("--no-color", t("global.noColor")).option("--verbose", t("global.verbose")).action(async (directory, opts) => {
44090
+ cmd.description(t("extension.create.description")).argument("<directory>", t("extension.create.argDirectory")).option("--name <package-id>", t("extension.create.optionName")).option("--template-name <name>", t("extension.create.optionTemplateName")).option("--description <description>", t("extension.create.optionDescription")).option("--with-tasks", t("extension.create.optionWithTasks")).option("--with-pipeline", t("extension.create.optionWithPipeline")).option("--category <category>", t("extension.create.optionCategory")).option("--with-project", t("extension.create.optionWithProject")).option("--with-capability <type>", t("extension.create.optionWithCapability"), collectCapability, []).option("--yes", t("extension.create.optionYes")).option("--json", t("global.json")).option("--no-color", t("global.noColor")).option("--verbose", t("global.verbose")).action(async (directory, opts) => {
43996
44091
  const options = {
43997
44092
  name: opts.name,
43998
44093
  templateName: opts.templateName,
43999
44094
  description: opts.description,
44000
44095
  category: opts.category,
44001
- withProject: Boolean(opts.withProject),
44002
- withTasks: Boolean(opts.withTasks),
44096
+ withProject: opts.withProject !== void 0 ? Boolean(opts.withProject) : void 0,
44097
+ withTasks: opts.withTasks !== void 0 ? Boolean(opts.withTasks) : void 0,
44003
44098
  withPipeline: opts.withPipeline !== void 0 ? Boolean(opts.withPipeline) : void 0,
44004
44099
  withCapability: Array.isArray(opts.withCapability) ? opts.withCapability : [],
44005
44100
  yes: Boolean(opts.yes),
@@ -44037,7 +44132,7 @@ async function executeExtensionCreate(directory, options) {
44037
44132
  const dirBase = basename4(targetDir);
44038
44133
  const isInteractive = !options.yes && !options.json && Boolean(process.stdin.isTTY);
44039
44134
  try {
44040
- const entries = await readdir9(targetDir);
44135
+ const entries = await readdir10(targetDir);
44041
44136
  if (entries.length > 0) {
44042
44137
  if (output.json) {
44043
44138
  emitFailureJson(
@@ -44058,7 +44153,7 @@ async function executeExtensionCreate(directory, options) {
44058
44153
  if (!packageId) {
44059
44154
  if (isInteractive) {
44060
44155
  packageId = await dist_default6({
44061
- message: "\u8BF7\u8F93\u5165\u6A21\u677F\u5305\u540D (Package ID):",
44156
+ message: t("extension.create.promptName"),
44062
44157
  default: sanitizePackageId(dirBase) || "my-template"
44063
44158
  });
44064
44159
  } else {
@@ -44069,7 +44164,7 @@ async function executeExtensionCreate(directory, options) {
44069
44164
  if (!templateName) {
44070
44165
  if (isInteractive) {
44071
44166
  templateName = await dist_default6({
44072
- message: "\u8BF7\u8F93\u5165\u6A21\u677F\u540D\u79F0 (Name):",
44167
+ message: t("extension.create.promptTemplateName"),
44073
44168
  default: packageId.replace(/^@[^/]+\//, "")
44074
44169
  });
44075
44170
  } else {
@@ -44080,24 +44175,31 @@ async function executeExtensionCreate(directory, options) {
44080
44175
  if (!description) {
44081
44176
  if (isInteractive) {
44082
44177
  description = await dist_default6({
44083
- message: "\u8BF7\u8F93\u5165\u6A21\u677F\u7B80\u8981\u63CF\u8FF0 (Description):",
44178
+ message: t("extension.create.promptDescription"),
44084
44179
  default: `${templateName} template for Mano Coding`
44085
44180
  });
44086
44181
  } else {
44087
44182
  description = `${templateName} template for Mano Coding`;
44088
44183
  }
44089
44184
  }
44185
+ let withProject = options.withProject;
44186
+ if (withProject === void 0 && isInteractive) {
44187
+ withProject = await dist_default5({
44188
+ message: t("extension.create.promptWithProject"),
44189
+ default: false
44190
+ });
44191
+ }
44090
44192
  let withTasks = options.withTasks;
44091
44193
  if (withTasks === void 0 && isInteractive) {
44092
44194
  withTasks = await dist_default5({
44093
- message: "\u662F\u5426\u5305\u542B\u9879\u76EE\u811A\u624B\u67B6\u521D\u59CB\u5316\u4EFB\u52A1 (Tasks) \u793A\u4F8B\uFF1F",
44195
+ message: t("extension.create.promptWithTasks"),
44094
44196
  default: true
44095
44197
  });
44096
44198
  }
44097
44199
  let withPipeline = options.withPipeline;
44098
44200
  if (withPipeline === void 0 && isInteractive) {
44099
44201
  withPipeline = await dist_default5({
44100
- message: "\u662F\u5426\u751F\u6210 GitLab CI/CD \u81EA\u52A8\u540C\u6B65\u6D41\u6C34\u7EBF\u914D\u7F6E (.gitlab-ci.yml)\uFF1F",
44202
+ message: t("extension.create.promptWithPipeline"),
44101
44203
  default: true
44102
44204
  });
44103
44205
  }
@@ -44108,6 +44210,17 @@ async function executeExtensionCreate(directory, options) {
44108
44210
  if (withPipeline) {
44109
44211
  scripts.release = "npm version patch";
44110
44212
  }
44213
+ const pkgFiles = [
44214
+ "manifest.yaml",
44215
+ "AGENTS.md",
44216
+ "skills",
44217
+ "rules",
44218
+ "mcp",
44219
+ "README.md"
44220
+ ];
44221
+ if (withProject) {
44222
+ pkgFiles.push("project");
44223
+ }
44111
44224
  const pkgJson = {
44112
44225
  name: packageId,
44113
44226
  version: "0.1.0",
@@ -44115,14 +44228,7 @@ async function executeExtensionCreate(directory, options) {
44115
44228
  type: "module",
44116
44229
  engines: { node: ">=22.0.0" },
44117
44230
  scripts,
44118
- files: [
44119
- "manifest.yaml",
44120
- "AGENTS.md",
44121
- "skills",
44122
- "rules",
44123
- "mcp",
44124
- "README.md"
44125
- ],
44231
+ files: pkgFiles,
44126
44232
  devDependencies: {
44127
44233
  vitest: "^3.0.5"
44128
44234
  }
@@ -44239,6 +44345,50 @@ describe('${packageId} template manifest', () => {
44239
44345
  "package.json",
44240
44346
  "test/manifest.test.ts"
44241
44347
  ];
44348
+ if (withProject) {
44349
+ const projectDir = resolve15(targetDir, "project");
44350
+ const projectSrcDir = resolve15(projectDir, "src");
44351
+ await mkdir17(projectSrcDir, { recursive: true });
44352
+ const starterPkgName = `${packageId.replace(/^@[^/]+\//, "")}-starter`;
44353
+ const projectPkgJson = {
44354
+ name: starterPkgName,
44355
+ version: "0.1.0",
44356
+ private: true,
44357
+ type: "module",
44358
+ scripts: {
44359
+ dev: "vite",
44360
+ build: "vite build"
44361
+ }
44362
+ };
44363
+ await writeFile10(
44364
+ resolve15(projectDir, "package.json"),
44365
+ JSON.stringify(projectPkgJson, null, 2) + "\n",
44366
+ "utf-8"
44367
+ );
44368
+ const projectReadme = `# ${starterPkgName}
44369
+
44370
+ \u8FD9\u662F\u4E00\u4E2A\u7531 ${packageId} \u6A21\u677F\u63D0\u4F9B\u7684\u521D\u59CB\u5DE5\u7A0B\u811A\u624B\u67B6\uFF08\u9879\u76EE\u9AA8\u67B6\u79CD\u5B50\uFF09\u3002
44371
+
44372
+ \u5728\u6267\u884C \`mano-coding create\` \u65F6\uFF0C\u6B64\u76EE\u5F55\u4E2D\u7684\u6587\u4EF6\u5C06\u81EA\u52A8\u91CA\u653E\u5230\u76EE\u6807\u5DE5\u7A0B\u6839\u76EE\u5F55\u3002
44373
+ \u6CE8\u610F\uFF1A\u672C\u76EE\u5F55\u4E2D\u7684\u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6\u6587\u4EF6\u4E3A bootstrap \u8D44\u6E90\uFF0C\u4E0D\u7EB3\u5165 \`.ai-coding.lock\` \u53D7\u7BA1\u8D44\u4EA7\u8DDF\u8E2A\u3002
44374
+ `;
44375
+ await writeFile10(resolve15(projectDir, "README.md"), projectReadme, "utf-8");
44376
+ const projectIndexTs = `/**
44377
+ * ${starterPkgName} \u5165\u53E3\u6587\u4EF6
44378
+ */
44379
+ export function main(): void {
44380
+ console.log('Hello from ${starterPkgName}!');
44381
+ }
44382
+
44383
+ main();
44384
+ `;
44385
+ await writeFile10(resolve15(projectSrcDir, "index.ts"), projectIndexTs, "utf-8");
44386
+ createdFiles.push(
44387
+ "project/package.json",
44388
+ "project/README.md",
44389
+ "project/src/index.ts"
44390
+ );
44391
+ }
44242
44392
  if (withPipeline) {
44243
44393
  await writeFile10(
44244
44394
  resolve15(targetDir, ".gitlab-ci.yml"),
@@ -44252,7 +44402,8 @@ describe('${packageId} template manifest', () => {
44252
44402
  templateName,
44253
44403
  description,
44254
44404
  withTasks: Boolean(withTasks),
44255
- withPipeline: Boolean(withPipeline)
44405
+ withPipeline: Boolean(withPipeline),
44406
+ withProject: Boolean(withProject)
44256
44407
  });
44257
44408
  await writeFile10(resolve15(targetDir, "README.md"), readmeContent, "utf-8");
44258
44409
  if (output.json) {
@@ -44262,9 +44413,9 @@ describe('${packageId} template manifest', () => {
44262
44413
  files: createdFiles
44263
44414
  });
44264
44415
  } else {
44265
- process.stdout.write(`\u2713 \u6210\u529F\u521D\u59CB\u5316\u6A21\u677F\u5DE5\u7A0B: ${targetDir}
44416
+ process.stdout.write(`${t("extension.create.success", targetDir)}
44266
44417
  `);
44267
- process.stdout.write(`\u5DF2\u751F\u6210\u6587\u4EF6\u6E05\u5355:
44418
+ process.stdout.write(`${t("extension.create.generatedFiles")}
44268
44419
  - ${createdFiles.join("\n - ")}
44269
44420
  `);
44270
44421
  }
@@ -44299,6 +44450,21 @@ git push --follow-tags origin main
44299
44450
  mano-coding extension pipeline .
44300
44451
  \`\`\`
44301
44452
  `;
44453
+ const projectSection = options.withProject ? `
44454
+ ---
44455
+
44456
+ ## \u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6 (project/ \u76EE\u5F55)
44457
+
44458
+ \u672C\u6A21\u677F\u5305\u542B\u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6\u76EE\u5F55 \`project/\`\uFF1A
44459
+ - \u6267\u884C \`mano-coding create <\u9879\u76EE\u540D> --template <\u672C\u6A21\u677F>\` \u65F6\uFF0C\`project/\` \u4E0B\u7684\u6587\u4EF6\u5C06\u81EA\u52A8\u590D\u5236\u5230\u65B0\u5EFA\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF0C\u4F5C\u4E3A\u521D\u59CB\u6E90\u4EE3\u7801\u9AA8\u67B6\u3002
44460
+ - \u9759\u6001\u5DE5\u7A0B\u6587\u4EF6\u4F5C\u4E3A bootstrap \u79CD\u5B50\u8D44\u6E90\uFF0C\u4E0D\u4F1A\u8BA1\u5165 \`.ai-coding.lock\` \u53D7\u7BA1\u6E05\u5355\uFF0C\u540E\u7EED\u6267\u884C \`apply\` \u6216 \`sync\` \u65F6\u4E0D\u4F1A\u8986\u76D6\u7528\u6237\u5BF9\u5DE5\u7A0B\u6587\u4EF6\u7684\u4FEE\u6539\u3002
44461
+ ` : "";
44462
+ const projectTree = options.withProject ? `\u251C\u2500\u2500 project/ # [\u53EF\u9009] \u9759\u6001\u5DE5\u7A0B\u811A\u624B\u67B6\u79CD\u5B50\u76EE\u5F55\uFF08\u5728 create \u65F6\u91CA\u653E\u5230\u9879\u76EE\u6839\u76EE\u5F55\uFF0C\u4F5C\u4E3A\u521D\u59CB\u6E90\u7801\u6846\u67B6\uFF09
44463
+ \u2502 \u251C\u2500\u2500 package.json
44464
+ \u2502 \u251C\u2500\u2500 README.md
44465
+ \u2502 \u2514\u2500\u2500 src/
44466
+ \u2502 \u2514\u2500\u2500 index.ts
44467
+ ` : "";
44302
44468
  return `# ${options.templateName} (\`${options.packageId}\`)
44303
44469
 
44304
44470
  ${options.description}
@@ -44314,7 +44480,7 @@ ${options.description}
44314
44480
  \`\`\`text
44315
44481
  \u251C\u2500\u2500 manifest.yaml # \u6A21\u677F\u58F0\u660E\u6E05\u5355\uFF08\u5143\u6570\u636E\u4E0E\u53EF\u9009\u7684\u4EFB\u52A1\uFF09
44316
44482
  \u251C\u2500\u2500 AGENTS.md # \u9879\u76EE\u7EA7\u901A\u7528 AI \u7F16\u7801\u6307\u5BFC\uFF0C\u5B89\u88C5\u65F6\u81EA\u52A8\u590D\u5236\u5230\u9879\u76EE\u6839\u76EE\u5F55
44317
- \u251C\u2500\u2500 skills/ # \u8DE8 IDE \u53EF\u590D\u7528\u7684 Agent Skills\uFF08\u4E00\u9879 Skill \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF09
44483
+ ${projectTree}\u251C\u2500\u2500 skills/ # \u8DE8 IDE \u53EF\u590D\u7528\u7684 Agent Skills\uFF08\u4E00\u9879 Skill \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF09
44318
44484
  \u2502 \u2514\u2500\u2500 example-skill/
44319
44485
  \u2502 \u2514\u2500\u2500 SKILL.md
44320
44486
  \u251C\u2500\u2500 rules/ # IDE \u539F\u751F\u89C4\u5219\u76EE\u5F55
@@ -44325,7 +44491,7 @@ ${options.description}
44325
44491
  \u2502 \u2514\u2500\u2500 mcp.json # \u8FDC\u7AEF Streamable HTTP MCP \u670D\u52A1\u5668\u914D\u7F6E
44326
44492
  \u251C\u2500\u2500 README.md # \u6A21\u677F\u4F7F\u7528\u4E0E\u5F00\u53D1\u6587\u6863
44327
44493
  \u2514\u2500\u2500 package.json # \u6A21\u677F\u5305\u914D\u7F6E
44328
- \`\`\`
44494
+ \`\`\`${projectSection}
44329
44495
 
44330
44496
  ---
44331
44497
 
@@ -44635,7 +44801,7 @@ async function executeExtensionDev(packageDirectory, options) {
44635
44801
  argv.push("--source-type", "local");
44636
44802
  argv.push("--source-path", sourcePath);
44637
44803
  }
44638
- if (options.operation === "remove" && packageId) argv.push("--package", packageId);
44804
+ if (options.operation === "remove" && packageId) argv.push("--template", packageId);
44639
44805
  for (const target of options.target) {
44640
44806
  argv.push("--target", target);
44641
44807
  }
@@ -45989,7 +46155,7 @@ var init_service_locator = __esm({
45989
46155
  });
45990
46156
 
45991
46157
  // packages/cli/src/commands/plan-execution.ts
45992
- import { readFile as readFile30, readdir as readdir10, stat as stat7 } from "node:fs/promises";
46158
+ import { readFile as readFile30, readdir as readdir11, stat as stat7 } from "node:fs/promises";
45993
46159
  import { join as join23, resolve as resolve21 } from "node:path";
45994
46160
  import { createHash as createHash15 } from "node:crypto";
45995
46161
  async function buildIntentsFromPlan(_plan, resolutions, service, projectTargets, _userInstallationKeys, options) {
@@ -46004,9 +46170,15 @@ async function buildIntentsFromPlan(_plan, resolutions, service, projectTargets,
46004
46170
  templateDir: packageRoot,
46005
46171
  projectRoot: service.projectRoot,
46006
46172
  targets: projectTargets.map((t2) => t2.id),
46007
- filter: options?.filter
46173
+ filter: {
46174
+ ...options?.filter,
46175
+ skipProjectDir: options?.skipProjectDir ?? options?.filter?.skipProjectDir
46176
+ }
46008
46177
  });
46009
- intents.push(...contractIntents);
46178
+ intents.push(...contractIntents.map((intent) => ({
46179
+ ...intent,
46180
+ packageId: manifest.id
46181
+ })));
46010
46182
  for (const asset of manifest.assets ?? []) {
46011
46183
  if (options?.skipProjectDir && (asset.source === "project" || asset.source.startsWith("project/"))) {
46012
46184
  options.onDiscloseSkipped?.(`\u8DF3\u8FC7\u8D44\u4EA7 '${asset.source}' (\u7531\u4E8E\u547D\u4EE4\u8BED\u4E49\u4E0D\u4EA4\u4ED8 project \u76EE\u5F55)`);
@@ -46105,7 +46277,7 @@ async function collectAssetIntents(packageRoot, source, destination, metadata) {
46105
46277
  }
46106
46278
  if (!sourceStat.isDirectory()) throw new Error(`Asset '${source}' \u65E2\u4E0D\u662F\u6587\u4EF6\u4E5F\u4E0D\u662F\u76EE\u5F55`);
46107
46279
  const intents = [];
46108
- for (const entry of await readdir10(sourcePath, { withFileTypes: true })) {
46280
+ for (const entry of await readdir11(sourcePath, { withFileTypes: true })) {
46109
46281
  intents.push(...await collectAssetIntents(packageRoot, join23(source, entry.name), join23(destination, entry.name).replaceAll("\\", "/"), metadata));
46110
46282
  }
46111
46283
  return intents;
@@ -46293,6 +46465,7 @@ async function buildLock(_operation, templateResolution, addonResolutions, proje
46293
46465
  }
46294
46466
  }
46295
46467
  for (const intent of intents) {
46468
+ if (intent.assetType === "project-seed") continue;
46296
46469
  if (!intent.target) continue;
46297
46470
  const targetId = typeof intent.target === "string" ? intent.target : intent.target.id;
46298
46471
  const selector = (intent.type === "config-entry" ? intent.selector : intent.type === "managed-section" ? intent.sectionId : null) ?? null;
@@ -46438,7 +46611,8 @@ function toInquirerChoices(choices) {
46438
46611
  return choices.map((choice) => ({
46439
46612
  value: choice,
46440
46613
  name: choice.label ?? choice.id,
46441
- description: choice.description
46614
+ description: choice.description,
46615
+ checked: choice.checked
46442
46616
  }));
46443
46617
  }
46444
46618
  function toContext(options) {
@@ -46824,10 +46998,11 @@ import { randomUUID as randomUUID6 } from "node:crypto";
46824
46998
  import { unlink as unlink9 } from "node:fs/promises";
46825
46999
  function createCreateCommand(cliVersion) {
46826
47000
  const cmd = new Command("create");
46827
- cmd.description(t("create.description")).argument("[package-spec]", t("create.argPackageSpec")).argument("[directory]", t("create.argDirectory")).option("--package <package-spec>", t("create.optionPackage"), collectPackage, []).option("--template <package-spec>", t("create.optionTemplate")).option("--addon <package-spec>", t("create.optionAddon"), collectPackage, []).action(async (packageSpec, directory, opts) => {
47001
+ cmd.description(t("create.description")).argument("[template-spec]", t("create.argTemplateSpec")).argument("[directory]", t("create.argDirectory")).option("--template <template-spec>", t("create.optionTemplate"), collectTemplate, []).action(async (templateSpec, directory, opts) => {
47002
+ const templateOptions = Array.isArray(opts.template) ? opts.template : [];
46828
47003
  const options = {
46829
47004
  ...extractMutationOptions(opts),
46830
- packages: Array.isArray(opts.package) ? opts.package : []
47005
+ templates: templateOptions
46831
47006
  };
46832
47007
  const output = {
46833
47008
  json: options.json,
@@ -46837,7 +47012,7 @@ function createCreateCommand(cliVersion) {
46837
47012
  if (options.only || options.skip) {
46838
47013
  reportCliError(
46839
47014
  new CliError(
46840
- "create \u547D\u4EE4\u4E0D\u652F\u6301 --only / --skip \u8D44\u4EA7\u8FC7\u6EE4\uFF0C\u4EE5\u4FDD\u8BC1\u6A21\u677F\u5B8C\u6574\u4EA4\u4ED8\u3002\u5982\u9700\u5B9A\u5236\u53D7\u7BA1\u8D44\u4EA7\u8BF7\u4F7F\u7528 apply \u547D\u4EE4\u3002",
47015
+ t("create.filterUnsupported"),
46841
47016
  ExitCode.SchemaInvalid,
46842
47017
  "UNSUPPORTED_OPTION"
46843
47018
  ),
@@ -46847,27 +47022,21 @@ function createCreateCommand(cliVersion) {
46847
47022
  process.exitCode = ExitCode.SchemaInvalid;
46848
47023
  return;
46849
47024
  }
46850
- const rawPackages = [
46851
- ...Array.isArray(opts.package) ? opts.package : [],
46852
- ...Array.isArray(opts.addon) ? opts.addon : []
46853
- ];
46854
- if (typeof opts.template === "string" && opts.template.trim().length > 0) {
46855
- rawPackages.push(opts.template.trim());
46856
- }
46857
- let effectivePackages = [...rawPackages];
47025
+ const rawTemplates = [...templateOptions];
47026
+ let effectiveTemplates = [...rawTemplates];
46858
47027
  let effectiveDirectory = directory;
46859
- if (rawPackages.length > 0) {
46860
- if (packageSpec && !directory) {
46861
- effectiveDirectory = packageSpec;
47028
+ if (rawTemplates.length > 0) {
47029
+ if (templateSpec && !directory) {
47030
+ effectiveDirectory = templateSpec;
46862
47031
  }
46863
47032
  } else {
46864
- if (packageSpec) {
46865
- effectivePackages.push(packageSpec);
47033
+ if (templateSpec) {
47034
+ effectiveTemplates.push(templateSpec);
46866
47035
  }
46867
47036
  }
46868
47037
  const events = createEventEmitter("create", output);
46869
47038
  const exitCode = await executeCreate(
46870
- effectivePackages,
47039
+ effectiveTemplates,
46871
47040
  effectiveDirectory,
46872
47041
  options,
46873
47042
  cliVersion,
@@ -46885,7 +47054,7 @@ function createCreateCommand(cliVersion) {
46885
47054
  addMutationOptions(cmd);
46886
47055
  return cmd;
46887
47056
  }
46888
- function collectPackage(value, previous = []) {
47057
+ function collectTemplate(value, previous = []) {
46889
47058
  return previous.concat(value);
46890
47059
  }
46891
47060
  async function executeCreate(packageSpecs, directory, options, cliVersion, events) {
@@ -46926,7 +47095,7 @@ async function executeCreate(packageSpecs, directory, options, cliVersion, event
46926
47095
  const allResolutions = [];
46927
47096
  for (const spec of packageSpecs) {
46928
47097
  const resolution = await events.measure("resolve", () => withSpinner(
46929
- `\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6269\u5C55\u5305 (${spec})...`,
47098
+ t("template.resolving", spec),
46930
47099
  () => resolvePackageWith(
46931
47100
  service,
46932
47101
  spec,
@@ -46935,8 +47104,8 @@ async function executeCreate(packageSpecs, directory, options, cliVersion, event
46935
47104
  ),
46936
47105
  {
46937
47106
  enabled: spinnerEnabled,
46938
- successText: (res) => `\u2714 \u6A21\u677F\u89E3\u6790\u5B8C\u6210: ${res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? spec} (v${res.manifest.version ?? "0.0.0"})`,
46939
- failText: `\u2716 \u6269\u5C55\u5305\u89E3\u6790\u5931\u8D25: ${spec}`
47107
+ successText: (res) => t("template.resolved", res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? spec, res.manifest.version ?? "0.0.0"),
47108
+ failText: t("template.resolveFailed", spec)
46940
47109
  }
46941
47110
  ), { packageId: spec });
46942
47111
  allResolutions.push(resolution);
@@ -46974,7 +47143,7 @@ async function executeCreate(packageSpecs, directory, options, cliVersion, event
46974
47143
  for (const res of allResolutions) {
46975
47144
  if (existingPkgIds.has(res.manifest.id)) {
46976
47145
  throw new CliError(
46977
- `\u5305 '${res.manifest.id}' \u5DF2\u7ECF\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D\u3002\u4E0D\u80FD\u901A\u8FC7 create \u91CD\u65B0\u5B89\u88C5\u3002\u5982\u9700\u66F4\u65B0\u914D\u7F6E\u6216\u540C\u6B65\u8D44\u4EA7\u8BF7\u4F7F\u7528 'apply'\u3001'sync' \u6216 'upgrade' \u547D\u4EE4\u3002`,
47146
+ t("create.templateAlreadyInstalled", res.manifest.id),
46978
47147
  ExitCode.ConflictOrDrift,
46979
47148
  "PACKAGE_ALREADY_INSTALLED"
46980
47149
  );
@@ -46995,20 +47164,19 @@ async function executeCreate(packageSpecs, directory, options, cliVersion, event
46995
47164
  if (options.noInput || options.json || !process.stdin.isTTY) {
46996
47165
  const missing = taskValidation.missingInputs.join(", ");
46997
47166
  throw new CliError(
46998
- `\u5305 '${pkgId}' \u7F3A\u5C11\u521D\u59CB\u5316\u53C2\u6570: ${missing}\uFF0C\u8BF7\u4F7F\u7528\uFF1A
46999
- ${taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).join("\n")}`,
47167
+ t("create.missingTaskInputs", pkgId, missing, taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).join("\n")),
47000
47168
  ExitCode.NeedsInputOrDenied,
47001
47169
  "INPUT_REQUIRED",
47002
47170
  { inputs: taskValidation.missingInputs }
47003
47171
  );
47004
47172
  }
47005
47173
  for (const missingKey of taskValidation.missingInputs) {
47006
- const val = await dist_default6({ message: `[${pkgId}] \u8BF7\u8F93\u5165\u521D\u59CB\u5316\u53C2\u6570 '${missingKey}':` });
47174
+ const val = await dist_default6({ message: t("create.promptTaskInput", pkgId, missingKey) });
47007
47175
  inputValues[missingKey] = val;
47008
47176
  }
47009
47177
  } else {
47010
47178
  throw new CliError(
47011
- taskValidation.error ?? "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
47179
+ taskValidation.error ?? t("create.taskValidationFailed"),
47012
47180
  ExitCode.SchemaInvalid,
47013
47181
  "INVALID_OPTIONS"
47014
47182
  );
@@ -47068,12 +47236,12 @@ ${taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).joi
47068
47236
  );
47069
47237
  const userInstallationKeys = /* @__PURE__ */ new Set();
47070
47238
  let staticIntents = await withSpinner(
47071
- "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
47239
+ t("create.computingPlan"),
47072
47240
  () => buildIntentsFromPlan(planResult.plan, allResolutions, service, projectTargets, userInstallationKeys),
47073
47241
  {
47074
47242
  enabled: spinnerEnabled,
47075
- successText: (res) => `\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 ${res.length} \u9879\u8D44\u6E90\u53D8\u66F4)`,
47076
- failText: "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25"
47243
+ successText: (res) => t("create.planReady", res.length),
47244
+ failText: t("create.planFailed")
47077
47245
  }
47078
47246
  );
47079
47247
  planResult = materializePlan(planResult.plan, staticIntents);
@@ -47172,7 +47340,7 @@ ${taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).joi
47172
47340
  operation: "create",
47173
47341
  version: resolution.manifest.version
47174
47342
  };
47175
- const title = `\u6B63\u5728\u6267\u884C\u524D\u7F6E\u521B\u5EFA\u4EFB\u52A1 (before:create) [${pkgIdx + 1}/${allResolutions.length}] (${resolution.manifest.id}):`;
47343
+ const title = t("task.runningBeforeCreate", pkgIdx + 1, allResolutions.length, resolution.manifest.id);
47176
47344
  try {
47177
47345
  await runTasksWithDynamicUI(pkgTasks, taskContext, {
47178
47346
  title,
@@ -47296,7 +47464,7 @@ ${taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).joi
47296
47464
  operation: "create",
47297
47465
  version: resolution.manifest.version
47298
47466
  };
47299
- const title = `\u6B63\u5728\u6267\u884C\u540E\u7F6E\u521D\u59CB\u5316\u4EFB\u52A1 (after:create) [${pkgIdx + 1}/${allResolutions.length}] (${resolution.manifest.id}):`;
47467
+ const title = t("task.runningAfterCreate", pkgIdx + 1, allResolutions.length, resolution.manifest.id);
47300
47468
  try {
47301
47469
  await runTasksWithDynamicUI(pkgTasks, taskContext, {
47302
47470
  title,
@@ -47327,18 +47495,14 @@ ${taskValidation.missingInputs.map((k2) => `--input ${pkgId}:${k2}=<value>`).joi
47327
47495
  });
47328
47496
  }
47329
47497
  function formatElapsed(startedAt) {
47330
- return `${((Date.now() - startedAt) / 1e3).toFixed(1)} \u79D2`;
47498
+ return t("common.seconds", ((Date.now() - startedAt) / 1e3).toFixed(1));
47331
47499
  }
47332
47500
  function writeUserInstallationProgress(progress) {
47333
47501
  const name = progress.displayName ?? `${progress.packageId}/${progress.capabilityId}`;
47334
- if (progress.status === "installing") writeHumanOutput(`\u6B63\u5728\u5B89\u88C5\uFF1A${name}
47335
- `);
47336
- else if (progress.status === "installed") writeHumanOutput(`\u2713 \u5DF2\u5B89\u88C5\uFF1A${name}
47337
- `);
47338
- else if (progress.status === "reused") writeHumanOutput(`\u2713 \u5DF2\u590D\u7528\uFF1A${name}
47339
- `);
47340
- else writeHumanOutput(`- \u65E0\u9700\u5B89\u88C5\uFF1A${name}
47341
- `);
47502
+ if (progress.status === "installing") writeHumanOutput(t("create.installing", name));
47503
+ else if (progress.status === "installed") writeHumanOutput(t("create.installed", name));
47504
+ else if (progress.status === "reused") writeHumanOutput(t("create.reused", name));
47505
+ else writeHumanOutput(t("create.skipped", name));
47342
47506
  }
47343
47507
  async function resolvePackageWith(service, spec, options, cliVersion) {
47344
47508
  const req = {
@@ -47391,7 +47555,7 @@ import { unlink as unlink10 } from "node:fs/promises";
47391
47555
  import { randomUUID as randomUUID7 } from "node:crypto";
47392
47556
  function createApplyCommand(cliVersion) {
47393
47557
  const cmd = new Command("apply");
47394
- cmd.description("Apply a template to an existing project").argument("[package-spec]", "Template spec (required if no project lock)").action(async (packageSpec, opts) => {
47558
+ cmd.description(t("apply.description")).argument("[template-spec]", t("apply.argTemplateSpec")).option("--template <template-spec>", t("apply.optionTemplate")).action(async (templateSpecArg, opts) => {
47395
47559
  const options = extractMutationOptions(opts);
47396
47560
  const output = {
47397
47561
  json: options.json,
@@ -47399,7 +47563,8 @@ function createApplyCommand(cliVersion) {
47399
47563
  noColor: options.noColor
47400
47564
  };
47401
47565
  const events = createEventEmitter("apply", output);
47402
- const exitCode = await executeApply(packageSpec, options, cliVersion, events).catch(
47566
+ const templateSpec = (typeof opts.template === "string" ? opts.template : void 0) ?? (typeof templateSpecArg === "string" ? templateSpecArg : void 0);
47567
+ const exitCode = await executeApply(templateSpec, options, cliVersion, events).catch(
47403
47568
  (err) => reportCliError(err, "apply", output, options.json && options.verbose ? getRedactedEvents(events) : void 0)
47404
47569
  );
47405
47570
  if (exitCode !== 0) {
@@ -47409,7 +47574,7 @@ function createApplyCommand(cliVersion) {
47409
47574
  addMutationOptions(cmd);
47410
47575
  return cmd;
47411
47576
  }
47412
- async function executeApply(packageSpec, options, cliVersion, events) {
47577
+ async function executeApply(templateSpec, options, cliVersion, events) {
47413
47578
  const output = {
47414
47579
  json: options.json,
47415
47580
  verbose: options.verbose,
@@ -47417,13 +47582,6 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47417
47582
  };
47418
47583
  const jsonEvents = () => options.json && options.verbose ? getRedactedEvents(events) : void 0;
47419
47584
  const isInteractive = !options.noInput && !options.json && Boolean(process.stdin.isTTY);
47420
- if (!packageSpec) {
47421
- throw new CliError(
47422
- t("apply.packageRequired"),
47423
- ExitCode.SchemaInvalid,
47424
- "PACKAGE_SPEC_REQUIRED"
47425
- );
47426
- }
47427
47585
  if (options.only && options.skip) {
47428
47586
  throw new CliError(
47429
47587
  t("apply.onlySkipExclusive"),
@@ -47485,28 +47643,72 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47485
47643
  const spinnerEnabled = !output.json && Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test";
47486
47644
  if (existingLock) {
47487
47645
  const existing = await withSpinner(
47488
- "\u6B63\u5728\u4ECE\u9501\u5B9A\u6587\u4EF6\u89E3\u6790\u5DF2\u5B89\u88C5\u5305...",
47646
+ t("template.resolving", "lock"),
47489
47647
  () => resolveLockedPackages(existingLock, service),
47490
47648
  {
47491
47649
  enabled: spinnerEnabled,
47492
- successText: "\u2714 \u5DF2\u52A0\u8F7D\u9501\u5B9A\u914D\u7F6E"
47650
+ successText: t("apply.lockedConfigLoaded")
47493
47651
  }
47494
47652
  );
47495
47653
  templateResolution = existing.template;
47496
47654
  addonResolutions = existing.addons;
47497
47655
  }
47656
+ let effectiveTemplateSpec = templateSpec;
47657
+ if (!effectiveTemplateSpec) {
47658
+ if (!isInteractive) {
47659
+ throw new CliError(
47660
+ t("apply.templateRequired"),
47661
+ ExitCode.SchemaInvalid,
47662
+ "PACKAGE_SPEC_REQUIRED"
47663
+ );
47664
+ }
47665
+ const client = service.getRegistryClient();
47666
+ if (!client.getIndex) {
47667
+ throw new CliError(t("create.registryIndexUnsupported"), ExitCode.ResolveFailed, "REGISTRY_INDEX_UNSUPPORTED");
47668
+ }
47669
+ const indexResult = await client.getIndex({ offline: options.offline });
47670
+ const installedIds = /* @__PURE__ */ new Set();
47671
+ if (existingLock) {
47672
+ for (const p2 of existingLock.desired?.packages ?? []) installedIds.add(p2.id);
47673
+ for (const p2 of existingLock.resolved?.packages ?? []) installedIds.add(p2.id);
47674
+ if (existingLock.desired?.template?.id) installedIds.add(existingLock.desired.template.id);
47675
+ for (const t2 of existingLock.desired?.templates ?? []) installedIds.add(t2.id);
47676
+ for (const a of existingLock.desired?.addons ?? []) installedIds.add(a.id);
47677
+ if (existingLock.resolved?.template?.id) installedIds.add(existingLock.resolved.template.id);
47678
+ for (const t2 of existingLock.resolved?.templates ?? []) installedIds.add(t2.id);
47679
+ for (const a of existingLock.resolved?.addons ?? []) installedIds.add(a.id);
47680
+ }
47681
+ const availableChoices = indexResult.packages.filter((entry) => !installedIds.has(entry.id)).map((entry) => ({
47682
+ id: entry.id,
47683
+ label: entry.name ?? entry.displayName ?? entry.id,
47684
+ description: entry.description ?? "",
47685
+ tags: entry.tags ?? []
47686
+ }));
47687
+ if (availableChoices.length === 0) {
47688
+ throw new CliError(t("apply.noAvailableTemplates"), ExitCode.NeedsInputOrDenied, "NO_TEMPLATES_AVAILABLE");
47689
+ }
47690
+ try {
47691
+ const chosen = await selectSearchable({ message: t("apply.chooseTemplate"), choices: availableChoices });
47692
+ effectiveTemplateSpec = chosen.id;
47693
+ } catch (error) {
47694
+ if (error instanceof SearchableSelectCancelled) {
47695
+ throw new CliError(t("apply.templateSelectionCancelled"), ExitCode.NeedsInputOrDenied, "PERMISSION_DENIED");
47696
+ }
47697
+ throw error;
47698
+ }
47699
+ }
47498
47700
  const newAddonResolution = await withSpinner(
47499
- `\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6A21\u677F (${packageSpec})...`,
47701
+ t("template.resolving", effectiveTemplateSpec),
47500
47702
  () => resolvePackageWith2(
47501
47703
  service,
47502
- packageSpec,
47704
+ effectiveTemplateSpec,
47503
47705
  options,
47504
47706
  cliVersion
47505
47707
  ),
47506
47708
  {
47507
47709
  enabled: spinnerEnabled,
47508
- successText: (res) => `\u2714 \u6A21\u677F\u89E3\u6790\u5B8C\u6210: ${res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? packageSpec} (v${res.manifest.version ?? "0.0.0"})`,
47509
- failText: `\u2716 \u6A21\u677F\u89E3\u6790\u5931\u8D25: ${packageSpec}`
47710
+ successText: (res) => t("template.resolved", res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? effectiveTemplateSpec, res.manifest.version ?? "0.0.0"),
47711
+ failText: t("template.resolveFailed", effectiveTemplateSpec)
47510
47712
  }
47511
47713
  );
47512
47714
  addonResolutions = [...addonResolutions.filter((resolution) => resolution.packageId !== newAddonResolution.packageId), newAddonResolution];
@@ -47536,24 +47738,31 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47536
47738
  }
47537
47739
  let cliTargets = options.target;
47538
47740
  if (cliTargets.length === 0) {
47539
- if (existingLock?.desired.targets && existingLock.desired.targets.length > 0) {
47540
- cliTargets = existingLock.desired.targets.map((t2) => typeof t2 === "string" ? t2 : t2.id);
47541
- } else if (isInteractive) {
47741
+ if (isInteractive) {
47742
+ const existingTargetIds = new Set(
47743
+ (existingLock?.desired.targets ?? []).map((t2) => typeof t2 === "string" ? t2 : t2.id)
47744
+ );
47745
+ const choices = OFFICIAL_TARGET_CHOICES.map((choice) => ({
47746
+ ...choice,
47747
+ checked: existingTargetIds.size > 0 ? existingTargetIds.has(choice.id) : void 0
47748
+ }));
47542
47749
  try {
47543
47750
  const selected = await selectSearchableMulti({
47544
- message: t("create.chooseTargets"),
47545
- choices: OFFICIAL_TARGET_CHOICES
47751
+ message: t("apply.chooseTargets"),
47752
+ choices
47546
47753
  });
47547
47754
  if (selected.length === 0) {
47548
- throw new CliError(t("create.targetSelectionCancelled"), ExitCode.NeedsInputOrDenied, "PERMISSION_DENIED");
47755
+ throw new CliError(t("apply.targetSelectionCancelled"), ExitCode.NeedsInputOrDenied, "PERMISSION_DENIED");
47549
47756
  }
47550
47757
  cliTargets = selected.map((choice) => choice.id);
47551
47758
  } catch (error) {
47552
47759
  if (error instanceof SearchableSelectCancelled) {
47553
- throw new CliError(t("create.targetSelectionCancelled"), ExitCode.NeedsInputOrDenied, "PERMISSION_DENIED");
47760
+ throw new CliError(t("apply.targetSelectionCancelled"), ExitCode.NeedsInputOrDenied, "PERMISSION_DENIED");
47554
47761
  }
47555
47762
  throw error;
47556
47763
  }
47764
+ } else if (existingLock?.desired.targets && existingLock.desired.targets.length > 0) {
47765
+ cliTargets = existingLock.desired.targets.map((t2) => typeof t2 === "string" ? t2 : t2.id);
47557
47766
  } else {
47558
47767
  cliTargets = ["codebuddy"];
47559
47768
  }
@@ -47573,7 +47782,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47573
47782
  );
47574
47783
  const userInstallationKeys = /* @__PURE__ */ new Set();
47575
47784
  const intents = await withSpinner(
47576
- "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
47785
+ t("apply.computingPlan"),
47577
47786
  () => buildIntentsFromPlan(
47578
47787
  planResult.plan,
47579
47788
  packagesToApply,
@@ -47581,7 +47790,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47581
47790
  projectTargets,
47582
47791
  userInstallationKeys,
47583
47792
  {
47584
- filter: { only: onlyTypes, skip: skipTypes },
47793
+ filter: { only: onlyTypes, skip: skipTypes, skipProjectDir: true },
47585
47794
  skipProjectDir: true,
47586
47795
  onDiscloseSkipped: (msg) => {
47587
47796
  if (!output.json) writeHumanOutput(`- ${msg}
@@ -47591,8 +47800,8 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47591
47800
  ),
47592
47801
  {
47593
47802
  enabled: spinnerEnabled,
47594
- successText: (res) => `\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 ${res.length} \u9879\u8D44\u6E90\u53D8\u66F4)`,
47595
- failText: "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25"
47803
+ successText: (res) => t("apply.planReady", res.length),
47804
+ failText: t("apply.planFailed")
47596
47805
  }
47597
47806
  );
47598
47807
  if (existingLock?.resources) {
@@ -47609,7 +47818,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47609
47818
  }
47610
47819
  if (newDigest && matched.hash && newDigest !== matched.hash) {
47611
47820
  throw new CliError(
47612
- `\u8D44\u6E90 '${intent.path}' \u4E0E\u5DF2\u6709\u6A21\u677F\u8D44\u6E90\u5B58\u5728\u51B2\u7A81`,
47821
+ t("apply.resourceConflict", intent.path),
47613
47822
  ExitCode.ConflictOrDrift,
47614
47823
  "PLAN_CONFLICT"
47615
47824
  );
@@ -47623,8 +47832,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47623
47832
  ...filterTasksByHook2(newAddonResolution.manifest.tasks ?? [], "after:create")
47624
47833
  ];
47625
47834
  if (skippedCreateTasks.length > 0 && !output.json) {
47626
- writeHumanOutput(`- \u5DF2\u8DF3\u8FC7 ${skippedCreateTasks.length} \u4E2A create \u751F\u547D\u5468\u671F\u94A9\u5B50\u4EFB\u52A1\uFF08apply \u8BED\u4E49\u4E0D\u6267\u884C before:create / after:create \u94A9\u5B50\uFF09
47627
- `);
47835
+ writeHumanOutput(t("apply.skippedCreateTasks", skippedCreateTasks.length));
47628
47836
  }
47629
47837
  const beforeApplyTasksForCheck = filterTasksByHook2(newAddonResolution.manifest.tasks ?? [], "before:apply");
47630
47838
  const afterApplyTasksForCheck = filterTasksByHook2(newAddonResolution.manifest.tasks ?? [], "after:apply");
@@ -47642,7 +47850,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47642
47850
  if (existingResolved.version === newAddonResolution.resolvedVersion && existingResolved.integrity && newAddonResolution.integrity) {
47643
47851
  if (existingResolved.integrity !== newAddonResolution.integrity) {
47644
47852
  throw new CliError(
47645
- `\u5305 '${newAddonResolution.packageId}' \u7248\u672C\u76F8\u540C\u4F46\u5185\u5BB9\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u4F7F\u7528 upgrade \u547D\u4EE4\u8FDB\u884C\u66F4\u65B0`,
47853
+ t("apply.templateUpdatedNeedsUpgrade", newAddonResolution.packageId),
47646
47854
  ExitCode.ConflictOrDrift,
47647
47855
  "PACKAGE_UPDATE_REQUIRES_UPGRADE"
47648
47856
  );
@@ -47651,9 +47859,9 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47651
47859
  const hasChanges = planResult.plan.files.length > 0 || planResult.plan.configEntries.length > 0 || planResult.plan.managedSections.length > 0 || planResult.plan.plugins.length > 0 || planResult.plan.userInstallations.length > 0;
47652
47860
  if (sameAssetTypes && !hasChanges) {
47653
47861
  if (output.json) {
47654
- emitSuccessJson("apply", { dryRun: false, message: "\u5DF2\u5E94\u7528\uFF0C\u65E0\u53D8\u5316", lockPath: lockRepo.path }, [], [], jsonEvents());
47862
+ emitSuccessJson("apply", { dryRun: false, message: t("apply.alreadyUpToDate"), lockPath: lockRepo.path }, [], [], jsonEvents());
47655
47863
  } else {
47656
- writeHumanOutput("\u5DF2\u5E94\u7528\uFF0C\u65E0\u53D8\u5316\n");
47864
+ writeHumanOutput(t("apply.alreadyUpToDate") + "\n");
47657
47865
  }
47658
47866
  return ExitCode.Success;
47659
47867
  }
@@ -47758,7 +47966,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47758
47966
  };
47759
47967
  try {
47760
47968
  await runTasksWithDynamicUI([task], taskContext, {
47761
- title: i === 0 ? "\u6B63\u5728\u6267\u884C\u524D\u7F6E\u5E94\u7528\u4EFB\u52A1 (before:apply):" : void 0,
47969
+ title: i === 0 ? t("task.runningBeforeApply", 1, 1, newAddonResolution.packageId) : void 0,
47762
47970
  verbose: options.verbose,
47763
47971
  json: options.json
47764
47972
  });
@@ -47836,7 +48044,7 @@ async function executeApply(packageSpec, options, cliVersion, events) {
47836
48044
  };
47837
48045
  try {
47838
48046
  await runTasksWithDynamicUI([task], taskContext, {
47839
- title: i === 0 ? "\u6B63\u5728\u6267\u884C\u540E\u7F6E\u5E94\u7528\u4EFB\u52A1 (after:apply):" : void 0,
48047
+ title: i === 0 ? t("task.runningAfterApply", 1, 1, newAddonResolution.packageId) : void 0,
47840
48048
  verbose: options.verbose,
47841
48049
  json: options.json
47842
48050
  });
@@ -47910,10 +48118,10 @@ import { randomUUID as randomUUID8 } from "node:crypto";
47910
48118
  import { basename as basename5, dirname as dirname17, resolve as resolve22 } from "node:path";
47911
48119
  function createSyncCommand(cliVersion) {
47912
48120
  const cmd = new Command("sync");
47913
- cmd.description(t("sync.description")).option("--package <packageId>", "\u4EC5\u540C\u6B65\u6307\u5B9A\u7684\u5DF2\u5B89\u88C5\u5305").action(async (opts) => {
48121
+ cmd.description(t("sync.description")).option("--template <templateId>", t("sync.optionTemplate")).action(async (opts) => {
47914
48122
  const options = extractMutationOptions(opts);
47915
- if (typeof opts.package === "string") {
47916
- options.package = opts.package;
48123
+ if (typeof opts.template === "string") {
48124
+ options.template = opts.template;
47917
48125
  }
47918
48126
  const output = {
47919
48127
  json: options.json,
@@ -47958,11 +48166,11 @@ async function executeSync(options, cliVersion, silent = false, events = new Lif
47958
48166
  }
47959
48167
  const locked = await events.measure("resolve", () => resolveLockedPackages(lock, service));
47960
48168
  let allResolutions = [...locked.template ? [locked.template] : [], ...locked.addons];
47961
- if (options.package) {
47962
- allResolutions = allResolutions.filter((r) => r.packageId === options.package);
48169
+ if (options.template) {
48170
+ allResolutions = allResolutions.filter((r) => r.packageId === options.template);
47963
48171
  if (allResolutions.length === 0) {
47964
48172
  throw new CliError(
47965
- `\u672A\u5728 Lock \u6587\u4EF6\u4E2D\u627E\u5230\u5305 '${options.package}'\u3002\u8BE5\u5305\u672A\u5B89\u88C5\u6216\u65E0\u6CD5\u540C\u6B65\u3002`,
48173
+ t("sync.templateNotFound", options.template),
47966
48174
  ExitCode.SchemaInvalid,
47967
48175
  "PACKAGE_NOT_FOUND"
47968
48176
  );
@@ -48311,7 +48519,7 @@ import { unlink as unlink11, readFile as readFile31 } from "node:fs/promises";
48311
48519
  import { basename as basename6, dirname as dirname18, join as join24, resolve as resolve23 } from "node:path";
48312
48520
  function createRemoveCommand(cliVersion) {
48313
48521
  const cmd = new Command("remove");
48314
- cmd.description(t("remove.description")).option("--package <package-id>", t("remove.optionPackage")).action(async (opts) => {
48522
+ cmd.description(t("remove.description")).argument("[template-id]", t("remove.argTemplate")).option("--template <template-id>", t("remove.optionTemplate")).action(async (templateArg, opts) => {
48315
48523
  const options = extractMutationOptions(opts);
48316
48524
  const output = {
48317
48525
  json: options.json,
@@ -48319,8 +48527,8 @@ function createRemoveCommand(cliVersion) {
48319
48527
  noColor: options.noColor
48320
48528
  };
48321
48529
  const events = createEventEmitter("remove", output);
48322
- const packageId = typeof opts.package === "string" ? opts.package : void 0;
48323
- const exitCode = await executeRemove(packageId, options, cliVersion, events).catch(
48530
+ const templateId = (typeof opts.template === "string" ? opts.template : void 0) ?? (typeof templateArg === "string" ? templateArg : void 0);
48531
+ const exitCode = await executeRemove(templateId, options, cliVersion, events).catch(
48324
48532
  (err) => reportCliError(err, "remove", output, options.json && options.verbose ? getRedactedEvents(events) : void 0)
48325
48533
  );
48326
48534
  if (exitCode !== 0) {
@@ -48330,7 +48538,7 @@ function createRemoveCommand(cliVersion) {
48330
48538
  addMutationOptions(cmd);
48331
48539
  return cmd;
48332
48540
  }
48333
- async function executeRemove(packageId, options, cliVersion, events) {
48541
+ async function executeRemove(templateId, options, cliVersion, events) {
48334
48542
  const output = {
48335
48543
  json: options.json,
48336
48544
  verbose: options.verbose,
@@ -48356,47 +48564,56 @@ async function executeRemove(packageId, options, cliVersion, events) {
48356
48564
  "LOCK_NOT_FOUND"
48357
48565
  );
48358
48566
  }
48359
- if (packageId) {
48360
- const allPackages = [
48567
+ if (templateId) {
48568
+ const allTemplates = [
48361
48569
  ...lock.desired?.packages ? lock.desired.packages.map((p2) => p2.id) : [],
48362
48570
  ...lock.resolved?.packages ? lock.resolved.packages.map((p2) => p2.id) : [],
48363
48571
  ...lock.resolved.template ? [lock.resolved.template.id] : [],
48364
48572
  ...lock.resolved.templates ? lock.resolved.templates.map((t2) => t2.id) : [],
48365
48573
  ...lock.resolved.addons ? lock.resolved.addons.map((a) => a.id) : []
48366
48574
  ];
48367
- if (!allPackages.includes(packageId)) {
48368
- if (lock.createdWith?.packages?.some((p2) => p2.packageId === packageId)) {
48575
+ if (!allTemplates.includes(templateId)) {
48576
+ if (lock.createdWith?.packages?.some((p2) => p2.packageId === templateId)) {
48369
48577
  throw new CliError(
48370
- `\u5305 '${packageId}' \u662F\u9879\u76EE\u7684\u521D\u59CB\u5DE5\u7A0B\u6A21\u677F (bootstrap-only)\uFF0C\u4E0D\u5305\u542B\u53D7\u7BA1\u77E5\u8BC6\u8D44\u4EA7\uFF0C\u65E0\u6CD5\u88AB remove\u3002\u82E5\u9700\u5220\u9664\u6574\u4E2A\u9879\u76EE\uFF0C\u8BF7\u76F4\u63A5\u5220\u9664\u9879\u76EE\u76EE\u5F55\u3002`,
48578
+ t("remove.bootstrapTemplateCannotBeRemoved", templateId),
48371
48579
  ExitCode.SchemaInvalid,
48372
48580
  "BOOTSTRAP_PACKAGE_CANNOT_BE_REMOVED"
48373
48581
  );
48374
48582
  }
48375
48583
  throw new CliError(
48376
- t("remove.packageNotInLock", packageId, allPackages.join(", ") || "none"),
48584
+ t("remove.templateNotInLock", templateId, allTemplates.join(", ") || "none"),
48377
48585
  ExitCode.SchemaInvalid,
48378
48586
  "PACKAGE_NOT_IN_LOCK",
48379
- { packageId, available: allPackages }
48587
+ { templateId, available: allTemplates }
48380
48588
  );
48381
48589
  }
48382
48590
  }
48383
48591
  events.report("resolve", "success", Date.now() - resolveStartedAt, {
48384
48592
  details: { packageCount: (lock.resolved.template ? 1 : 0) + (lock.resolved.addons?.length ?? 0) }
48385
48593
  });
48594
+ const ownerMatches = (owner) => !templateId || owner.packageId === templateId;
48595
+ const intents = lock.resources.filter((resource) => resource.owners.every(ownerMatches)).map((resource) => {
48596
+ const targetId = typeof resource.target === "string" ? resource.target : resource.target?.id;
48597
+ const metadata = { target: targetId, packageId: resource.owners[0]?.packageId };
48598
+ if (resource.type === "file" || !resource.type) return { action: "remove", type: "file", path: resource.path, ...metadata };
48599
+ if (resource.type === "managed-section") return { action: "remove", type: "managed-section", path: resource.path, sectionId: resource.sectionId ?? resource.selector ?? "", ...metadata };
48600
+ return { action: "remove", type: "config-entry", path: resource.path, selector: resource.selector ?? "", format: resource.format ?? "json", ...metadata };
48601
+ });
48386
48602
  const planStartedAt = Date.now();
48387
48603
  const planBuilder = service.getPlanBuilder();
48388
48604
  const projectTargets = lock.desired.targets.map((t2) => typeof t2 === "string" ? { id: t2, scope: "project" } : t2);
48389
- const planResult = planBuilder.build(
48605
+ let planResult = planBuilder.build(
48390
48606
  "remove",
48391
48607
  service.projectRoot,
48392
48608
  [],
48393
48609
  projectTargets
48394
48610
  );
48611
+ planResult = materializePlan(planResult.plan, intents);
48395
48612
  events.report("plan", "success", Date.now() - planStartedAt, { planDigest: planResult.plan.planDigest });
48396
48613
  const driftDetector = new DriftDetector({ projectRoot: service.projectRoot, driftMode: options.drift });
48397
48614
  const drift = await driftDetector.detect(lock);
48398
48615
  if (driftDetector.shouldAbort(drift)) {
48399
- throw new CliError(`\u68C0\u6D4B\u5230 ${drift.length} \u9879\u8D44\u6E90\u6F02\u79FB\uFF1B\u5982\u786E\u8BA4\u5220\u9664\u5DF2\u4FEE\u6539\u5185\u5BB9\uFF0C\u8BF7\u4F7F\u7528 --drift accept`, ExitCode.ConflictOrDrift, "RESOURCE_DRIFT", { drift });
48616
+ throw new CliError(t("remove.driftDetected", drift.length), ExitCode.ConflictOrDrift, "RESOURCE_DRIFT", { drift });
48400
48617
  }
48401
48618
  if (!options.dryRun && !options.yes) {
48402
48619
  if (options.noInput || !process.stdin.isTTY) {
@@ -48455,23 +48672,15 @@ async function executeRemove(packageId, options, cliVersion, events) {
48455
48672
  }
48456
48673
  return ExitCode.Success;
48457
48674
  }
48458
- const ownerMatches = (owner) => !packageId || owner.packageId === packageId;
48459
- const intents = lock.resources.filter((resource) => resource.owners.every(ownerMatches)).map((resource) => {
48460
- const targetId = typeof resource.target === "string" ? resource.target : resource.target?.id;
48461
- const metadata = { target: targetId, packageId: resource.owners[0]?.packageId };
48462
- if (resource.type === "file" || !resource.type) return { action: "remove", type: "file", path: resource.path, ...metadata };
48463
- if (resource.type === "managed-section") return { action: "remove", type: "managed-section", path: resource.path, sectionId: resource.sectionId ?? resource.selector ?? "", ...metadata };
48464
- return { action: "remove", type: "config-entry", path: resource.path, selector: resource.selector ?? "", format: resource.format ?? "json", ...metadata };
48465
- });
48466
- const packagesToRemove = packageId ? [packageId] : [
48675
+ const templatesToRemove = templateId ? [templateId] : [
48467
48676
  ...lock.desired?.packages ? lock.desired.packages.map((p2) => p2.id) : [],
48468
48677
  ...lock.resolved?.packages ? lock.resolved.packages.map((p2) => p2.id) : [],
48469
48678
  ...lock.resolved.template ? [lock.resolved.template.id] : [],
48470
48679
  ...lock.resolved.addons ? lock.resolved.addons.map((a) => a.id) : []
48471
48680
  ];
48472
- const uniquePackagesToRemove = [...new Set(packagesToRemove)];
48473
- const packageManifests = [];
48474
- for (const pkg of uniquePackagesToRemove) {
48681
+ const uniqueTemplatesToRemove = [...new Set(templatesToRemove)];
48682
+ const templateManifests = [];
48683
+ for (const pkg of uniqueTemplatesToRemove) {
48475
48684
  const resolved = lock.resolved?.packages?.find((p2) => p2.id === pkg) ?? (lock.resolved?.template?.id === pkg ? lock.resolved.template : void 0);
48476
48685
  const desired = lock.desired?.packages?.find((p2) => p2.id === pkg) ?? (lock.desired?.template?.id === pkg ? lock.desired.template : void 0);
48477
48686
  let templateDir;
@@ -48488,8 +48697,8 @@ async function executeRemove(packageId, options, cliVersion, events) {
48488
48697
  const manifestContent = await readFile31(join24(templateDir, "manifest.yaml"), "utf-8");
48489
48698
  const parsed = parseManifest(manifestContent);
48490
48699
  if (parsed.manifest) {
48491
- packageManifests.push({
48492
- packageId: pkg,
48700
+ templateManifests.push({
48701
+ templateId: pkg,
48493
48702
  manifest: parsed.manifest,
48494
48703
  templateDir,
48495
48704
  inputs: Object.fromEntries(Object.entries(desired?.inputs ?? {}).map(([k2, v2]) => [k2, String(v2)]))
@@ -48498,8 +48707,8 @@ async function executeRemove(packageId, options, cliVersion, events) {
48498
48707
  } catch {
48499
48708
  }
48500
48709
  }
48501
- for (let pkgIdx = 0; pkgIdx < packageManifests.length; pkgIdx++) {
48502
- const item = packageManifests[pkgIdx];
48710
+ for (let pkgIdx = 0; pkgIdx < templateManifests.length; pkgIdx++) {
48711
+ const item = templateManifests[pkgIdx];
48503
48712
  const pkgTasks = filterTasksByHook(item.manifest.tasks ?? [], "before:remove");
48504
48713
  if (pkgTasks.length > 0) {
48505
48714
  const taskContext = {
@@ -48513,7 +48722,7 @@ async function executeRemove(packageId, options, cliVersion, events) {
48513
48722
  operation: "remove",
48514
48723
  version: item.manifest.version
48515
48724
  };
48516
- const title = `\u6B63\u5728\u6267\u884C\u524D\u7F6E\u79FB\u9664\u4EFB\u52A1 (before:remove) [${pkgIdx + 1}/${packageManifests.length}] (${item.packageId}):`;
48725
+ const title = t("task.runningBeforeRemove", pkgIdx + 1, templateManifests.length, item.templateId);
48517
48726
  try {
48518
48727
  await runTasksWithDynamicUI(pkgTasks, taskContext, {
48519
48728
  title,
@@ -48544,36 +48753,36 @@ async function executeRemove(packageId, options, cliVersion, events) {
48544
48753
  }
48545
48754
  events.report("execute", "success", Date.now() - executeStartedAt, { planDigest: planResult.plan.planDigest, details: { intentCount: intents.length } });
48546
48755
  const remainingLock = structuredClone(lock);
48547
- if (packageId) {
48548
- if (remainingLock.desired.packages) remainingLock.desired.packages = remainingLock.desired.packages.filter((item) => item.id !== packageId);
48549
- if (remainingLock.resolved.packages) remainingLock.resolved.packages = remainingLock.resolved.packages.filter((item) => item.id !== packageId);
48550
- if (remainingLock.desired.template?.id === packageId) delete remainingLock.desired.template;
48551
- if (remainingLock.resolved.template?.id === packageId) delete remainingLock.resolved.template;
48552
- if (remainingLock.desired.templates) remainingLock.desired.templates = remainingLock.desired.templates.filter((item) => item.id !== packageId);
48553
- if (remainingLock.resolved.templates) remainingLock.resolved.templates = remainingLock.resolved.templates.filter((item) => item.id !== packageId);
48554
- if (remainingLock.desired.addons) remainingLock.desired.addons = remainingLock.desired.addons.filter((item) => item.id !== packageId);
48555
- if (remainingLock.resolved.addons) remainingLock.resolved.addons = remainingLock.resolved.addons.filter((item) => item.id !== packageId);
48556
- if (remainingLock.desired.capabilities) remainingLock.desired.capabilities = remainingLock.desired.capabilities.filter((item) => item.packageId !== packageId);
48557
- if (remainingLock.resolved.projects) remainingLock.resolved.projects = remainingLock.resolved.projects.filter((item) => item.packageId !== packageId);
48558
- if (remainingLock.resolved.capabilities) remainingLock.resolved.capabilities = remainingLock.resolved.capabilities.filter((item) => item.packageId !== packageId);
48559
- if (remainingLock.resolved.plugins) remainingLock.resolved.plugins = remainingLock.resolved.plugins.filter((item) => item.packageId !== packageId);
48560
- remainingLock.resources = remainingLock.resources.map((resource) => ({ ...resource, owners: resource.owners.filter((owner) => owner.packageId !== packageId) })).filter((resource) => resource.owners.length > 0);
48756
+ if (templateId) {
48757
+ if (remainingLock.desired.packages) remainingLock.desired.packages = remainingLock.desired.packages.filter((item) => item.id !== templateId);
48758
+ if (remainingLock.resolved.packages) remainingLock.resolved.packages = remainingLock.resolved.packages.filter((item) => item.id !== templateId);
48759
+ if (remainingLock.desired.template?.id === templateId) delete remainingLock.desired.template;
48760
+ if (remainingLock.resolved.template?.id === templateId) delete remainingLock.resolved.template;
48761
+ if (remainingLock.desired.templates) remainingLock.desired.templates = remainingLock.desired.templates.filter((item) => item.id !== templateId);
48762
+ if (remainingLock.resolved.templates) remainingLock.resolved.templates = remainingLock.resolved.templates.filter((item) => item.id !== templateId);
48763
+ if (remainingLock.desired.addons) remainingLock.desired.addons = remainingLock.desired.addons.filter((item) => item.id !== templateId);
48764
+ if (remainingLock.resolved.addons) remainingLock.resolved.addons = remainingLock.resolved.addons.filter((item) => item.id !== templateId);
48765
+ if (remainingLock.desired.capabilities) remainingLock.desired.capabilities = remainingLock.desired.capabilities.filter((item) => item.packageId !== templateId);
48766
+ if (remainingLock.resolved.projects) remainingLock.resolved.projects = remainingLock.resolved.projects.filter((item) => item.packageId !== templateId);
48767
+ if (remainingLock.resolved.capabilities) remainingLock.resolved.capabilities = remainingLock.resolved.capabilities.filter((item) => item.packageId !== templateId);
48768
+ if (remainingLock.resolved.plugins) remainingLock.resolved.plugins = remainingLock.resolved.plugins.filter((item) => item.packageId !== templateId);
48769
+ remainingLock.resources = remainingLock.resources.map((resource) => ({ ...resource, owners: resource.owners.filter((owner) => owner.packageId !== templateId) })).filter((resource) => resource.owners.length > 0);
48561
48770
  }
48562
48771
  const hasPackages = (remainingLock.resolved.packages?.length ?? 0) > 0 || Boolean(remainingLock.resolved.template) || (remainingLock.resolved.templates?.length ?? 0) > 0 || (remainingLock.resolved.addons?.length ?? 0) > 0;
48563
48772
  const recordStartedAt = Date.now();
48564
48773
  await commitExecution(executor, executeResult, async (addRollback) => {
48565
- if (packageId && hasPackages) await lockRepo.write(remainingLock);
48774
+ if (templateId && hasPackages) await lockRepo.write(remainingLock);
48566
48775
  else await unlink11(lockRepo.path).catch((error) => {
48567
48776
  if (error.code !== "ENOENT") throw error;
48568
48777
  });
48569
48778
  addRollback(() => lockRepo.write(lock));
48570
48779
  await prepareUserDataRecovery(journal, service.getUserDataDir(), ["installations.json"]);
48571
- await removeUserReferences(lock, packageId, service, output);
48780
+ await removeUserReferences(lock, templateId, service, output);
48572
48781
  await finishJournal(journal);
48573
48782
  });
48574
48783
  events.report("record", "success", Date.now() - recordStartedAt, { planDigest: planResult.plan.planDigest });
48575
- for (let pkgIdx = 0; pkgIdx < packageManifests.length; pkgIdx++) {
48576
- const item = packageManifests[pkgIdx];
48784
+ for (let pkgIdx = 0; pkgIdx < templateManifests.length; pkgIdx++) {
48785
+ const item = templateManifests[pkgIdx];
48577
48786
  const pkgTasks = filterTasksByHook(item.manifest.tasks ?? [], "after:remove");
48578
48787
  if (pkgTasks.length > 0) {
48579
48788
  const taskContext = {
@@ -48587,7 +48796,7 @@ async function executeRemove(packageId, options, cliVersion, events) {
48587
48796
  operation: "remove",
48588
48797
  version: item.manifest.version
48589
48798
  };
48590
- const title = `\u6B63\u5728\u6267\u884C\u540E\u7F6E\u79FB\u9664\u4EFB\u52A1 (after:remove) [${pkgIdx + 1}/${packageManifests.length}] (${item.packageId}):`;
48799
+ const title = t("task.runningAfterRemove", pkgIdx + 1, templateManifests.length, item.templateId);
48591
48800
  try {
48592
48801
  await runTasksWithDynamicUI(pkgTasks, taskContext, {
48593
48802
  title,
@@ -48607,18 +48816,18 @@ async function executeRemove(packageId, options, cliVersion, events) {
48607
48816
  emitSuccessJson("remove", {
48608
48817
  dryRun: false,
48609
48818
  ...summary,
48610
- removedLock: !packageId || !hasPackages,
48611
- packageId: packageId ?? "*"
48819
+ removedLock: !templateId || !hasPackages,
48820
+ templateId: templateId ?? "*"
48612
48821
  }, [], [], jsonEvents());
48613
48822
  } else {
48614
48823
  printPlanSummary(summary);
48615
- writeHumanOutput(t("remove.removed", packageId ?? t("remove.allPackages"), service.projectRoot) + "\n");
48616
- writeHumanOutput(t(!packageId || !hasPackages ? "remove.lockRemoved" : "remove.lockUpdated") + "\n");
48824
+ writeHumanOutput(t("remove.removed", templateId ?? t("remove.allTemplates"), service.projectRoot) + "\n");
48825
+ writeHumanOutput(t(!templateId || !hasPackages ? "remove.lockRemoved" : "remove.lockUpdated") + "\n");
48617
48826
  }
48618
48827
  return ExitCode.Success;
48619
48828
  });
48620
48829
  }
48621
- async function removeUserReferences(originalLock, packageId, service, output) {
48830
+ async function removeUserReferences(originalLock, templateId, service, output) {
48622
48831
  const installationsRepo = service.getInstallationsRepository();
48623
48832
  const lockRec = originalLock;
48624
48833
  const resolved = lockRec["resolved"];
@@ -48637,10 +48846,10 @@ async function removeUserReferences(originalLock, packageId, service, output) {
48637
48846
  }
48638
48847
  }
48639
48848
  }
48640
- if (packageId) {
48849
+ if (templateId) {
48641
48850
  capabilities = capabilities.filter((cap) => {
48642
48851
  const capPkgId = cap["packageId"];
48643
- return capPkgId === packageId;
48852
+ return capPkgId === templateId;
48644
48853
  });
48645
48854
  }
48646
48855
  const warnings = [];
@@ -49609,7 +49818,7 @@ import { createHash as createHash17, randomUUID as randomUUID10 } from "node:cry
49609
49818
  import { basename as basename7, dirname as dirname19 } from "node:path";
49610
49819
  function createUpgradeCommand(cliVersion) {
49611
49820
  const cmd = new Command("upgrade");
49612
- cmd.description(t("upgrade.description")).option("--project <path>", t("upgrade.optionProject"), process.cwd()).option("--package <package-id>", t("upgrade.optionPackage")).option("--capability <id>", t("upgrade.optionCapability")).option("--version <version>", t("upgrade.optionVersion")).option("--dry-run", t("upgrade.optionDryRun")).option("--yes, -y", t("upgrade.optionYes")).option("--allow <permission>", t("upgrade.optionAllow"), collectPermission, []).action(async (opts) => {
49821
+ cmd.description(t("upgrade.description")).option("--project <path>", t("upgrade.optionProject"), process.cwd()).option("--template <template-id>", t("upgrade.optionTemplate")).option("--capability <id>", t("upgrade.optionCapability")).option("--version <version>", t("upgrade.optionVersion")).option("--dry-run", t("upgrade.optionDryRun")).option("--yes, -y", t("upgrade.optionYes")).option("--allow <permission>", t("upgrade.optionAllow"), collectPermission, []).action(async (opts) => {
49613
49822
  const globalOpts = extractGlobalOptions(opts);
49614
49823
  const output = {
49615
49824
  json: globalOpts.json,
@@ -49628,7 +49837,7 @@ function createUpgradeCommand(cliVersion) {
49628
49837
  }
49629
49838
  async function executeUpgrade(opts, cliVersion) {
49630
49839
  const projectRoot = typeof opts.project === "string" ? opts.project : process.cwd();
49631
- const packageId = typeof opts.package === "string" ? opts.package : void 0;
49840
+ const templateId = typeof opts.template === "string" ? opts.template : void 0;
49632
49841
  const targetVersion = typeof opts.version === "string" ? opts.version : void 0;
49633
49842
  const dryRun = Boolean(opts.dryRun);
49634
49843
  const yes = Boolean(opts.yes);
@@ -49657,7 +49866,7 @@ async function executeUpgrade(opts, cliVersion) {
49657
49866
  { resources: drift.map((item) => ({ type: item.type, path: item.path })) }
49658
49867
  );
49659
49868
  }
49660
- let targetPackageId = packageId;
49869
+ let targetPackageId = templateId;
49661
49870
  const desiredPackages = lock.desired?.packages ?? [];
49662
49871
  if (!targetPackageId) {
49663
49872
  if (desiredPackages.length === 1) {
@@ -49666,9 +49875,9 @@ async function executeUpgrade(opts, cliVersion) {
49666
49875
  targetPackageId = lock.desired.template.id;
49667
49876
  } else {
49668
49877
  throw new CliError(
49669
- "\u8BF7\u901A\u8FC7 --package <package-id> \u6307\u5B9A\u9700\u8981\u5347\u7EA7\u7684\u5305\u3002",
49878
+ t("upgrade.missingTemplate"),
49670
49879
  ExitCode.SchemaInvalid,
49671
- "MISSING_OPTIONS"
49880
+ "PACKAGE_SPEC_REQUIRED"
49672
49881
  );
49673
49882
  }
49674
49883
  }
@@ -49753,12 +49962,7 @@ async function executeUpgrade(opts, cliVersion) {
49753
49962
  if (json) {
49754
49963
  emitSuccessJson("upgrade", { dryRun: true, ...plan });
49755
49964
  } else {
49756
- writeHumanOutput(`\u5347\u7EA7\u8BA1\u5212\uFF1A
49757
- \u5305\uFF1A${targetPackageId}
49758
- \u5F53\u524D\uFF1A${oldVersion}
49759
- \u76EE\u6807\uFF1A${templateResolution.resolvedVersion}
49760
- \u9879\u76EE\uFF1A${projectRoot}
49761
- `);
49965
+ writeHumanOutput(t("upgrade.planSummary", targetPackageId, oldVersion, templateResolution.resolvedVersion, projectRoot));
49762
49966
  }
49763
49967
  return ExitCode.Success;
49764
49968
  }
@@ -49798,7 +50002,7 @@ async function executeUpgrade(opts, cliVersion) {
49798
50002
  previousVersion: oldVersion,
49799
50003
  version: templateResolution.resolvedVersion
49800
50004
  };
49801
- const title = `\u6B63\u5728\u6267\u884C\u524D\u7F6E\u5347\u7EA7\u4EFB\u52A1 (before:upgrade) (${targetPackageId}):`;
50005
+ const title = t("task.runningBeforeUpgrade", targetPackageId);
49802
50006
  try {
49803
50007
  await runTasksWithDynamicUI(beforeTasks, taskContext, {
49804
50008
  title,
@@ -49854,7 +50058,7 @@ async function executeUpgrade(opts, cliVersion) {
49854
50058
  previousVersion: oldVersion,
49855
50059
  version: templateResolution.resolvedVersion
49856
50060
  };
49857
- const title = `\u6B63\u5728\u6267\u884C\u540E\u7F6E\u5347\u7EA7\u4EFB\u52A1 (after:upgrade) (${targetPackageId}):`;
50061
+ const title = t("task.runningAfterUpgrade", targetPackageId);
49858
50062
  try {
49859
50063
  await runTasksWithDynamicUI(afterTasks, taskContext, {
49860
50064
  title,
@@ -50267,11 +50471,12 @@ import { homedir as homedir4 } from "node:os";
50267
50471
  import { join as join26 } from "node:path";
50268
50472
  function createLaunchCommand() {
50269
50473
  const cmd = new Command("_launch");
50270
- cmd.description(t("launch.description")).option("--kind <kind>", t("launch.optionKind")).option("--package <package-id>", t("launch.optionPackage")).option("--id <id>", t("launch.optionId")).option("--version <version>", t("launch.optionVersion")).option("--command <name>", t("launch.optionCommand")).allowUnknownOption(true).allowExcessArguments(true).action(async (_opts, command) => {
50474
+ cmd.description(t("launch.description")).option("--kind <kind>", t("launch.optionKind")).option("--template <template-id>", t("launch.optionTemplate")).option("--id <id>", t("launch.optionId")).option("--version <version>", t("launch.optionVersion")).option("--command <name>", t("launch.optionCommand")).allowUnknownOption(true).allowExcessArguments(true).action(async (_opts, command) => {
50271
50475
  const opts = command.opts();
50272
50476
  const launcherArgs = [];
50273
50477
  if (opts.kind) launcherArgs.push("--kind", opts.kind);
50274
- if (opts.package) launcherArgs.push("--package", opts.package);
50478
+ const pkgOrTemplate = opts.template ?? opts.package;
50479
+ if (pkgOrTemplate) launcherArgs.push("--package", pkgOrTemplate);
50275
50480
  if (opts.id) launcherArgs.push("--id", opts.id);
50276
50481
  if (opts.version) launcherArgs.push("--version", opts.version);
50277
50482
  if (opts.command) launcherArgs.push("--command", opts.command);
@@ -50708,7 +50913,7 @@ import { createRequire as createRequire2 } from "node:module";
50708
50913
  import { readFileSync as readFileSync4 } from "node:fs";
50709
50914
  import { fileURLToPath as fileURLToPath5 } from "node:url";
50710
50915
  function resolveVersion() {
50711
- if (true) return "0.1.33";
50916
+ if (true) return "0.1.34";
50712
50917
  const candidates = [
50713
50918
  new URL("../package.json", import.meta.url),
50714
50919
  new URL("../../package.json", import.meta.url),