@zmice/zc 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +201 -55
- package/dist/cli/__tests__/platform.test.js +573 -34
- package/dist/cli/__tests__/platform.test.js.map +1 -1
- package/dist/cli/__tests__/toolkit.test.js +35 -0
- package/dist/cli/__tests__/toolkit.test.js.map +1 -1
- package/dist/cli/platform.d.ts +15 -1
- package/dist/cli/platform.d.ts.map +1 -1
- package/dist/cli/platform.js +1195 -87
- package/dist/cli/platform.js.map +1 -1
- package/dist/cli/toolkit.d.ts.map +1 -1
- package/dist/cli/toolkit.js +26 -1
- package/dist/cli/toolkit.js.map +1 -1
- package/dist/platform-state/doctor.d.ts +3 -0
- package/dist/platform-state/doctor.d.ts.map +1 -0
- package/dist/platform-state/doctor.js +96 -0
- package/dist/platform-state/doctor.js.map +1 -0
- package/dist/platform-state/index.d.ts +2 -1
- package/dist/platform-state/index.d.ts.map +1 -1
- package/dist/platform-state/index.js +1 -0
- package/dist/platform-state/index.js.map +1 -1
- package/dist/platform-state/receipt.d.ts +5 -0
- package/dist/platform-state/receipt.d.ts.map +1 -1
- package/dist/platform-state/receipt.js +5 -0
- package/dist/platform-state/receipt.js.map +1 -1
- package/dist/platform-state/types.d.ts +16 -0
- package/dist/platform-state/types.d.ts.map +1 -1
- package/dist/utils/install-target.d.ts +1 -1
- package/dist/utils/install-target.d.ts.map +1 -1
- package/dist/utils/install-target.js +16 -6
- package/dist/utils/install-target.js.map +1 -1
- package/dist/utils/install-target.test.js +19 -10
- package/dist/utils/install-target.test.js.map +1 -1
- package/dist/utils/platform-install-cleanup.d.ts +7 -0
- package/dist/utils/platform-install-cleanup.d.ts.map +1 -0
- package/dist/utils/platform-install-cleanup.js +34 -0
- package/dist/utils/platform-install-cleanup.js.map +1 -0
- package/dist/utils/platform-install-cleanup.test.d.ts +2 -0
- package/dist/utils/platform-install-cleanup.test.d.ts.map +1 -0
- package/dist/utils/platform-install-cleanup.test.js +30 -0
- package/dist/utils/platform-install-cleanup.test.js.map +1 -0
- package/dist/utils/platform-install-receipt.d.ts +1 -0
- package/dist/utils/platform-install-receipt.d.ts.map +1 -1
- package/dist/utils/platform-install-receipt.js +10 -2
- package/dist/utils/platform-install-receipt.js.map +1 -1
- package/dist/utils/platform-install-receipt.test.js +30 -2
- package/dist/utils/platform-install-receipt.test.js.map +1 -1
- package/dist/utils/qwen-extension-cli.d.ts +52 -0
- package/dist/utils/qwen-extension-cli.d.ts.map +1 -0
- package/dist/utils/qwen-extension-cli.js +169 -0
- package/dist/utils/qwen-extension-cli.js.map +1 -0
- package/dist/utils/qwen-extension-cli.test.d.ts +2 -0
- package/dist/utils/qwen-extension-cli.test.d.ts.map +1 -0
- package/dist/utils/qwen-extension-cli.test.js +100 -0
- package/dist/utils/qwen-extension-cli.test.js.map +1 -0
- package/package.json +5 -4
- package/vendor/node_modules/@zmice/platform-core/dist/index.d.ts +54 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.d.ts.map +1 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.js +53 -0
- package/vendor/node_modules/@zmice/platform-core/dist/index.js.map +1 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.test.js +1 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.test.js.map +1 -1
- package/vendor/node_modules/@zmice/platform-core/package.json +1 -1
- package/vendor/packages/platform-claude/dist/generate.d.ts +2 -0
- package/vendor/packages/platform-claude/dist/generate.d.ts.map +1 -0
- package/vendor/packages/platform-claude/dist/generate.js +2 -0
- package/vendor/packages/platform-claude/dist/generate.js.map +1 -0
- package/vendor/packages/platform-claude/dist/index.d.ts +50 -0
- package/vendor/packages/platform-claude/dist/index.d.ts.map +1 -0
- package/vendor/packages/platform-claude/dist/index.js +250 -0
- package/vendor/packages/platform-claude/dist/index.js.map +1 -0
- package/vendor/packages/platform-claude/dist/index.test.js +81 -0
- package/vendor/packages/platform-claude/dist/index.test.js.map +1 -0
- package/vendor/packages/platform-claude/dist/install.d.ts +2 -0
- package/vendor/packages/platform-claude/dist/install.d.ts.map +1 -0
- package/vendor/packages/platform-claude/dist/install.js +2 -0
- package/vendor/packages/platform-claude/dist/install.js.map +1 -0
- package/vendor/packages/platform-claude/package.json +46 -0
- package/vendor/packages/platform-claude/templates/.gitkeep +1 -0
- package/vendor/packages/platform-claude/templates/CLAUDE.md +1 -0
- package/vendor/packages/platform-codex/dist/index.d.ts +36 -2
- package/vendor/packages/platform-codex/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-codex/dist/index.js +231 -6
- package/vendor/packages/platform-codex/dist/index.js.map +1 -1
- package/vendor/packages/platform-codex/dist/index.test.js +40 -10
- package/vendor/packages/platform-codex/dist/index.test.js.map +1 -1
- package/vendor/packages/platform-opencode/dist/generate.d.ts +2 -0
- package/vendor/packages/platform-opencode/dist/generate.d.ts.map +1 -0
- package/vendor/packages/platform-opencode/dist/generate.js +2 -0
- package/vendor/packages/platform-opencode/dist/generate.js.map +1 -0
- package/vendor/packages/platform-opencode/dist/index.d.ts +46 -0
- package/vendor/packages/platform-opencode/dist/index.d.ts.map +1 -0
- package/vendor/packages/platform-opencode/dist/index.js +308 -0
- package/vendor/packages/platform-opencode/dist/index.js.map +1 -0
- package/vendor/packages/platform-opencode/dist/index.test.d.ts +2 -0
- package/vendor/packages/platform-opencode/dist/index.test.d.ts.map +1 -0
- package/vendor/packages/platform-opencode/dist/index.test.js +106 -0
- package/vendor/packages/platform-opencode/dist/index.test.js.map +1 -0
- package/vendor/packages/platform-opencode/dist/install.d.ts +2 -0
- package/vendor/packages/platform-opencode/dist/install.d.ts.map +1 -0
- package/vendor/packages/platform-opencode/dist/install.js +2 -0
- package/vendor/packages/platform-opencode/dist/install.js.map +1 -0
- package/vendor/packages/{platform-qoder → platform-opencode}/package.json +2 -2
- package/vendor/packages/platform-opencode/templates/AGENTS.md +1 -0
- package/vendor/packages/platform-qwen/dist/index.d.ts +55 -2
- package/vendor/packages/platform-qwen/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-qwen/dist/index.js +229 -11
- package/vendor/packages/platform-qwen/dist/index.js.map +1 -1
- package/vendor/packages/platform-qwen/dist/index.test.js +54 -16
- package/vendor/packages/platform-qwen/dist/index.test.js.map +1 -1
- package/vendor/packages/toolkit/dist/loaders.test.js +1 -1
- package/vendor/packages/toolkit/dist/loaders.test.js.map +1 -1
- package/vendor/packages/toolkit/dist/manifests.test.js +29 -2
- package/vendor/packages/toolkit/dist/manifests.test.js.map +1 -1
- package/vendor/packages/toolkit/dist/query/toolkit-query.d.ts +4 -6
- package/vendor/packages/toolkit/dist/query/toolkit-query.d.ts.map +1 -1
- package/vendor/packages/toolkit/dist/query/toolkit-query.js +99 -1
- package/vendor/packages/toolkit/dist/query/toolkit-query.js.map +1 -1
- package/vendor/packages/toolkit/dist/query.test.js +209 -0
- package/vendor/packages/toolkit/dist/query.test.js.map +1 -1
- package/vendor/packages/toolkit/dist/schema/asset-meta.d.ts.map +1 -1
- package/vendor/packages/toolkit/dist/schema/asset-meta.js +105 -1
- package/vendor/packages/toolkit/dist/schema/asset-meta.js.map +1 -1
- package/vendor/packages/toolkit/dist/types.d.ts +41 -1
- package/vendor/packages/toolkit/dist/types.d.ts.map +1 -1
- package/vendor/packages/toolkit/dist/types.js +26 -1
- package/vendor/packages/toolkit/dist/types.js.map +1 -1
- package/vendor/packages/toolkit/package.json +1 -1
- package/vendor/packages/toolkit/src/content/agents/architect/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/backend-specialist/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/code-reviewer/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/frontend-specialist/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/performance-engineer/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/product-owner/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/security-auditor/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/agents/test-engineer/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/api/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/build/body.md +15 -20
- package/vendor/packages/toolkit/src/content/commands/build/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/careful/body.md +21 -11
- package/vendor/packages/toolkit/src/content/commands/careful/meta.yaml +16 -1
- package/vendor/packages/toolkit/src/content/commands/ci/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/commit/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/ctx-health/body.md +16 -16
- package/vendor/packages/toolkit/src/content/commands/ctx-health/meta.yaml +11 -1
- package/vendor/packages/toolkit/src/content/commands/debug/body.md +16 -17
- package/vendor/packages/toolkit/src/content/commands/debug/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/doc/body.md +15 -16
- package/vendor/packages/toolkit/src/content/commands/doc/meta.yaml +11 -1
- package/vendor/packages/toolkit/src/content/commands/freeze/body.md +20 -9
- package/vendor/packages/toolkit/src/content/commands/freeze/meta.yaml +16 -1
- package/vendor/packages/toolkit/src/content/commands/guard/body.md +21 -10
- package/vendor/packages/toolkit/src/content/commands/guard/meta.yaml +16 -1
- package/vendor/packages/toolkit/src/content/commands/idea/body.md +15 -16
- package/vendor/packages/toolkit/src/content/commands/idea/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/learn/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/migrate/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/onboard/body.md +15 -17
- package/vendor/packages/toolkit/src/content/commands/onboard/meta.yaml +11 -1
- package/vendor/packages/toolkit/src/content/commands/perf/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/plan-review/body.md +21 -20
- package/vendor/packages/toolkit/src/content/commands/plan-review/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/product-analysis/body.md +52 -0
- package/vendor/packages/toolkit/src/content/commands/product-analysis/meta.yaml +35 -0
- package/vendor/packages/toolkit/src/content/commands/qa/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/quality-review/body.md +13 -18
- package/vendor/packages/toolkit/src/content/commands/quality-review/meta.yaml +13 -1
- package/vendor/packages/toolkit/src/content/commands/retro/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/sdd-tdd/body.md +29 -29
- package/vendor/packages/toolkit/src/content/commands/sdd-tdd/meta.yaml +11 -1
- package/vendor/packages/toolkit/src/content/commands/secure/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/ship/body.md +16 -11
- package/vendor/packages/toolkit/src/content/commands/ship/meta.yaml +11 -1
- package/vendor/packages/toolkit/src/content/commands/simplify/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/spec/body.md +16 -21
- package/vendor/packages/toolkit/src/content/commands/spec/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/start/body.md +148 -0
- package/vendor/packages/toolkit/src/content/commands/start/meta.yaml +55 -0
- package/vendor/packages/toolkit/src/content/commands/task-plan/body.md +13 -18
- package/vendor/packages/toolkit/src/content/commands/task-plan/meta.yaml +12 -1
- package/vendor/packages/toolkit/src/content/commands/ui/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/commands/verify/body.md +12 -17
- package/vendor/packages/toolkit/src/content/commands/verify/meta.yaml +15 -1
- package/vendor/packages/toolkit/src/content/skills/api-and-interface-design/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/brainstorming-and-design/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/branch-finish-and-cleanup/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/browser-qa-testing/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/ci-cd-and-automation/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/code-review-and-quality/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/code-simplification/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/codebase-onboarding/body.md +6 -3
- package/vendor/packages/toolkit/src/content/skills/codebase-onboarding/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/context-budget-audit/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/context-engineering/body.md +7 -5
- package/vendor/packages/toolkit/src/content/skills/context-engineering/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/continuous-learning/body.md +15 -15
- package/vendor/packages/toolkit/src/content/skills/continuous-learning/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/debugging-and-error-recovery/body.md +9 -6
- package/vendor/packages/toolkit/src/content/skills/debugging-and-error-recovery/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/deprecation-and-migration/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/developer-experience-audit/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/documentation-and-adrs/body.md +7 -11
- package/vendor/packages/toolkit/src/content/skills/documentation-and-adrs/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/engineering-principles/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/frontend-ui-engineering/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/git-workflow-and-versioning/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/idea-refine/body.md +31 -160
- package/vendor/packages/toolkit/src/content/skills/idea-refine/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/incremental-implementation/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/multi-perspective-review/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/parallel-agent-dispatch/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/performance-optimization/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/planning-and-task-breakdown/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/release-documentation-sync/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/review-response-and-resolution/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/safety-guardrails/body.md +6 -2
- package/vendor/packages/toolkit/src/content/skills/safety-guardrails/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/sdd-tdd-workflow/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/security-and-hardening/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/shipping-and-launch/body.md +7 -11
- package/vendor/packages/toolkit/src/content/skills/shipping-and-launch/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/source-driven-development/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/spec-driven-development/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/sprint-retrospective/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/subagent-driven-development/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/team-orchestration/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/test-driven-development/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/using-agent-skills/meta.yaml +2 -1
- package/vendor/packages/toolkit/src/content/skills/verification-before-completion/meta.yaml +2 -1
- package/vendor/packages/platform-qoder/dist/generate.d.ts +0 -2
- package/vendor/packages/platform-qoder/dist/generate.d.ts.map +0 -1
- package/vendor/packages/platform-qoder/dist/generate.js +0 -2
- package/vendor/packages/platform-qoder/dist/generate.js.map +0 -1
- package/vendor/packages/platform-qoder/dist/index.d.ts +0 -15
- package/vendor/packages/platform-qoder/dist/index.d.ts.map +0 -1
- package/vendor/packages/platform-qoder/dist/index.js +0 -46
- package/vendor/packages/platform-qoder/dist/index.js.map +0 -1
- package/vendor/packages/platform-qoder/dist/index.test.js +0 -38
- package/vendor/packages/platform-qoder/dist/index.test.js.map +0 -1
- package/vendor/packages/platform-qoder/dist/install.d.ts +0 -2
- package/vendor/packages/platform-qoder/dist/install.d.ts.map +0 -1
- package/vendor/packages/platform-qoder/dist/install.js +0 -2
- package/vendor/packages/platform-qoder/dist/install.js.map +0 -1
- package/vendor/packages/platform-qoder/templates/instructions.md +0 -7
- /package/vendor/packages/{platform-qoder → platform-claude}/dist/index.test.d.ts +0 -0
- /package/vendor/packages/{platform-qoder → platform-claude}/dist/index.test.d.ts.map +0 -0
package/dist/cli/platform.js
CHANGED
|
@@ -2,12 +2,110 @@ import { InvalidArgumentError } from "commander";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { attachPlanMetadata } from "@zmice/platform-core";
|
|
5
|
+
import { resolvePlatformInstallDoctor } from "../platform-state/doctor.js";
|
|
5
6
|
import { resolvePlatformInstallStatus } from "../platform-state/status.js";
|
|
6
7
|
import { normalizeInstallSelector, resolveInstallTarget } from "../utils/install-target.js";
|
|
7
|
-
import { resolvePlatformInstallReceiptPath, writePlatformInstallReceiptForPlan, } from "../utils/platform-install-receipt.js";
|
|
8
|
+
import { deletePlatformInstallReceipt, resolvePlatformInstallReceiptPath, writePlatformInstallReceiptForPlan, } from "../utils/platform-install-receipt.js";
|
|
9
|
+
import { pathExists, removeManagedPaths } from "../utils/platform-install-cleanup.js";
|
|
8
10
|
import { ArtifactConflictError, importWorkspaceDistModule, resolveWorkspacePath, writeArtifacts, } from "../utils/workspace.js";
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
+
import { QwenOfficialCliUnavailableError, installQwenExtensionFromOfficialRepoWithCli, installQwenExtensionWithOfficialCli, qwenOfficialExtensionRepoUrl, relinkQwenExtensionWithOfficialCli, resolveQwenOfficialCliReleaseBundleDir, syncQwenOfficialCliReleaseBundle, toQwenOfficialCliReleaseArtifacts, uninstallQwenExtensionWithOfficialCli, updateQwenExtensionWithOfficialCli, } from "../utils/qwen-extension-cli.js";
|
|
12
|
+
const platformNames = ["qwen", "codex", "claude", "opencode"];
|
|
13
|
+
function getPlanCapabilitySummary(plan) {
|
|
14
|
+
const capability = plan.capability;
|
|
15
|
+
if (!capability) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const exposure = (() => {
|
|
19
|
+
switch (plan.platform) {
|
|
20
|
+
case "codex":
|
|
21
|
+
return {
|
|
22
|
+
style: "skill-alias",
|
|
23
|
+
entryPattern: "$zc-*",
|
|
24
|
+
examples: [
|
|
25
|
+
"zc:start -> $zc-start",
|
|
26
|
+
"zc:product-analysis -> $zc-product-analysis",
|
|
27
|
+
"zc:sdd-tdd -> $zc-sdd-tdd",
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
case "claude":
|
|
31
|
+
return {
|
|
32
|
+
style: "slash-command",
|
|
33
|
+
entryPattern: "/zc-*",
|
|
34
|
+
examples: [
|
|
35
|
+
"zc:start -> /zc-start",
|
|
36
|
+
"zc:product-analysis -> /zc-product-analysis",
|
|
37
|
+
"zc:sdd-tdd -> /zc-sdd-tdd",
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
case "opencode":
|
|
41
|
+
return {
|
|
42
|
+
style: "slash-command",
|
|
43
|
+
entryPattern: "/zc-*",
|
|
44
|
+
examples: [
|
|
45
|
+
"zc:start -> /zc-start",
|
|
46
|
+
"zc:product-analysis -> /zc-product-analysis",
|
|
47
|
+
"zc:sdd-tdd -> /zc-sdd-tdd",
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
case "qwen":
|
|
51
|
+
return {
|
|
52
|
+
style: "namespaced-command",
|
|
53
|
+
entryPattern: "zc:*",
|
|
54
|
+
examples: [
|
|
55
|
+
"zc:start -> zc:start",
|
|
56
|
+
"zc:product-analysis -> zc:product-analysis",
|
|
57
|
+
"zc:sdd-tdd -> zc:sdd-tdd",
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
62
|
+
return {
|
|
63
|
+
namespace: capability.namespace,
|
|
64
|
+
surfaces: capability.surfaces,
|
|
65
|
+
entryFile: capability.entryFile?.fileName ?? null,
|
|
66
|
+
commandsDir: capability.commands?.relativeDir ?? null,
|
|
67
|
+
skillsDir: capability.skills?.relativeDir ?? null,
|
|
68
|
+
agentsDir: capability.agents?.relativeDir ?? null,
|
|
69
|
+
extensionDir: capability.extension
|
|
70
|
+
? `${capability.extension.relativeDir}/${capability.extension.name}`
|
|
71
|
+
: null,
|
|
72
|
+
exposure,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function formatSurfaceLabel(surface) {
|
|
76
|
+
switch (surface) {
|
|
77
|
+
case "entry-file":
|
|
78
|
+
return "入口文件";
|
|
79
|
+
case "skills-dir":
|
|
80
|
+
return "skills 目录";
|
|
81
|
+
case "commands-dir":
|
|
82
|
+
return "commands 目录";
|
|
83
|
+
case "agents-dir":
|
|
84
|
+
return "agents 目录";
|
|
85
|
+
case "extension-dir":
|
|
86
|
+
return "extension 目录";
|
|
87
|
+
default:
|
|
88
|
+
return surface;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function summarizeCapability(plan) {
|
|
92
|
+
const capability = getPlanCapabilitySummary(plan);
|
|
93
|
+
if (!capability) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return [
|
|
97
|
+
`命名空间:${capability.namespace}`,
|
|
98
|
+
`入口形式:${capability.exposure.entryPattern}`,
|
|
99
|
+
`安装面:${capability.surfaces.map((surface) => formatSurfaceLabel(surface)).join("、")}`,
|
|
100
|
+
...(capability.entryFile ? [`入口文件:${capability.entryFile}`] : []),
|
|
101
|
+
...(capability.commandsDir ? [`commands 目录:${capability.commandsDir}`] : []),
|
|
102
|
+
...(capability.skillsDir ? [`skills 目录:${capability.skillsDir}`] : []),
|
|
103
|
+
...(capability.agentsDir ? [`agents 目录:${capability.agentsDir}`] : []),
|
|
104
|
+
...(capability.extensionDir ? [`extension 目录:${capability.extensionDir}`] : []),
|
|
105
|
+
`示例映射:${capability.exposure.examples.join(";")}`,
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
const defaultPlatforms = ["qwen", "codex", "claude", "opencode"];
|
|
11
109
|
function getCliVersion() {
|
|
12
110
|
const packageJsonPath = new URL("../../package.json", import.meta.url);
|
|
13
111
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
@@ -19,10 +117,13 @@ function normalizeManifest(manifest) {
|
|
|
19
117
|
assets: manifest.assets.map((asset) => ({
|
|
20
118
|
id: asset.id,
|
|
21
119
|
kind: asset.meta.kind,
|
|
120
|
+
name: asset.meta.name,
|
|
22
121
|
platforms: asset.meta.platforms ?? defaultPlatforms,
|
|
23
122
|
title: asset.meta.title,
|
|
24
123
|
summary: asset.meta.description,
|
|
25
|
-
body: asset.body
|
|
124
|
+
body: asset.body,
|
|
125
|
+
tools: asset.meta.tools,
|
|
126
|
+
requires: asset.meta.requires
|
|
26
127
|
}))
|
|
27
128
|
};
|
|
28
129
|
}
|
|
@@ -37,30 +138,38 @@ async function loadPlatformModule(platform) {
|
|
|
37
138
|
const packageMap = {
|
|
38
139
|
qwen: "packages/platform-qwen/dist/index.js",
|
|
39
140
|
codex: "packages/platform-codex/dist/index.js",
|
|
40
|
-
|
|
141
|
+
claude: "packages/platform-claude/dist/index.js",
|
|
142
|
+
opencode: "packages/platform-opencode/dist/index.js"
|
|
41
143
|
};
|
|
42
144
|
return importWorkspaceDistModule(packageMap[platform]);
|
|
43
145
|
}
|
|
44
146
|
function createGenerationPlan(platform, platformModule, manifest) {
|
|
147
|
+
const extensionVersion = getCliVersion();
|
|
45
148
|
switch (platform) {
|
|
46
149
|
case "qwen":
|
|
47
150
|
if (!platformModule.createQwenGenerationPlan) {
|
|
48
151
|
throw new Error("Qwen 平台包未导出 createQwenGenerationPlan()");
|
|
49
152
|
}
|
|
50
|
-
return finalizePlan(platformModule.createQwenGenerationPlan(manifest, { manifestSource: manifest.source }));
|
|
153
|
+
return finalizePlan(platformModule.createQwenGenerationPlan(manifest, { manifestSource: manifest.source, extensionVersion }));
|
|
51
154
|
case "codex":
|
|
52
155
|
if (!platformModule.createCodexGenerationPlan) {
|
|
53
156
|
throw new Error("Codex 平台包未导出 createCodexGenerationPlan()");
|
|
54
157
|
}
|
|
55
|
-
return finalizePlan(platformModule.createCodexGenerationPlan(manifest, { manifestSource: manifest.source }));
|
|
56
|
-
case "
|
|
57
|
-
if (!platformModule.
|
|
58
|
-
throw new Error("
|
|
158
|
+
return finalizePlan(platformModule.createCodexGenerationPlan(manifest, { manifestSource: manifest.source, extensionVersion }));
|
|
159
|
+
case "claude":
|
|
160
|
+
if (!platformModule.createClaudeGenerationPlan) {
|
|
161
|
+
throw new Error("Claude 平台包未导出 createClaudeGenerationPlan()");
|
|
59
162
|
}
|
|
60
|
-
return finalizePlan(platformModule.
|
|
163
|
+
return finalizePlan(platformModule.createClaudeGenerationPlan(manifest, { manifestSource: manifest.source, extensionVersion }));
|
|
164
|
+
case "opencode":
|
|
165
|
+
if (!platformModule.createOpenCodeGenerationPlan) {
|
|
166
|
+
throw new Error("OpenCode 平台包未导出 createOpenCodeGenerationPlan()");
|
|
167
|
+
}
|
|
168
|
+
return finalizePlan(platformModule.createOpenCodeGenerationPlan(manifest, { manifestSource: manifest.source, extensionVersion }));
|
|
61
169
|
}
|
|
62
170
|
}
|
|
63
|
-
function createInstallPlan(platform, platformModule, manifest, destinationRoot, overwrite) {
|
|
171
|
+
function createInstallPlan(platform, platformModule, manifest, destinationRoot, scope, overwrite) {
|
|
172
|
+
const extensionVersion = getCliVersion();
|
|
64
173
|
switch (platform) {
|
|
65
174
|
case "qwen":
|
|
66
175
|
if (!platformModule.createQwenInstallPlan) {
|
|
@@ -69,7 +178,9 @@ function createInstallPlan(platform, platformModule, manifest, destinationRoot,
|
|
|
69
178
|
return finalizePlan(platformModule.createQwenInstallPlan(manifest, {
|
|
70
179
|
manifestSource: manifest.source,
|
|
71
180
|
destinationRoot,
|
|
72
|
-
|
|
181
|
+
scope,
|
|
182
|
+
overwrite,
|
|
183
|
+
extensionVersion,
|
|
73
184
|
}));
|
|
74
185
|
case "codex":
|
|
75
186
|
if (!platformModule.createCodexInstallPlan) {
|
|
@@ -78,16 +189,31 @@ function createInstallPlan(platform, platformModule, manifest, destinationRoot,
|
|
|
78
189
|
return finalizePlan(platformModule.createCodexInstallPlan(manifest, {
|
|
79
190
|
manifestSource: manifest.source,
|
|
80
191
|
destinationRoot,
|
|
81
|
-
|
|
192
|
+
scope,
|
|
193
|
+
overwrite,
|
|
194
|
+
extensionVersion,
|
|
195
|
+
}));
|
|
196
|
+
case "claude":
|
|
197
|
+
if (!platformModule.createClaudeInstallPlan) {
|
|
198
|
+
throw new Error("Claude 平台包未导出 createClaudeInstallPlan()");
|
|
199
|
+
}
|
|
200
|
+
return finalizePlan(platformModule.createClaudeInstallPlan(manifest, {
|
|
201
|
+
manifestSource: manifest.source,
|
|
202
|
+
destinationRoot,
|
|
203
|
+
scope,
|
|
204
|
+
overwrite,
|
|
205
|
+
extensionVersion,
|
|
82
206
|
}));
|
|
83
|
-
case "
|
|
84
|
-
if (!platformModule.
|
|
85
|
-
throw new Error("
|
|
207
|
+
case "opencode":
|
|
208
|
+
if (!platformModule.createOpenCodeInstallPlan) {
|
|
209
|
+
throw new Error("OpenCode 平台包未导出 createOpenCodeInstallPlan()");
|
|
86
210
|
}
|
|
87
|
-
return finalizePlan(platformModule.
|
|
211
|
+
return finalizePlan(platformModule.createOpenCodeInstallPlan(manifest, {
|
|
88
212
|
manifestSource: manifest.source,
|
|
89
213
|
destinationRoot,
|
|
90
|
-
|
|
214
|
+
scope,
|
|
215
|
+
overwrite,
|
|
216
|
+
extensionVersion,
|
|
91
217
|
}));
|
|
92
218
|
}
|
|
93
219
|
}
|
|
@@ -97,6 +223,10 @@ function resolveOverwriteMode(force) {
|
|
|
97
223
|
function resolveOutputFormat(json) {
|
|
98
224
|
return json ? "json" : "text";
|
|
99
225
|
}
|
|
226
|
+
function mergeHints(...hints) {
|
|
227
|
+
const merged = hints.filter(Boolean);
|
|
228
|
+
return merged.length > 0 ? merged.join(";") : undefined;
|
|
229
|
+
}
|
|
100
230
|
function resolveScopeFromSelector(opts) {
|
|
101
231
|
return normalizeInstallSelector(opts).mode;
|
|
102
232
|
}
|
|
@@ -128,6 +258,10 @@ function formatActionLabel(action) {
|
|
|
128
258
|
return "安装";
|
|
129
259
|
case "update":
|
|
130
260
|
return "更新";
|
|
261
|
+
case "repair":
|
|
262
|
+
return "修复";
|
|
263
|
+
case "uninstall":
|
|
264
|
+
return "卸载";
|
|
131
265
|
}
|
|
132
266
|
}
|
|
133
267
|
function formatRootLabel(action, root, metadata) {
|
|
@@ -149,30 +283,121 @@ function formatStatusLabel(kind) {
|
|
|
149
283
|
return "已漂移";
|
|
150
284
|
}
|
|
151
285
|
}
|
|
286
|
+
function formatInstallMethodLabel(method) {
|
|
287
|
+
return method === "qwen-cli" ? "官方 qwen extensions CLI" : "直接写入";
|
|
288
|
+
}
|
|
289
|
+
function formatInstallSourceLabel(source) {
|
|
290
|
+
return source === "github-repo" ? "GitHub 扩展仓库" : "本地 bundle";
|
|
291
|
+
}
|
|
292
|
+
function formatBundleTypeLabel(type) {
|
|
293
|
+
return type === "release-bundle" ? "发布态扩展包" : "开发态源包";
|
|
294
|
+
}
|
|
295
|
+
function formatScopeFlag(scope, root) {
|
|
296
|
+
switch (scope) {
|
|
297
|
+
case "global":
|
|
298
|
+
return " --global";
|
|
299
|
+
case "project":
|
|
300
|
+
return " --project";
|
|
301
|
+
case "dir":
|
|
302
|
+
return ` --dir ${JSON.stringify(root)}`;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function buildNextStep(action, target, root, options) {
|
|
306
|
+
const scopeFlag = formatScopeFlag(options?.scope ?? "project", root);
|
|
307
|
+
switch (action) {
|
|
308
|
+
case "generate":
|
|
309
|
+
return `下一步:如需写入平台目录,运行 \`zc platform install ${target} --project\`、\`--global\` 或 \`--dir <path>\`。`;
|
|
310
|
+
case "install":
|
|
311
|
+
return options?.noop
|
|
312
|
+
? `下一步:当前已是目标状态;如需确认细节,运行 \`zc platform status ${target}${scopeFlag} --json\`。`
|
|
313
|
+
: `下一步:运行 \`zc platform status ${target}${scopeFlag}\` 确认安装状态。`;
|
|
314
|
+
case "update":
|
|
315
|
+
return options?.noop
|
|
316
|
+
? "下一步:当前已经是最新版本,无需额外操作。"
|
|
317
|
+
: `下一步:运行 \`zc platform status ${target}${scopeFlag}\` 确认更新结果。`;
|
|
318
|
+
case "repair":
|
|
319
|
+
return options?.noop
|
|
320
|
+
? "下一步:当前安装健康,无需修复。"
|
|
321
|
+
: `下一步:运行 \`zc platform doctor ${target}${scopeFlag}\` 复查健康度。`;
|
|
322
|
+
case "uninstall":
|
|
323
|
+
return `下一步:如需重新安装,运行 \`zc platform install ${target}${scopeFlag}\`。`;
|
|
324
|
+
case "where":
|
|
325
|
+
return `下一步:运行 \`zc platform install ${target}${scopeFlag}\` 执行安装,或追加 \`--plan --json\` 先看计划。`;
|
|
326
|
+
case "status":
|
|
327
|
+
switch (options?.status) {
|
|
328
|
+
case "not-installed":
|
|
329
|
+
return `下一步:运行 \`zc platform install ${target}${scopeFlag}\`。`;
|
|
330
|
+
case "update-available":
|
|
331
|
+
return `下一步:运行 \`zc platform update ${target}${scopeFlag}\`。`;
|
|
332
|
+
case "drifted":
|
|
333
|
+
return `下一步:先运行 \`zc platform doctor ${target}${scopeFlag}\`,再按结果选择 \`repair\` 或带 \`--force\` 的 \`update\`。`;
|
|
334
|
+
case "up-to-date":
|
|
335
|
+
return "下一步:当前已是最新状态,无需动作。";
|
|
336
|
+
default:
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
case "doctor":
|
|
340
|
+
switch (options?.health) {
|
|
341
|
+
case "healthy":
|
|
342
|
+
return "下一步:未发现需要处理的问题。";
|
|
343
|
+
case "warning":
|
|
344
|
+
return `下一步:优先运行 \`zc platform repair ${target}${scopeFlag}\`,再复查状态。`;
|
|
345
|
+
case "broken":
|
|
346
|
+
return `下一步:先运行 \`zc platform repair ${target}${scopeFlag}\`;如仍异常,再查看 \`zc platform status ${target}${scopeFlag} --json\`。`;
|
|
347
|
+
default:
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
152
352
|
function summarizeResult(action, target, root, result, metadata) {
|
|
153
353
|
const mode = result.dryRun ? "预演完成" : "完成";
|
|
154
|
-
|
|
354
|
+
const lines = [
|
|
155
355
|
`${target} ${formatActionLabel(action)}${mode}`,
|
|
156
356
|
formatRootLabel(action, root, metadata),
|
|
157
357
|
...(metadata?.status ? [`状态:${metadata.status}`] : []),
|
|
358
|
+
...(metadata?.installMethod ? [`安装方式:${formatInstallMethodLabel(metadata.installMethod)}`] : []),
|
|
359
|
+
...(metadata?.installSource ? [`安装来源:${formatInstallSourceLabel(metadata.installSource)}`] : []),
|
|
360
|
+
...(metadata?.sourceRef ? [`来源:${metadata.sourceRef}`] : []),
|
|
361
|
+
...(metadata?.bundleType ? [`Bundle 类型:${formatBundleTypeLabel(metadata.bundleType)}`] : []),
|
|
362
|
+
...(metadata?.bundlePath ? [`Bundle 目录:${metadata.bundlePath}`] : []),
|
|
158
363
|
...(metadata?.receiptPath ? [`回执:${metadata.receiptPath}`] : []),
|
|
159
|
-
...(metadata?.zcVersion ? [`zc 版本:${metadata.zcVersion}`] : []),
|
|
160
|
-
...(metadata?.contentFingerprint ? [`内容指纹:${metadata.contentFingerprint}`] : []),
|
|
161
364
|
...(metadata?.hint ? [`提示:${metadata.hint}`] : []),
|
|
162
365
|
metadata?.noop
|
|
163
366
|
? "无需写入,当前安装已满足目标状态。"
|
|
164
367
|
: `新增 ${result.created},覆盖 ${result.overwritten},未变更 ${result.unchanged}${result.dryRun ? `,跳过写入 ${result.skipped}` : ""}`,
|
|
165
|
-
]
|
|
368
|
+
];
|
|
369
|
+
const nextStep = buildNextStep(action, target, root, {
|
|
370
|
+
scope: metadata?.scope,
|
|
371
|
+
status: metadata?.status,
|
|
372
|
+
noop: metadata?.noop,
|
|
373
|
+
});
|
|
374
|
+
if (nextStep) {
|
|
375
|
+
lines.push(nextStep);
|
|
376
|
+
}
|
|
377
|
+
return lines.join("\n");
|
|
166
378
|
}
|
|
167
379
|
function summarizePlan(action, target, root, plan, metadata) {
|
|
168
|
-
|
|
380
|
+
const lines = [
|
|
169
381
|
`${target} ${formatActionLabel(action)}计划`,
|
|
170
382
|
formatRootLabel(action, root, metadata),
|
|
171
383
|
...(metadata?.status ? [`状态:${metadata.status}`] : []),
|
|
384
|
+
...(metadata?.installSource ? [`安装来源:${formatInstallSourceLabel(metadata.installSource)}`] : []),
|
|
385
|
+
...(metadata?.sourceRef ? [`来源:${metadata.sourceRef}`] : []),
|
|
386
|
+
...(metadata?.bundleType ? [`Bundle 类型:${formatBundleTypeLabel(metadata.bundleType)}`] : []),
|
|
387
|
+
...(metadata?.bundlePath ? [`Bundle 目录:${metadata.bundlePath}`] : []),
|
|
172
388
|
...(metadata?.hint ? [`提示:${metadata.hint}`] : []),
|
|
389
|
+
...summarizeCapability(plan),
|
|
173
390
|
`产物数量:${plan.artifacts.length}`,
|
|
174
391
|
...plan.artifacts.map((artifact) => `- ${artifact.path}`),
|
|
175
|
-
]
|
|
392
|
+
];
|
|
393
|
+
const nextStep = buildNextStep(action, target, root, {
|
|
394
|
+
scope: metadata?.scope,
|
|
395
|
+
status: metadata?.status,
|
|
396
|
+
});
|
|
397
|
+
if (nextStep) {
|
|
398
|
+
lines.push(nextStep);
|
|
399
|
+
}
|
|
400
|
+
return lines.join("\n");
|
|
176
401
|
}
|
|
177
402
|
function buildPlanPayload(action, target, root, plan, metadata) {
|
|
178
403
|
return {
|
|
@@ -185,12 +410,23 @@ function buildPlanPayload(action, target, root, plan, metadata) {
|
|
|
185
410
|
autoResolvedRoot: metadata?.autoResolvedRoot ?? false,
|
|
186
411
|
hint: metadata?.hint ?? null,
|
|
187
412
|
status: metadata?.status ?? null,
|
|
413
|
+
installSource: metadata?.installSource ?? null,
|
|
414
|
+
sourceRef: metadata?.sourceRef ?? null,
|
|
415
|
+
bundleType: metadata?.bundleType ?? null,
|
|
416
|
+
bundlePath: metadata?.bundlePath ?? null,
|
|
417
|
+
capability: getPlanCapabilitySummary(plan),
|
|
188
418
|
artifactCount: plan.artifacts.length,
|
|
189
419
|
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
190
420
|
overwrite: "overwrite" in plan ? plan.overwrite : null,
|
|
191
421
|
artifacts: plan.artifacts,
|
|
192
422
|
};
|
|
193
423
|
}
|
|
424
|
+
function parseGenerateBundleType(value) {
|
|
425
|
+
if (value === "release-bundle" || value === "release") {
|
|
426
|
+
return "release-bundle";
|
|
427
|
+
}
|
|
428
|
+
throw new InvalidArgumentError(`不支持的 bundle 类型:${value}。当前仅支持:release-bundle`);
|
|
429
|
+
}
|
|
194
430
|
function buildResultPayload(action, target, root, result, metadata) {
|
|
195
431
|
return {
|
|
196
432
|
mode: "result",
|
|
@@ -201,6 +437,11 @@ function buildResultPayload(action, target, root, result, metadata) {
|
|
|
201
437
|
rootSource: metadata?.rootSource ?? (metadata?.autoResolvedRoot ? "project-root" : "explicit"),
|
|
202
438
|
autoResolvedRoot: metadata?.autoResolvedRoot ?? false,
|
|
203
439
|
hint: metadata?.hint ?? null,
|
|
440
|
+
installMethod: metadata?.installMethod ?? "filesystem",
|
|
441
|
+
installSource: metadata?.installSource ?? null,
|
|
442
|
+
sourceRef: metadata?.sourceRef ?? null,
|
|
443
|
+
bundleType: metadata?.bundleType ?? null,
|
|
444
|
+
bundlePath: metadata?.bundlePath ?? null,
|
|
204
445
|
receiptPath: metadata?.receiptPath ?? null,
|
|
205
446
|
zcVersion: metadata?.zcVersion ?? null,
|
|
206
447
|
status: metadata?.status ?? null,
|
|
@@ -209,15 +450,71 @@ function buildResultPayload(action, target, root, result, metadata) {
|
|
|
209
450
|
...result,
|
|
210
451
|
};
|
|
211
452
|
}
|
|
453
|
+
function shouldPreferQwenOfficialCli(target, scope) {
|
|
454
|
+
return target === "qwen" && scope === "global";
|
|
455
|
+
}
|
|
456
|
+
function shouldPreferQwenOfficialRepoInstall(target, scope) {
|
|
457
|
+
return shouldPreferQwenOfficialCli(target, scope);
|
|
458
|
+
}
|
|
459
|
+
function estimateManagedInstallResult(plan, status) {
|
|
460
|
+
if (status.kind === "not-installed") {
|
|
461
|
+
return {
|
|
462
|
+
created: plan.artifacts.length,
|
|
463
|
+
overwritten: 0,
|
|
464
|
+
unchanged: 0,
|
|
465
|
+
skipped: 0,
|
|
466
|
+
dryRun: false,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
let created = 0;
|
|
470
|
+
let overwritten = 0;
|
|
471
|
+
let unchanged = 0;
|
|
472
|
+
for (const artifact of status.artifacts) {
|
|
473
|
+
if (artifact.plannedSha256 === null) {
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (artifact.actualSha256 === artifact.plannedSha256) {
|
|
477
|
+
unchanged += 1;
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
if (artifact.actualSha256 === null) {
|
|
481
|
+
created += 1;
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
overwritten += 1;
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
created,
|
|
488
|
+
overwritten,
|
|
489
|
+
unchanged,
|
|
490
|
+
skipped: 0,
|
|
491
|
+
dryRun: false,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
212
494
|
function summarizeWhere(target, root, metadata) {
|
|
213
|
-
|
|
495
|
+
const lines = [
|
|
214
496
|
`${target} 安装目标`,
|
|
215
497
|
`范围:${metadata.scope}`,
|
|
216
498
|
`解析来源:${metadata.rootSource}`,
|
|
217
499
|
...(metadata.marker ? [`命中标记:${metadata.marker}`] : []),
|
|
218
500
|
`目录:${root}`,
|
|
501
|
+
...(metadata.capability
|
|
502
|
+
? [
|
|
503
|
+
`命名空间:${metadata.capability.namespace}`,
|
|
504
|
+
`入口形式:${metadata.capability.exposure.entryPattern}`,
|
|
505
|
+
`安装面:${metadata.capability.surfaces.map((surface) => formatSurfaceLabel(surface)).join("、")}`,
|
|
506
|
+
`示例映射:${metadata.capability.exposure.examples.join(";")}`,
|
|
507
|
+
]
|
|
508
|
+
: []),
|
|
219
509
|
...(metadata.hint ? [`提示:${metadata.hint}`] : []),
|
|
220
|
-
]
|
|
510
|
+
];
|
|
511
|
+
const nextStep = buildNextStep("where", target, root, {
|
|
512
|
+
scope: metadata.scope,
|
|
513
|
+
});
|
|
514
|
+
if (nextStep) {
|
|
515
|
+
lines.push(nextStep);
|
|
516
|
+
}
|
|
517
|
+
return lines.join("\n");
|
|
221
518
|
}
|
|
222
519
|
function buildWherePayload(target, root, metadata) {
|
|
223
520
|
return {
|
|
@@ -228,6 +525,7 @@ function buildWherePayload(target, root, metadata) {
|
|
|
228
525
|
rootSource: metadata.rootSource,
|
|
229
526
|
marker: metadata.marker ?? null,
|
|
230
527
|
hint: metadata.hint ?? null,
|
|
528
|
+
capability: metadata.capability ?? null,
|
|
231
529
|
};
|
|
232
530
|
}
|
|
233
531
|
function reportConflict(error, target, destinationRoot) {
|
|
@@ -240,19 +538,33 @@ function reportConflict(error, target, destinationRoot) {
|
|
|
240
538
|
console.error("如需覆盖,请追加 --force。");
|
|
241
539
|
}
|
|
242
540
|
function summarizeStatus(target, root, status, metadata) {
|
|
243
|
-
|
|
541
|
+
const lines = [
|
|
244
542
|
`${target} 安装状态`,
|
|
245
543
|
`范围:${metadata.scope}`,
|
|
246
544
|
`目录:${root}`,
|
|
247
545
|
`状态:${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
248
546
|
`回执:${status.receiptPath}`,
|
|
249
|
-
...(
|
|
250
|
-
...(metadata.
|
|
251
|
-
...(
|
|
252
|
-
...(
|
|
547
|
+
...(metadata.installMethod ? [`安装方式:${formatInstallMethodLabel(metadata.installMethod)}`] : []),
|
|
548
|
+
...(metadata.installSource ? [`安装来源:${formatInstallSourceLabel(metadata.installSource)}`] : []),
|
|
549
|
+
...(metadata.sourceRef ? [`来源:${metadata.sourceRef}`] : []),
|
|
550
|
+
...(metadata.bundleType ? [`Bundle 类型:${formatBundleTypeLabel(metadata.bundleType)}`] : []),
|
|
551
|
+
...(metadata.bundlePath ? [`Bundle 目录:${metadata.bundlePath}`] : []),
|
|
552
|
+
...(metadata.recommendedInstallMethod ? [`推荐安装方式:${formatInstallMethodLabel(metadata.recommendedInstallMethod)}`] : []),
|
|
553
|
+
...(metadata.recommendedInstallSource ? [`推荐来源:${formatInstallSourceLabel(metadata.recommendedInstallSource)}`] : []),
|
|
554
|
+
...(metadata.recommendedSourceRef ? [`推荐来源地址:${metadata.recommendedSourceRef}`] : []),
|
|
555
|
+
...(metadata.recommendedBundleType ? [`推荐 Bundle:${formatBundleTypeLabel(metadata.recommendedBundleType)}`] : []),
|
|
556
|
+
...(metadata.recommendedBundlePath ? [`推荐 Bundle 目录:${metadata.recommendedBundlePath}`] : []),
|
|
253
557
|
`跟踪产物:${status.summary.trackedArtifacts},漂移:${status.summary.driftedArtifacts},缺失:${status.summary.missingArtifacts},待更新:${status.summary.plannedChanges}`,
|
|
254
558
|
...(metadata.hint ? [`提示:${metadata.hint}`] : []),
|
|
255
|
-
]
|
|
559
|
+
];
|
|
560
|
+
const nextStep = buildNextStep("status", target, root, {
|
|
561
|
+
scope: metadata.scope,
|
|
562
|
+
status: status.kind,
|
|
563
|
+
});
|
|
564
|
+
if (nextStep) {
|
|
565
|
+
lines.push(nextStep);
|
|
566
|
+
}
|
|
567
|
+
return lines.join("\n");
|
|
256
568
|
}
|
|
257
569
|
function buildStatusPayload(target, root, status, metadata) {
|
|
258
570
|
return {
|
|
@@ -262,6 +574,17 @@ function buildStatusPayload(target, root, status, metadata) {
|
|
|
262
574
|
root,
|
|
263
575
|
rootSource: metadata.rootSource,
|
|
264
576
|
hint: metadata.hint ?? null,
|
|
577
|
+
capability: getPlanCapabilitySummary(metadata.plan),
|
|
578
|
+
installMethod: metadata.installMethod ?? null,
|
|
579
|
+
installSource: metadata.installSource ?? null,
|
|
580
|
+
sourceRef: metadata.sourceRef ?? null,
|
|
581
|
+
bundleType: metadata.bundleType ?? null,
|
|
582
|
+
bundlePath: metadata.bundlePath ?? null,
|
|
583
|
+
recommendedInstallMethod: metadata.recommendedInstallMethod ?? null,
|
|
584
|
+
recommendedInstallSource: metadata.recommendedInstallSource ?? null,
|
|
585
|
+
recommendedSourceRef: metadata.recommendedSourceRef ?? null,
|
|
586
|
+
recommendedBundleType: metadata.recommendedBundleType ?? null,
|
|
587
|
+
recommendedBundlePath: metadata.recommendedBundlePath ?? null,
|
|
265
588
|
status: status.kind,
|
|
266
589
|
receiptPath: status.receiptPath,
|
|
267
590
|
zcVersion: metadata.zcVersion ?? null,
|
|
@@ -272,37 +595,143 @@ function buildStatusPayload(target, root, status, metadata) {
|
|
|
272
595
|
artifacts: status.artifacts,
|
|
273
596
|
};
|
|
274
597
|
}
|
|
598
|
+
function summarizeDoctor(target, root, status, doctor, metadata) {
|
|
599
|
+
const lines = [
|
|
600
|
+
`${target} 安装诊断`,
|
|
601
|
+
`范围:${metadata.scope}`,
|
|
602
|
+
`目录:${root}`,
|
|
603
|
+
`状态:${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
604
|
+
`健康度:${doctor.health}`,
|
|
605
|
+
...(doctor.issues.length > 0
|
|
606
|
+
? doctor.issues.flatMap((issue) => [
|
|
607
|
+
`- [${issue.severity}] ${issue.code}: ${issue.message}`,
|
|
608
|
+
...(issue.paths && issue.paths.length > 0 ? issue.paths.map((path) => ` - ${path}`) : []),
|
|
609
|
+
])
|
|
610
|
+
: ["- 未发现需要处理的问题。"]),
|
|
611
|
+
...(metadata.hint ? [`提示:${metadata.hint}`] : []),
|
|
612
|
+
];
|
|
613
|
+
const nextStep = buildNextStep("doctor", target, root, {
|
|
614
|
+
scope: metadata.scope,
|
|
615
|
+
status: status.kind,
|
|
616
|
+
health: doctor.health,
|
|
617
|
+
});
|
|
618
|
+
if (nextStep) {
|
|
619
|
+
lines.push(nextStep);
|
|
620
|
+
}
|
|
621
|
+
return lines.join("\n");
|
|
622
|
+
}
|
|
623
|
+
function buildDoctorPayload(target, root, status, doctor, metadata) {
|
|
624
|
+
return {
|
|
625
|
+
mode: "doctor",
|
|
626
|
+
target,
|
|
627
|
+
scope: metadata.scope,
|
|
628
|
+
root,
|
|
629
|
+
rootSource: metadata.rootSource,
|
|
630
|
+
hint: metadata.hint ?? null,
|
|
631
|
+
capability: getPlanCapabilitySummary(metadata.plan),
|
|
632
|
+
status: status.kind,
|
|
633
|
+
health: doctor.health,
|
|
634
|
+
receiptPath: status.receiptPath,
|
|
635
|
+
issues: doctor.issues,
|
|
636
|
+
summary: status.summary,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
function summarizeUninstall(target, root, result, metadata) {
|
|
640
|
+
const lines = [
|
|
641
|
+
`${target} 卸载完成`,
|
|
642
|
+
formatRootLabel("uninstall", root, metadata),
|
|
643
|
+
...(metadata.installMethod ? [`安装方式:${formatInstallMethodLabel(metadata.installMethod)}`] : []),
|
|
644
|
+
...(metadata.installSource ? [`安装来源:${formatInstallSourceLabel(metadata.installSource)}`] : []),
|
|
645
|
+
...(metadata.sourceRef ? [`来源:${metadata.sourceRef}`] : []),
|
|
646
|
+
...(metadata.bundlePath ? [`Bundle 目录:${metadata.bundlePath}`] : []),
|
|
647
|
+
`回执:${metadata.receiptPath}`,
|
|
648
|
+
...(metadata.hint ? [`提示:${metadata.hint}`] : []),
|
|
649
|
+
`移除受管产物 ${result.removedArtifacts},原本缺失 ${result.missingArtifacts}`,
|
|
650
|
+
`Bundle:${result.bundleRemoved ? "已删除" : result.bundleMissing ? "本就不存在" : "未涉及"}`,
|
|
651
|
+
`回执:${result.receiptRemoved ? "已删除" : result.receiptMissing ? "本就不存在" : "未涉及"}`,
|
|
652
|
+
];
|
|
653
|
+
const nextStep = buildNextStep("uninstall", target, root, {
|
|
654
|
+
scope: metadata.scope,
|
|
655
|
+
});
|
|
656
|
+
if (nextStep) {
|
|
657
|
+
lines.push(nextStep);
|
|
658
|
+
}
|
|
659
|
+
return lines.join("\n");
|
|
660
|
+
}
|
|
661
|
+
function buildUninstallPayload(target, root, result, metadata) {
|
|
662
|
+
return {
|
|
663
|
+
mode: "result",
|
|
664
|
+
action: "uninstall",
|
|
665
|
+
target,
|
|
666
|
+
root,
|
|
667
|
+
scope: metadata.scope ?? "project",
|
|
668
|
+
rootSource: metadata.rootSource ?? (metadata.autoResolvedRoot ? "project-root" : "explicit"),
|
|
669
|
+
autoResolvedRoot: metadata.autoResolvedRoot ?? false,
|
|
670
|
+
hint: metadata.hint ?? null,
|
|
671
|
+
installMethod: metadata.installMethod ?? null,
|
|
672
|
+
installSource: metadata.installSource ?? null,
|
|
673
|
+
sourceRef: metadata.sourceRef ?? null,
|
|
674
|
+
bundlePath: metadata.bundlePath ?? null,
|
|
675
|
+
receiptPath: metadata.receiptPath,
|
|
676
|
+
...result,
|
|
677
|
+
};
|
|
678
|
+
}
|
|
275
679
|
export async function runPlatformGenerate(target, opts) {
|
|
276
680
|
const format = resolveOutputFormat(opts.json);
|
|
277
681
|
const outputRoot = opts.dir ? resolve(opts.dir) : resolveWorkspacePath(`.generated/${target}`);
|
|
278
682
|
try {
|
|
279
683
|
const manifest = await loadToolkitManifest();
|
|
280
684
|
const platformModule = await loadPlatformModule(target);
|
|
281
|
-
|
|
685
|
+
let plan = createGenerationPlan(target, platformModule, manifest);
|
|
686
|
+
let bundleType;
|
|
687
|
+
let bundlePath;
|
|
688
|
+
if (opts.bundle) {
|
|
689
|
+
if (target !== "qwen") {
|
|
690
|
+
throw new Error(`${target} 暂不支持 bundle 导出。当前仅 qwen 支持 --bundle release-bundle。`);
|
|
691
|
+
}
|
|
692
|
+
const installPlan = createInstallPlan(target, platformModule, manifest, outputRoot, "dir", resolveOverwriteMode(opts.force));
|
|
693
|
+
bundleType = opts.bundle;
|
|
694
|
+
bundlePath = outputRoot;
|
|
695
|
+
plan = {
|
|
696
|
+
...installPlan,
|
|
697
|
+
artifacts: toQwenOfficialCliReleaseArtifacts(installPlan, outputRoot),
|
|
698
|
+
};
|
|
699
|
+
}
|
|
282
700
|
if (opts.plan) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
701
|
+
const outputPlan = bundleType
|
|
702
|
+
? plan
|
|
703
|
+
: {
|
|
704
|
+
...plan,
|
|
705
|
+
artifacts: plan.artifacts.map((artifact) => ({
|
|
706
|
+
path: join(outputRoot, artifact.path),
|
|
707
|
+
content: artifact.content,
|
|
708
|
+
})),
|
|
709
|
+
};
|
|
710
|
+
emitOutput(format, buildPlanPayload("generate", target, outputRoot, outputPlan, {
|
|
711
|
+
bundleType,
|
|
712
|
+
bundlePath,
|
|
713
|
+
}), summarizePlan("generate", target, outputRoot, outputPlan, {
|
|
714
|
+
bundleType,
|
|
715
|
+
bundlePath,
|
|
295
716
|
}));
|
|
296
717
|
return;
|
|
297
718
|
}
|
|
298
|
-
const result = await writeArtifacts(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
719
|
+
const result = await writeArtifacts((bundleType
|
|
720
|
+
? plan.artifacts
|
|
721
|
+
: plan.artifacts.map((artifact) => ({
|
|
722
|
+
path: join(outputRoot, artifact.path),
|
|
723
|
+
content: artifact.content,
|
|
724
|
+
}))), {
|
|
302
725
|
dryRun: false,
|
|
303
726
|
overwrite: resolveOverwriteMode(opts.force)
|
|
304
727
|
});
|
|
305
|
-
emitOutput(format, buildResultPayload("generate", target, outputRoot, result
|
|
728
|
+
emitOutput(format, buildResultPayload("generate", target, outputRoot, result, {
|
|
729
|
+
bundleType,
|
|
730
|
+
bundlePath,
|
|
731
|
+
}), summarizeResult("generate", target, outputRoot, result, {
|
|
732
|
+
bundleType,
|
|
733
|
+
bundlePath,
|
|
734
|
+
}));
|
|
306
735
|
}
|
|
307
736
|
catch (error) {
|
|
308
737
|
emitPlatformError(format, target, "generate", error instanceof Error ? `${target} 生成失败:${error.message}` : `${target} 生成失败。`);
|
|
@@ -315,9 +744,29 @@ function getUpdateOverwriteMode(status, force) {
|
|
|
315
744
|
}
|
|
316
745
|
return resolveOverwriteMode(force);
|
|
317
746
|
}
|
|
747
|
+
async function removeOptionalManagedPath(path) {
|
|
748
|
+
if (!path) {
|
|
749
|
+
return {
|
|
750
|
+
removed: false,
|
|
751
|
+
missing: false,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
if (!(await pathExists(path))) {
|
|
755
|
+
return {
|
|
756
|
+
removed: false,
|
|
757
|
+
missing: true,
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
await removeManagedPaths([path]);
|
|
761
|
+
return {
|
|
762
|
+
removed: true,
|
|
763
|
+
missing: false,
|
|
764
|
+
};
|
|
765
|
+
}
|
|
318
766
|
export async function runPlatformInstall(target, opts) {
|
|
319
767
|
const format = resolveOutputFormat(opts.json);
|
|
320
768
|
let destinationRoot = "";
|
|
769
|
+
let fallbackHint;
|
|
321
770
|
try {
|
|
322
771
|
const scope = resolveScopeFromSelector(opts);
|
|
323
772
|
const targetResolution = await resolveInstallTarget(target, {
|
|
@@ -331,20 +780,128 @@ export async function runPlatformInstall(target, opts) {
|
|
|
331
780
|
const overwrite = resolveOverwriteMode(opts.force);
|
|
332
781
|
const manifest = await loadToolkitManifest();
|
|
333
782
|
const platformModule = await loadPlatformModule(target);
|
|
334
|
-
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, overwrite);
|
|
783
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, overwrite);
|
|
784
|
+
const qwenReleaseBundlePath = shouldPreferQwenOfficialCli(target, scope)
|
|
785
|
+
? resolveQwenOfficialCliReleaseBundleDir(plan)
|
|
786
|
+
: null;
|
|
787
|
+
const qwenInstallSource = shouldPreferQwenOfficialRepoInstall(target, scope) ? "github-repo" : "local-bundle";
|
|
335
788
|
if (opts.plan) {
|
|
336
789
|
emitOutput(format, buildPlanPayload("install", target, destinationRoot, plan, {
|
|
337
790
|
autoResolvedRoot,
|
|
338
791
|
rootSource: targetResolution.source,
|
|
339
792
|
hint: targetResolution.hint,
|
|
340
793
|
scope,
|
|
794
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
795
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
796
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
797
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath : null,
|
|
341
798
|
}), summarizePlan("install", target, destinationRoot, plan, {
|
|
342
799
|
autoResolvedRoot,
|
|
343
800
|
rootSource: targetResolution.source,
|
|
344
801
|
hint: targetResolution.hint,
|
|
802
|
+
scope,
|
|
803
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
804
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
805
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
806
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath : null,
|
|
345
807
|
}));
|
|
346
808
|
return;
|
|
347
809
|
}
|
|
810
|
+
if (shouldPreferQwenOfficialCli(target, scope)) {
|
|
811
|
+
const status = await resolvePlatformInstallStatus(plan);
|
|
812
|
+
if (status.kind === "drifted" && !opts.force) {
|
|
813
|
+
emitPlatformError(format, target, "install", `${target} 安装目录已漂移。请先运行 \`zc platform status ${target}\` 检查差异,确认后追加 \`--force\` 再安装。`, {
|
|
814
|
+
root: destinationRoot,
|
|
815
|
+
receiptPath: status.receiptPath,
|
|
816
|
+
status: status.kind,
|
|
817
|
+
});
|
|
818
|
+
process.exitCode = 1;
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
try {
|
|
822
|
+
let releaseBundleDir = null;
|
|
823
|
+
if (format === "text") {
|
|
824
|
+
console.log(`正在调用官方命令:qwen extensions ${status.kind === "not-installed" ? "install" : "update"} …`);
|
|
825
|
+
}
|
|
826
|
+
if (status.kind === "not-installed") {
|
|
827
|
+
if (qwenInstallSource === "github-repo") {
|
|
828
|
+
await installQwenExtensionFromOfficialRepoWithCli(qwenOfficialExtensionRepoUrl);
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
const releaseBundle = await syncQwenOfficialCliReleaseBundle(plan);
|
|
832
|
+
releaseBundleDir = releaseBundle.bundleDir;
|
|
833
|
+
await installQwenExtensionWithOfficialCli(releaseBundle.bundleDir);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
else if (status.kind !== "up-to-date") {
|
|
837
|
+
if (qwenInstallSource === "github-repo") {
|
|
838
|
+
await updateQwenExtensionWithOfficialCli(plan.capability?.extension?.name ?? "zc-toolkit");
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
const releaseBundle = await syncQwenOfficialCliReleaseBundle(plan);
|
|
842
|
+
releaseBundleDir = releaseBundle.bundleDir;
|
|
843
|
+
await uninstallQwenExtensionWithOfficialCli(releaseBundle.extensionName);
|
|
844
|
+
await relinkQwenExtensionWithOfficialCli(releaseBundle.bundleDir);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
await writePlatformInstallReceiptForPlan(plan, {
|
|
848
|
+
installedAt: new Date().toISOString(),
|
|
849
|
+
zcVersion: getCliVersion(),
|
|
850
|
+
installMethod: "qwen-cli",
|
|
851
|
+
installSource: qwenInstallSource,
|
|
852
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : undefined,
|
|
853
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : undefined,
|
|
854
|
+
bundlePath: qwenInstallSource === "local-bundle" ? releaseBundleDir ?? qwenReleaseBundlePath ?? undefined : undefined,
|
|
855
|
+
});
|
|
856
|
+
const result = status.kind === "up-to-date"
|
|
857
|
+
? {
|
|
858
|
+
created: 0,
|
|
859
|
+
overwritten: 0,
|
|
860
|
+
unchanged: plan.artifacts.length,
|
|
861
|
+
skipped: 0,
|
|
862
|
+
dryRun: false,
|
|
863
|
+
}
|
|
864
|
+
: estimateManagedInstallResult(plan, status);
|
|
865
|
+
emitOutput(format, buildResultPayload("install", target, destinationRoot, result, {
|
|
866
|
+
autoResolvedRoot,
|
|
867
|
+
rootSource: targetResolution.source,
|
|
868
|
+
hint: targetResolution.hint,
|
|
869
|
+
scope,
|
|
870
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
871
|
+
zcVersion: getCliVersion(),
|
|
872
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
873
|
+
status: status.kind === "up-to-date" ? status.kind : "installed",
|
|
874
|
+
noop: status.kind === "up-to-date",
|
|
875
|
+
installMethod: "qwen-cli",
|
|
876
|
+
installSource: qwenInstallSource,
|
|
877
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
878
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
879
|
+
bundlePath: qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath : null,
|
|
880
|
+
}), summarizeResult("install", target, destinationRoot, result, {
|
|
881
|
+
autoResolvedRoot,
|
|
882
|
+
rootSource: targetResolution.source,
|
|
883
|
+
hint: targetResolution.hint,
|
|
884
|
+
scope,
|
|
885
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
886
|
+
zcVersion: getCliVersion(),
|
|
887
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
888
|
+
status: status.kind === "up-to-date" ? `${status.kind}(${formatStatusLabel(status.kind)})` : "installed",
|
|
889
|
+
noop: status.kind === "up-to-date",
|
|
890
|
+
installMethod: "qwen-cli",
|
|
891
|
+
installSource: qwenInstallSource,
|
|
892
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
893
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
894
|
+
bundlePath: qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath : null,
|
|
895
|
+
}));
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
catch (error) {
|
|
899
|
+
if (!(error instanceof QwenOfficialCliUnavailableError)) {
|
|
900
|
+
throw error;
|
|
901
|
+
}
|
|
902
|
+
fallbackHint = "未检测到 qwen CLI,已回退为直接写入官方扩展目录。";
|
|
903
|
+
}
|
|
904
|
+
}
|
|
348
905
|
const result = await writeArtifacts(plan.artifacts.map((artifact) => ({
|
|
349
906
|
path: artifact.path,
|
|
350
907
|
content: artifact.content
|
|
@@ -359,20 +916,31 @@ export async function runPlatformInstall(target, opts) {
|
|
|
359
916
|
emitOutput(format, buildResultPayload("install", target, destinationRoot, result, {
|
|
360
917
|
autoResolvedRoot,
|
|
361
918
|
rootSource: targetResolution.source,
|
|
362
|
-
hint: targetResolution.hint,
|
|
919
|
+
hint: mergeHints(targetResolution.hint, fallbackHint),
|
|
363
920
|
scope,
|
|
364
921
|
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
365
922
|
zcVersion: getCliVersion(),
|
|
366
923
|
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
367
924
|
status: "installed",
|
|
925
|
+
installMethod: "filesystem",
|
|
926
|
+
installSource: null,
|
|
927
|
+
sourceRef: null,
|
|
928
|
+
bundleType: null,
|
|
929
|
+
bundlePath: qwenReleaseBundlePath,
|
|
368
930
|
}), summarizeResult("install", target, destinationRoot, result, {
|
|
369
931
|
autoResolvedRoot,
|
|
370
932
|
rootSource: targetResolution.source,
|
|
371
|
-
hint: targetResolution.hint,
|
|
933
|
+
hint: mergeHints(targetResolution.hint, fallbackHint),
|
|
934
|
+
scope,
|
|
372
935
|
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
373
936
|
zcVersion: getCliVersion(),
|
|
374
937
|
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
375
938
|
status: "installed",
|
|
939
|
+
installMethod: "filesystem",
|
|
940
|
+
installSource: null,
|
|
941
|
+
sourceRef: null,
|
|
942
|
+
bundleType: undefined,
|
|
943
|
+
bundlePath: qwenReleaseBundlePath ?? undefined,
|
|
376
944
|
}));
|
|
377
945
|
}
|
|
378
946
|
catch (error) {
|
|
@@ -398,22 +966,53 @@ export async function runPlatformStatus(target, opts) {
|
|
|
398
966
|
const destinationRoot = resolve(targetResolution.root);
|
|
399
967
|
const manifest = await loadToolkitManifest();
|
|
400
968
|
const platformModule = await loadPlatformModule(target);
|
|
401
|
-
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, "error");
|
|
969
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, "error");
|
|
402
970
|
const status = await resolvePlatformInstallStatus(plan);
|
|
403
971
|
const zcVersion = getCliVersion();
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
972
|
+
const installMethod = status.receipt ? (status.receipt.installMethod ?? "filesystem") : undefined;
|
|
973
|
+
const installSource = status.receipt?.installSource ?? undefined;
|
|
974
|
+
const sourceRef = status.receipt?.sourceRef ?? undefined;
|
|
975
|
+
const bundleType = status.receipt?.bundleType ?? undefined;
|
|
976
|
+
const bundlePath = status.receipt?.bundlePath ?? undefined;
|
|
977
|
+
const recommendedInstallMethod = shouldPreferQwenOfficialCli(target, scope) ? "qwen-cli" : undefined;
|
|
978
|
+
const recommendedInstallSource = shouldPreferQwenOfficialRepoInstall(target, scope) ? "github-repo" : undefined;
|
|
979
|
+
const recommendedSourceRef = recommendedInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : undefined;
|
|
980
|
+
const recommendedBundleType = shouldPreferQwenOfficialCli(target, scope) ? "release-bundle" : undefined;
|
|
981
|
+
const recommendedBundlePath = shouldPreferQwenOfficialCli(target, scope)
|
|
982
|
+
? resolveQwenOfficialCliReleaseBundleDir(plan)
|
|
983
|
+
: undefined;
|
|
984
|
+
emitOutput(format, buildStatusPayload(target, destinationRoot, status, {
|
|
408
985
|
scope,
|
|
409
986
|
rootSource: targetResolution.source,
|
|
410
987
|
hint: targetResolution.hint,
|
|
411
988
|
zcVersion,
|
|
989
|
+
plan,
|
|
990
|
+
installMethod,
|
|
991
|
+
installSource,
|
|
992
|
+
sourceRef,
|
|
993
|
+
bundleType,
|
|
994
|
+
bundlePath,
|
|
995
|
+
recommendedInstallMethod,
|
|
996
|
+
recommendedInstallSource,
|
|
997
|
+
recommendedSourceRef,
|
|
998
|
+
recommendedBundleType,
|
|
999
|
+
recommendedBundlePath,
|
|
412
1000
|
}), summarizeStatus(target, destinationRoot, status, {
|
|
413
1001
|
scope,
|
|
414
1002
|
rootSource: targetResolution.source,
|
|
415
1003
|
hint: targetResolution.hint,
|
|
416
1004
|
zcVersion,
|
|
1005
|
+
plan,
|
|
1006
|
+
installMethod,
|
|
1007
|
+
installSource,
|
|
1008
|
+
sourceRef,
|
|
1009
|
+
bundleType,
|
|
1010
|
+
bundlePath,
|
|
1011
|
+
recommendedInstallMethod,
|
|
1012
|
+
recommendedInstallSource,
|
|
1013
|
+
recommendedSourceRef,
|
|
1014
|
+
recommendedBundleType,
|
|
1015
|
+
recommendedBundlePath,
|
|
417
1016
|
}));
|
|
418
1017
|
}
|
|
419
1018
|
catch (error) {
|
|
@@ -424,6 +1023,7 @@ export async function runPlatformStatus(target, opts) {
|
|
|
424
1023
|
export async function runPlatformUpdate(target, opts) {
|
|
425
1024
|
const format = resolveOutputFormat(opts.json);
|
|
426
1025
|
let destinationRoot = "";
|
|
1026
|
+
let fallbackHint;
|
|
427
1027
|
try {
|
|
428
1028
|
const scope = resolveScopeFromSelector(opts);
|
|
429
1029
|
const targetResolution = await resolveInstallTarget(target, {
|
|
@@ -436,9 +1036,13 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
436
1036
|
destinationRoot = resolve(targetResolution.root);
|
|
437
1037
|
const manifest = await loadToolkitManifest();
|
|
438
1038
|
const platformModule = await loadPlatformModule(target);
|
|
439
|
-
const statusPlan = createInstallPlan(target, platformModule, manifest, destinationRoot, "error");
|
|
1039
|
+
const statusPlan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, "error");
|
|
440
1040
|
const status = await resolvePlatformInstallStatus(statusPlan);
|
|
441
1041
|
const zcVersion = getCliVersion();
|
|
1042
|
+
const qwenReleaseBundlePath = shouldPreferQwenOfficialCli(target, scope)
|
|
1043
|
+
? resolveQwenOfficialCliReleaseBundleDir(statusPlan)
|
|
1044
|
+
: undefined;
|
|
1045
|
+
const qwenInstallSource = shouldPreferQwenOfficialRepoInstall(target, scope) ? "github-repo" : "local-bundle";
|
|
442
1046
|
if (status.kind === "not-installed") {
|
|
443
1047
|
emitPlatformError(format, target, "update", `${target} 尚未安装到该目录。请先运行 \`zc platform install ${target}\`。`, {
|
|
444
1048
|
root: destinationRoot,
|
|
@@ -465,15 +1069,26 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
465
1069
|
contentFingerprint: status.contentFingerprint ?? null,
|
|
466
1070
|
status: status.kind,
|
|
467
1071
|
noop: true,
|
|
1072
|
+
installMethod: target === "qwen" && scope === "global" ? "qwen-cli" : undefined,
|
|
1073
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
1074
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1075
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
1076
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? null : null,
|
|
468
1077
|
}), summarizeResult("update", target, destinationRoot, result, {
|
|
469
1078
|
autoResolvedRoot,
|
|
470
1079
|
rootSource: targetResolution.source,
|
|
471
1080
|
hint: targetResolution.hint,
|
|
1081
|
+
scope,
|
|
472
1082
|
receiptPath: status.receiptPath,
|
|
473
1083
|
zcVersion,
|
|
474
1084
|
contentFingerprint: status.contentFingerprint ?? null,
|
|
475
1085
|
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
476
1086
|
noop: true,
|
|
1087
|
+
installMethod: target === "qwen" && scope === "global" ? "qwen-cli" : undefined,
|
|
1088
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
1089
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1090
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : undefined,
|
|
1091
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath : undefined,
|
|
477
1092
|
}));
|
|
478
1093
|
return;
|
|
479
1094
|
}
|
|
@@ -487,7 +1102,7 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
487
1102
|
return;
|
|
488
1103
|
}
|
|
489
1104
|
const overwrite = getUpdateOverwriteMode(status, opts.force);
|
|
490
|
-
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, overwrite);
|
|
1105
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, overwrite);
|
|
491
1106
|
if (opts.plan) {
|
|
492
1107
|
emitOutput(format, buildPlanPayload("update", target, destinationRoot, plan, {
|
|
493
1108
|
autoResolvedRoot,
|
|
@@ -495,14 +1110,84 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
495
1110
|
hint: targetResolution.hint,
|
|
496
1111
|
scope,
|
|
497
1112
|
status: status.kind,
|
|
1113
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
1114
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1115
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
1116
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? null : null,
|
|
498
1117
|
}), summarizePlan("update", target, destinationRoot, plan, {
|
|
499
1118
|
autoResolvedRoot,
|
|
500
1119
|
rootSource: targetResolution.source,
|
|
501
1120
|
hint: targetResolution.hint,
|
|
1121
|
+
scope,
|
|
502
1122
|
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1123
|
+
installSource: target === "qwen" && scope === "global" ? qwenInstallSource : null,
|
|
1124
|
+
sourceRef: target === "qwen" && scope === "global" && qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1125
|
+
bundleType: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
1126
|
+
bundlePath: target === "qwen" && scope === "global" && qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? null : null,
|
|
503
1127
|
}));
|
|
504
1128
|
return;
|
|
505
1129
|
}
|
|
1130
|
+
if (shouldPreferQwenOfficialCli(target, scope)) {
|
|
1131
|
+
try {
|
|
1132
|
+
if (format === "text") {
|
|
1133
|
+
console.log("正在调用官方命令:qwen extensions update …");
|
|
1134
|
+
}
|
|
1135
|
+
if (qwenInstallSource === "github-repo") {
|
|
1136
|
+
await updateQwenExtensionWithOfficialCli(plan.capability?.extension?.name ?? "zc-toolkit");
|
|
1137
|
+
}
|
|
1138
|
+
else {
|
|
1139
|
+
const releaseBundle = await syncQwenOfficialCliReleaseBundle(plan);
|
|
1140
|
+
await uninstallQwenExtensionWithOfficialCli(releaseBundle.extensionName);
|
|
1141
|
+
await relinkQwenExtensionWithOfficialCli(releaseBundle.bundleDir);
|
|
1142
|
+
}
|
|
1143
|
+
await writePlatformInstallReceiptForPlan(plan, {
|
|
1144
|
+
installedAt: new Date().toISOString(),
|
|
1145
|
+
zcVersion,
|
|
1146
|
+
installMethod: "qwen-cli",
|
|
1147
|
+
installSource: qwenInstallSource,
|
|
1148
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : undefined,
|
|
1149
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : undefined,
|
|
1150
|
+
bundlePath: qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? undefined : undefined,
|
|
1151
|
+
});
|
|
1152
|
+
const result = estimateManagedInstallResult(plan, status);
|
|
1153
|
+
emitOutput(format, buildResultPayload("update", target, destinationRoot, result, {
|
|
1154
|
+
autoResolvedRoot,
|
|
1155
|
+
rootSource: targetResolution.source,
|
|
1156
|
+
hint: targetResolution.hint,
|
|
1157
|
+
scope,
|
|
1158
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1159
|
+
zcVersion,
|
|
1160
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1161
|
+
status: status.kind,
|
|
1162
|
+
installMethod: "qwen-cli",
|
|
1163
|
+
installSource: qwenInstallSource,
|
|
1164
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1165
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
1166
|
+
bundlePath: qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? null : null,
|
|
1167
|
+
}), summarizeResult("update", target, destinationRoot, result, {
|
|
1168
|
+
autoResolvedRoot,
|
|
1169
|
+
rootSource: targetResolution.source,
|
|
1170
|
+
hint: targetResolution.hint,
|
|
1171
|
+
scope,
|
|
1172
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1173
|
+
zcVersion,
|
|
1174
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1175
|
+
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1176
|
+
installMethod: "qwen-cli",
|
|
1177
|
+
installSource: qwenInstallSource,
|
|
1178
|
+
sourceRef: qwenInstallSource === "github-repo" ? qwenOfficialExtensionRepoUrl : null,
|
|
1179
|
+
bundleType: qwenInstallSource === "local-bundle" ? "release-bundle" : null,
|
|
1180
|
+
bundlePath: qwenInstallSource === "local-bundle" ? qwenReleaseBundlePath ?? null : null,
|
|
1181
|
+
}));
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
catch (error) {
|
|
1185
|
+
if (!(error instanceof QwenOfficialCliUnavailableError)) {
|
|
1186
|
+
throw error;
|
|
1187
|
+
}
|
|
1188
|
+
fallbackHint = "未检测到 qwen CLI,已回退为直接写入官方扩展目录。";
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
506
1191
|
const result = await writeArtifacts(plan.artifacts.map((artifact) => ({
|
|
507
1192
|
path: artifact.path,
|
|
508
1193
|
content: artifact.content,
|
|
@@ -517,20 +1202,31 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
517
1202
|
emitOutput(format, buildResultPayload("update", target, destinationRoot, result, {
|
|
518
1203
|
autoResolvedRoot,
|
|
519
1204
|
rootSource: targetResolution.source,
|
|
520
|
-
hint: targetResolution.hint,
|
|
1205
|
+
hint: mergeHints(targetResolution.hint, fallbackHint),
|
|
521
1206
|
scope,
|
|
522
1207
|
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
523
1208
|
zcVersion,
|
|
524
1209
|
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
525
1210
|
status: status.kind,
|
|
1211
|
+
installMethod: "filesystem",
|
|
1212
|
+
installSource: null,
|
|
1213
|
+
sourceRef: null,
|
|
1214
|
+
bundleType: null,
|
|
1215
|
+
bundlePath: null,
|
|
526
1216
|
}), summarizeResult("update", target, destinationRoot, result, {
|
|
527
1217
|
autoResolvedRoot,
|
|
528
1218
|
rootSource: targetResolution.source,
|
|
529
|
-
hint: targetResolution.hint,
|
|
1219
|
+
hint: mergeHints(targetResolution.hint, fallbackHint),
|
|
1220
|
+
scope,
|
|
530
1221
|
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
531
1222
|
zcVersion,
|
|
532
1223
|
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
533
1224
|
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1225
|
+
installMethod: "filesystem",
|
|
1226
|
+
installSource: null,
|
|
1227
|
+
sourceRef: null,
|
|
1228
|
+
bundleType: undefined,
|
|
1229
|
+
bundlePath: undefined,
|
|
534
1230
|
}));
|
|
535
1231
|
}
|
|
536
1232
|
catch (error) {
|
|
@@ -543,6 +1239,382 @@ export async function runPlatformUpdate(target, opts) {
|
|
|
543
1239
|
process.exitCode = 1;
|
|
544
1240
|
}
|
|
545
1241
|
}
|
|
1242
|
+
export async function runPlatformUninstall(target, opts) {
|
|
1243
|
+
const format = resolveOutputFormat(opts.json);
|
|
1244
|
+
try {
|
|
1245
|
+
const scope = resolveScopeFromSelector(opts);
|
|
1246
|
+
const targetResolution = await resolveInstallTarget(target, {
|
|
1247
|
+
dir: opts.dir,
|
|
1248
|
+
cwd: process.cwd(),
|
|
1249
|
+
project: opts.project,
|
|
1250
|
+
global: opts.global,
|
|
1251
|
+
});
|
|
1252
|
+
const autoResolvedRoot = targetResolution.source !== "explicit";
|
|
1253
|
+
const destinationRoot = resolve(targetResolution.root);
|
|
1254
|
+
const manifest = await loadToolkitManifest();
|
|
1255
|
+
const platformModule = await loadPlatformModule(target);
|
|
1256
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, "error");
|
|
1257
|
+
const status = await resolvePlatformInstallStatus(plan);
|
|
1258
|
+
if (!status.receipt) {
|
|
1259
|
+
emitPlatformError(format, target, "uninstall", `${target} 当前目录没有受管安装回执,拒绝自动卸载。请先运行 \`zc platform status ${target}\` 检查。`, {
|
|
1260
|
+
root: destinationRoot,
|
|
1261
|
+
receiptPath: status.receiptPath,
|
|
1262
|
+
status: status.kind,
|
|
1263
|
+
});
|
|
1264
|
+
process.exitCode = 1;
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
if (status.kind === "drifted" && !opts.force) {
|
|
1268
|
+
emitPlatformError(format, target, "uninstall", `${target} 安装目录已漂移。请先运行 \`zc platform doctor ${target}\` 或 \`zc platform status ${target}\` 检查,确认后追加 \`--force\` 再卸载。`, {
|
|
1269
|
+
root: destinationRoot,
|
|
1270
|
+
receiptPath: status.receiptPath,
|
|
1271
|
+
status: status.kind,
|
|
1272
|
+
});
|
|
1273
|
+
process.exitCode = 1;
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
const installMethod = status.receipt.installMethod ?? "filesystem";
|
|
1277
|
+
const installSource = status.receipt.installSource ?? null;
|
|
1278
|
+
const sourceRef = status.receipt.sourceRef ?? null;
|
|
1279
|
+
const bundlePath = status.receipt.bundlePath ?? null;
|
|
1280
|
+
if (opts.plan) {
|
|
1281
|
+
emitOutput(format, {
|
|
1282
|
+
mode: "plan",
|
|
1283
|
+
action: "uninstall",
|
|
1284
|
+
target,
|
|
1285
|
+
root: destinationRoot,
|
|
1286
|
+
scope,
|
|
1287
|
+
rootSource: targetResolution.source,
|
|
1288
|
+
autoResolvedRoot,
|
|
1289
|
+
hint: targetResolution.hint ?? null,
|
|
1290
|
+
status: status.kind,
|
|
1291
|
+
receiptPath: status.receiptPath,
|
|
1292
|
+
installMethod,
|
|
1293
|
+
installSource,
|
|
1294
|
+
sourceRef,
|
|
1295
|
+
bundlePath,
|
|
1296
|
+
artifactCount: status.receipt.artifacts.length,
|
|
1297
|
+
artifacts: status.receipt.artifacts.map((artifact) => artifact.path),
|
|
1298
|
+
}, [
|
|
1299
|
+
`${target} 卸载计划`,
|
|
1300
|
+
formatRootLabel("uninstall", destinationRoot, {
|
|
1301
|
+
autoResolvedRoot,
|
|
1302
|
+
rootSource: targetResolution.source,
|
|
1303
|
+
hint: targetResolution.hint,
|
|
1304
|
+
}),
|
|
1305
|
+
`状态:${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1306
|
+
`安装方式:${installMethod === "qwen-cli" ? "官方 qwen extensions CLI" : "直接写入"}`,
|
|
1307
|
+
...(installSource ? [`安装来源:${installSource === "github-repo" ? "GitHub 扩展仓库" : "本地 bundle"}`] : []),
|
|
1308
|
+
...(sourceRef ? [`来源:${sourceRef}`] : []),
|
|
1309
|
+
`回执:${status.receiptPath}`,
|
|
1310
|
+
...(bundlePath ? [`Bundle 目录:${bundlePath}`] : []),
|
|
1311
|
+
`受管产物:${status.receipt.artifacts.length}`,
|
|
1312
|
+
...status.receipt.artifacts.map((artifact) => `- ${artifact.path}`),
|
|
1313
|
+
].join("\n"));
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
let artifactCleanup = { removed: 0, missing: 0 };
|
|
1317
|
+
if (target === "qwen" && installMethod === "qwen-cli") {
|
|
1318
|
+
const extensionName = plan.capability?.extension?.name ?? "zc-toolkit";
|
|
1319
|
+
if (format === "text") {
|
|
1320
|
+
console.log(`正在调用官方命令:qwen extensions uninstall ${extensionName} …`);
|
|
1321
|
+
}
|
|
1322
|
+
await uninstallQwenExtensionWithOfficialCli(extensionName);
|
|
1323
|
+
}
|
|
1324
|
+
else {
|
|
1325
|
+
artifactCleanup = await removeManagedPaths(status.receipt.artifacts.map((artifact) => artifact.path));
|
|
1326
|
+
}
|
|
1327
|
+
const bundleCleanup = await removeOptionalManagedPath(bundlePath);
|
|
1328
|
+
const receiptExisted = await pathExists(status.receiptPath);
|
|
1329
|
+
if (receiptExisted) {
|
|
1330
|
+
await deletePlatformInstallReceipt(status.receiptPath);
|
|
1331
|
+
}
|
|
1332
|
+
const result = {
|
|
1333
|
+
removedArtifacts: artifactCleanup.removed,
|
|
1334
|
+
missingArtifacts: artifactCleanup.missing,
|
|
1335
|
+
bundleRemoved: bundleCleanup.removed,
|
|
1336
|
+
bundleMissing: bundleCleanup.missing,
|
|
1337
|
+
receiptRemoved: receiptExisted,
|
|
1338
|
+
receiptMissing: !receiptExisted,
|
|
1339
|
+
};
|
|
1340
|
+
emitOutput(format, buildUninstallPayload(target, destinationRoot, result, {
|
|
1341
|
+
autoResolvedRoot,
|
|
1342
|
+
rootSource: targetResolution.source,
|
|
1343
|
+
hint: targetResolution.hint,
|
|
1344
|
+
scope,
|
|
1345
|
+
receiptPath: status.receiptPath,
|
|
1346
|
+
installMethod,
|
|
1347
|
+
installSource,
|
|
1348
|
+
sourceRef,
|
|
1349
|
+
bundlePath,
|
|
1350
|
+
}), summarizeUninstall(target, destinationRoot, result, {
|
|
1351
|
+
autoResolvedRoot,
|
|
1352
|
+
rootSource: targetResolution.source,
|
|
1353
|
+
hint: targetResolution.hint,
|
|
1354
|
+
scope,
|
|
1355
|
+
receiptPath: status.receiptPath,
|
|
1356
|
+
installMethod,
|
|
1357
|
+
installSource,
|
|
1358
|
+
sourceRef,
|
|
1359
|
+
bundlePath,
|
|
1360
|
+
}));
|
|
1361
|
+
}
|
|
1362
|
+
catch (error) {
|
|
1363
|
+
emitPlatformError(format, target, "uninstall", error instanceof Error ? `${target} 卸载失败:${error.message}` : `${target} 卸载失败。`);
|
|
1364
|
+
process.exitCode = 1;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
export async function runPlatformRepair(target, opts) {
|
|
1368
|
+
const format = resolveOutputFormat(opts.json);
|
|
1369
|
+
try {
|
|
1370
|
+
const scope = resolveScopeFromSelector(opts);
|
|
1371
|
+
const targetResolution = await resolveInstallTarget(target, {
|
|
1372
|
+
dir: opts.dir,
|
|
1373
|
+
cwd: process.cwd(),
|
|
1374
|
+
project: opts.project,
|
|
1375
|
+
global: opts.global,
|
|
1376
|
+
});
|
|
1377
|
+
const autoResolvedRoot = targetResolution.source !== "explicit";
|
|
1378
|
+
const destinationRoot = resolve(targetResolution.root);
|
|
1379
|
+
const manifest = await loadToolkitManifest();
|
|
1380
|
+
const platformModule = await loadPlatformModule(target);
|
|
1381
|
+
const statusPlan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, "error");
|
|
1382
|
+
const status = await resolvePlatformInstallStatus(statusPlan);
|
|
1383
|
+
if (!status.receipt) {
|
|
1384
|
+
emitPlatformError(format, target, "repair", `${target} 当前目录尚未建立受管安装状态。请先运行 \`zc platform install ${target}\`。`, {
|
|
1385
|
+
root: destinationRoot,
|
|
1386
|
+
receiptPath: status.receiptPath,
|
|
1387
|
+
});
|
|
1388
|
+
process.exitCode = 1;
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
const installMethod = status.receipt.installMethod ?? "filesystem";
|
|
1392
|
+
const installSource = status.receipt.installSource
|
|
1393
|
+
?? (target === "qwen" && scope === "global" ? "github-repo" : undefined);
|
|
1394
|
+
const sourceRef = status.receipt.sourceRef
|
|
1395
|
+
?? (installSource === "github-repo" ? qwenOfficialExtensionRepoUrl : undefined);
|
|
1396
|
+
const bundlePath = status.receipt.bundlePath
|
|
1397
|
+
?? (shouldPreferQwenOfficialCli(target, scope) ? resolveQwenOfficialCliReleaseBundleDir(statusPlan) : null);
|
|
1398
|
+
const bundleMissing = installSource === "local-bundle" && bundlePath ? !(await pathExists(bundlePath)) : false;
|
|
1399
|
+
if (status.kind === "up-to-date" && !(target === "qwen" && installMethod === "qwen-cli" && bundleMissing)) {
|
|
1400
|
+
const result = {
|
|
1401
|
+
created: 0,
|
|
1402
|
+
overwritten: 0,
|
|
1403
|
+
unchanged: status.summary.trackedArtifacts,
|
|
1404
|
+
skipped: 0,
|
|
1405
|
+
dryRun: false,
|
|
1406
|
+
};
|
|
1407
|
+
emitOutput(format, buildResultPayload("repair", target, destinationRoot, result, {
|
|
1408
|
+
autoResolvedRoot,
|
|
1409
|
+
rootSource: targetResolution.source,
|
|
1410
|
+
hint: targetResolution.hint,
|
|
1411
|
+
scope,
|
|
1412
|
+
receiptPath: status.receiptPath,
|
|
1413
|
+
zcVersion: getCliVersion(),
|
|
1414
|
+
contentFingerprint: status.contentFingerprint ?? null,
|
|
1415
|
+
status: status.kind,
|
|
1416
|
+
noop: true,
|
|
1417
|
+
installMethod,
|
|
1418
|
+
installSource,
|
|
1419
|
+
sourceRef,
|
|
1420
|
+
bundleType: status.receipt.bundleType ?? null,
|
|
1421
|
+
bundlePath,
|
|
1422
|
+
}), summarizeResult("repair", target, destinationRoot, result, {
|
|
1423
|
+
autoResolvedRoot,
|
|
1424
|
+
rootSource: targetResolution.source,
|
|
1425
|
+
hint: targetResolution.hint,
|
|
1426
|
+
scope,
|
|
1427
|
+
receiptPath: status.receiptPath,
|
|
1428
|
+
zcVersion: getCliVersion(),
|
|
1429
|
+
contentFingerprint: status.contentFingerprint ?? null,
|
|
1430
|
+
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1431
|
+
noop: true,
|
|
1432
|
+
installMethod,
|
|
1433
|
+
installSource,
|
|
1434
|
+
sourceRef,
|
|
1435
|
+
bundleType: status.receipt.bundleType ?? undefined,
|
|
1436
|
+
bundlePath: bundlePath ?? undefined,
|
|
1437
|
+
}));
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
const overwrite = "force";
|
|
1441
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, overwrite);
|
|
1442
|
+
if (opts.plan) {
|
|
1443
|
+
emitOutput(format, buildPlanPayload("repair", target, destinationRoot, plan, {
|
|
1444
|
+
autoResolvedRoot,
|
|
1445
|
+
rootSource: targetResolution.source,
|
|
1446
|
+
hint: targetResolution.hint,
|
|
1447
|
+
scope,
|
|
1448
|
+
status: status.kind,
|
|
1449
|
+
installSource: installSource ?? null,
|
|
1450
|
+
sourceRef: sourceRef ?? null,
|
|
1451
|
+
bundleType: status.receipt.bundleType ?? null,
|
|
1452
|
+
bundlePath: bundlePath ?? null,
|
|
1453
|
+
}), summarizePlan("repair", target, destinationRoot, plan, {
|
|
1454
|
+
autoResolvedRoot,
|
|
1455
|
+
rootSource: targetResolution.source,
|
|
1456
|
+
hint: targetResolution.hint,
|
|
1457
|
+
scope,
|
|
1458
|
+
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1459
|
+
installSource: installSource ?? null,
|
|
1460
|
+
sourceRef: sourceRef ?? null,
|
|
1461
|
+
bundleType: status.receipt.bundleType ?? null,
|
|
1462
|
+
bundlePath: bundlePath ?? null,
|
|
1463
|
+
}));
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
if (target === "qwen" && installMethod === "qwen-cli") {
|
|
1467
|
+
if (format === "text") {
|
|
1468
|
+
console.log(`正在调用官方命令:qwen extensions ${installSource === "github-repo" ? "update" : bundleMissing ? "link" : "relink"} …`);
|
|
1469
|
+
}
|
|
1470
|
+
let repairedBundlePath;
|
|
1471
|
+
if (installSource === "github-repo") {
|
|
1472
|
+
await updateQwenExtensionWithOfficialCli(plan.capability?.extension?.name ?? "zc-toolkit");
|
|
1473
|
+
}
|
|
1474
|
+
else {
|
|
1475
|
+
const releaseBundle = await syncQwenOfficialCliReleaseBundle(plan);
|
|
1476
|
+
repairedBundlePath = releaseBundle.bundleDir;
|
|
1477
|
+
if (bundleMissing) {
|
|
1478
|
+
await relinkQwenExtensionWithOfficialCli(releaseBundle.bundleDir);
|
|
1479
|
+
}
|
|
1480
|
+
else {
|
|
1481
|
+
await uninstallQwenExtensionWithOfficialCli(releaseBundle.extensionName);
|
|
1482
|
+
await relinkQwenExtensionWithOfficialCli(releaseBundle.bundleDir);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
await writePlatformInstallReceiptForPlan(plan, {
|
|
1486
|
+
installedAt: new Date().toISOString(),
|
|
1487
|
+
zcVersion: getCliVersion(),
|
|
1488
|
+
installMethod: "qwen-cli",
|
|
1489
|
+
installSource,
|
|
1490
|
+
sourceRef,
|
|
1491
|
+
bundleType: installSource === "local-bundle" ? "release-bundle" : undefined,
|
|
1492
|
+
bundlePath: installSource === "local-bundle" ? repairedBundlePath ?? bundlePath ?? undefined : undefined,
|
|
1493
|
+
});
|
|
1494
|
+
const result = status.kind === "up-to-date"
|
|
1495
|
+
? {
|
|
1496
|
+
created: 0,
|
|
1497
|
+
overwritten: 0,
|
|
1498
|
+
unchanged: plan.artifacts.length,
|
|
1499
|
+
skipped: 0,
|
|
1500
|
+
dryRun: false,
|
|
1501
|
+
}
|
|
1502
|
+
: estimateManagedInstallResult(plan, status);
|
|
1503
|
+
emitOutput(format, buildResultPayload("repair", target, destinationRoot, result, {
|
|
1504
|
+
autoResolvedRoot,
|
|
1505
|
+
rootSource: targetResolution.source,
|
|
1506
|
+
hint: targetResolution.hint,
|
|
1507
|
+
scope,
|
|
1508
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1509
|
+
zcVersion: getCliVersion(),
|
|
1510
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1511
|
+
status: status.kind,
|
|
1512
|
+
installMethod: "qwen-cli",
|
|
1513
|
+
installSource,
|
|
1514
|
+
sourceRef,
|
|
1515
|
+
bundleType: installSource === "local-bundle" ? "release-bundle" : null,
|
|
1516
|
+
bundlePath: installSource === "local-bundle" ? repairedBundlePath ?? bundlePath ?? null : null,
|
|
1517
|
+
}), summarizeResult("repair", target, destinationRoot, result, {
|
|
1518
|
+
autoResolvedRoot,
|
|
1519
|
+
rootSource: targetResolution.source,
|
|
1520
|
+
hint: targetResolution.hint,
|
|
1521
|
+
scope,
|
|
1522
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1523
|
+
zcVersion: getCliVersion(),
|
|
1524
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1525
|
+
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1526
|
+
installMethod: "qwen-cli",
|
|
1527
|
+
installSource,
|
|
1528
|
+
sourceRef,
|
|
1529
|
+
bundleType: installSource === "local-bundle" ? "release-bundle" : null,
|
|
1530
|
+
bundlePath: installSource === "local-bundle" ? repairedBundlePath ?? bundlePath ?? null : null,
|
|
1531
|
+
}));
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
const result = await writeArtifacts(plan.artifacts.map((artifact) => ({
|
|
1535
|
+
path: artifact.path,
|
|
1536
|
+
content: artifact.content,
|
|
1537
|
+
})), {
|
|
1538
|
+
dryRun: false,
|
|
1539
|
+
overwrite,
|
|
1540
|
+
});
|
|
1541
|
+
await writePlatformInstallReceiptForPlan(plan, {
|
|
1542
|
+
installedAt: new Date().toISOString(),
|
|
1543
|
+
zcVersion: getCliVersion(),
|
|
1544
|
+
installMethod,
|
|
1545
|
+
installSource,
|
|
1546
|
+
sourceRef,
|
|
1547
|
+
bundleType: status.receipt.bundleType,
|
|
1548
|
+
bundlePath: status.receipt.bundlePath,
|
|
1549
|
+
});
|
|
1550
|
+
emitOutput(format, buildResultPayload("repair", target, destinationRoot, result, {
|
|
1551
|
+
autoResolvedRoot,
|
|
1552
|
+
rootSource: targetResolution.source,
|
|
1553
|
+
hint: targetResolution.hint,
|
|
1554
|
+
scope,
|
|
1555
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1556
|
+
zcVersion: getCliVersion(),
|
|
1557
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1558
|
+
status: status.kind,
|
|
1559
|
+
installMethod,
|
|
1560
|
+
installSource,
|
|
1561
|
+
sourceRef,
|
|
1562
|
+
bundleType: status.receipt.bundleType ?? null,
|
|
1563
|
+
bundlePath: status.receipt.bundlePath ?? null,
|
|
1564
|
+
}), summarizeResult("repair", target, destinationRoot, result, {
|
|
1565
|
+
autoResolvedRoot,
|
|
1566
|
+
rootSource: targetResolution.source,
|
|
1567
|
+
hint: targetResolution.hint,
|
|
1568
|
+
scope,
|
|
1569
|
+
receiptPath: resolvePlatformInstallReceiptPath(plan),
|
|
1570
|
+
zcVersion: getCliVersion(),
|
|
1571
|
+
contentFingerprint: plan.metadata?.fingerprint.value ?? null,
|
|
1572
|
+
status: `${status.kind}(${formatStatusLabel(status.kind)})`,
|
|
1573
|
+
installMethod,
|
|
1574
|
+
installSource,
|
|
1575
|
+
sourceRef,
|
|
1576
|
+
bundleType: status.receipt.bundleType ?? undefined,
|
|
1577
|
+
bundlePath: status.receipt.bundlePath ?? undefined,
|
|
1578
|
+
}));
|
|
1579
|
+
}
|
|
1580
|
+
catch (error) {
|
|
1581
|
+
emitPlatformError(format, target, "repair", error instanceof Error ? `${target} 修复失败:${error.message}` : `${target} 修复失败。`);
|
|
1582
|
+
process.exitCode = 1;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
export async function runPlatformDoctor(target, opts) {
|
|
1586
|
+
const format = resolveOutputFormat(opts.json);
|
|
1587
|
+
try {
|
|
1588
|
+
const scope = resolveScopeFromSelector(opts);
|
|
1589
|
+
const targetResolution = await resolveInstallTarget(target, {
|
|
1590
|
+
dir: opts.dir,
|
|
1591
|
+
cwd: process.cwd(),
|
|
1592
|
+
project: opts.project,
|
|
1593
|
+
global: opts.global,
|
|
1594
|
+
});
|
|
1595
|
+
const destinationRoot = resolve(targetResolution.root);
|
|
1596
|
+
const manifest = await loadToolkitManifest();
|
|
1597
|
+
const platformModule = await loadPlatformModule(target);
|
|
1598
|
+
const plan = createInstallPlan(target, platformModule, manifest, destinationRoot, scope, "error");
|
|
1599
|
+
const status = await resolvePlatformInstallStatus(plan);
|
|
1600
|
+
const doctor = await resolvePlatformInstallDoctor(plan, status);
|
|
1601
|
+
emitOutput(format, buildDoctorPayload(target, destinationRoot, status, doctor, {
|
|
1602
|
+
scope,
|
|
1603
|
+
rootSource: targetResolution.source,
|
|
1604
|
+
hint: targetResolution.hint,
|
|
1605
|
+
plan,
|
|
1606
|
+
}), summarizeDoctor(target, destinationRoot, status, doctor, {
|
|
1607
|
+
scope,
|
|
1608
|
+
rootSource: targetResolution.source,
|
|
1609
|
+
hint: targetResolution.hint,
|
|
1610
|
+
plan,
|
|
1611
|
+
}));
|
|
1612
|
+
}
|
|
1613
|
+
catch (error) {
|
|
1614
|
+
emitPlatformError(format, target, "doctor", error instanceof Error ? `${target} 诊断失败:${error.message}` : `${target} 诊断失败。`);
|
|
1615
|
+
process.exitCode = 1;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
546
1618
|
export async function runPlatformWhere(target, opts) {
|
|
547
1619
|
const format = resolveOutputFormat(opts.json);
|
|
548
1620
|
try {
|
|
@@ -554,16 +1626,21 @@ export async function runPlatformWhere(target, opts) {
|
|
|
554
1626
|
global: opts.global,
|
|
555
1627
|
});
|
|
556
1628
|
const root = resolve(targetResolution.root);
|
|
1629
|
+
const manifest = await loadToolkitManifest();
|
|
1630
|
+
const platformModule = await loadPlatformModule(target);
|
|
1631
|
+
const plan = createInstallPlan(target, platformModule, manifest, root, scope, "error");
|
|
557
1632
|
emitOutput(format, buildWherePayload(target, root, {
|
|
558
1633
|
scope,
|
|
559
1634
|
rootSource: targetResolution.source,
|
|
560
1635
|
marker: targetResolution.marker,
|
|
561
1636
|
hint: targetResolution.hint,
|
|
1637
|
+
capability: getPlanCapabilitySummary(plan),
|
|
562
1638
|
}), summarizeWhere(target, root, {
|
|
563
1639
|
scope,
|
|
564
1640
|
rootSource: targetResolution.source,
|
|
565
1641
|
marker: targetResolution.marker,
|
|
566
1642
|
hint: targetResolution.hint,
|
|
1643
|
+
capability: getPlanCapabilitySummary(plan),
|
|
567
1644
|
}));
|
|
568
1645
|
}
|
|
569
1646
|
catch (error) {
|
|
@@ -578,58 +1655,89 @@ function parsePlatformName(value) {
|
|
|
578
1655
|
throw new InvalidArgumentError(`不支持的平台:${value}。可选值:${platformNames.join(" | ")}`);
|
|
579
1656
|
}
|
|
580
1657
|
export function registerPlatformCommand(program) {
|
|
581
|
-
const platform = program.command("platform").description("
|
|
1658
|
+
const platform = program.command("platform").description("查看、安装、更新和诊断平台内容");
|
|
582
1659
|
platform
|
|
583
1660
|
.command("generate")
|
|
584
1661
|
.alias("g")
|
|
585
|
-
.description("
|
|
586
|
-
.argument("<target>", "目标平台 (qwen|codex|
|
|
1662
|
+
.description("导出平台内容或 Qwen 发布 bundle")
|
|
1663
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
587
1664
|
.option("-d, --dir <dir>", "输出目录")
|
|
588
|
-
.option("--
|
|
589
|
-
.option("
|
|
1665
|
+
.option("-b, --bundle <type>", "导出指定 bundle 布局(当前仅 qwen: release-bundle)", parseGenerateBundleType)
|
|
1666
|
+
.option("--plan", "只查看生成计划,不写文件")
|
|
1667
|
+
.option("-j, --json", "输出 JSON")
|
|
590
1668
|
.option("-f, --force", "覆盖目标目录中已有但内容不同的产物")
|
|
591
1669
|
.action(runPlatformGenerate);
|
|
592
1670
|
platform
|
|
593
1671
|
.command("install")
|
|
594
1672
|
.alias("i")
|
|
595
|
-
.description("
|
|
596
|
-
.argument("<target>", "目标平台 (qwen|codex|
|
|
597
|
-
.option("-d, --dir <dir>", "
|
|
1673
|
+
.description("把平台内容安装到项目、用户级或指定目录")
|
|
1674
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1675
|
+
.option("-d, --dir <dir>", "安装到指定目录")
|
|
598
1676
|
.option("-p, --project", "安装到当前目录向上解析出的最近项目根")
|
|
599
|
-
.option("-g, --global", "
|
|
600
|
-
.option("--plan", "
|
|
601
|
-
.option("-j, --json", "
|
|
1677
|
+
.option("-g, --global", "安装到官方文档定义的用户级默认位置")
|
|
1678
|
+
.option("--plan", "只查看安装计划,不写文件")
|
|
1679
|
+
.option("-j, --json", "输出 JSON")
|
|
602
1680
|
.option("-f, --force", "覆盖目标目录中已有但内容不同的产物")
|
|
603
1681
|
.action(runPlatformInstall);
|
|
604
1682
|
platform
|
|
605
1683
|
.command("where")
|
|
606
1684
|
.alias("w")
|
|
607
|
-
.description("
|
|
608
|
-
.argument("<target>", "目标平台 (qwen|codex|
|
|
609
|
-
.option("-d, --dir <dir>", "
|
|
1685
|
+
.description("查看平台内容会安装到哪里")
|
|
1686
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1687
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
610
1688
|
.option("-p, --project", "解析最近项目根")
|
|
611
1689
|
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
612
|
-
.option("-j, --json", "
|
|
1690
|
+
.option("-j, --json", "输出 JSON")
|
|
613
1691
|
.action(runPlatformWhere);
|
|
614
1692
|
platform
|
|
615
1693
|
.command("status")
|
|
616
|
-
.description("
|
|
617
|
-
.argument("<target>", "目标平台 (qwen|codex|
|
|
618
|
-
.option("-d, --dir <dir>", "
|
|
1694
|
+
.description("查看是否已安装、是否可更新、是否漂移")
|
|
1695
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1696
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
619
1697
|
.option("-p, --project", "解析最近项目根")
|
|
620
1698
|
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
621
|
-
.option("-j, --json", "
|
|
1699
|
+
.option("-j, --json", "输出 JSON")
|
|
622
1700
|
.action(runPlatformStatus);
|
|
623
1701
|
platform
|
|
624
1702
|
.command("update")
|
|
625
|
-
.description("
|
|
626
|
-
.argument("<target>", "目标平台 (qwen|codex|
|
|
627
|
-
.option("-d, --dir <dir>", "
|
|
1703
|
+
.description("更新已安装的平台内容")
|
|
1704
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1705
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
628
1706
|
.option("-p, --project", "解析最近项目根")
|
|
629
1707
|
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
630
|
-
.option("--plan", "
|
|
631
|
-
.option("-j, --json", "
|
|
1708
|
+
.option("--plan", "只查看更新计划,不写文件")
|
|
1709
|
+
.option("-j, --json", "输出 JSON")
|
|
632
1710
|
.option("-f, --force", "覆盖已漂移的已安装产物")
|
|
633
1711
|
.action(runPlatformUpdate);
|
|
1712
|
+
platform
|
|
1713
|
+
.command("uninstall")
|
|
1714
|
+
.description("卸载受管平台内容并删除安装记录")
|
|
1715
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1716
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
1717
|
+
.option("-p, --project", "解析最近项目根")
|
|
1718
|
+
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
1719
|
+
.option("--plan", "只查看卸载计划,不写文件")
|
|
1720
|
+
.option("-j, --json", "输出 JSON")
|
|
1721
|
+
.option("-f, --force", "允许卸载已漂移的受管内容")
|
|
1722
|
+
.action(runPlatformUninstall);
|
|
1723
|
+
platform
|
|
1724
|
+
.command("repair")
|
|
1725
|
+
.description("修复漂移、缺失或官方 CLI 失配的安装")
|
|
1726
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1727
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
1728
|
+
.option("-p, --project", "解析最近项目根")
|
|
1729
|
+
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
1730
|
+
.option("--plan", "只查看修复计划,不写文件")
|
|
1731
|
+
.option("-j, --json", "输出 JSON")
|
|
1732
|
+
.action(runPlatformRepair);
|
|
1733
|
+
platform
|
|
1734
|
+
.command("doctor")
|
|
1735
|
+
.description("诊断当前平台安装的健康度和下一步建议")
|
|
1736
|
+
.argument("<target>", "目标平台 (qwen|codex|claude|opencode)", parsePlatformName)
|
|
1737
|
+
.option("-d, --dir <dir>", "指定目录")
|
|
1738
|
+
.option("-p, --project", "解析最近项目根")
|
|
1739
|
+
.option("-g, --global", "解析官方文档定义的默认全局位置")
|
|
1740
|
+
.option("-j, --json", "输出 JSON")
|
|
1741
|
+
.action(runPlatformDoctor);
|
|
634
1742
|
}
|
|
635
1743
|
//# sourceMappingURL=platform.js.map
|