@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,239 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { AI_TOOLS, OPENSPEC_SKILL_NAMES } from './config.js';
|
|
4
|
+
import { FileSystemUtils } from '../utils/file-system.js';
|
|
5
|
+
import { resolveCommandSurfaceCapability } from './command-surface.js';
|
|
6
|
+
import { DISK_VIEW } from './file-view.js';
|
|
7
|
+
const TARGET_MARKER = '.freespec-target';
|
|
8
|
+
/** Returns the ownership-marker path for one shared skills root. */
|
|
9
|
+
function markerPath(projectPath, skillsDir) {
|
|
10
|
+
return path.join(projectPath, skillsDir, 'skills', TARGET_MARKER);
|
|
11
|
+
}
|
|
12
|
+
/** Reads a valid-looking marker value without letting linked roots escape. */
|
|
13
|
+
export function readSharedSkillTarget(projectPath, skillsDir, view = DISK_VIEW) {
|
|
14
|
+
try {
|
|
15
|
+
const target = markerPath(projectPath, skillsDir);
|
|
16
|
+
FileSystemUtils.assertProjectArtifactPath(projectPath, target);
|
|
17
|
+
return view.read(target).trim() || undefined;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Whether a tool still has an allowlisted managed skill under an old root. */
|
|
24
|
+
export function hasLegacySkills(projectPath, tool, view = DISK_VIEW) {
|
|
25
|
+
return (tool.legacySkillsDirs ?? []).some((root) => {
|
|
26
|
+
const skillsDir = path.join(projectPath, root, 'skills');
|
|
27
|
+
return OPENSPEC_SKILL_NAMES.some((skillName) => {
|
|
28
|
+
try {
|
|
29
|
+
const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
|
|
30
|
+
FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
|
|
31
|
+
return view.exists(skillFile);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Infers pre-marker ownership from generated invocation syntax. This preserves
|
|
41
|
+
* both existing generic `.agents` trees and Codex trees users moved manually.
|
|
42
|
+
*/
|
|
43
|
+
function inferSharedSkillTarget(projectPath, skillsDir, view = DISK_VIEW) {
|
|
44
|
+
let foundGenericReference = false;
|
|
45
|
+
for (const skillName of OPENSPEC_SKILL_NAMES) {
|
|
46
|
+
const skillFile = path.join(projectPath, skillsDir, 'skills', skillName, 'SKILL.md');
|
|
47
|
+
try {
|
|
48
|
+
FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
|
|
49
|
+
const content = view.read(skillFile);
|
|
50
|
+
if (content.includes('$freespec-'))
|
|
51
|
+
return 'codex';
|
|
52
|
+
if (content.includes('/freespec-'))
|
|
53
|
+
foundGenericReference = true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Missing, unreadable, or out-of-project files provide no ownership signal.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return foundGenericReference ? 'agents' : undefined;
|
|
60
|
+
}
|
|
61
|
+
/** Whether the canonical shared root already contains a FreeSpec skill. */
|
|
62
|
+
function hasCurrentSkills(projectPath, skillsDir, view = DISK_VIEW) {
|
|
63
|
+
return OPENSPEC_SKILL_NAMES.some((skillName) => {
|
|
64
|
+
const skillFile = path.join(projectPath, skillsDir, 'skills', skillName, 'SKILL.md');
|
|
65
|
+
try {
|
|
66
|
+
FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
|
|
67
|
+
return view.exists(skillFile);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Chooses the one selected tool that may render each physical skills root.
|
|
76
|
+
* Command files are not part of this arbitration: tools that share a skills
|
|
77
|
+
* root can still write their own command surface elsewhere under that root.
|
|
78
|
+
*
|
|
79
|
+
* Existing compatible owners win. On a new root, prefer a skills-native
|
|
80
|
+
* renderer over an adapter-backed renderer because its references remain
|
|
81
|
+
* usable by every consumer of the shared tree. Codex is the best fresh owner
|
|
82
|
+
* because its renderer includes both Codex and generic skill invocation forms.
|
|
83
|
+
*/
|
|
84
|
+
export function resolveSharedSkillWriters(projectPath, tools, view = DISK_VIEW) {
|
|
85
|
+
const byRoot = new Map();
|
|
86
|
+
const writers = new Set();
|
|
87
|
+
for (const tool of tools) {
|
|
88
|
+
if (!tool.skillsDir)
|
|
89
|
+
continue;
|
|
90
|
+
const group = byRoot.get(tool.skillsDir) ?? [];
|
|
91
|
+
group.push(tool);
|
|
92
|
+
byRoot.set(tool.skillsDir, group);
|
|
93
|
+
}
|
|
94
|
+
for (const [root, unsortedGroup] of byRoot) {
|
|
95
|
+
const group = [...unsortedGroup].sort((left, right) => AI_TOOLS.indexOf(left) - AI_TOOLS.indexOf(right));
|
|
96
|
+
if (group.length === 1) {
|
|
97
|
+
writers.add(group[0].value);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const skillsNative = group.filter((tool) => resolveCommandSurfaceCapability(tool.value) !== 'adapter-backed');
|
|
101
|
+
const preferredPool = skillsNative.length > 0 ? skillsNative : group;
|
|
102
|
+
const marked = readSharedSkillTarget(projectPath, root, view);
|
|
103
|
+
const inferred = inferSharedSkillTarget(projectPath, root, view);
|
|
104
|
+
const owner = preferredPool.find((tool) => tool.value === marked) ??
|
|
105
|
+
preferredPool.find((tool) => tool.value === inferred) ??
|
|
106
|
+
(hasCurrentSkills(projectPath, root, view)
|
|
107
|
+
? preferredPool.find((tool) => tool.value === 'agents')
|
|
108
|
+
: undefined) ??
|
|
109
|
+
preferredPool.find((tool) => tool.value === 'codex') ??
|
|
110
|
+
preferredPool[0];
|
|
111
|
+
writers.add(owner.value);
|
|
112
|
+
}
|
|
113
|
+
return writers;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A shared skill root can only hold one rendered variant of each skill.
|
|
117
|
+
* Keep the writer recorded so later updates do not infer every tool that
|
|
118
|
+
* happens to use the same directory.
|
|
119
|
+
*/
|
|
120
|
+
export function reconcileSharedSkillTargets(projectPath, tools, view = DISK_VIEW) {
|
|
121
|
+
const byRoot = new Map();
|
|
122
|
+
for (const tool of tools) {
|
|
123
|
+
if (!tool.skillsDir)
|
|
124
|
+
continue;
|
|
125
|
+
const group = byRoot.get(tool.skillsDir) ?? [];
|
|
126
|
+
group.push(tool);
|
|
127
|
+
byRoot.set(tool.skillsDir, group);
|
|
128
|
+
}
|
|
129
|
+
const reconciled = [];
|
|
130
|
+
for (const group of byRoot.values()) {
|
|
131
|
+
if (group.length === 1) {
|
|
132
|
+
reconciled.push(group[0]);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const root = group[0].skillsDir;
|
|
136
|
+
const marked = readSharedSkillTarget(projectPath, root, view);
|
|
137
|
+
const markedTool = group.find((tool) => tool.value === marked);
|
|
138
|
+
if (markedTool) {
|
|
139
|
+
reconciled.push(markedTool);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const inferred = inferSharedSkillTarget(projectPath, root, view);
|
|
143
|
+
const legacyCodex = group.find((tool) => tool.value === 'codex' && hasLegacySkills(projectPath, tool, view));
|
|
144
|
+
if (inferred === 'agents' && legacyCodex) {
|
|
145
|
+
// Before ownership markers existed, selecting both targets produced a
|
|
146
|
+
// generic canonical tree plus a Codex-only legacy tree. Codex now emits
|
|
147
|
+
// a dual-syntax canonical tree, so it can safely consolidate that state.
|
|
148
|
+
reconciled.push(legacyCodex);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const inferredTool = group.find((tool) => tool.value === inferred);
|
|
152
|
+
if (inferredTool) {
|
|
153
|
+
reconciled.push(inferredTool);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
// An unmarked canonical tree predates Codex's move into `.agents`; keep
|
|
157
|
+
// that established agents target instead of overwriting it from `.codex`.
|
|
158
|
+
if (hasCurrentSkills(projectPath, root, view)) {
|
|
159
|
+
reconciled.push(group.find((tool) => tool.value === 'agents') ?? group[0]);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const legacyTool = group.find((tool) => hasLegacySkills(projectPath, tool, view));
|
|
163
|
+
if (legacyTool) {
|
|
164
|
+
reconciled.push(legacyTool);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
// `.agents` existed as the vendor-neutral target before Codex adopted it.
|
|
168
|
+
// Unmarked trees therefore retain that established meaning.
|
|
169
|
+
reconciled.push(group.find((tool) => tool.value === 'agents') ?? group[0]);
|
|
170
|
+
}
|
|
171
|
+
return reconciled;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns whether a tool is the active writer for its physical skills root.
|
|
175
|
+
* Non-shared roots are always active.
|
|
176
|
+
*/
|
|
177
|
+
export function isSharedSkillTargetActive(projectPath, toolId, view = DISK_VIEW) {
|
|
178
|
+
const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
|
|
179
|
+
if (!tool?.skillsDir)
|
|
180
|
+
return false;
|
|
181
|
+
const sharingRoot = AI_TOOLS.filter((candidate) => candidate.skillsDir === tool.skillsDir);
|
|
182
|
+
if (sharingRoot.length < 2)
|
|
183
|
+
return true;
|
|
184
|
+
return reconcileSharedSkillTargets(projectPath, sharingRoot, view)
|
|
185
|
+
.some((candidate) => candidate.value === toolId);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The tool that already owns `toolId`'s shared skills root, when a DIFFERENT
|
|
189
|
+
* one does. Returns the owner's tool id only when the root already carries an
|
|
190
|
+
* ownership signal (a marker or generated skills) AND reconciliation resolves
|
|
191
|
+
* it to another tool. An empty or unclaimed root returns undefined, so a
|
|
192
|
+
* genuine first-time legacy upgrade — e.g. a Codex-only user with no `.agents`
|
|
193
|
+
* yet — is never reported as owned.
|
|
194
|
+
*/
|
|
195
|
+
export function sharedSkillRootOwner(projectPath, toolId) {
|
|
196
|
+
const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
|
|
197
|
+
if (!tool?.skillsDir)
|
|
198
|
+
return undefined;
|
|
199
|
+
const sharingRoot = AI_TOOLS.filter((candidate) => candidate.skillsDir === tool.skillsDir);
|
|
200
|
+
if (sharingRoot.length < 2)
|
|
201
|
+
return undefined;
|
|
202
|
+
const hasOwnerSignal = readSharedSkillTarget(projectPath, tool.skillsDir) !== undefined ||
|
|
203
|
+
hasCurrentSkills(projectPath, tool.skillsDir);
|
|
204
|
+
if (!hasOwnerSignal)
|
|
205
|
+
return undefined;
|
|
206
|
+
const owner = reconcileSharedSkillTargets(projectPath, sharingRoot)[0]?.value;
|
|
207
|
+
return owner && owner !== toolId ? owner : undefined;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Whether generating `toolId` into its shared skills root would clobber a tree
|
|
211
|
+
* a DIFFERENT tool already owns — the guard the legacy-upgrade path uses before
|
|
212
|
+
* writing skills. See {@link sharedSkillRootOwner} for the ownership rules.
|
|
213
|
+
*/
|
|
214
|
+
export function sharedSkillRootOwnedByOther(projectPath, toolId) {
|
|
215
|
+
return sharedSkillRootOwner(projectPath, toolId) !== undefined;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Path of the owner marker for a tool's shared skills root, or null when the
|
|
219
|
+
* tool has no shared root to mark. Lets a caller write the marker itself —
|
|
220
|
+
* `update` routes it through its write seam so a dry run can list it.
|
|
221
|
+
*/
|
|
222
|
+
export function sharedSkillTargetMarkerPath(projectPath, toolId) {
|
|
223
|
+
const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
|
|
224
|
+
if (!tool?.skillsDir)
|
|
225
|
+
return null;
|
|
226
|
+
const sharingRoot = AI_TOOLS.filter((candidate) => candidate.skillsDir === tool.skillsDir);
|
|
227
|
+
if (sharingRoot.length < 2)
|
|
228
|
+
return null;
|
|
229
|
+
return markerPath(projectPath, tool.skillsDir);
|
|
230
|
+
}
|
|
231
|
+
export function writeSharedSkillTarget(projectPath, toolId) {
|
|
232
|
+
const target = sharedSkillTargetMarkerPath(projectPath, toolId);
|
|
233
|
+
if (!target)
|
|
234
|
+
return;
|
|
235
|
+
FileSystemUtils.assertProjectArtifactPath(projectPath, target);
|
|
236
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
237
|
+
fs.writeFileSync(target, `${toolId}\n`, 'utf-8');
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=shared-skill-target.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type StoreDiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
2
|
+
export interface StoreDiagnostic {
|
|
3
|
+
severity: StoreDiagnosticSeverity;
|
|
4
|
+
code: string;
|
|
5
|
+
message: string;
|
|
6
|
+
target?: string;
|
|
7
|
+
fix?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class StoreError extends Error {
|
|
10
|
+
readonly diagnostic: StoreDiagnostic;
|
|
11
|
+
constructor(message: string, code: string, options?: {
|
|
12
|
+
target?: string;
|
|
13
|
+
fix?: string;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export declare function makeStoreDiagnostic(severity: StoreDiagnosticSeverity, code: string, message: string, options?: {
|
|
17
|
+
target?: string;
|
|
18
|
+
fix?: string;
|
|
19
|
+
}): StoreDiagnostic;
|
|
20
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export class StoreError extends Error {
|
|
2
|
+
diagnostic;
|
|
3
|
+
constructor(message, code, options = {}) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'StoreError';
|
|
6
|
+
this.diagnostic = {
|
|
7
|
+
severity: 'error',
|
|
8
|
+
code,
|
|
9
|
+
message,
|
|
10
|
+
...options,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function makeStoreDiagnostic(severity, code, message, options = {}) {
|
|
15
|
+
return {
|
|
16
|
+
severity,
|
|
17
|
+
code,
|
|
18
|
+
message,
|
|
19
|
+
...options,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional-Workflow Conditionals
|
|
3
|
+
*
|
|
4
|
+
* Not every workflow is installed. The `core` profile ships six of the twelve
|
|
5
|
+
* (`propose`, `explore`, `apply`, `update`, `sync`, `archive`), and a `custom`
|
|
6
|
+
* profile can ship any subset. A template that names `/freespec:continue` is
|
|
7
|
+
* therefore writing a dead reference for anyone whose profile omits it — the
|
|
8
|
+
* agent is told to hand off to a workflow that was never generated (#1734,
|
|
9
|
+
* umbrella #919).
|
|
10
|
+
*
|
|
11
|
+
* `command-references.ts` rewrites how a reference is spelled; this module
|
|
12
|
+
* decides whether it is emitted at all. Templates author both branches with
|
|
13
|
+
* `optionalWorkflow()`, and `resolveOptionalWorkflows()` picks one at
|
|
14
|
+
* generation time against the resolved workflow set, so the generated file
|
|
15
|
+
* states one path instead of asking the model to check availability at runtime.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Authors a passage whose wording depends on whether `workflowId` is installed.
|
|
19
|
+
*
|
|
20
|
+
* Both branches must read correctly on their own: the generated file contains
|
|
21
|
+
* exactly one of them, with no trace of the other.
|
|
22
|
+
*
|
|
23
|
+
* @param workflowId - Workflow id as it appears in ALL_WORKFLOWS (e.g. 'continue')
|
|
24
|
+
* @param whenInstalled - Text to emit when the workflow is part of the profile
|
|
25
|
+
* @param whenMissing - Text to emit otherwise, typically a CLI fallback
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* optionalWorkflow('continue', 'suggest `/freespec:continue`', 'run `freespec status`')
|
|
29
|
+
*/
|
|
30
|
+
export declare function optionalWorkflow(workflowId: string, whenInstalled: string, whenMissing: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* A passage that is dropped entirely when `workflowId` is not installed.
|
|
33
|
+
*
|
|
34
|
+
* Use for a line that only makes sense alongside the workflow it names — a
|
|
35
|
+
* command-reference table row, a bullet listing one workflow. When the
|
|
36
|
+
* conditional is the whole line, the line goes with it rather than leaving a
|
|
37
|
+
* blank one behind.
|
|
38
|
+
*
|
|
39
|
+
* @param workflowId - Workflow id as it appears in ALL_WORKFLOWS
|
|
40
|
+
* @param whenInstalled - Text to emit when the workflow is part of the profile
|
|
41
|
+
*/
|
|
42
|
+
export declare function onlyWithWorkflow(workflowId: string, whenInstalled: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Resolves every `optionalWorkflow()` passage in `text` against the workflows
|
|
45
|
+
* that will actually be installed.
|
|
46
|
+
*
|
|
47
|
+
* Runs before the command-reference transformers, so a reference in a branch
|
|
48
|
+
* that was dropped never reaches them.
|
|
49
|
+
*
|
|
50
|
+
* @param text - Template body, possibly containing conditionals
|
|
51
|
+
* @param installedWorkflows - The resolved workflow set for this installation
|
|
52
|
+
* @returns The body with one branch of each conditional kept
|
|
53
|
+
* @throws If a malformed conditional leaves a marker in the output
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveOptionalWorkflows(text: string, installedWorkflows: ReadonlySet<string>): string;
|
|
56
|
+
/**
|
|
57
|
+
* Fails loudly if `text` still carries a conditional marker.
|
|
58
|
+
*
|
|
59
|
+
* Called at the end of resolution to catch a malformed block, and again at the
|
|
60
|
+
* points that write a generated file — so a body that skipped resolution
|
|
61
|
+
* altogether (a generation path that bypassed getSkillTemplates /
|
|
62
|
+
* getCommandTemplates) throws instead of shipping literal markers to a user.
|
|
63
|
+
*
|
|
64
|
+
* @param text - Text about to be written, or just resolved
|
|
65
|
+
* @param reason - What went wrong, used as the message prefix
|
|
66
|
+
* @throws If any `[[freespec:...]]` marker remains
|
|
67
|
+
*/
|
|
68
|
+
export declare function assertWorkflowConditionalsResolved(text: string, reason: string): void;
|
|
69
|
+
//# sourceMappingURL=optional-workflow.d.ts.map
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional-Workflow Conditionals
|
|
3
|
+
*
|
|
4
|
+
* Not every workflow is installed. The `core` profile ships six of the twelve
|
|
5
|
+
* (`propose`, `explore`, `apply`, `update`, `sync`, `archive`), and a `custom`
|
|
6
|
+
* profile can ship any subset. A template that names `/freespec:continue` is
|
|
7
|
+
* therefore writing a dead reference for anyone whose profile omits it — the
|
|
8
|
+
* agent is told to hand off to a workflow that was never generated (#1734,
|
|
9
|
+
* umbrella #919).
|
|
10
|
+
*
|
|
11
|
+
* `command-references.ts` rewrites how a reference is spelled; this module
|
|
12
|
+
* decides whether it is emitted at all. Templates author both branches with
|
|
13
|
+
* `optionalWorkflow()`, and `resolveOptionalWorkflows()` picks one at
|
|
14
|
+
* generation time against the resolved workflow set, so the generated file
|
|
15
|
+
* states one path instead of asking the model to check availability at runtime.
|
|
16
|
+
*/
|
|
17
|
+
const OPEN = '[[freespec:if-workflow ';
|
|
18
|
+
const OPEN_END = ']]';
|
|
19
|
+
const ELSE = '[[freespec:else]]';
|
|
20
|
+
const END = '[[freespec:end]]';
|
|
21
|
+
/**
|
|
22
|
+
* A conditional that occupies a whole line on its own. Matched first so a
|
|
23
|
+
* branch that resolves to empty takes its line with it — otherwise dropping a
|
|
24
|
+
* table row or a bullet would leave a blank line behind, which markdown reads
|
|
25
|
+
* as the end of the table or list.
|
|
26
|
+
*/
|
|
27
|
+
const WHOLE_LINE_PATTERN = /^([ \t]*)\[\[freespec:if-workflow ([a-z-]+)\]\]([^\n]*?)\[\[freespec:else\]\]([^\n]*?)\[\[freespec:end\]\][ \t]*\r?\n/gm;
|
|
28
|
+
const CONDITIONAL_PATTERN = /\[\[freespec:if-workflow ([a-z-]+)\]\]([\s\S]*?)\[\[freespec:else\]\]([\s\S]*?)\[\[freespec:end\]\]/g;
|
|
29
|
+
/** Any leftover marker, used to fail loudly on malformed authoring. */
|
|
30
|
+
const RESIDUAL_MARKER_PATTERN = /\[\[freespec:(if-workflow|else|end)/;
|
|
31
|
+
/** A single well-formed marker, in any position. */
|
|
32
|
+
const MARKER_PATTERN = /\[\[freespec:(?:if-workflow [a-z-]+|else|end)\]\]/g;
|
|
33
|
+
/** Anything that opens like a marker, well-formed or not. */
|
|
34
|
+
const MARKER_LIKE_PATTERN = /\[\[freespec:/;
|
|
35
|
+
/**
|
|
36
|
+
* Rejects a malformed conditional before any branch is chosen.
|
|
37
|
+
*
|
|
38
|
+
* Checking after resolution is not enough: the unselected branch is discarded
|
|
39
|
+
* first, so a truncated block inside it would pass for one profile and throw
|
|
40
|
+
* for another — the exact profile-dependent behavior this module exists to
|
|
41
|
+
* remove. Authoring is either valid for every profile or valid for none.
|
|
42
|
+
*
|
|
43
|
+
* @param text - Template body as authored
|
|
44
|
+
* @throws If a marker is unrecognized, or the blocks are not a flat sequence
|
|
45
|
+
* of if / else / end
|
|
46
|
+
*/
|
|
47
|
+
function assertConditionalsWellFormed(text) {
|
|
48
|
+
const kinds = [];
|
|
49
|
+
const withoutMarkers = text.replace(MARKER_PATTERN, (marker) => {
|
|
50
|
+
kinds.push(marker.startsWith(OPEN) ? 'if' : marker === ELSE ? 'else' : 'end');
|
|
51
|
+
return '';
|
|
52
|
+
});
|
|
53
|
+
const unrecognized = MARKER_LIKE_PATTERN.exec(withoutMarkers);
|
|
54
|
+
if (unrecognized) {
|
|
55
|
+
throw new Error(`Malformed optional-workflow conditional: unrecognized marker at '${withoutMarkers
|
|
56
|
+
.slice(unrecognized.index, unrecognized.index + 40)
|
|
57
|
+
.split('\n')[0]}'. Markers are [[freespec:if-workflow <id>]], [[freespec:else]] and [[freespec:end]].`);
|
|
58
|
+
}
|
|
59
|
+
for (let i = 0; i < kinds.length; i += 3) {
|
|
60
|
+
if (kinds[i] !== 'if' || kinds[i + 1] !== 'else' || kinds[i + 2] !== 'end') {
|
|
61
|
+
throw new Error('Malformed optional-workflow conditional: markers are out of order or a ' +
|
|
62
|
+
'block is incomplete. Each block needs the full [[freespec:if-workflow <id>]] ' +
|
|
63
|
+
'... [[freespec:else]] ... [[freespec:end]] form, and blocks cannot nest.');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Authors a passage whose wording depends on whether `workflowId` is installed.
|
|
69
|
+
*
|
|
70
|
+
* Both branches must read correctly on their own: the generated file contains
|
|
71
|
+
* exactly one of them, with no trace of the other.
|
|
72
|
+
*
|
|
73
|
+
* @param workflowId - Workflow id as it appears in ALL_WORKFLOWS (e.g. 'continue')
|
|
74
|
+
* @param whenInstalled - Text to emit when the workflow is part of the profile
|
|
75
|
+
* @param whenMissing - Text to emit otherwise, typically a CLI fallback
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* optionalWorkflow('continue', 'suggest `/freespec:continue`', 'run `freespec status`')
|
|
79
|
+
*/
|
|
80
|
+
export function optionalWorkflow(workflowId, whenInstalled, whenMissing) {
|
|
81
|
+
return `${OPEN}${workflowId}${OPEN_END}${whenInstalled}${ELSE}${whenMissing}${END}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A passage that is dropped entirely when `workflowId` is not installed.
|
|
85
|
+
*
|
|
86
|
+
* Use for a line that only makes sense alongside the workflow it names — a
|
|
87
|
+
* command-reference table row, a bullet listing one workflow. When the
|
|
88
|
+
* conditional is the whole line, the line goes with it rather than leaving a
|
|
89
|
+
* blank one behind.
|
|
90
|
+
*
|
|
91
|
+
* @param workflowId - Workflow id as it appears in ALL_WORKFLOWS
|
|
92
|
+
* @param whenInstalled - Text to emit when the workflow is part of the profile
|
|
93
|
+
*/
|
|
94
|
+
export function onlyWithWorkflow(workflowId, whenInstalled) {
|
|
95
|
+
return optionalWorkflow(workflowId, whenInstalled, '');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolves every `optionalWorkflow()` passage in `text` against the workflows
|
|
99
|
+
* that will actually be installed.
|
|
100
|
+
*
|
|
101
|
+
* Runs before the command-reference transformers, so a reference in a branch
|
|
102
|
+
* that was dropped never reaches them.
|
|
103
|
+
*
|
|
104
|
+
* @param text - Template body, possibly containing conditionals
|
|
105
|
+
* @param installedWorkflows - The resolved workflow set for this installation
|
|
106
|
+
* @returns The body with one branch of each conditional kept
|
|
107
|
+
* @throws If a malformed conditional leaves a marker in the output
|
|
108
|
+
*/
|
|
109
|
+
export function resolveOptionalWorkflows(text, installedWorkflows) {
|
|
110
|
+
assertConditionalsWellFormed(text);
|
|
111
|
+
const wholeLinesResolved = text.replace(WHOLE_LINE_PATTERN, (_match, indent, workflowId, whenInstalled, whenMissing) => {
|
|
112
|
+
const chosen = installedWorkflows.has(workflowId) ? whenInstalled : whenMissing;
|
|
113
|
+
return chosen === '' ? '' : `${indent}${chosen}\n`;
|
|
114
|
+
});
|
|
115
|
+
const resolved = wholeLinesResolved.replace(CONDITIONAL_PATTERN, (_match, workflowId, whenInstalled, whenMissing) => installedWorkflows.has(workflowId) ? whenInstalled : whenMissing);
|
|
116
|
+
assertWorkflowConditionalsResolved(resolved, 'Malformed optional-workflow conditional');
|
|
117
|
+
return resolved;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fails loudly if `text` still carries a conditional marker.
|
|
121
|
+
*
|
|
122
|
+
* Called at the end of resolution to catch a malformed block, and again at the
|
|
123
|
+
* points that write a generated file — so a body that skipped resolution
|
|
124
|
+
* altogether (a generation path that bypassed getSkillTemplates /
|
|
125
|
+
* getCommandTemplates) throws instead of shipping literal markers to a user.
|
|
126
|
+
*
|
|
127
|
+
* @param text - Text about to be written, or just resolved
|
|
128
|
+
* @param reason - What went wrong, used as the message prefix
|
|
129
|
+
* @throws If any `[[freespec:...]]` marker remains
|
|
130
|
+
*/
|
|
131
|
+
export function assertWorkflowConditionalsResolved(text, reason) {
|
|
132
|
+
const residual = RESIDUAL_MARKER_PATTERN.exec(text);
|
|
133
|
+
if (residual) {
|
|
134
|
+
throw new Error(`${reason}: '${residual[0]}' is unresolved. Optional-workflow blocks are ` +
|
|
135
|
+
'resolved by getSkillTemplates()/getCommandTemplates() against the installed ' +
|
|
136
|
+
'workflow set, and each needs the full [[freespec:if-workflow <id>]] ... ' +
|
|
137
|
+
'[[freespec:else]] ... [[freespec:end]] form.');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=optional-workflow.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core template types for skills and slash commands.
|
|
3
|
+
*/
|
|
4
|
+
export interface SkillTemplate {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
instructions: string;
|
|
8
|
+
license?: string;
|
|
9
|
+
compatibility?: string;
|
|
10
|
+
metadata?: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export interface CommandTemplate {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
category: string;
|
|
16
|
+
tags: string[];
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SkillTemplate, CommandTemplate } from '../types.js';
|
|
2
|
+
export declare function getNewSkillTemplate(): SkillTemplate;
|
|
3
|
+
export declare function getNewCommandTemplate(): CommandTemplate;
|
|
4
|
+
export declare function getAskSkillTemplate(): SkillTemplate;
|
|
5
|
+
export declare function getAskCommandTemplate(): CommandTemplate;
|
|
6
|
+
export declare function getRequirementsSkillTemplate(): SkillTemplate;
|
|
7
|
+
export declare function getRequirementsCommandTemplate(): CommandTemplate;
|
|
8
|
+
export declare function getDesignSkillTemplate(): SkillTemplate;
|
|
9
|
+
export declare function getDesignCommandTemplate(): CommandTemplate;
|
|
10
|
+
export declare function getTasksSkillTemplate(): SkillTemplate;
|
|
11
|
+
export declare function getTasksCommandTemplate(): CommandTemplate;
|
|
12
|
+
export declare function getCasesSkillTemplate(): SkillTemplate;
|
|
13
|
+
export declare function getCasesCommandTemplate(): CommandTemplate;
|
|
14
|
+
export declare function getReviewDocsSkillTemplate(): SkillTemplate;
|
|
15
|
+
export declare function getReviewDocsCommandTemplate(): CommandTemplate;
|
|
16
|
+
export declare function getCheckSkillTemplate(): SkillTemplate;
|
|
17
|
+
export declare function getCheckCommandTemplate(): CommandTemplate;
|
|
18
|
+
export declare function getJavaImplSkillTemplate(): SkillTemplate;
|
|
19
|
+
export declare function getJavaImplCommandTemplate(): CommandTemplate;
|
|
20
|
+
export declare function getJavaReviewSkillTemplate(): SkillTemplate;
|
|
21
|
+
export declare function getJavaReviewCommandTemplate(): CommandTemplate;
|
|
22
|
+
//# sourceMappingURL=personal.d.ts.map
|