@superkou/openspec 1.4.1
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 +22 -0
- package/README.md +213 -0
- package/bin/openspec.js +5 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +544 -0
- package/dist/commands/change.d.ts +35 -0
- package/dist/commands/change.js +277 -0
- package/dist/commands/completion.d.ts +72 -0
- package/dist/commands/completion.js +264 -0
- package/dist/commands/config.d.ts +36 -0
- package/dist/commands/config.js +611 -0
- package/dist/commands/context-store.d.ts +3 -0
- package/dist/commands/context-store.js +475 -0
- package/dist/commands/feedback.d.ts +9 -0
- package/dist/commands/feedback.js +183 -0
- package/dist/commands/initiative.d.ts +13 -0
- package/dist/commands/initiative.js +318 -0
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/schema.js +869 -0
- package/dist/commands/show.d.ts +14 -0
- package/dist/commands/show.js +132 -0
- package/dist/commands/spec.d.ts +15 -0
- package/dist/commands/spec.js +225 -0
- package/dist/commands/validate.d.ts +24 -0
- package/dist/commands/validate.js +294 -0
- package/dist/commands/workflow/index.d.ts +19 -0
- package/dist/commands/workflow/index.js +13 -0
- package/dist/commands/workflow/initiative-link.d.ts +24 -0
- package/dist/commands/workflow/initiative-link.js +47 -0
- package/dist/commands/workflow/instructions.d.ts +29 -0
- package/dist/commands/workflow/instructions.js +344 -0
- package/dist/commands/workflow/new-change.d.ts +17 -0
- package/dist/commands/workflow/new-change.js +141 -0
- package/dist/commands/workflow/schemas.d.ts +10 -0
- package/dist/commands/workflow/schemas.js +34 -0
- package/dist/commands/workflow/set-change.d.ts +13 -0
- package/dist/commands/workflow/set-change.js +87 -0
- package/dist/commands/workflow/shared.d.ts +59 -0
- package/dist/commands/workflow/shared.js +116 -0
- package/dist/commands/workflow/status.d.ts +14 -0
- package/dist/commands/workflow/status.js +90 -0
- package/dist/commands/workflow/templates.d.ts +16 -0
- package/dist/commands/workflow/templates.js +69 -0
- package/dist/commands/workspace/context-status.d.ts +4 -0
- package/dist/commands/workspace/context-status.js +59 -0
- package/dist/commands/workspace/open-target-selection.d.ts +13 -0
- package/dist/commands/workspace/open-target-selection.js +146 -0
- package/dist/commands/workspace/open-view.d.ts +62 -0
- package/dist/commands/workspace/open-view.js +249 -0
- package/dist/commands/workspace/open.d.ts +37 -0
- package/dist/commands/workspace/open.js +110 -0
- package/dist/commands/workspace/opener-selection.d.ts +11 -0
- package/dist/commands/workspace/opener-selection.js +98 -0
- package/dist/commands/workspace/operations.d.ts +29 -0
- package/dist/commands/workspace/operations.js +543 -0
- package/dist/commands/workspace/prompt-theme.d.ts +29 -0
- package/dist/commands/workspace/prompt-theme.js +24 -0
- package/dist/commands/workspace/registration.d.ts +13 -0
- package/dist/commands/workspace/registration.js +84 -0
- package/dist/commands/workspace/selection.d.ts +8 -0
- package/dist/commands/workspace/selection.js +104 -0
- package/dist/commands/workspace/setup-prompts.d.ts +13 -0
- package/dist/commands/workspace/setup-prompts.js +121 -0
- package/dist/commands/workspace/types.d.ts +103 -0
- package/dist/commands/workspace/types.js +36 -0
- package/dist/commands/workspace.d.ts +5 -0
- package/dist/commands/workspace.js +577 -0
- package/dist/core/archive.d.ts +11 -0
- package/dist/core/archive.js +318 -0
- package/dist/core/artifact-graph/graph.d.ts +56 -0
- package/dist/core/artifact-graph/graph.js +141 -0
- package/dist/core/artifact-graph/index.d.ts +9 -0
- package/dist/core/artifact-graph/index.js +14 -0
- package/dist/core/artifact-graph/instruction-loader.d.ts +183 -0
- package/dist/core/artifact-graph/instruction-loader.js +256 -0
- package/dist/core/artifact-graph/outputs.d.ts +14 -0
- package/dist/core/artifact-graph/outputs.js +39 -0
- package/dist/core/artifact-graph/resolver.d.ts +81 -0
- package/dist/core/artifact-graph/resolver.js +257 -0
- package/dist/core/artifact-graph/schema.d.ts +13 -0
- package/dist/core/artifact-graph/schema.js +108 -0
- package/dist/core/artifact-graph/state.d.ts +12 -0
- package/dist/core/artifact-graph/state.js +31 -0
- package/dist/core/artifact-graph/types.d.ts +40 -0
- package/dist/core/artifact-graph/types.js +29 -0
- package/dist/core/available-tools.d.ts +17 -0
- package/dist/core/available-tools.js +43 -0
- package/dist/core/change-metadata/index.d.ts +2 -0
- package/dist/core/change-metadata/index.js +2 -0
- package/dist/core/change-metadata/schema.d.ts +18 -0
- package/dist/core/change-metadata/schema.js +28 -0
- package/dist/core/change-status-policy.d.ts +50 -0
- package/dist/core/change-status-policy.js +70 -0
- package/dist/core/collections/index.d.ts +3 -0
- package/dist/core/collections/index.js +3 -0
- package/dist/core/collections/initiatives/collection.d.ts +4 -0
- package/dist/core/collections/initiatives/collection.js +17 -0
- package/dist/core/collections/initiatives/index.d.ts +6 -0
- package/dist/core/collections/initiatives/index.js +6 -0
- package/dist/core/collections/initiatives/operations.d.ts +49 -0
- package/dist/core/collections/initiatives/operations.js +175 -0
- package/dist/core/collections/initiatives/resolution.d.ts +87 -0
- package/dist/core/collections/initiatives/resolution.js +374 -0
- package/dist/core/collections/initiatives/schema.d.ts +41 -0
- package/dist/core/collections/initiatives/schema.js +134 -0
- package/dist/core/collections/initiatives/templates.d.ts +12 -0
- package/dist/core/collections/initiatives/templates.js +90 -0
- package/dist/core/collections/runtime.d.ts +46 -0
- package/dist/core/collections/runtime.js +194 -0
- package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
- package/dist/core/command-generation/adapters/amazon-q.js +26 -0
- package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
- package/dist/core/command-generation/adapters/antigravity.js +26 -0
- package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
- package/dist/core/command-generation/adapters/auggie.js +27 -0
- package/dist/core/command-generation/adapters/bob.d.ts +14 -0
- package/dist/core/command-generation/adapters/bob.js +45 -0
- package/dist/core/command-generation/adapters/claude.d.ts +13 -0
- package/dist/core/command-generation/adapters/claude.js +50 -0
- package/dist/core/command-generation/adapters/cline.d.ts +14 -0
- package/dist/core/command-generation/adapters/cline.js +27 -0
- package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
- package/dist/core/command-generation/adapters/codebuddy.js +28 -0
- package/dist/core/command-generation/adapters/codex.d.ts +16 -0
- package/dist/core/command-generation/adapters/codex.js +39 -0
- package/dist/core/command-generation/adapters/continue.d.ts +13 -0
- package/dist/core/command-generation/adapters/continue.js +28 -0
- package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
- package/dist/core/command-generation/adapters/costrict.js +27 -0
- package/dist/core/command-generation/adapters/crush.d.ts +13 -0
- package/dist/core/command-generation/adapters/crush.js +30 -0
- package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
- package/dist/core/command-generation/adapters/cursor.js +44 -0
- package/dist/core/command-generation/adapters/factory.d.ts +13 -0
- package/dist/core/command-generation/adapters/factory.js +27 -0
- package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
- package/dist/core/command-generation/adapters/gemini.js +26 -0
- package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
- package/dist/core/command-generation/adapters/github-copilot.js +26 -0
- package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
- package/dist/core/command-generation/adapters/iflow.js +29 -0
- package/dist/core/command-generation/adapters/index.d.ts +32 -0
- package/dist/core/command-generation/adapters/index.js +32 -0
- package/dist/core/command-generation/adapters/junie.d.ts +13 -0
- package/dist/core/command-generation/adapters/junie.js +26 -0
- package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
- package/dist/core/command-generation/adapters/kilocode.js +23 -0
- package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
- package/dist/core/command-generation/adapters/kiro.js +26 -0
- package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
- package/dist/core/command-generation/adapters/lingma.js +30 -0
- package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
- package/dist/core/command-generation/adapters/opencode.js +29 -0
- package/dist/core/command-generation/adapters/pi.d.ts +18 -0
- package/dist/core/command-generation/adapters/pi.js +55 -0
- package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
- package/dist/core/command-generation/adapters/qoder.js +30 -0
- package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
- package/dist/core/command-generation/adapters/qwen.js +26 -0
- package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
- package/dist/core/command-generation/adapters/roocode.js +27 -0
- package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
- package/dist/core/command-generation/adapters/windsurf.js +51 -0
- package/dist/core/command-generation/generator.d.ts +21 -0
- package/dist/core/command-generation/generator.js +27 -0
- package/dist/core/command-generation/index.d.ts +22 -0
- package/dist/core/command-generation/index.js +24 -0
- package/dist/core/command-generation/registry.d.ts +36 -0
- package/dist/core/command-generation/registry.js +98 -0
- package/dist/core/command-generation/types.d.ts +56 -0
- package/dist/core/command-generation/types.js +8 -0
- package/dist/core/completions/command-registry.d.ts +3 -0
- package/dist/core/completions/command-registry.js +961 -0
- package/dist/core/completions/completion-provider.d.ts +71 -0
- package/dist/core/completions/completion-provider.js +129 -0
- package/dist/core/completions/factory.d.ts +64 -0
- package/dist/core/completions/factory.js +75 -0
- package/dist/core/completions/generators/bash-generator.d.ts +35 -0
- package/dist/core/completions/generators/bash-generator.js +230 -0
- package/dist/core/completions/generators/fish-generator.d.ts +32 -0
- package/dist/core/completions/generators/fish-generator.js +160 -0
- package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
- package/dist/core/completions/generators/powershell-generator.js +266 -0
- package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
- package/dist/core/completions/generators/zsh-generator.js +274 -0
- package/dist/core/completions/installers/bash-installer.d.ts +87 -0
- package/dist/core/completions/installers/bash-installer.js +318 -0
- package/dist/core/completions/installers/fish-installer.d.ts +43 -0
- package/dist/core/completions/installers/fish-installer.js +143 -0
- package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
- package/dist/core/completions/installers/powershell-installer.js +387 -0
- package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
- package/dist/core/completions/installers/zsh-installer.js +421 -0
- package/dist/core/completions/shared-flags.d.ts +12 -0
- package/dist/core/completions/shared-flags.js +28 -0
- package/dist/core/completions/templates/bash-templates.d.ts +6 -0
- package/dist/core/completions/templates/bash-templates.js +30 -0
- package/dist/core/completions/templates/fish-templates.d.ts +7 -0
- package/dist/core/completions/templates/fish-templates.js +45 -0
- package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
- package/dist/core/completions/templates/powershell-templates.js +34 -0
- package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
- package/dist/core/completions/templates/zsh-templates.js +45 -0
- package/dist/core/completions/types.d.ts +101 -0
- package/dist/core/completions/types.js +2 -0
- package/dist/core/config-prompts.d.ts +9 -0
- package/dist/core/config-prompts.js +34 -0
- package/dist/core/config-schema.d.ts +86 -0
- package/dist/core/config-schema.js +213 -0
- package/dist/core/config.d.ts +18 -0
- package/dist/core/config.js +39 -0
- package/dist/core/context-store/binding.d.ts +53 -0
- package/dist/core/context-store/binding.js +197 -0
- package/dist/core/context-store/errors.d.ts +20 -0
- package/dist/core/context-store/errors.js +22 -0
- package/dist/core/context-store/foundation.d.ts +55 -0
- package/dist/core/context-store/foundation.js +321 -0
- package/dist/core/context-store/index.d.ts +6 -0
- package/dist/core/context-store/index.js +6 -0
- package/dist/core/context-store/operations.d.ts +85 -0
- package/dist/core/context-store/operations.js +528 -0
- package/dist/core/context-store/registry.d.ts +45 -0
- package/dist/core/context-store/registry.js +229 -0
- package/dist/core/converters/json-converter.d.ts +6 -0
- package/dist/core/converters/json-converter.js +51 -0
- package/dist/core/global-config.d.ts +49 -0
- package/dist/core/global-config.js +124 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +7 -0
- package/dist/core/init.d.ts +37 -0
- package/dist/core/init.js +593 -0
- package/dist/core/legacy-cleanup.d.ts +162 -0
- package/dist/core/legacy-cleanup.js +514 -0
- package/dist/core/list.d.ts +9 -0
- package/dist/core/list.js +171 -0
- package/dist/core/migration.d.ts +23 -0
- package/dist/core/migration.js +108 -0
- package/dist/core/parsers/change-parser.d.ts +13 -0
- package/dist/core/parsers/change-parser.js +197 -0
- package/dist/core/parsers/markdown-parser.d.ts +26 -0
- package/dist/core/parsers/markdown-parser.js +227 -0
- package/dist/core/parsers/requirement-blocks.d.ts +37 -0
- package/dist/core/parsers/requirement-blocks.js +201 -0
- package/dist/core/parsers/spec-structure.d.ts +9 -0
- package/dist/core/parsers/spec-structure.js +88 -0
- package/dist/core/planning-home.d.ts +21 -0
- package/dist/core/planning-home.js +108 -0
- package/dist/core/profile-sync-drift.d.ts +38 -0
- package/dist/core/profile-sync-drift.js +200 -0
- package/dist/core/profiles.d.ts +26 -0
- package/dist/core/profiles.js +40 -0
- package/dist/core/project-config.d.ts +64 -0
- package/dist/core/project-config.js +223 -0
- package/dist/core/schemas/base.schema.d.ts +13 -0
- package/dist/core/schemas/base.schema.js +13 -0
- package/dist/core/schemas/change.schema.d.ts +73 -0
- package/dist/core/schemas/change.schema.js +31 -0
- package/dist/core/schemas/index.d.ts +4 -0
- package/dist/core/schemas/index.js +4 -0
- package/dist/core/schemas/spec.schema.d.ts +18 -0
- package/dist/core/schemas/spec.schema.js +15 -0
- package/dist/core/shared/index.d.ts +8 -0
- package/dist/core/shared/index.js +8 -0
- package/dist/core/shared/skill-generation.d.ts +49 -0
- package/dist/core/shared/skill-generation.js +96 -0
- package/dist/core/shared/tool-detection.d.ts +71 -0
- package/dist/core/shared/tool-detection.js +158 -0
- package/dist/core/specs-apply.d.ts +73 -0
- package/dist/core/specs-apply.js +392 -0
- package/dist/core/styles/palette.d.ts +7 -0
- package/dist/core/styles/palette.js +8 -0
- package/dist/core/templates/index.d.ts +8 -0
- package/dist/core/templates/index.js +9 -0
- package/dist/core/templates/skill-templates.d.ts +19 -0
- package/dist/core/templates/skill-templates.js +18 -0
- package/dist/core/templates/types.d.ts +19 -0
- package/dist/core/templates/types.js +5 -0
- package/dist/core/templates/workflows/apply-change.d.ts +10 -0
- package/dist/core/templates/workflows/apply-change.js +314 -0
- package/dist/core/templates/workflows/archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/archive-change.js +277 -0
- package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/bulk-archive-change.js +492 -0
- package/dist/core/templates/workflows/continue-change.d.ts +10 -0
- package/dist/core/templates/workflows/continue-change.js +234 -0
- package/dist/core/templates/workflows/explore.d.ts +10 -0
- package/dist/core/templates/workflows/explore.js +459 -0
- package/dist/core/templates/workflows/feedback.d.ts +9 -0
- package/dist/core/templates/workflows/feedback.js +108 -0
- package/dist/core/templates/workflows/ff-change.d.ts +10 -0
- package/dist/core/templates/workflows/ff-change.js +200 -0
- package/dist/core/templates/workflows/new-change.d.ts +10 -0
- package/dist/core/templates/workflows/new-change.js +143 -0
- package/dist/core/templates/workflows/onboard.d.ts +10 -0
- package/dist/core/templates/workflows/onboard.js +563 -0
- package/dist/core/templates/workflows/propose.d.ts +10 -0
- package/dist/core/templates/workflows/propose.js +218 -0
- package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
- package/dist/core/templates/workflows/sync-specs.js +290 -0
- package/dist/core/templates/workflows/verify-change.d.ts +10 -0
- package/dist/core/templates/workflows/verify-change.js +338 -0
- package/dist/core/update.d.ts +82 -0
- package/dist/core/update.js +557 -0
- package/dist/core/validation/constants.d.ts +34 -0
- package/dist/core/validation/constants.js +40 -0
- package/dist/core/validation/types.d.ts +18 -0
- package/dist/core/validation/types.js +2 -0
- package/dist/core/validation/validator.d.ts +43 -0
- package/dist/core/validation/validator.js +435 -0
- package/dist/core/view.d.ts +8 -0
- package/dist/core/view.js +168 -0
- package/dist/core/workspace/foundation.d.ts +67 -0
- package/dist/core/workspace/foundation.js +295 -0
- package/dist/core/workspace/index.d.ts +8 -0
- package/dist/core/workspace/index.js +8 -0
- package/dist/core/workspace/legacy-state.d.ts +28 -0
- package/dist/core/workspace/legacy-state.js +200 -0
- package/dist/core/workspace/link-input.d.ts +9 -0
- package/dist/core/workspace/link-input.js +32 -0
- package/dist/core/workspace/open-surface.d.ts +45 -0
- package/dist/core/workspace/open-surface.js +215 -0
- package/dist/core/workspace/openers.d.ts +21 -0
- package/dist/core/workspace/openers.js +124 -0
- package/dist/core/workspace/registry.d.ts +24 -0
- package/dist/core/workspace/registry.js +146 -0
- package/dist/core/workspace/skills.d.ts +57 -0
- package/dist/core/workspace/skills.js +334 -0
- package/dist/core/workspace/state-io.d.ts +10 -0
- package/dist/core/workspace/state-io.js +121 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/prompts/searchable-multi-select.d.ts +28 -0
- package/dist/prompts/searchable-multi-select.js +159 -0
- package/dist/telemetry/config.d.ts +38 -0
- package/dist/telemetry/config.js +136 -0
- package/dist/telemetry/index.d.ts +31 -0
- package/dist/telemetry/index.js +164 -0
- package/dist/ui/ascii-patterns.d.ts +16 -0
- package/dist/ui/ascii-patterns.js +133 -0
- package/dist/ui/welcome-screen.d.ts +10 -0
- package/dist/ui/welcome-screen.js +146 -0
- package/dist/utils/change-metadata.d.ts +54 -0
- package/dist/utils/change-metadata.js +141 -0
- package/dist/utils/change-utils.d.ts +71 -0
- package/dist/utils/change-utils.js +123 -0
- package/dist/utils/command-references.d.ts +18 -0
- package/dist/utils/command-references.js +20 -0
- package/dist/utils/file-system.d.ts +41 -0
- package/dist/utils/file-system.js +301 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/interactive.d.ts +18 -0
- package/dist/utils/interactive.js +21 -0
- package/dist/utils/item-discovery.d.ts +4 -0
- package/dist/utils/item-discovery.js +72 -0
- package/dist/utils/match.d.ts +3 -0
- package/dist/utils/match.js +22 -0
- package/dist/utils/shell-detection.d.ts +20 -0
- package/dist/utils/shell-detection.js +41 -0
- package/dist/utils/task-progress.d.ts +8 -0
- package/dist/utils/task-progress.js +36 -0
- package/package.json +85 -0
- package/schemas/spec-driven/schema.yaml +151 -0
- package/schemas/spec-driven/templates/design.md +19 -0
- package/schemas/spec-driven/templates/proposal.md +23 -0
- package/schemas/spec-driven/templates/spec.md +8 -0
- package/schemas/spec-driven/templates/tasks.md +9 -0
- package/schemas/workspace-planning/schema.yaml +72 -0
- package/schemas/workspace-planning/templates/design.md +33 -0
- package/schemas/workspace-planning/templates/proposal.md +28 -0
- package/schemas/workspace-planning/templates/spec.md +9 -0
- package/schemas/workspace-planning/templates/tasks.md +15 -0
- package/scripts/postinstall.js +83 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { createWorkspaceSkillSkippedReport, generateWorkspaceAgentSkills, getWorkspaceSkillCapableTools, getWorkspaceSkillToolIds, getWorkspaceOpenerLabel, parseWorkspaceSkillToolsValue, updateWorkspaceAgentSkills, listKnownWorkspaceEntries, readWorkspaceViewState, syncWorkspaceOpenSurface, writeWorkspaceViewState, } from '../core/workspace/index.js';
|
|
3
|
+
import { isInteractive, resolveNoInteractive } from '../utils/interactive.js';
|
|
4
|
+
import { addWorkspaceLink, createManagedWorkspace, loadWorkspaceForDoctor, loadWorkspaceForList, parseSetupLinks, readWorkspaceForMutation, updateWorkspaceLink, validateWorkspaceNameForSetup, } from './workspace/operations.js';
|
|
5
|
+
import { selectWorkspaceForCommand } from './workspace/selection.js';
|
|
6
|
+
import { launchWorkspaceOpenCommand, } from './workspace/open.js';
|
|
7
|
+
import { buildWorkspaceOpenJsonPayload, prepareWorkspaceOpen, } from './workspace/open-view.js';
|
|
8
|
+
import { getPreferredWorkspaceSkillAgentId, parseSetupOpenerOption, promptPreferredOpener, } from './workspace/opener-selection.js';
|
|
9
|
+
import { workspacePromptTheme } from './workspace/prompt-theme.js';
|
|
10
|
+
import { registerWorkspaceCommandWith } from './workspace/registration.js';
|
|
11
|
+
import { promptSetupLinks } from './workspace/setup-prompts.js';
|
|
12
|
+
import { WorkspaceCliError, appendStatus, asErrorMessage, asStatus, } from './workspace/types.js';
|
|
13
|
+
function printJson(payload) {
|
|
14
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
15
|
+
}
|
|
16
|
+
function printWorkspaceSetupIntro() {
|
|
17
|
+
console.log(chalk.bold('工作区设置'));
|
|
18
|
+
console.log('');
|
|
19
|
+
}
|
|
20
|
+
function isPromptCancellationError(error) {
|
|
21
|
+
return (error instanceof Error &&
|
|
22
|
+
(error.name === 'ExitPromptError' || error.message.includes('force closed the prompt with SIGINT')));
|
|
23
|
+
}
|
|
24
|
+
async function promptWorkspaceName(initialName) {
|
|
25
|
+
if (initialName) {
|
|
26
|
+
return validateWorkspaceNameForSetup(initialName);
|
|
27
|
+
}
|
|
28
|
+
const { input } = await import('@inquirer/prompts');
|
|
29
|
+
console.log(chalk.bold('[1/5] 命名工作区'));
|
|
30
|
+
console.log(chalk.dim('为仓库组使用一个稳定的名称,例如 platform。'));
|
|
31
|
+
console.log('');
|
|
32
|
+
return input({
|
|
33
|
+
message: '工作区名称:',
|
|
34
|
+
required: true,
|
|
35
|
+
theme: workspacePromptTheme,
|
|
36
|
+
validate(value) {
|
|
37
|
+
try {
|
|
38
|
+
validateWorkspaceNameForSetup(value);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return '工作区名称必须是小写字母、数字和单连字符分隔的 kebab-case 格式。';
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function parseSetupToolsOption(tools) {
|
|
48
|
+
try {
|
|
49
|
+
return parseWorkspaceSkillToolsValue(tools);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
throw new WorkspaceCliError(asErrorMessage(error), 'invalid_workspace_setup_tools', {
|
|
53
|
+
target: 'workspace.skills',
|
|
54
|
+
fix: `请使用 --tools all、--tools none,或以下之一:${getWorkspaceSkillToolIds().join(', ')}`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function parseUpdateToolsOption(tools) {
|
|
59
|
+
try {
|
|
60
|
+
return parseWorkspaceSkillToolsValue(tools);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new WorkspaceCliError(asErrorMessage(error), 'invalid_workspace_update_tools', {
|
|
64
|
+
target: 'workspace.skills',
|
|
65
|
+
fix: `请使用 --tools all、--tools none,或以下之一:${getWorkspaceSkillToolIds().join(', ')}`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function promptWorkspaceSkillAgents(preferredOpener) {
|
|
70
|
+
const { searchableMultiSelect } = await import('../prompts/searchable-multi-select.js');
|
|
71
|
+
const preferredAgentId = getPreferredWorkspaceSkillAgentId(preferredOpener);
|
|
72
|
+
const tools = getWorkspaceSkillCapableTools();
|
|
73
|
+
const sortedChoices = tools
|
|
74
|
+
.map((tool) => ({
|
|
75
|
+
name: tool.name,
|
|
76
|
+
value: tool.value,
|
|
77
|
+
preSelected: tool.value === preferredAgentId,
|
|
78
|
+
}))
|
|
79
|
+
.sort((a, b) => {
|
|
80
|
+
if (a.preSelected !== b.preSelected) {
|
|
81
|
+
return a.preSelected ? -1 : 1;
|
|
82
|
+
}
|
|
83
|
+
return a.name.localeCompare(b.name);
|
|
84
|
+
});
|
|
85
|
+
if (preferredAgentId) {
|
|
86
|
+
const preferredTool = tools.find((tool) => tool.value === preferredAgentId);
|
|
87
|
+
if (preferredTool) {
|
|
88
|
+
console.log(`${preferredTool.name} 与您偏好的打开方式匹配,已预选。`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return searchableMultiSelect({
|
|
92
|
+
message: '哪些 Agent 应该在此工作区中获得 OpenSpec 技能?',
|
|
93
|
+
pageSize: 15,
|
|
94
|
+
choices: sortedChoices,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function printStatusLines(statuses) {
|
|
98
|
+
for (const status of statuses) {
|
|
99
|
+
const label = status.severity === 'warning' ? '警告' : '问题';
|
|
100
|
+
console.log(`${label}:${status.message}`);
|
|
101
|
+
if (status.fix) {
|
|
102
|
+
console.log(`修复:${status.fix}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function printLinksHuman(links) {
|
|
107
|
+
if (links.length === 0) {
|
|
108
|
+
console.log(' (无已链接的仓库或文件夹)');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
for (const link of links) {
|
|
112
|
+
const suffix = link.status.some((status) => status.severity === 'error') ? ' [问题]' : '';
|
|
113
|
+
console.log(` ${link.name} -> ${link.path ?? '(未记录本地路径)'}${suffix}`);
|
|
114
|
+
if (link.repo_specs_path) {
|
|
115
|
+
console.log(` 仓库规格:${link.repo_specs_path}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function collectWorkspaceIssues(workspace) {
|
|
120
|
+
return [
|
|
121
|
+
...workspace.status,
|
|
122
|
+
...workspace.links.flatMap((link) => link.status),
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
function printDoctorHuman(result) {
|
|
126
|
+
console.log(`工作区:${result.workspace.name}`);
|
|
127
|
+
console.log(`位置:${result.workspace.root}`);
|
|
128
|
+
if (result.workspace.context) {
|
|
129
|
+
const selector = result.workspace.context.store_selector;
|
|
130
|
+
const suffix = selector.kind === 'path' ? ` 通过 ${selector.path}` : '';
|
|
131
|
+
console.log(`上下文:${result.workspace.context.store}/${result.workspace.context.initiative}${suffix}`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log('上下文:(无)');
|
|
135
|
+
}
|
|
136
|
+
console.log(`规划路径:${result.workspace.planning_path}`);
|
|
137
|
+
console.log('');
|
|
138
|
+
printStatusLines(result.status);
|
|
139
|
+
if (result.status.length > 0) {
|
|
140
|
+
console.log('');
|
|
141
|
+
}
|
|
142
|
+
console.log('已链接的仓库或文件夹:');
|
|
143
|
+
printLinksHuman(result.workspace.links);
|
|
144
|
+
const issues = collectWorkspaceIssues(result.workspace);
|
|
145
|
+
console.log('');
|
|
146
|
+
console.log('Advisory edit boundaries:');
|
|
147
|
+
if (result.workspace.context) {
|
|
148
|
+
console.log(' Initiative/context-store files are shared coordination context.');
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log(' No initiative coordination context is attached.');
|
|
152
|
+
}
|
|
153
|
+
console.log(' Linked repos and folders are local implementation context when selected.');
|
|
154
|
+
if (issues.length === 0) {
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log('未发现工作区问题。');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
console.log('');
|
|
160
|
+
console.log('问题:');
|
|
161
|
+
for (const issue of issues) {
|
|
162
|
+
console.log(` - ${issue.message}`);
|
|
163
|
+
if (issue.target) {
|
|
164
|
+
console.log(` 目标:${issue.target}`);
|
|
165
|
+
}
|
|
166
|
+
if (issue.fix) {
|
|
167
|
+
console.log(` 修复:${issue.fix}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function printWorkspaceListHuman(workspaces) {
|
|
172
|
+
console.log(chalk.bold(`OpenSpec 工作区(${workspaces.length})`));
|
|
173
|
+
for (const workspace of workspaces) {
|
|
174
|
+
console.log('');
|
|
175
|
+
console.log(chalk.bold(workspace.name));
|
|
176
|
+
console.log(` 位置:${workspace.root}`);
|
|
177
|
+
if (workspace.status.length > 0) {
|
|
178
|
+
console.log(' 状态:');
|
|
179
|
+
for (const status of workspace.status) {
|
|
180
|
+
const statusLabel = status.severity === 'warning' ? chalk.yellow('警告') : chalk.red('问题');
|
|
181
|
+
console.log(` ${statusLabel}:${status.message}`);
|
|
182
|
+
if (status.fix) {
|
|
183
|
+
console.log(` 修复:${status.fix}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
console.log(` 已链接的仓库或文件夹(${workspace.links.length}):`);
|
|
188
|
+
if (workspace.links.length === 0) {
|
|
189
|
+
console.log(chalk.dim(' (无)'));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
for (const link of workspace.links) {
|
|
193
|
+
const suffix = link.status.some((status) => status.severity === 'error') ? chalk.red(' [问题]') : '';
|
|
194
|
+
console.log(` ${link.name} -> ${link.path ?? '(未记录本地路径)'}${suffix}`);
|
|
195
|
+
if (link.repo_specs_path) {
|
|
196
|
+
console.log(chalk.dim(` 仓库规格:${link.repo_specs_path}`));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function printWorkspaceCheckSummaryHuman(result) {
|
|
202
|
+
printStatusLines(result.status);
|
|
203
|
+
const issues = collectWorkspaceIssues(result.workspace);
|
|
204
|
+
if (issues.length === 0) {
|
|
205
|
+
console.log(' 未发现工作区问题。');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
console.log(' 问题:');
|
|
209
|
+
for (const issue of issues) {
|
|
210
|
+
console.log(` - ${issue.message}`);
|
|
211
|
+
if (issue.target) {
|
|
212
|
+
console.log(` 目标:${issue.target}`);
|
|
213
|
+
}
|
|
214
|
+
if (issue.fix) {
|
|
215
|
+
console.log(` 修复:${issue.fix}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function printLinkMutationHuman(heading, payload) {
|
|
220
|
+
printStatusLines(payload.status);
|
|
221
|
+
console.log(heading);
|
|
222
|
+
console.log(` ${payload.link.name} -> ${payload.link.path}`);
|
|
223
|
+
console.log(`工作区:${payload.workspace.name}`);
|
|
224
|
+
}
|
|
225
|
+
function formatWorkspaceSkillAgentResult(result) {
|
|
226
|
+
const workflowCount = result.workflow_ids?.length ?? 0;
|
|
227
|
+
const workflowLabel = workflowCount === 1 ? '1 个工作流' : `${workflowCount} 个工作流`;
|
|
228
|
+
return `${result.name}(${workflowLabel})`;
|
|
229
|
+
}
|
|
230
|
+
function formatWorkspaceSkillRemovedResult(result) {
|
|
231
|
+
const workflowCount = result.workflow_ids?.length ?? 0;
|
|
232
|
+
const workflowLabel = workflowCount === 1 ? '1 个工作流' : `${workflowCount} 个工作流`;
|
|
233
|
+
return `${result.name}(${workflowLabel} 已移除)`;
|
|
234
|
+
}
|
|
235
|
+
function printWorkspaceSkillReportHuman(report) {
|
|
236
|
+
console.log('Agent 技能:');
|
|
237
|
+
console.log(` 配置:${report.profile}`);
|
|
238
|
+
console.log(` 工作流:${report.workflow_ids.length > 0 ? report.workflow_ids.join(', ') : '(未选择)'}`);
|
|
239
|
+
if (report.generated.length > 0) {
|
|
240
|
+
console.log(` 已生成:${report.generated.map(formatWorkspaceSkillAgentResult).join(', ')}`);
|
|
241
|
+
}
|
|
242
|
+
if (report.added.length > 0) {
|
|
243
|
+
console.log(` 已添加:${report.added.map(formatWorkspaceSkillAgentResult).join(', ')}`);
|
|
244
|
+
}
|
|
245
|
+
if (report.refreshed.length > 0) {
|
|
246
|
+
console.log(` 已刷新:${report.refreshed.map(formatWorkspaceSkillAgentResult).join(', ')}`);
|
|
247
|
+
}
|
|
248
|
+
if (report.removed.length > 0) {
|
|
249
|
+
console.log(` 已移除:${report.removed.map(formatWorkspaceSkillRemovedResult).join(', ')}`);
|
|
250
|
+
}
|
|
251
|
+
if (report.skipped.length > 0) {
|
|
252
|
+
for (const skipped of report.skipped) {
|
|
253
|
+
const prefix = skipped.name ? `${skipped.name}:` : '';
|
|
254
|
+
console.log(` 已跳过:${prefix}${skipped.message}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (report.failed.length > 0) {
|
|
258
|
+
console.log(chalk.red(` 失败:${report.failed.map((failure) => `${failure.name}(${failure.error})`).join(', ')}`));
|
|
259
|
+
}
|
|
260
|
+
if (report.delivery_notice) {
|
|
261
|
+
console.log(chalk.dim(` ${report.delivery_notice}`));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function hasWorkspaceSkillFailures(report) {
|
|
265
|
+
return report.failed.length > 0;
|
|
266
|
+
}
|
|
267
|
+
function setWorkspaceSkillFailureExitCode(report) {
|
|
268
|
+
if (hasWorkspaceSkillFailures(report)) {
|
|
269
|
+
process.exitCode = 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function writeWorkspaceSkillState(workspaceRoot, selectedAgentIds, report) {
|
|
273
|
+
const viewState = await readWorkspaceViewState(workspaceRoot);
|
|
274
|
+
await writeWorkspaceViewState(workspaceRoot, {
|
|
275
|
+
...viewState,
|
|
276
|
+
workspace_skills: {
|
|
277
|
+
selected_agents: selectedAgentIds,
|
|
278
|
+
last_applied_profile: report.profile,
|
|
279
|
+
last_applied_delivery: report.delivery,
|
|
280
|
+
last_applied_workflow_ids: report.workflow_ids,
|
|
281
|
+
last_applied_at: new Date().toISOString(),
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
function resolveUpdateWorkspaceName(positionalName, options) {
|
|
286
|
+
if (positionalName && options.workspace && positionalName !== options.workspace) {
|
|
287
|
+
throw new WorkspaceCliError(`工作区选择器冲突:位置参数 '${positionalName}' 和 --workspace '${options.workspace}'。`, 'workspace_selection_conflict', {
|
|
288
|
+
target: 'workspace.name',
|
|
289
|
+
fix: '请使用位置参数的工作区名称或 --workspace 并传相同的值。',
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return positionalName ?? options.workspace;
|
|
293
|
+
}
|
|
294
|
+
function printWorkspaceOpenHuman(prepared) {
|
|
295
|
+
console.log(`正在打开工作区:${prepared.selected.name}`);
|
|
296
|
+
console.log(`位置:${prepared.selected.root}`);
|
|
297
|
+
if (prepared.initiative) {
|
|
298
|
+
console.log(`计划:${prepared.initiative.store}/${prepared.initiative.id}`);
|
|
299
|
+
console.log(`计划路径:${prepared.initiative.root}`);
|
|
300
|
+
}
|
|
301
|
+
console.log(`打开方式:${getWorkspaceOpenerLabel(prepared.opener)}`);
|
|
302
|
+
if (prepared.skipped.length === 0) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
console.log('');
|
|
306
|
+
console.log('跳过的已链接仓库或文件夹:');
|
|
307
|
+
for (const link of prepared.skipped) {
|
|
308
|
+
const location = link.path ?? '(未记录本地路径)';
|
|
309
|
+
console.log(` ${link.name} -> ${location}`);
|
|
310
|
+
}
|
|
311
|
+
console.log('请使用 openspec workspace doctor 修复跳过的链接。');
|
|
312
|
+
}
|
|
313
|
+
class WorkspaceCommand {
|
|
314
|
+
async setup(options = {}) {
|
|
315
|
+
try {
|
|
316
|
+
const noInteractive = resolveNoInteractive(options);
|
|
317
|
+
if (options.json && !noInteractive) {
|
|
318
|
+
throw new WorkspaceCliError('workspace setup --json 需要 --no-interactive。', 'setup_json_requires_no_interactive', {
|
|
319
|
+
fix: 'openspec workspace setup --no-interactive --json --name <name> --link <path>',
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
const interactive = !noInteractive && isInteractive(options);
|
|
323
|
+
if (interactive) {
|
|
324
|
+
printWorkspaceSetupIntro();
|
|
325
|
+
}
|
|
326
|
+
if (!interactive && (!options.name || (options.link ?? []).length === 0)) {
|
|
327
|
+
throw new WorkspaceCliError('workspace setup --no-interactive 需要 --name <name> 和至少一个 --link <path>。', 'missing_setup_inputs', {
|
|
328
|
+
fix: 'openspec workspace setup --no-interactive --name platform --link /path/to/repo',
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const workspaceName = interactive
|
|
332
|
+
? await promptWorkspaceName(options.name)
|
|
333
|
+
: validateWorkspaceNameForSetup(options.name ?? '');
|
|
334
|
+
const links = interactive ? await promptSetupLinks() : await parseSetupLinks(options.link);
|
|
335
|
+
if (interactive) {
|
|
336
|
+
console.log('');
|
|
337
|
+
console.log(chalk.bold('[3/5] 选择偏好打开方式'));
|
|
338
|
+
}
|
|
339
|
+
const preferredOpener = interactive
|
|
340
|
+
? await promptPreferredOpener('偏好打开方式:')
|
|
341
|
+
: parseSetupOpenerOption(options.opener);
|
|
342
|
+
let selectedWorkspaceSkillAgents;
|
|
343
|
+
if (options.tools !== undefined) {
|
|
344
|
+
selectedWorkspaceSkillAgents = parseSetupToolsOption(options.tools);
|
|
345
|
+
}
|
|
346
|
+
else if (interactive) {
|
|
347
|
+
console.log('');
|
|
348
|
+
console.log(chalk.bold('[4/5] 安装 Agent 技能'));
|
|
349
|
+
console.log(chalk.dim('选择哪些编码 Agent 应在此工作区中获得 OpenSpec 技能。'));
|
|
350
|
+
console.log(chalk.dim('若不选择任何 Agent 直接按回车,则暂时跳过技能安装。'));
|
|
351
|
+
console.log('');
|
|
352
|
+
selectedWorkspaceSkillAgents = await promptWorkspaceSkillAgents(preferredOpener);
|
|
353
|
+
}
|
|
354
|
+
if (Object.keys(links).length === 0) {
|
|
355
|
+
throw new WorkspaceCliError('workspace setup --no-interactive 需要 --name <name> 和至少一个 --link <path>。', 'missing_setup_inputs', {
|
|
356
|
+
fix: 'openspec workspace setup --no-interactive --name platform --link /path/to/repo',
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
if (interactive) {
|
|
360
|
+
console.log('');
|
|
361
|
+
console.log(chalk.bold('[5/5] 创建工作区文件'));
|
|
362
|
+
}
|
|
363
|
+
const workspace = await createManagedWorkspace(workspaceName, links, preferredOpener);
|
|
364
|
+
const skillReport = selectedWorkspaceSkillAgents === undefined
|
|
365
|
+
? createWorkspaceSkillSkippedReport('tools_omitted', '未安装任何工作区技能。请稍后运行 openspec workspace update --tools <ids> 来安装。')
|
|
366
|
+
: await generateWorkspaceAgentSkills(workspace.root, selectedWorkspaceSkillAgents);
|
|
367
|
+
if (selectedWorkspaceSkillAgents !== undefined && !hasWorkspaceSkillFailures(skillReport)) {
|
|
368
|
+
await writeWorkspaceSkillState(workspace.root, selectedWorkspaceSkillAgents, skillReport);
|
|
369
|
+
}
|
|
370
|
+
const doctorResult = await loadWorkspaceForDoctor({
|
|
371
|
+
name: workspace.name,
|
|
372
|
+
root: workspace.root,
|
|
373
|
+
status: [],
|
|
374
|
+
unregisteredCurrentWorkspace: false,
|
|
375
|
+
});
|
|
376
|
+
if (options.json) {
|
|
377
|
+
printJson({
|
|
378
|
+
workspace: doctorResult.workspace,
|
|
379
|
+
workspace_skills: skillReport,
|
|
380
|
+
status: doctorResult.status,
|
|
381
|
+
});
|
|
382
|
+
setWorkspaceSkillFailureExitCode(skillReport);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
console.log(chalk.green('工作区设置完成'));
|
|
386
|
+
console.log('');
|
|
387
|
+
printWorkspaceListHuman([doctorResult.workspace]);
|
|
388
|
+
console.log('');
|
|
389
|
+
console.log(`规划路径:${doctorResult.workspace.planning_path}`);
|
|
390
|
+
console.log('');
|
|
391
|
+
console.log('工作区检查:');
|
|
392
|
+
printWorkspaceCheckSummaryHuman(doctorResult);
|
|
393
|
+
console.log('');
|
|
394
|
+
printWorkspaceSkillReportHuman(skillReport);
|
|
395
|
+
console.log('');
|
|
396
|
+
console.log('后续常用命令:');
|
|
397
|
+
console.log(` openspec workspace doctor --workspace ${workspace.name}`);
|
|
398
|
+
console.log(` openspec workspace update --workspace ${workspace.name} --tools <ids>`);
|
|
399
|
+
console.log(' openspec workspace list');
|
|
400
|
+
setWorkspaceSkillFailureExitCode(skillReport);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
this.handleFailure(options.json, { workspace: null, status: [] }, error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async list(options = {}) {
|
|
407
|
+
try {
|
|
408
|
+
const entries = await listKnownWorkspaceEntries();
|
|
409
|
+
const workspaces = await Promise.all(entries.map((entry) => loadWorkspaceForList(entry)));
|
|
410
|
+
const payload = { workspaces, status: [] };
|
|
411
|
+
if (options.json) {
|
|
412
|
+
printJson(payload);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (workspaces.length === 0) {
|
|
416
|
+
console.log("未找到 OpenSpec 工作区。请先运行 'openspec workspace setup'。");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
printWorkspaceListHuman(workspaces);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
this.handleFailure(options.json, { workspaces: [], status: [] }, error);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async link(nameOrPath, linkPath, options = {}) {
|
|
426
|
+
try {
|
|
427
|
+
if (!nameOrPath) {
|
|
428
|
+
throw new WorkspaceCliError('workspace link 需要一个仓库或文件夹路径。', 'missing_link_path', {
|
|
429
|
+
fix: 'openspec workspace link /path/to/repo',
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
const selected = await selectWorkspaceForCommand(options, 'link');
|
|
433
|
+
const payload = await addWorkspaceLink(selected, nameOrPath, linkPath);
|
|
434
|
+
if (options.json) {
|
|
435
|
+
printJson(payload);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
printLinkMutationHuman('已链接的仓库或文件夹:', payload);
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
this.handleFailure(options.json, { workspace: null, link: null, status: [] }, error);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async relink(linkNameInput, linkPath, options = {}) {
|
|
445
|
+
try {
|
|
446
|
+
if (!linkNameInput || !linkPath) {
|
|
447
|
+
throw new WorkspaceCliError('workspace relink 需要链接名称和仓库或文件夹路径。', 'missing_relink_arguments', {
|
|
448
|
+
fix: 'openspec workspace relink <name> /path/to/repo',
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
const selected = await selectWorkspaceForCommand(options, 'relink');
|
|
452
|
+
const payload = await updateWorkspaceLink(selected, linkNameInput, linkPath);
|
|
453
|
+
if (options.json) {
|
|
454
|
+
printJson(payload);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
printLinkMutationHuman('已重新链接的仓库或文件夹:', payload);
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
this.handleFailure(options.json, { workspace: null, link: null, status: [] }, error);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
async doctor(options = {}) {
|
|
464
|
+
try {
|
|
465
|
+
const selected = await selectWorkspaceForCommand(options, 'doctor');
|
|
466
|
+
const result = await loadWorkspaceForDoctor(selected);
|
|
467
|
+
if (options.json) {
|
|
468
|
+
printJson(result);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
printDoctorHuman(result);
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
this.handleFailure(options.json, { workspace: null, status: [] }, error);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
async update(positionalName, options = {}) {
|
|
478
|
+
try {
|
|
479
|
+
const workspaceName = resolveUpdateWorkspaceName(positionalName, options);
|
|
480
|
+
const selected = await selectWorkspaceForCommand({
|
|
481
|
+
...options,
|
|
482
|
+
workspace: workspaceName,
|
|
483
|
+
}, 'update', { preferPositionalName: Boolean(positionalName) });
|
|
484
|
+
await this.updateSelected(selected, options);
|
|
485
|
+
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
this.handleFailure(options.json, { workspace: null, workspace_skills: null, status: [] }, error);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
async updateSelected(selected, options) {
|
|
491
|
+
const viewState = await readWorkspaceForMutation(selected);
|
|
492
|
+
await syncWorkspaceOpenSurface(selected.root, viewState);
|
|
493
|
+
const hasExplicitToolSelection = options.tools !== undefined;
|
|
494
|
+
const selectedAgentIds = hasExplicitToolSelection
|
|
495
|
+
? parseUpdateToolsOption(options.tools ?? '')
|
|
496
|
+
: viewState.workspace_skills?.selected_agents ?? [];
|
|
497
|
+
const previousSkillState = hasExplicitToolSelection
|
|
498
|
+
? viewState.workspace_skills ?? { selected_agents: [] }
|
|
499
|
+
: viewState.workspace_skills;
|
|
500
|
+
const skillReport = await updateWorkspaceAgentSkills(selected.root, selectedAgentIds, previousSkillState);
|
|
501
|
+
const shouldStoreSelection = hasExplicitToolSelection || Boolean(viewState.workspace_skills);
|
|
502
|
+
if (shouldStoreSelection && !hasWorkspaceSkillFailures(skillReport)) {
|
|
503
|
+
await writeWorkspaceSkillState(selected.root, selectedAgentIds, skillReport);
|
|
504
|
+
}
|
|
505
|
+
const doctorResult = await loadWorkspaceForDoctor(selected);
|
|
506
|
+
if (options.json) {
|
|
507
|
+
printJson({
|
|
508
|
+
workspace: doctorResult.workspace,
|
|
509
|
+
workspace_skills: skillReport,
|
|
510
|
+
status: doctorResult.status,
|
|
511
|
+
});
|
|
512
|
+
setWorkspaceSkillFailureExitCode(skillReport);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
console.log(chalk.green('工作区更新完成'));
|
|
516
|
+
console.log(`工作区:${doctorResult.workspace.name}`);
|
|
517
|
+
console.log(`位置:${doctorResult.workspace.root}`);
|
|
518
|
+
console.log('');
|
|
519
|
+
printStatusLines(doctorResult.status);
|
|
520
|
+
if (doctorResult.status.length > 0) {
|
|
521
|
+
console.log('');
|
|
522
|
+
}
|
|
523
|
+
printWorkspaceSkillReportHuman(skillReport);
|
|
524
|
+
console.log('');
|
|
525
|
+
console.log('后续常用命令:');
|
|
526
|
+
console.log(` openspec workspace doctor --workspace ${doctorResult.workspace.name}`);
|
|
527
|
+
console.log(` openspec workspace update --workspace ${doctorResult.workspace.name} --tools <ids>`);
|
|
528
|
+
setWorkspaceSkillFailureExitCode(skillReport);
|
|
529
|
+
}
|
|
530
|
+
async open(positionalName, options = {}) {
|
|
531
|
+
try {
|
|
532
|
+
const prepared = await prepareWorkspaceOpen(positionalName, options);
|
|
533
|
+
if (!options.json) {
|
|
534
|
+
printStatusLines(prepared.selected.status);
|
|
535
|
+
if (prepared.selected.status.length > 0) {
|
|
536
|
+
console.log('');
|
|
537
|
+
}
|
|
538
|
+
printWorkspaceOpenHuman(prepared);
|
|
539
|
+
}
|
|
540
|
+
await launchWorkspaceOpenCommand(prepared.command, {
|
|
541
|
+
stdio: options.json ? 'ignore' : 'inherit',
|
|
542
|
+
});
|
|
543
|
+
if (options.json) {
|
|
544
|
+
printJson(buildWorkspaceOpenJsonPayload(prepared));
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
this.handleFailure(options.json, { workspace: null, status: [] }, error);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
handleFailure(json, payload, error) {
|
|
552
|
+
if (!json && isPromptCancellationError(error)) {
|
|
553
|
+
console.error('已取消。');
|
|
554
|
+
process.exitCode = 130;
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
if (json) {
|
|
558
|
+
printJson(appendStatus(payload, asStatus(error)));
|
|
559
|
+
process.exitCode = 1;
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const status = asStatus(error);
|
|
563
|
+
console.error(`错误:${status.message}`);
|
|
564
|
+
if (status.fix) {
|
|
565
|
+
console.error(`修复:${status.fix}`);
|
|
566
|
+
}
|
|
567
|
+
process.exitCode = 1;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
export async function runWorkspaceUpdate(positionalName, options = {}) {
|
|
571
|
+
const workspaceCommand = new WorkspaceCommand();
|
|
572
|
+
await workspaceCommand.update(positionalName, options);
|
|
573
|
+
}
|
|
574
|
+
export function registerWorkspaceCommand(program) {
|
|
575
|
+
registerWorkspaceCommandWith(program, new WorkspaceCommand());
|
|
576
|
+
}
|
|
577
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class ArchiveCommand {
|
|
2
|
+
execute(changeName?: string, options?: {
|
|
3
|
+
yes?: boolean;
|
|
4
|
+
skipSpecs?: boolean;
|
|
5
|
+
noValidate?: boolean;
|
|
6
|
+
validate?: boolean;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
private selectChange;
|
|
9
|
+
private getArchiveDate;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=archive.d.ts.map
|