@niujiajie/freespec 0.0.0-stage → 1.15.0
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 +58 -2
- package/bin/freespec.js +5 -0
- package/dist/cli/index.d.ts +25 -0
- package/dist/cli/index.js +359 -0
- package/dist/commands/shared-output.d.ts +18 -0
- package/dist/commands/shared-output.js +61 -0
- package/dist/commands/workflow/default-schema.d.ts +2 -0
- package/dist/commands/workflow/default-schema.js +4 -0
- package/dist/commands/workflow/index.d.ts +13 -0
- package/dist/commands/workflow/index.js +10 -0
- package/dist/commands/workflow/instructions.d.ts +39 -0
- package/dist/commands/workflow/instructions.js +565 -0
- package/dist/commands/workflow/new-change.d.ts +19 -0
- package/dist/commands/workflow/new-change.js +135 -0
- package/dist/commands/workflow/shared.d.ts +94 -0
- package/dist/commands/workflow/shared.js +169 -0
- package/dist/commands/workflow/status.d.ts +18 -0
- package/dist/commands/workflow/status.js +201 -0
- package/dist/core/artifact-graph/graph.d.ts +72 -0
- package/dist/core/artifact-graph/graph.js +165 -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 +208 -0
- package/dist/core/artifact-graph/instruction-loader.js +268 -0
- package/dist/core/artifact-graph/outputs.d.ts +19 -0
- package/dist/core/artifact-graph/outputs.js +351 -0
- package/dist/core/artifact-graph/resolver.d.ts +89 -0
- package/dist/core/artifact-graph/resolver.js +342 -0
- package/dist/core/artifact-graph/schema.d.ts +27 -0
- package/dist/core/artifact-graph/schema.js +160 -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 +59 -0
- package/dist/core/available-tools.d.ts +18 -0
- package/dist/core/available-tools.js +49 -0
- package/dist/core/change-layout.d.ts +17 -0
- package/dist/core/change-layout.js +30 -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 +23 -0
- package/dist/core/change-metadata/schema.js +46 -0
- package/dist/core/change-status-policy.d.ts +49 -0
- package/dist/core/change-status-policy.js +50 -0
- package/dist/core/command-generation/adapters/amazon-q.d.ts +17 -0
- package/dist/core/command-generation/adapters/amazon-q.js +32 -0
- package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
- package/dist/core/command-generation/adapters/antigravity.js +27 -0
- package/dist/core/command-generation/adapters/atomcode.d.ts +24 -0
- package/dist/core/command-generation/adapters/atomcode.js +46 -0
- package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
- package/dist/core/command-generation/adapters/auggie.js +28 -0
- package/dist/core/command-generation/adapters/bob.d.ts +18 -0
- package/dist/core/command-generation/adapters/bob.js +33 -0
- package/dist/core/command-generation/adapters/claude.d.ts +13 -0
- package/dist/core/command-generation/adapters/claude.js +32 -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/codeassistant.d.ts +15 -0
- package/dist/core/command-generation/adapters/codeassistant.js +29 -0
- package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
- package/dist/core/command-generation/adapters/codebuddy.js +29 -0
- package/dist/core/command-generation/adapters/codestudio.d.ts +13 -0
- package/dist/core/command-generation/adapters/codestudio.js +27 -0
- package/dist/core/command-generation/adapters/command-code.d.ts +19 -0
- package/dist/core/command-generation/adapters/command-code.js +34 -0
- package/dist/core/command-generation/adapters/continue.d.ts +13 -0
- package/dist/core/command-generation/adapters/continue.js +33 -0
- package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
- package/dist/core/command-generation/adapters/costrict.js +28 -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 +31 -0
- package/dist/core/command-generation/adapters/devin.d.ts +19 -0
- package/dist/core/command-generation/adapters/devin.js +36 -0
- package/dist/core/command-generation/adapters/easycode.d.ts +17 -0
- package/dist/core/command-generation/adapters/easycode.js +28 -0
- package/dist/core/command-generation/adapters/factory.d.ts +13 -0
- package/dist/core/command-generation/adapters/factory.js +28 -0
- package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
- package/dist/core/command-generation/adapters/gemini.js +27 -0
- package/dist/core/command-generation/adapters/gigacode.d.ts +17 -0
- package/dist/core/command-generation/adapters/gigacode.js +31 -0
- package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
- package/dist/core/command-generation/adapters/github-copilot.js +27 -0
- package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
- package/dist/core/command-generation/adapters/iflow.js +30 -0
- package/dist/core/command-generation/adapters/index.d.ts +40 -0
- package/dist/core/command-generation/adapters/index.js +40 -0
- package/dist/core/command-generation/adapters/junie.d.ts +13 -0
- package/dist/core/command-generation/adapters/junie.js +27 -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 +27 -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/oh-my-pi.d.ts +21 -0
- package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
- package/dist/core/command-generation/adapters/opencode.d.ts +14 -0
- package/dist/core/command-generation/adapters/opencode.js +38 -0
- package/dist/core/command-generation/adapters/pi.d.ts +18 -0
- package/dist/core/command-generation/adapters/pi.js +39 -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 +17 -0
- package/dist/core/command-generation/adapters/qwen.js +31 -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/trae.d.ts +13 -0
- package/dist/core/command-generation/adapters/trae.js +28 -0
- package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
- package/dist/core/command-generation/adapters/zcode.js +33 -0
- package/dist/core/command-generation/generator.d.ts +29 -0
- package/dist/core/command-generation/generator.js +43 -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/invocation.d.ts +73 -0
- package/dist/core/command-generation/invocation.js +77 -0
- package/dist/core/command-generation/registry.d.ts +36 -0
- package/dist/core/command-generation/registry.js +114 -0
- package/dist/core/command-generation/toml.d.ts +19 -0
- package/dist/core/command-generation/toml.js +39 -0
- package/dist/core/command-generation/types.d.ts +63 -0
- package/dist/core/command-generation/types.js +8 -0
- package/dist/core/command-generation/yaml.d.ts +36 -0
- package/dist/core/command-generation/yaml.js +48 -0
- package/dist/core/command-surface.d.ts +15 -0
- package/dist/core/command-surface.js +33 -0
- package/dist/core/config-prompts.d.ts +9 -0
- package/dist/core/config-prompts.js +56 -0
- package/dist/core/config-schema.d.ts +98 -0
- package/dist/core/config-schema.js +308 -0
- package/dist/core/config.d.ts +50 -0
- package/dist/core/config.js +122 -0
- package/dist/core/file-state.d.ts +36 -0
- package/dist/core/file-state.js +144 -0
- package/dist/core/file-view.d.ts +13 -0
- package/dist/core/file-view.js +14 -0
- package/dist/core/global-config.d.ts +101 -0
- package/dist/core/global-config.js +182 -0
- package/dist/core/id.d.ts +17 -0
- package/dist/core/id.js +30 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +7 -0
- package/dist/core/init.d.ts +57 -0
- package/dist/core/init.js +836 -0
- package/dist/core/list.d.ts +11 -0
- package/dist/core/list.js +197 -0
- package/dist/core/migration.d.ts +121 -0
- package/dist/core/migration.js +540 -0
- package/dist/core/onboarding-commands.d.ts +30 -0
- package/dist/core/onboarding-commands.js +38 -0
- package/dist/core/openspec-root.d.ts +47 -0
- package/dist/core/openspec-root.js +196 -0
- package/dist/core/planning-home.d.ts +16 -0
- package/dist/core/planning-home.js +67 -0
- package/dist/core/profile-sync-drift.d.ts +31 -0
- package/dist/core/profile-sync-drift.js +201 -0
- package/dist/core/profiles.d.ts +19 -0
- package/dist/core/profiles.js +33 -0
- package/dist/core/project-config.d.ts +132 -0
- package/dist/core/project-config.js +519 -0
- package/dist/core/references.d.ts +10 -0
- package/dist/core/references.js +46 -0
- package/dist/core/root-selection.d.ts +59 -0
- package/dist/core/root-selection.js +132 -0
- package/dist/core/shared/allowed-tools.d.ts +12 -0
- package/dist/core/shared/allowed-tools.js +12 -0
- package/dist/core/shared/ide-restart.d.ts +26 -0
- package/dist/core/shared/ide-restart.js +42 -0
- package/dist/core/shared/index.d.ts +11 -0
- package/dist/core/shared/index.js +11 -0
- package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
- package/dist/core/shared/skill-content-equivalence.js +45 -0
- package/dist/core/shared/skill-files.d.ts +7 -0
- package/dist/core/shared/skill-files.js +43 -0
- package/dist/core/shared/skill-generation.d.ts +49 -0
- package/dist/core/shared/skill-generation.js +125 -0
- package/dist/core/shared/skill-paths.d.ts +13 -0
- package/dist/core/shared/skill-paths.js +23 -0
- package/dist/core/shared/tool-detection.d.ts +99 -0
- package/dist/core/shared/tool-detection.js +318 -0
- package/dist/core/shared-skill-target.d.ts +51 -0
- package/dist/core/shared-skill-target.js +239 -0
- package/dist/core/store/errors.d.ts +20 -0
- package/dist/core/store/errors.js +22 -0
- package/dist/core/store/index.d.ts +2 -0
- package/dist/core/store/index.js +2 -0
- package/dist/core/styles/palette.d.ts +7 -0
- package/dist/core/styles/palette.js +8 -0
- package/dist/core/templates/optional-workflow.d.ts +69 -0
- package/dist/core/templates/optional-workflow.js +140 -0
- package/dist/core/templates/types.d.ts +19 -0
- package/dist/core/templates/types.js +5 -0
- package/dist/core/templates/workflows/personal.d.ts +22 -0
- package/dist/core/templates/workflows/personal.js +225 -0
- package/dist/core/update-plan.d.ts +127 -0
- package/dist/core/update-plan.js +390 -0
- package/dist/core/update.d.ts +154 -0
- package/dist/core/update.js +723 -0
- package/dist/core/version-check.d.ts +188 -0
- package/dist/core/version-check.js +906 -0
- package/dist/core/zod-issues.d.ts +4 -0
- package/dist/core/zod-issues.js +10 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/prompts/searchable-multi-select.d.ts +35 -0
- package/dist/prompts/searchable-multi-select.js +188 -0
- package/dist/telemetry/config.d.ts +37 -0
- package/dist/telemetry/config.js +148 -0
- package/dist/telemetry/index.d.ts +39 -0
- package/dist/telemetry/index.js +217 -0
- package/dist/telemetry/opt-out.d.ts +17 -0
- package/dist/telemetry/opt-out.js +27 -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 +18 -0
- package/dist/ui/welcome-screen.js +199 -0
- package/dist/utils/change-metadata.d.ts +116 -0
- package/dist/utils/change-metadata.js +324 -0
- package/dist/utils/change-utils.d.ts +79 -0
- package/dist/utils/change-utils.js +121 -0
- package/dist/utils/ci.d.ts +12 -0
- package/dist/utils/ci.js +16 -0
- package/dist/utils/command-references.d.ts +104 -0
- package/dist/utils/command-references.js +190 -0
- package/dist/utils/date.d.ts +8 -0
- package/dist/utils/date.js +13 -0
- package/dist/utils/executable-path.d.ts +5 -0
- package/dist/utils/executable-path.js +44 -0
- package/dist/utils/file-system.d.ts +58 -0
- package/dist/utils/file-system.js +432 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/interactive.d.ts +85 -0
- package/dist/utils/interactive.js +174 -0
- package/dist/utils/item-discovery.d.ts +15 -0
- package/dist/utils/item-discovery.js +33 -0
- package/dist/utils/line-endings.d.ts +34 -0
- package/dist/utils/line-endings.js +46 -0
- package/dist/utils/match.d.ts +3 -0
- package/dist/utils/match.js +22 -0
- package/dist/utils/nested-change.d.ts +35 -0
- package/dist/utils/nested-change.js +185 -0
- package/dist/utils/shell-detection.d.ts +20 -0
- package/dist/utils/shell-detection.js +94 -0
- package/dist/utils/task-progress.d.ts +67 -0
- package/dist/utils/task-progress.js +184 -0
- package/package.json +74 -4
- package/schemas//351/273/230/350/256/244/schema.yaml +68 -0
- package/schemas//351/273/230/350/256/244/templates//344/273/273/345/212/241/346/270/205/345/215/225.md +25 -0
- package/schemas//351/273/230/350/256/244/templates//346/265/213/350/257/225/347/224/250/344/276/213.md +34 -0
- package/schemas//351/273/230/350/256/244/templates//350/256/276/350/256/241/346/226/207/346/241/243.md +172 -0
- package/schemas//351/273/230/350/256/244/templates//351/234/200/346/261/202/346/226/207/346/241/243.md +19 -0
- package/skill-files//344/273/273/345/212/241/references//346/212/244/346/240/217.md +43 -0
- package/skill-files//344/273/273/345/212/241/references//347/262/222/345/272/246.md +23 -0
- package/skill-files//344/273/273/345/212/241/references//347/272/246/346/235/237.md +8 -0
- package/skill-files//344/273/273/345/212/241/scripts/check-tasks.mjs +83 -0
- package/skill-files//345/206/231Java/references/Java/350/247/204/350/214/203.md +25 -0
- package/skill-files//345/206/231Java/references//345/215/261/351/231/251/345/206/231/346/263/225.md +27 -0
- package/skill-files//345/206/231Java/references//345/256/214/346/210/220/345/257/271/347/205/247.md +15 -0
- package/skill-files//345/206/231Java/references//346/212/244/346/240/217.md +35 -0
- package/skill-files//345/206/231Java/references//347/272/246/346/235/237.md +8 -0
- package/skill-files//345/206/231Java/references//350/270/251/345/235/221.md +17 -0
- package/skill-files//345/256/241Java/references//346/212/244/346/240/217.md +19 -0
- package/skill-files//345/256/241Java/references//347/244/272/344/276/213.md +23 -0
- package/skill-files//345/256/241Java/references//347/272/246/346/235/237.md +7 -0
- package/skill-files//345/256/241Java/references//350/247/204/345/210/231.md +23 -0
- package/skill-files//345/256/241Java/references//351/242/206/345/237/237/346/243/200/351/241/271.md +58 -0
- package/skill-files//345/256/241/346/226/207/346/241/243/references//346/212/244/346/240/217.md +18 -0
- package/skill-files//345/256/241/346/226/207/346/241/243/references//347/272/246/346/235/237.md +8 -0
- package/skill-files//345/256/241/346/226/207/346/241/243/references//347/273/264/345/272/246.md +17 -0
- package/skill-files//345/256/241/346/226/207/346/241/243/references//350/270/251/345/235/221.md +11 -0
- package/skill-files//346/226/260/345/273/272/references//344/272/244/346/216/245.md +11 -0
- package/skill-files//346/226/260/345/273/272/references//346/212/244/346/240/217.md +14 -0
- package/skill-files//346/226/260/345/273/272/references//347/272/246/346/235/237.md +7 -0
- package/skill-files//346/267/261/346/200/235/config/prompts.yaml +114 -0
- package/skill-files//346/267/261/346/200/235/references//344/270/211/346/226/271/346/240/270/345/257/271.md +72 -0
- package/skill-files//346/267/261/346/200/235/references//344/276/213/345/255/220.md +39 -0
- package/skill-files//346/267/261/346/200/235/references//346/200/216/344/271/210/346/203/263.md +61 -0
- package/skill-files//346/267/261/346/200/235/references//346/212/244/346/240/217.md +26 -0
- package/skill-files//346/267/261/346/200/235/references//347/202/271/351/200/211/346/217/220/351/227/256.md +66 -0
- package/skill-files//346/267/261/346/200/235/references//347/231/273/350/256/260.md +45 -0
- package/skill-files//346/267/261/346/200/235/references//347/272/246/346/235/237.md +9 -0
- package/skill-files//347/224/250/344/276/213/references//346/200/216/344/271/210/345/206/231.md +13 -0
- package/skill-files//347/224/250/344/276/213/references//346/212/244/346/240/217.md +42 -0
- package/skill-files//347/224/250/344/276/213/references//347/272/246/346/235/237.md +5 -0
- package/skill-files//347/224/250/344/276/213/scripts/check-cases.mjs +70 -0
- package/skill-files//350/256/276/350/256/241/references//345/207/206/345/244/207.md +25 -0
- package/skill-files//350/256/276/350/256/241/references//346/212/244/346/240/217.md +134 -0
- package/skill-files//350/256/276/350/256/241/references//346/226/207/351/243/216.md +17 -0
- package/skill-files//350/256/276/350/256/241/references//347/225/214/351/235/242.md +18 -0
- package/skill-files//350/256/276/350/256/241/references//347/261/273/345/236/213.md +19 -0
- package/skill-files//350/256/276/350/256/241/references//347/272/246/346/235/237.md +25 -0
- package/skill-files//350/256/276/350/256/241/scripts/_smoke.mjs +72 -0
- package/skill-files//350/256/276/350/256/241/scripts/check-design.mjs +331 -0
- package/skill-files//351/234/200/346/261/202/references//346/212/244/346/240/217.md +26 -0
- package/skill-files//351/234/200/346/261/202/references//346/226/207/351/243/216.md +23 -0
- package/skill-files//351/234/200/346/261/202/references//346/267/261/346/200/235/346/221/204/345/205/245.md +21 -0
- package/skill-files//351/234/200/346/261/202/references//347/272/246/346/235/237.md +8 -0
- package/skill-files//351/234/200/346/261/202/references//351/234/200/346/261/202/345/276/205/345/256/232.md +13 -0
- package/skill-files//351/234/200/346/261/202/scripts/check-requirements.mjs +60 -0
- package/skill-files//351/252/214/346/224/266/references//346/212/244/346/240/217.md +27 -0
- package/skill-files//351/252/214/346/224/266/references//346/240/270/345/257/271.md +17 -0
- package/skill-files//351/252/214/346/224/266/references//347/272/246/346/235/237.md +7 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { AI_TOOLS } from '../config.js';
|
|
4
|
+
export function toolSupportsSkills(tool) {
|
|
5
|
+
return Boolean(tool.skillsDir || tool.globalSkillsDir);
|
|
6
|
+
}
|
|
7
|
+
export function getSkillCapableTools() {
|
|
8
|
+
return AI_TOOLS.filter(toolSupportsSkills);
|
|
9
|
+
}
|
|
10
|
+
export function hasGlobalSkillTarget(tool) {
|
|
11
|
+
return Boolean(tool.globalSkillsDir);
|
|
12
|
+
}
|
|
13
|
+
export function resolveToolSkillsDir(projectRoot, tool, options = {}) {
|
|
14
|
+
if (tool.globalSkillsDir) {
|
|
15
|
+
const homeDir = options.homeDir ?? process.env.USERPROFILE ?? process.env.HOME ?? os.homedir();
|
|
16
|
+
return path.join(homeDir, tool.globalSkillsDir, 'skills');
|
|
17
|
+
}
|
|
18
|
+
if (tool.skillsDir) {
|
|
19
|
+
return path.join(projectRoot, tool.skillsDir, 'skills');
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Tool '${tool.value}' does not support skill generation.`);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=skill-paths.js.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Detection Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for detecting tool configurations and version status.
|
|
5
|
+
*/
|
|
6
|
+
import { type Delivery } from '../global-config.js';
|
|
7
|
+
import { type FileView } from '../file-view.js';
|
|
8
|
+
/**
|
|
9
|
+
* Names of skill directories created by freespec init.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SKILL_NAMES: readonly ["freespec-新建", "freespec-深思", "freespec-需求", "freespec-设计", "freespec-任务", "freespec-审文档", "freespec-用例", "freespec-验收", "freespec-写Java", "freespec-审Java"];
|
|
12
|
+
export type SkillName = (typeof SKILL_NAMES)[number];
|
|
13
|
+
/**
|
|
14
|
+
* IDs of command templates created by freespec init.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMMAND_IDS: readonly ["新建", "深思", "需求", "设计", "任务", "审文档", "用例", "验收", "写Java", "审Java"];
|
|
17
|
+
export type CommandId = (typeof COMMAND_IDS)[number];
|
|
18
|
+
/**
|
|
19
|
+
* Status of skill configuration for a tool.
|
|
20
|
+
*/
|
|
21
|
+
export interface ToolSkillStatus {
|
|
22
|
+
/** Whether the tool has any skills configured */
|
|
23
|
+
configured: boolean;
|
|
24
|
+
/** Whether all skills are configured */
|
|
25
|
+
fullyConfigured: boolean;
|
|
26
|
+
/** Number of skills currently configured */
|
|
27
|
+
skillCount: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Version information for a tool's skills.
|
|
31
|
+
*/
|
|
32
|
+
export interface ToolVersionStatus {
|
|
33
|
+
/** The tool ID */
|
|
34
|
+
toolId: string;
|
|
35
|
+
/** The tool's display name */
|
|
36
|
+
toolName: string;
|
|
37
|
+
/** Whether the tool has any skills or commands configured */
|
|
38
|
+
configured: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The generatedBy version recorded in the tool's skill files. For a tool that
|
|
41
|
+
* has commands but no skills, the current version when the command files match
|
|
42
|
+
* what would be generated now. Null when neither says the files are current.
|
|
43
|
+
*/
|
|
44
|
+
generatedByVersion: string | null;
|
|
45
|
+
/** Whether the tool needs updating (version mismatch or missing) */
|
|
46
|
+
needsUpdate: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Gets the list of tools with skillsDir configured.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getToolsWithSkillsDir(): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Checks which skill files exist for a tool.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getToolSkillStatus(projectRoot: string, toolId: string, view?: FileView): ToolSkillStatus;
|
|
56
|
+
/**
|
|
57
|
+
* Checks whether a tool has at least one generated FreeSpec command file.
|
|
58
|
+
*/
|
|
59
|
+
export declare function toolHasAnyConfiguredCommand(projectPath: string, toolId: string, view?: FileView): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Checks whether command files for a tool on disk match current generated command contents.
|
|
62
|
+
*
|
|
63
|
+
* Command files carry no version stamp, so content equality is the only available
|
|
64
|
+
* "is this current?" signal for a commands-only install.
|
|
65
|
+
*/
|
|
66
|
+
export declare function areCommandFilesUpToDate(projectRoot: string, toolId: string, options?: {
|
|
67
|
+
workflows?: readonly string[];
|
|
68
|
+
/** The tree to read; the disk unless an update is planning. */
|
|
69
|
+
view?: FileView;
|
|
70
|
+
}): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Gets the skill status for all tools with skillsDir configured.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getToolStates(projectRoot: string): Map<string, ToolSkillStatus>;
|
|
75
|
+
/**
|
|
76
|
+
* Extracts the generatedBy version from a skill file's YAML frontmatter.
|
|
77
|
+
* Returns null if the field is not found or the file doesn't exist.
|
|
78
|
+
*/
|
|
79
|
+
export declare function extractGeneratedByVersion(skillFilePath: string, view?: FileView): string | null;
|
|
80
|
+
/**
|
|
81
|
+
* Gets version status for a tool by reading its skill files, falling back to a
|
|
82
|
+
* command-content fingerprint for installs that have commands but no skills.
|
|
83
|
+
*/
|
|
84
|
+
export declare function getToolVersionStatus(projectRoot: string, toolId: string, currentVersion: string, options?: {
|
|
85
|
+
workflows?: readonly string[];
|
|
86
|
+
/** The tree to read; the disk unless an update is planning. */
|
|
87
|
+
view?: FileView;
|
|
88
|
+
/** Effective delivery; read from the global config when omitted. */
|
|
89
|
+
delivery?: Delivery;
|
|
90
|
+
}): ToolVersionStatus;
|
|
91
|
+
/**
|
|
92
|
+
* Gets all configured tools in the project (configured via skills or commands).
|
|
93
|
+
*/
|
|
94
|
+
export declare function getConfiguredTools(projectRoot: string, view?: FileView): string[];
|
|
95
|
+
/**
|
|
96
|
+
* Gets version status for all configured tools.
|
|
97
|
+
*/
|
|
98
|
+
export declare function getAllToolVersionStatus(projectRoot: string, currentVersion: string): ToolVersionStatus[];
|
|
99
|
+
//# sourceMappingURL=tool-detection.d.ts.map
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Detection Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for detecting tool configurations and version status.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { AI_TOOLS, OPENSPEC_SKILL_NAMES } from '../config.js';
|
|
8
|
+
import { CommandAdapterRegistry, generateCommands } from '../command-generation/index.js';
|
|
9
|
+
import { getCommandContents } from './skill-generation.js';
|
|
10
|
+
import { getGlobalConfig } from '../global-config.js';
|
|
11
|
+
import { getProfileWorkflows, ALL_WORKFLOWS } from '../profiles.js';
|
|
12
|
+
import { isSharedSkillTargetActive, hasLegacySkills, readSharedSkillTarget, reconcileSharedSkillTargets, } from '../shared-skill-target.js';
|
|
13
|
+
import { shouldGenerateCommandsForTool, shouldGenerateSkillsForTool, resolveCommandSurfaceCapability, } from '../command-surface.js';
|
|
14
|
+
import { getSkillCapableTools, resolveToolSkillsDir, toolSupportsSkills, } from './skill-paths.js';
|
|
15
|
+
import { DISK_VIEW } from '../file-view.js';
|
|
16
|
+
/**
|
|
17
|
+
* Names of skill directories created by freespec init.
|
|
18
|
+
*/
|
|
19
|
+
export const SKILL_NAMES = OPENSPEC_SKILL_NAMES;
|
|
20
|
+
/**
|
|
21
|
+
* IDs of command templates created by freespec init.
|
|
22
|
+
*/
|
|
23
|
+
export const COMMAND_IDS = ALL_WORKFLOWS;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the list of tools with skillsDir configured.
|
|
26
|
+
*/
|
|
27
|
+
export function getToolsWithSkillsDir() {
|
|
28
|
+
return getSkillCapableTools().map((tool) => tool.value);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Checks which skill files exist for a tool.
|
|
32
|
+
*/
|
|
33
|
+
export function getToolSkillStatus(projectRoot, toolId, view = DISK_VIEW) {
|
|
34
|
+
const tool = AI_TOOLS.find((t) => t.value === toolId);
|
|
35
|
+
if (!tool || !toolSupportsSkills(tool)) {
|
|
36
|
+
return { configured: false, fullyConfigured: false, skillCount: 0 };
|
|
37
|
+
}
|
|
38
|
+
if (tool.skillsDir && !isSharedSkillTargetActive(projectRoot, toolId, view)) {
|
|
39
|
+
return { configured: false, fullyConfigured: false, skillCount: 0 };
|
|
40
|
+
}
|
|
41
|
+
const skillsDirs = [
|
|
42
|
+
resolveToolSkillsDir(projectRoot, tool),
|
|
43
|
+
...(tool.legacySkillsDirs ?? []).map((root) => path.join(projectRoot, root, 'skills')),
|
|
44
|
+
];
|
|
45
|
+
let skillCount = 0;
|
|
46
|
+
for (const skillName of SKILL_NAMES) {
|
|
47
|
+
if (skillsDirs.some((skillsDir) => view.exists(path.join(skillsDir, skillName, 'SKILL.md')))) {
|
|
48
|
+
skillCount++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
configured: skillCount > 0,
|
|
53
|
+
fullyConfigured: skillCount === SKILL_NAMES.length,
|
|
54
|
+
skillCount,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Checks whether a tool has at least one generated FreeSpec command file.
|
|
59
|
+
*/
|
|
60
|
+
export function toolHasAnyConfiguredCommand(projectPath, toolId, view = DISK_VIEW) {
|
|
61
|
+
const adapter = CommandAdapterRegistry.get(toolId);
|
|
62
|
+
if (!adapter)
|
|
63
|
+
return false;
|
|
64
|
+
for (const commandId of COMMAND_IDS) {
|
|
65
|
+
const cmdPath = adapter.getFilePath(commandId);
|
|
66
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
67
|
+
if (view.exists(fullPath)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Normalizes checkout artifacts that are not real content drift: a UTF-8 BOM and
|
|
75
|
+
* CRLF line endings, which a Windows clone with `core.autocrlf` reintroduces on
|
|
76
|
+
* every checkout of committed command files.
|
|
77
|
+
*/
|
|
78
|
+
function normalizeCommandContent(content) {
|
|
79
|
+
return content.replace(/^\uFEFF/, '').replace(/\r\n/g, '\n');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Checks whether command files for a tool on disk match current generated command contents.
|
|
83
|
+
*
|
|
84
|
+
* Command files carry no version stamp, so content equality is the only available
|
|
85
|
+
* "is this current?" signal for a commands-only install.
|
|
86
|
+
*/
|
|
87
|
+
export function areCommandFilesUpToDate(projectRoot, toolId, options) {
|
|
88
|
+
const adapter = CommandAdapterRegistry.get(toolId);
|
|
89
|
+
if (!adapter)
|
|
90
|
+
return false;
|
|
91
|
+
const view = options?.view ?? DISK_VIEW;
|
|
92
|
+
let workflows;
|
|
93
|
+
if (options?.workflows) {
|
|
94
|
+
workflows = options.workflows;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
try {
|
|
98
|
+
const globalCfg = getGlobalConfig();
|
|
99
|
+
const profile = globalCfg.profile ?? 'core';
|
|
100
|
+
workflows = getProfileWorkflows(profile, globalCfg.workflows);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
workflows = ALL_WORKFLOWS;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const knownWorkflows = workflows.filter((w) => ALL_WORKFLOWS.includes(w));
|
|
107
|
+
const commandContents = getCommandContents(knownWorkflows);
|
|
108
|
+
const generatedCommands = generateCommands(commandContents, adapter);
|
|
109
|
+
if (generatedCommands.length === 0) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
for (const cmd of generatedCommands) {
|
|
113
|
+
const cmdPath = path.isAbsolute(cmd.path) ? cmd.path : path.join(projectRoot, cmd.path);
|
|
114
|
+
if (!view.exists(cmdPath)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const existingContent = view.read(cmdPath);
|
|
119
|
+
if (normalizeCommandContent(existingContent) !== normalizeCommandContent(cmd.fileContent)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Also check no extra command files exist for deselected workflows
|
|
128
|
+
const desiredWorkflowSet = new Set(knownWorkflows);
|
|
129
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
130
|
+
if (desiredWorkflowSet.has(workflow))
|
|
131
|
+
continue;
|
|
132
|
+
const cmdPath = adapter.getFilePath(workflow);
|
|
133
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectRoot, cmdPath);
|
|
134
|
+
if (view.exists(fullPath)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Gets the skill status for all tools with skillsDir configured.
|
|
142
|
+
*/
|
|
143
|
+
export function getToolStates(projectRoot) {
|
|
144
|
+
const states = new Map();
|
|
145
|
+
const tools = getSkillCapableTools();
|
|
146
|
+
for (const tool of tools) {
|
|
147
|
+
const skillStatus = getToolSkillStatus(projectRoot, tool.value);
|
|
148
|
+
const markerConfigured = Boolean(tool.skillsDir) &&
|
|
149
|
+
readSharedSkillTarget(projectRoot, tool.skillsDir) === tool.value;
|
|
150
|
+
states.set(tool.value, markerConfigured
|
|
151
|
+
? { ...skillStatus, configured: true }
|
|
152
|
+
: skillStatus);
|
|
153
|
+
}
|
|
154
|
+
const configuredTools = tools.filter((tool) => tool.skillsDir && states.get(tool.value)?.configured);
|
|
155
|
+
const activeSharedTargets = new Set(reconcileSharedSkillTargets(projectRoot, configuredTools).map((tool) => tool.value));
|
|
156
|
+
for (const tool of configuredTools) {
|
|
157
|
+
if (!activeSharedTargets.has(tool.value)) {
|
|
158
|
+
states.set(tool.value, { configured: false, fullyConfigured: false, skillCount: 0 });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return states;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Extracts the generatedBy version from a skill file's YAML frontmatter.
|
|
165
|
+
* Returns null if the field is not found or the file doesn't exist.
|
|
166
|
+
*/
|
|
167
|
+
export function extractGeneratedByVersion(skillFilePath, view = DISK_VIEW) {
|
|
168
|
+
try {
|
|
169
|
+
if (!view.exists(skillFilePath)) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const content = view.read(skillFilePath);
|
|
173
|
+
// Look for generatedBy in the YAML frontmatter
|
|
174
|
+
// The file format is:
|
|
175
|
+
// ---
|
|
176
|
+
// ...
|
|
177
|
+
// metadata:
|
|
178
|
+
// author: freespec
|
|
179
|
+
// version: "1.0"
|
|
180
|
+
// generatedBy: "0.23.0"
|
|
181
|
+
// ---
|
|
182
|
+
// Scanned per line, and with `[ \t]` rather than `\s`, so the leading
|
|
183
|
+
// whitespace run can never cross a newline. A single `m`-anchored `\s*`
|
|
184
|
+
// over the whole file re-scans it from every line start, which is
|
|
185
|
+
// quadratic on a whitespace-heavy SKILL.md.
|
|
186
|
+
for (const line of content.split(/\r\n?|\n/)) {
|
|
187
|
+
const generatedByMatch = line.match(/^[ \t]*generatedBy:[ \t]*["']?([^"'\n]+)["']?[ \t]*$/);
|
|
188
|
+
if (generatedByMatch && generatedByMatch[1]) {
|
|
189
|
+
return generatedByMatch[1].trim();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Gets version status for a tool by reading its skill files, falling back to a
|
|
200
|
+
* command-content fingerprint for installs that have commands but no skills.
|
|
201
|
+
*/
|
|
202
|
+
export function getToolVersionStatus(projectRoot, toolId, currentVersion, options) {
|
|
203
|
+
const view = options?.view ?? DISK_VIEW;
|
|
204
|
+
const tool = AI_TOOLS.find((t) => t.value === toolId);
|
|
205
|
+
if (!tool || !toolSupportsSkills(tool)) {
|
|
206
|
+
return {
|
|
207
|
+
toolId,
|
|
208
|
+
toolName: toolId,
|
|
209
|
+
configured: false,
|
|
210
|
+
generatedByVersion: null,
|
|
211
|
+
needsUpdate: false,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
const skillsDirs = [
|
|
215
|
+
resolveToolSkillsDir(projectRoot, tool),
|
|
216
|
+
...(tool.legacySkillsDirs ?? []).map((root) => path.join(projectRoot, root, 'skills')),
|
|
217
|
+
];
|
|
218
|
+
let generatedByVersion = null;
|
|
219
|
+
let foundSkill = false;
|
|
220
|
+
// 1. Find the first skill file that exists and read its version
|
|
221
|
+
for (const skillName of SKILL_NAMES) {
|
|
222
|
+
for (const skillsDir of skillsDirs) {
|
|
223
|
+
const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
|
|
224
|
+
if (view.exists(skillFile)) {
|
|
225
|
+
generatedByVersion = extractGeneratedByVersion(skillFile, view);
|
|
226
|
+
foundSkill = true;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (foundSkill)
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
const skillConfigured = getToolSkillStatus(projectRoot, toolId, view).configured;
|
|
234
|
+
const commandConfigured = toolHasAnyConfiguredCommand(projectRoot, toolId, view);
|
|
235
|
+
const markerConfigured = Boolean(tool.skillsDir) &&
|
|
236
|
+
readSharedSkillTarget(projectRoot, tool.skillsDir, view) === toolId;
|
|
237
|
+
const configured = skillConfigured || commandConfigured || markerConfigured;
|
|
238
|
+
// 2. Commands-only installs have no skill file to read a version from, so fall
|
|
239
|
+
// back to comparing the generated command content. Deliberately skipped when
|
|
240
|
+
// skill files exist: an unreadable version there must still force a rewrite.
|
|
241
|
+
if (!skillConfigured && commandConfigured && areCommandFilesUpToDate(projectRoot, toolId, options)) {
|
|
242
|
+
generatedByVersion = currentVersion;
|
|
243
|
+
}
|
|
244
|
+
if (!skillConfigured && !commandConfigured && markerConfigured) {
|
|
245
|
+
const delivery = options?.delivery ?? getGlobalConfig().delivery ?? 'both';
|
|
246
|
+
if (!shouldGenerateSkillsForTool(toolId, delivery) &&
|
|
247
|
+
!shouldGenerateCommandsForTool(toolId, delivery)) {
|
|
248
|
+
generatedByVersion = currentVersion;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// 3. A version marker in a skill file only proves the SKILL files came from
|
|
252
|
+
// this CLI. It says nothing about the command files written beside them,
|
|
253
|
+
// which a user may have hand-edited or a partial write may have truncated.
|
|
254
|
+
// Without this, `update` answered "all tools up to date" while a damaged
|
|
255
|
+
// command file sat on disk, repairable only by knowing to pass --force.
|
|
256
|
+
// The content comparison already exists; it was simply never consulted
|
|
257
|
+
// once a skill file supplied a version.
|
|
258
|
+
//
|
|
259
|
+
// Scoped to tools that have BOTH, so the commands-only path above keeps
|
|
260
|
+
// its exact behaviour, and skipped when the delivery mode generates no
|
|
261
|
+
// commands for this tool - there would be nothing to compare against, and
|
|
262
|
+
// `areCommandFilesUpToDate` reports an empty command set as "not current".
|
|
263
|
+
let commandsDrifted = false;
|
|
264
|
+
if (skillConfigured && commandConfigured) {
|
|
265
|
+
let generatesCommands = true;
|
|
266
|
+
try {
|
|
267
|
+
generatesCommands = shouldGenerateCommandsForTool(toolId, options?.delivery ?? getGlobalConfig().delivery ?? 'both');
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
generatesCommands = true;
|
|
271
|
+
}
|
|
272
|
+
commandsDrifted =
|
|
273
|
+
generatesCommands && !areCommandFilesUpToDate(projectRoot, toolId, options);
|
|
274
|
+
}
|
|
275
|
+
const needsUpdate = configured &&
|
|
276
|
+
(generatedByVersion === null ||
|
|
277
|
+
generatedByVersion !== currentVersion ||
|
|
278
|
+
commandsDrifted);
|
|
279
|
+
return {
|
|
280
|
+
toolId,
|
|
281
|
+
toolName: tool.name,
|
|
282
|
+
configured,
|
|
283
|
+
generatedByVersion,
|
|
284
|
+
needsUpdate,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Gets all configured tools in the project (configured via skills or commands).
|
|
289
|
+
*/
|
|
290
|
+
export function getConfiguredTools(projectRoot, view = DISK_VIEW) {
|
|
291
|
+
const configured = AI_TOOLS
|
|
292
|
+
.filter((t) => {
|
|
293
|
+
if (!toolSupportsSkills(t))
|
|
294
|
+
return false;
|
|
295
|
+
return (getToolSkillStatus(projectRoot, t.value, view).configured ||
|
|
296
|
+
toolHasAnyConfiguredCommand(projectRoot, t.value, view) ||
|
|
297
|
+
(resolveCommandSurfaceCapability(t.value) === 'adapter-backed' &&
|
|
298
|
+
hasLegacySkills(projectRoot, t, view)) ||
|
|
299
|
+
(Boolean(t.skillsDir) &&
|
|
300
|
+
readSharedSkillTarget(projectRoot, t.skillsDir, view) === t.value));
|
|
301
|
+
});
|
|
302
|
+
const activeProjectTools = new Set(reconcileSharedSkillTargets(projectRoot, configured.filter((tool) => tool.skillsDir), view).map((tool) => tool.value));
|
|
303
|
+
return configured
|
|
304
|
+
.filter((tool) => tool.globalSkillsDir ||
|
|
305
|
+
toolHasAnyConfiguredCommand(projectRoot, tool.value, view) ||
|
|
306
|
+
(resolveCommandSurfaceCapability(tool.value) === 'adapter-backed' &&
|
|
307
|
+
hasLegacySkills(projectRoot, tool, view)) ||
|
|
308
|
+
activeProjectTools.has(tool.value))
|
|
309
|
+
.map((tool) => tool.value);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Gets version status for all configured tools.
|
|
313
|
+
*/
|
|
314
|
+
export function getAllToolVersionStatus(projectRoot, currentVersion) {
|
|
315
|
+
const configuredTools = getConfiguredTools(projectRoot);
|
|
316
|
+
return configuredTools.map((toolId) => getToolVersionStatus(projectRoot, toolId, currentVersion));
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=tool-detection.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type AIToolOption } from './config.js';
|
|
2
|
+
import { type FileView } from './file-view.js';
|
|
3
|
+
/** Reads a valid-looking marker value without letting linked roots escape. */
|
|
4
|
+
export declare function readSharedSkillTarget(projectPath: string, skillsDir: string, view?: FileView): string | undefined;
|
|
5
|
+
/** Whether a tool still has an allowlisted managed skill under an old root. */
|
|
6
|
+
export declare function hasLegacySkills(projectPath: string, tool: AIToolOption, view?: FileView): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Chooses the one selected tool that may render each physical skills root.
|
|
9
|
+
* Command files are not part of this arbitration: tools that share a skills
|
|
10
|
+
* root can still write their own command surface elsewhere under that root.
|
|
11
|
+
*
|
|
12
|
+
* Existing compatible owners win. On a new root, prefer a skills-native
|
|
13
|
+
* renderer over an adapter-backed renderer because its references remain
|
|
14
|
+
* usable by every consumer of the shared tree. Codex is the best fresh owner
|
|
15
|
+
* because its renderer includes both Codex and generic skill invocation forms.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveSharedSkillWriters(projectPath: string, tools: AIToolOption[], view?: FileView): Set<string>;
|
|
18
|
+
/**
|
|
19
|
+
* A shared skill root can only hold one rendered variant of each skill.
|
|
20
|
+
* Keep the writer recorded so later updates do not infer every tool that
|
|
21
|
+
* happens to use the same directory.
|
|
22
|
+
*/
|
|
23
|
+
export declare function reconcileSharedSkillTargets(projectPath: string, tools: AIToolOption[], view?: FileView): AIToolOption[];
|
|
24
|
+
/**
|
|
25
|
+
* Returns whether a tool is the active writer for its physical skills root.
|
|
26
|
+
* Non-shared roots are always active.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isSharedSkillTargetActive(projectPath: string, toolId: string, view?: FileView): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* The tool that already owns `toolId`'s shared skills root, when a DIFFERENT
|
|
31
|
+
* one does. Returns the owner's tool id only when the root already carries an
|
|
32
|
+
* ownership signal (a marker or generated skills) AND reconciliation resolves
|
|
33
|
+
* it to another tool. An empty or unclaimed root returns undefined, so a
|
|
34
|
+
* genuine first-time legacy upgrade — e.g. a Codex-only user with no `.agents`
|
|
35
|
+
* yet — is never reported as owned.
|
|
36
|
+
*/
|
|
37
|
+
export declare function sharedSkillRootOwner(projectPath: string, toolId: string): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Whether generating `toolId` into its shared skills root would clobber a tree
|
|
40
|
+
* a DIFFERENT tool already owns — the guard the legacy-upgrade path uses before
|
|
41
|
+
* writing skills. See {@link sharedSkillRootOwner} for the ownership rules.
|
|
42
|
+
*/
|
|
43
|
+
export declare function sharedSkillRootOwnedByOther(projectPath: string, toolId: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Path of the owner marker for a tool's shared skills root, or null when the
|
|
46
|
+
* tool has no shared root to mark. Lets a caller write the marker itself —
|
|
47
|
+
* `update` routes it through its write seam so a dry run can list it.
|
|
48
|
+
*/
|
|
49
|
+
export declare function sharedSkillTargetMarkerPath(projectPath: string, toolId: string): string | null;
|
|
50
|
+
export declare function writeSharedSkillTarget(projectPath: string, toolId: string): void;
|
|
51
|
+
//# sourceMappingURL=shared-skill-target.d.ts.map
|