@opengsd/gsd-core 1.4.4 → 1.5.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +3 -3
- package/agents/gsd-code-fixer.md +3 -2
- package/agents/gsd-debug-session-manager.md +2 -1
- package/agents/gsd-debugger.md +4 -3
- package/agents/gsd-executor.md +17 -16
- package/agents/gsd-intel-updater.md +38 -41
- package/agents/gsd-phase-researcher.md +8 -8
- package/agents/gsd-plan-checker.md +23 -13
- package/agents/gsd-planner.md +32 -188
- package/agents/gsd-project-researcher.md +5 -4
- package/agents/gsd-research-synthesizer.md +2 -1
- package/agents/gsd-ui-researcher.md +2 -1
- package/agents/gsd-verifier.md +12 -11
- package/bin/install.js +965 -1486
- package/commands/gsd/autonomous.md +5 -1
- package/commands/gsd/ns-manage.md +8 -1
- package/commands/gsd/ns-project.md +5 -0
- package/commands/gsd/ns-review.md +4 -1
- package/commands/gsd/ns-workflow.md +7 -1
- package/commands/gsd/plan-review-convergence.md +5 -4
- package/commands/gsd/surface.md +12 -5
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +198 -101
- package/gsd-core/bin/gsd_run +20 -0
- package/gsd-core/bin/lib/audit-command-router.cjs +61 -0
- package/gsd-core/bin/lib/capability-registry.cjs +2234 -0
- package/gsd-core/bin/lib/capability-state.cjs +336 -0
- package/gsd-core/bin/lib/check-command-router.cjs +133 -2
- package/gsd-core/bin/lib/cli-exit.cjs +22 -3
- package/gsd-core/bin/lib/config-loader.cjs +716 -0
- package/gsd-core/bin/lib/configuration.cjs +4 -34
- package/gsd-core/bin/lib/core-utils.cjs +198 -0
- package/gsd-core/bin/lib/core.cjs +107 -1817
- package/gsd-core/bin/lib/edge-probe.cjs +173 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +63 -25
- package/gsd-core/bin/lib/federated-config.cjs +182 -0
- package/gsd-core/bin/lib/graphify-command-router.cjs +74 -0
- package/gsd-core/bin/lib/init.cjs +58 -12
- package/gsd-core/bin/lib/install-profiles.cjs +157 -3
- package/gsd-core/bin/lib/intel-command-router.cjs +116 -0
- package/gsd-core/bin/lib/intel.cjs +3 -3
- package/gsd-core/bin/lib/io.cjs +222 -0
- package/gsd-core/bin/lib/loop-host-contract.cjs +105 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +460 -0
- package/gsd-core/bin/lib/model-resolver.cjs +426 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -0
- package/gsd-core/bin/lib/phase-id.cjs +215 -0
- package/gsd-core/bin/lib/phase-locator.cjs +148 -0
- package/gsd-core/bin/lib/phase.cjs +17 -0
- package/gsd-core/bin/lib/probe-core.cjs +257 -0
- package/gsd-core/bin/lib/profile-pipeline.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +443 -0
- package/gsd-core/bin/lib/roadmap.cjs +44 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +92 -95
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +68 -29
- package/gsd-core/bin/lib/runtime-homes.cjs +163 -87
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +1439 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +2 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +7 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +13 -0
- package/gsd-core/bin/lib/state-document.cjs +8 -0
- package/gsd-core/bin/lib/state.cjs +114 -2
- package/gsd-core/bin/lib/surface.cjs +66 -14
- package/gsd-core/bin/lib/uat-predicate.cjs +329 -0
- package/gsd-core/bin/lib/update-context.cjs +4 -1
- package/gsd-core/bin/lib/verify.cjs +104 -1
- package/gsd-core/bin/lib/worktree-base-ref.cjs +33 -8
- package/gsd-core/bin/shared/model-catalog.json +11 -6
- package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -1
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +7 -0
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +8 -0
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +7 -0
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +7 -0
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +8 -0
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +8 -0
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/requirements.json +1 -0
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/resolutions.json +4 -0
- package/gsd-core/references/edge-probe.md +261 -0
- package/gsd-core/references/planner-antipatterns.md +41 -0
- package/gsd-core/references/planner-guidance.md +186 -0
- package/gsd-core/references/planner-reviews.md +5 -2
- package/gsd-core/templates/phase-prompt.md +7 -7
- package/gsd-core/templates/project.md +19 -2
- package/gsd-core/templates/spec.md +12 -0
- package/gsd-core/templates/summary-complex.md +1 -0
- package/gsd-core/templates/summary-minimal.md +1 -0
- package/gsd-core/templates/summary-standard.md +1 -0
- package/gsd-core/templates/summary.md +1 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +1 -1
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +111 -51
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +6 -4
- package/gsd-core/workflows/code-review.md +53 -17
- package/gsd-core/workflows/complete-milestone.md +11 -5
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/auto.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +8 -1
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +1 -1
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +4 -1
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase.md +8 -1
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +1 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +1 -1
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +9 -1
- package/gsd-core/workflows/new-project.md +9 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-milestone-gaps.md +1 -1
- package/gsd-core/workflows/plan-phase.md +65 -28
- package/gsd-core/workflows/plan-review-convergence.md +60 -33
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick.md +2 -2
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +1 -1
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +7 -7
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +2 -2
- package/gsd-core/workflows/ship.md +8 -1
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +130 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +1 -1
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/update.md +2 -2
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +8 -1
- package/package.json +11 -3
- package/scripts/base64-scan.sh +1 -1
- package/scripts/changeset/cli.cjs +8 -1
- package/scripts/changeset/lint.cjs +38 -2
- package/scripts/ci-test-scope.cjs +21 -10
- package/scripts/gen-capability-registry.cjs +2293 -0
- package/scripts/gen-loop-host-contract.cjs +471 -0
- package/scripts/lib/allowlist-ratchet.cjs +101 -1
- package/scripts/lint-regression-test-names.allowlist.json +269 -0
- package/scripts/lint-regression-test-names.cjs +117 -0
- package/scripts/lint-test-file-count.allowlist.json +25 -4
- package/scripts/lint-windows-test-portability.cjs +178 -0
- package/scripts/prompt-injection-scan.sh +4 -4
- package/scripts/research-profiles.cjs +10 -10
- package/scripts/run-tests.cjs +133 -29
- package/scripts/secret-scan.sh +3 -3
- package/scripts/sync-next-version.cjs +133 -0
- package/scripts/sync-runtime-launcher.cjs +21 -5
- package/scripts/update-size-baseline.cjs +68 -0
- package/scripts/workflow-policy.cjs +42 -9
- package/scripts/workflow-size.cjs +90 -0
- package/scripts/run-cross-platform-tests.cjs +0 -67
|
@@ -16,6 +16,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
*/
|
|
17
17
|
const node_path_1 = __importDefault(require("node:path"));
|
|
18
18
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
19
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
19
20
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
20
21
|
const installProfiles = require("./install-profiles.cjs");
|
|
21
22
|
const { stageSkillsForProfile, stageAgentsForProfile, stageSkillsForRuntimeAsSkills, stageCommandsForRuntimeFlat, } = installProfiles;
|
|
@@ -129,7 +130,7 @@ function findAgentsSourceRoot(runtimeConfigDir) {
|
|
|
129
130
|
const ALLOWED_RUNTIMES = new Set([
|
|
130
131
|
'claude', 'cursor', 'gemini', 'codex', 'copilot', 'antigravity',
|
|
131
132
|
'windsurf', 'augment', 'trae', 'qwen', 'hermes', 'codebuddy',
|
|
132
|
-
'cline', 'opencode', 'kilo',
|
|
133
|
+
'cline', 'kimi', 'opencode', 'kilo',
|
|
133
134
|
]);
|
|
134
135
|
// ---------------------------------------------------------------------------
|
|
135
136
|
// Layout table builders
|
|
@@ -150,6 +151,43 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
150
151
|
stage: (resolved) => stageAgentsForProfile(findAgentsSourceRoot(configDir), resolved),
|
|
151
152
|
};
|
|
152
153
|
}
|
|
154
|
+
function kimiAgentsKind(destSubpath, prefix, configDir) {
|
|
155
|
+
return {
|
|
156
|
+
kind: 'kimi-agents',
|
|
157
|
+
destSubpath,
|
|
158
|
+
prefix,
|
|
159
|
+
stage: (resolved) => {
|
|
160
|
+
const installExports = getInstallExports();
|
|
161
|
+
const buildKimiAgentArtifacts = installExports['buildKimiAgentArtifacts'];
|
|
162
|
+
const stagedAgents = stageAgentsForProfile(findAgentsSourceRoot(configDir), resolved);
|
|
163
|
+
const subagents = [];
|
|
164
|
+
if (node_fs_1.default.existsSync(stagedAgents)) {
|
|
165
|
+
for (const entry of node_fs_1.default.readdirSync(stagedAgents, { withFileTypes: true })) {
|
|
166
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
167
|
+
continue;
|
|
168
|
+
const agentPath = node_path_1.default.join(stagedAgents, entry.name);
|
|
169
|
+
subagents.push({
|
|
170
|
+
path: node_path_1.default.join('agents', entry.name).replace(/\\/g, '/'),
|
|
171
|
+
content: node_fs_1.default.readFileSync(agentPath, 'utf8'),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const rootAgent = `---\nname: gsd\ndescription: Run GSD workflows in Kimi CLI.\ntools: Agent\n---\n\n# GSD for Kimi CLI\n\nCoordinate installed /skill:gsd-* workflows and route work to generated GSD subagents when a workflow requires an agent handoff.\n`;
|
|
176
|
+
const artifacts = buildKimiAgentArtifacts({ rootAgent, subagents });
|
|
177
|
+
const stageDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'gsd-kimi-agents-'));
|
|
178
|
+
installProfiles.STAGED_DIRS.add(stageDir);
|
|
179
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(stageDir, 'gsd.yaml'), artifacts.root.yaml);
|
|
180
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(stageDir, 'gsd.md'), artifacts.root.prompt);
|
|
181
|
+
const subagentsDir = node_path_1.default.join(stageDir, 'subagents');
|
|
182
|
+
node_fs_1.default.mkdirSync(subagentsDir, { recursive: true });
|
|
183
|
+
for (const artifact of artifacts.subagents) {
|
|
184
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.yaml`), artifact.yaml);
|
|
185
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.md`), artifact.prompt);
|
|
186
|
+
}
|
|
187
|
+
return stageDir;
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
153
191
|
/**
|
|
154
192
|
* Build a skills kind descriptor.
|
|
155
193
|
*
|
|
@@ -158,8 +196,13 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
158
196
|
* @param converterName name of converter function in bin/install.js exports
|
|
159
197
|
* @param runtime canonical runtime ID (gates Hermes/Qwen branding in converter)
|
|
160
198
|
* @param configDir runtime config dir (for .gsd-source marker resolution)
|
|
199
|
+
* @param nested if true, nest concrete skills under their ns-* routers (#69)
|
|
200
|
+
* @param scope install scope; converted to isGlobal and passed as 5th positional
|
|
201
|
+
* arg so scope-aware converters (antigravity, copilot) can choose
|
|
202
|
+
* between global home paths and workspace-relative paths without
|
|
203
|
+
* colliding with the `runtime` string at position 3.
|
|
161
204
|
*/
|
|
162
|
-
function skillsKind(destSubpath, prefix, converterName, runtime, configDir) {
|
|
205
|
+
function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nested = false, scope = 'global') {
|
|
163
206
|
return {
|
|
164
207
|
kind: 'skills',
|
|
165
208
|
destSubpath,
|
|
@@ -168,10 +211,15 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir) {
|
|
|
168
211
|
const installExports = getInstallExports();
|
|
169
212
|
const realConverter = installExports[converterName];
|
|
170
213
|
// Compute cmdNames once per stage call for performance (#3583).
|
|
171
|
-
// Extra args are ignored by converters that don't need
|
|
214
|
+
// Extra trailing args are ignored by converters that don't need them. The
|
|
215
|
+
// isGlobal flag is the 5th positional (NOT the 3rd): the 3rd positional is
|
|
216
|
+
// `runtime` for the claude/kimi/cline converters, so the scope-aware
|
|
217
|
+
// converters (antigravity, copilot) read isGlobal from position 5 to avoid
|
|
218
|
+
// colliding with `runtime` and always taking the global branch.
|
|
172
219
|
const cmdNames = installExports.readGsdCommandNames();
|
|
173
|
-
const
|
|
174
|
-
|
|
220
|
+
const isGlobal = scope === 'global';
|
|
221
|
+
const wrappedConverter = (content, skillName) => realConverter(content, skillName, runtime, cmdNames, isGlobal);
|
|
222
|
+
return stageSkillsForRuntimeAsSkills(findInstallSourceRoot(configDir), resolved, wrappedConverter, prefix, nested);
|
|
175
223
|
},
|
|
176
224
|
};
|
|
177
225
|
}
|
|
@@ -203,11 +251,41 @@ function convertedCommandsKind(destSubpath, prefix, converterName, configDir) {
|
|
|
203
251
|
},
|
|
204
252
|
};
|
|
205
253
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
254
|
+
/** Lazy registry accessor — mirrors pattern from 5b/5c (runtime-homes.cts). */
|
|
255
|
+
function getRegistry() {
|
|
256
|
+
return _require('./capability-registry.cjs');
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Map a single ArtifactKindDescriptor entry to an ArtifactKind using the
|
|
260
|
+
* matching builder function. Mirrors the hand-built calls in the old switch.
|
|
261
|
+
*/
|
|
262
|
+
function dispatchKindEntry(entry, runtime, configDir, scope) {
|
|
263
|
+
const { kind, destSubpath, prefix, nesting, converter } = entry;
|
|
264
|
+
const nested = nesting === 'nested';
|
|
265
|
+
switch (kind) {
|
|
266
|
+
case 'commands':
|
|
267
|
+
if (converter == null) {
|
|
268
|
+
return commandsKind(destSubpath, prefix, configDir);
|
|
269
|
+
}
|
|
270
|
+
return convertedCommandsKind(destSubpath, prefix, converter, configDir);
|
|
271
|
+
case 'agents':
|
|
272
|
+
return agentsKind(destSubpath, prefix, configDir);
|
|
273
|
+
case 'skills':
|
|
274
|
+
if (converter == null) {
|
|
275
|
+
throw new TypeError(`resolveRuntimeArtifactLayout: skills entry for '${runtime}' has converter=null (converter is required for skills)`);
|
|
276
|
+
}
|
|
277
|
+
return skillsKind(destSubpath, prefix, converter, runtime, configDir, nested, scope);
|
|
278
|
+
case 'kimi-agents':
|
|
279
|
+
return kimiAgentsKind(destSubpath, prefix, configDir);
|
|
280
|
+
default:
|
|
281
|
+
throw new TypeError(`resolveRuntimeArtifactLayout: unknown kind '${kind}' in descriptor for runtime '${runtime}'`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
209
284
|
/**
|
|
210
285
|
* Resolve the artifact layout for a given runtime and config directory.
|
|
286
|
+
*
|
|
287
|
+
* ADR-857 phase 5d: driven by the capability-registry artifactLayout descriptor
|
|
288
|
+
* instead of a hardcoded switch statement.
|
|
211
289
|
*/
|
|
212
290
|
function resolveRuntimeArtifactLayout(runtime, configDir, scope = 'global') {
|
|
213
291
|
if (typeof configDir !== 'string' || configDir === '') {
|
|
@@ -219,94 +297,13 @@ function resolveRuntimeArtifactLayout(runtime, configDir, scope = 'global') {
|
|
|
219
297
|
if (!ALLOWED_RUNTIMES.has(runtime)) {
|
|
220
298
|
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
221
299
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
kinds = [
|
|
227
|
-
commandsKind('commands/gsd', 'gsd-', configDir),
|
|
228
|
-
agentsKind('agents', 'gsd-', configDir),
|
|
229
|
-
];
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', 'claude', configDir)];
|
|
233
|
-
}
|
|
234
|
-
break;
|
|
235
|
-
case 'cursor':
|
|
236
|
-
// Cursor 1.6+ supports two artifact surfaces:
|
|
237
|
-
// 1. skills/gsd-<name>/SKILL.md — rich skills with frontmatter + adapter header
|
|
238
|
-
// 2. commands/gsd-<name>.md — plain markdown slash commands (no frontmatter)
|
|
239
|
-
// accessed via '/' in the Agent input (#785)
|
|
240
|
-
kinds = [
|
|
241
|
-
skillsKind('skills', 'gsd-', 'convertClaudeCommandToCursorSkill', 'cursor', configDir),
|
|
242
|
-
convertedCommandsKind('commands', 'gsd-', 'convertClaudeCommandToCursorCommand', configDir),
|
|
243
|
-
];
|
|
244
|
-
break;
|
|
245
|
-
case 'gemini':
|
|
246
|
-
kinds = [commandsKind('commands/gsd', 'gsd-', configDir)];
|
|
247
|
-
break;
|
|
248
|
-
case 'codex':
|
|
249
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodexSkill', 'codex', configDir)];
|
|
250
|
-
break;
|
|
251
|
-
case 'copilot':
|
|
252
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCopilotSkill', 'copilot', configDir)];
|
|
253
|
-
break;
|
|
254
|
-
case 'antigravity':
|
|
255
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToAntigravitySkill', 'antigravity', configDir)];
|
|
256
|
-
break;
|
|
257
|
-
case 'windsurf':
|
|
258
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToWindsurfSkill', 'windsurf', configDir)];
|
|
259
|
-
break;
|
|
260
|
-
case 'augment':
|
|
261
|
-
kinds = [
|
|
262
|
-
commandsKind('commands', 'gsd-', configDir),
|
|
263
|
-
skillsKind('skills', 'gsd-', 'convertClaudeCommandToAugmentSkill', 'augment', configDir),
|
|
264
|
-
];
|
|
265
|
-
break;
|
|
266
|
-
case 'trae':
|
|
267
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToTraeSkill', 'trae', configDir)];
|
|
268
|
-
break;
|
|
269
|
-
case 'qwen':
|
|
270
|
-
kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', 'qwen', configDir)];
|
|
271
|
-
break;
|
|
272
|
-
case 'hermes':
|
|
273
|
-
kinds = [skillsKind('skills/gsd', '', 'convertClaudeCommandToClaudeSkill', 'hermes', configDir)];
|
|
274
|
-
break;
|
|
275
|
-
case 'codebuddy':
|
|
276
|
-
// CodeBuddy (Tencent) reads two user-level surfaces (codebuddy.ai/docs/cli):
|
|
277
|
-
// 1. commands/gsd-<name>.md — slash commands shown in the '/' menu (#789)
|
|
278
|
-
// 2. skills/gsd-<name>/SKILL.md — model-invocable skills, emitted with
|
|
279
|
-
// user-invocable:false so they stay OUT of '/' (the commands surface is
|
|
280
|
-
// the sole '/' entry point) — avoids a duplicated /gsd-* per workflow.
|
|
281
|
-
// Subagents (~/.codebuddy/agents/) are already emitted by the generic agents
|
|
282
|
-
// block in bin/install.js; MCP is excluded (gsd ships no MCP server).
|
|
283
|
-
kinds = [
|
|
284
|
-
convertedCommandsKind('commands', 'gsd-', 'convertClaudeCommandToCodebuddyCommand', configDir),
|
|
285
|
-
skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodebuddySkill', 'codebuddy', configDir),
|
|
286
|
-
];
|
|
287
|
-
break;
|
|
288
|
-
case 'cline':
|
|
289
|
-
kinds = scope === 'global' ? [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClineSkill', 'cline', configDir)] : [];
|
|
290
|
-
break;
|
|
291
|
-
case 'opencode':
|
|
292
|
-
// OpenCode reads flat slash commands from command/ and on-demand skills
|
|
293
|
-
// from skills/<name>/SKILL.md (https://opencode.ai/docs/skills). Emit both.
|
|
294
|
-
kinds = [
|
|
295
|
-
commandsKind('command', 'gsd-', configDir),
|
|
296
|
-
skillsKind('skills', 'gsd-', 'convertClaudeCommandToOpencodeSkill', 'opencode', configDir),
|
|
297
|
-
];
|
|
298
|
-
break;
|
|
299
|
-
case 'kilo':
|
|
300
|
-
// Kilo derives from OpenCode and shares the skills/<name>/SKILL.md layout
|
|
301
|
-
// (https://kilo.ai/docs/customize/skills). Emit flat commands + skills.
|
|
302
|
-
kinds = [
|
|
303
|
-
commandsKind('command', 'gsd-', configDir),
|
|
304
|
-
skillsKind('skills', 'gsd-', 'convertClaudeCommandToKiloSkill', 'kilo', configDir),
|
|
305
|
-
];
|
|
306
|
-
break;
|
|
307
|
-
default:
|
|
308
|
-
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
300
|
+
const desc = getRegistry().runtimes[runtime]?.runtime?.artifactLayout;
|
|
301
|
+
if (!desc) {
|
|
302
|
+
// Runtime is in ALLOWED_RUNTIMES but has no descriptor — reproduce old default: throw.
|
|
303
|
+
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
309
304
|
}
|
|
305
|
+
const entries = desc[scope] ?? [];
|
|
306
|
+
const kinds = entries.map((entry) => dispatchKindEntry(entry, runtime, configDir, scope));
|
|
310
307
|
return { runtime, configDir, scope, kinds };
|
|
311
308
|
}
|
|
312
309
|
module.exports = { resolveRuntimeArtifactLayout, findInstallSourceRoot, getInstallExports };
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Runtime config adapter registry — dispatch table for install-phase config
|
|
4
|
+
* mutations (issue #60), replacing inline `runtime === '...'` branching in
|
|
5
|
+
* bin/install.js.
|
|
6
|
+
*
|
|
7
|
+
* ADR-857 phase 5g drive 2: The hand-kept REGISTRY const has been retired.
|
|
8
|
+
* Values are now read directly from the capability-registry.cjs descriptor
|
|
9
|
+
* (capabilities/<id>/capability.json runtime block) so a single source of
|
|
10
|
+
* truth drives all surfaces.
|
|
11
|
+
*
|
|
12
|
+
* Design notes:
|
|
13
|
+
* - `installSurface` selects which config handler install() runs:
|
|
14
|
+
* 'settings-json' → fall through to the shared settings.json accumulation.
|
|
15
|
+
* 'codex-toml' → early-return after writing codex.toml.
|
|
16
|
+
* 'copilot-instructions' → early-return after writing .github/copilot-instructions.md.
|
|
17
|
+
* 'cline-rules' → early-return after writing .clinerules.
|
|
18
|
+
* 'cursor-hooks-json' → early-return after writing .cursor/hooks.json (issue #777).
|
|
19
|
+
* 'profile-marker-only' → early-return after writing only the profile marker.
|
|
20
|
+
* - `writesSharedSettings` is the finishInstall writeSettings gate:
|
|
21
|
+
* false for codex / copilot / kilo / cursor / windsurf / trae / cline / kimi (legacy exclusion list).
|
|
22
|
+
* true for all other runtimes.
|
|
23
|
+
* - `finishPermissionWriter` names the finishInstall-phase dedicated config writer:
|
|
24
|
+
* 'opencode' → writes BOTH shared settings AND its own permissions file.
|
|
25
|
+
* 'kilo' → writes only its own permissions file.
|
|
26
|
+
* null → no dedicated permission writer.
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
|
+
const { runtimes } = require('./capability-registry.cjs');
|
|
22
30
|
// ---------------------------------------------------------------------------
|
|
23
31
|
// Exports
|
|
24
32
|
// ---------------------------------------------------------------------------
|
|
25
|
-
/** The complete set of
|
|
26
|
-
const ALLOWED_CONFIG_RUNTIMES = new Set(Object.
|
|
33
|
+
/** The complete set of 16 supported runtimes for config-adapter dispatch. */
|
|
34
|
+
const ALLOWED_CONFIG_RUNTIMES = new Set(Object.entries(runtimes)
|
|
35
|
+
.filter(([, cap]) => cap && cap.runtime && typeof cap.runtime['installSurface'] === 'string')
|
|
36
|
+
.map(([id]) => id));
|
|
27
37
|
/** All valid installSurface values. */
|
|
28
38
|
const INSTALL_SURFACES = Object.freeze([
|
|
29
39
|
'settings-json',
|
|
@@ -42,15 +52,44 @@ const INSTALL_SURFACES = Object.freeze([
|
|
|
42
52
|
* @throws {TypeError} if runtime is not a known supported runtime.
|
|
43
53
|
*/
|
|
44
54
|
function resolveRuntimeConfigIntent(runtime) {
|
|
45
|
-
|
|
55
|
+
const entry = runtimes[runtime]?.runtime;
|
|
56
|
+
if (!entry)
|
|
46
57
|
throw new TypeError(`Unknown runtime for config adapter: ${runtime}`);
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
const permissionWriter = entry['permissionWriter'];
|
|
59
|
+
return {
|
|
60
|
+
runtime,
|
|
61
|
+
installSurface: entry['installSurface'],
|
|
62
|
+
writesSharedSettings: entry['writesSharedSettings'],
|
|
63
|
+
finishPermissionWriter: permissionWriter == null ? null : permissionWriter,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the complete install plan for a given runtime.
|
|
68
|
+
*
|
|
69
|
+
* Composes the config-intent axes from resolveRuntimeConfigIntent PLUS the
|
|
70
|
+
* three hook axes (hookEvents / extendedHookEvents / hooksSurface) that
|
|
71
|
+
* install() previously read scattered from the capability registry.
|
|
72
|
+
*
|
|
73
|
+
* ADR-857 phase 5g capstone — single typed seam for all install-level
|
|
74
|
+
* descriptor reads. Returns a fresh object each call.
|
|
75
|
+
*
|
|
76
|
+
* @throws {TypeError} if runtime is not a known supported runtime.
|
|
77
|
+
*/
|
|
78
|
+
function resolveInstallPlan(runtime) {
|
|
79
|
+
const desc = runtimes[runtime]?.runtime;
|
|
80
|
+
if (!desc)
|
|
81
|
+
throw new TypeError(`Unknown runtime for install plan: ${runtime}`);
|
|
82
|
+
const configIntent = resolveRuntimeConfigIntent(runtime);
|
|
49
83
|
return {
|
|
50
84
|
runtime,
|
|
51
|
-
installSurface:
|
|
52
|
-
writesSharedSettings:
|
|
53
|
-
finishPermissionWriter:
|
|
85
|
+
installSurface: configIntent.installSurface,
|
|
86
|
+
writesSharedSettings: configIntent.writesSharedSettings,
|
|
87
|
+
finishPermissionWriter: configIntent.finishPermissionWriter,
|
|
88
|
+
hookEvents: desc['hookEvents'],
|
|
89
|
+
extendedHookEvents: Array.isArray(desc['extendedHookEvents']) ? desc['extendedHookEvents'] : [],
|
|
90
|
+
hooksSurface: desc['hooksSurface'] != null
|
|
91
|
+
? desc['hooksSurface']
|
|
92
|
+
: ((runtime === 'opencode' || runtime === 'kilo') ? 'none' : 'settings-json'),
|
|
54
93
|
};
|
|
55
94
|
}
|
|
56
|
-
module.exports = { resolveRuntimeConfigIntent, ALLOWED_CONFIG_RUNTIMES, INSTALL_SURFACES };
|
|
95
|
+
module.exports = { resolveRuntimeConfigIntent, resolveInstallPlan, ALLOWED_CONFIG_RUNTIMES, INSTALL_SURFACES };
|
|
@@ -15,12 +15,28 @@
|
|
|
15
15
|
* cline — Skills-capable since v3.48.0 (#782). SKILL.md files live at
|
|
16
16
|
* ~/.cline/skills/<skillName>/SKILL.md (same flat layout as cursor/codex).
|
|
17
17
|
* .clinerules is also emitted (rules-based compatibility layer).
|
|
18
|
+
* kimi — Agent Skills are discovered from Kimi's generic user roots:
|
|
19
|
+
* ~/.config/agents/skills (recommended) then ~/.agents/skills,
|
|
20
|
+
* with Kimi selecting the first existing generic skills directory.
|
|
21
|
+
* ~/.kimi-code/skills is brand-specific and can be selected as a
|
|
22
|
+
* GSD write target with --config-dir or KIMI_CONFIG_DIR.
|
|
23
|
+
* trae — Targets Trae IDE (trae.ai), the Electron-based IDE — NOT
|
|
24
|
+
* trae-agent (github.com/bytedance/trae-agent), a Python CLI that
|
|
25
|
+
* uses trae_config.yaml, has no ~/.trae directory, and has no
|
|
26
|
+
* skills system. Both are ByteDance "Trae" products; they are
|
|
27
|
+
* entirely distinct. The global ~/.trae/skills/ path is
|
|
28
|
+
* community-soft-confirmed: docs.trae.ai/ide/skills documents the
|
|
29
|
+
* SKILL.md format and project-level .trae/skills/, but does NOT
|
|
30
|
+
* publish the global on-disk path; ~/.trae/skills/ rests on
|
|
31
|
+
* community evidence incl. Trae-AI/TRAE#2253. Best-effort only.
|
|
18
32
|
*/
|
|
19
33
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
20
34
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
21
35
|
};
|
|
22
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.resolveConfigHomeFromDescriptor = resolveConfigHomeFromDescriptor;
|
|
23
38
|
exports.resolveAntigravityGlobalDir = resolveAntigravityGlobalDir;
|
|
39
|
+
exports.resolveKimiGlobalDir = resolveKimiGlobalDir;
|
|
24
40
|
exports.getGlobalConfigDir = getGlobalConfigDir;
|
|
25
41
|
exports.getGlobalSkillsBase = getGlobalSkillsBase;
|
|
26
42
|
exports.getGlobalSkillDir = getGlobalSkillDir;
|
|
@@ -38,26 +54,142 @@ function expandTilde(p) {
|
|
|
38
54
|
return node_path_1.default.join(node_os_1.default.homedir(), p.slice(1));
|
|
39
55
|
return p;
|
|
40
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a configHome descriptor to an absolute directory path.
|
|
59
|
+
*
|
|
60
|
+
* Implements the four descriptor kinds:
|
|
61
|
+
* - dot-home: env-override → path.join(home, name)
|
|
62
|
+
* - dot-home-nested: env-override → probed subdir of path.join(home, parent)
|
|
63
|
+
* - xdg: env[0] → env[1](dirname) → env[2](XDG subdir) → ~/.config/<name>
|
|
64
|
+
* - generic-agents-root:env[0] → first probe where probeExists exists → probe[0]
|
|
65
|
+
*/
|
|
66
|
+
function resolveConfigHomeFromDescriptor(configHome, opts = {}) {
|
|
67
|
+
const env = opts.env ?? process.env;
|
|
68
|
+
const home = opts.home ?? node_os_1.default.homedir();
|
|
69
|
+
const existsSyncFn = opts.existsSync ?? node_fs_1.default.existsSync;
|
|
70
|
+
switch (configHome.kind) {
|
|
71
|
+
case 'dot-home': {
|
|
72
|
+
// First env var that is set wins
|
|
73
|
+
for (const varName of configHome.env) {
|
|
74
|
+
const val = env[varName];
|
|
75
|
+
if (val)
|
|
76
|
+
return expandTilde(val);
|
|
77
|
+
}
|
|
78
|
+
return node_path_1.default.join(home, configHome.name);
|
|
79
|
+
}
|
|
80
|
+
case 'dot-home-nested': {
|
|
81
|
+
// env override
|
|
82
|
+
const nestedEnv0Val = env[configHome.env[0]];
|
|
83
|
+
if (configHome.env[0] && nestedEnv0Val) {
|
|
84
|
+
return expandTilde(nestedEnv0Val);
|
|
85
|
+
}
|
|
86
|
+
const base = node_path_1.default.join(home, configHome.parent);
|
|
87
|
+
if (configHome.probe && configHome.probe.length > 0) {
|
|
88
|
+
// probe each candidate under base; return first that exists
|
|
89
|
+
for (const candidate of configHome.probe) {
|
|
90
|
+
const resolved = node_path_1.default.join(base, candidate);
|
|
91
|
+
if (existsSyncFn(resolved))
|
|
92
|
+
return resolved;
|
|
93
|
+
}
|
|
94
|
+
// fallback: first probe candidate
|
|
95
|
+
return node_path_1.default.join(base, configHome.probe[0]);
|
|
96
|
+
}
|
|
97
|
+
// no probe (e.g. windsurf): always name under parent
|
|
98
|
+
return node_path_1.default.join(base, configHome.name);
|
|
99
|
+
}
|
|
100
|
+
case 'xdg': {
|
|
101
|
+
// env[0]: direct override dir
|
|
102
|
+
const xdgEnv0Val = env[configHome.env[0]];
|
|
103
|
+
if (configHome.env[0] && xdgEnv0Val) {
|
|
104
|
+
return expandTilde(xdgEnv0Val);
|
|
105
|
+
}
|
|
106
|
+
// env[1]: FILE path → dirname
|
|
107
|
+
const xdgEnv1Val = env[configHome.env[1]];
|
|
108
|
+
if (configHome.env[1] && xdgEnv1Val) {
|
|
109
|
+
return node_path_1.default.dirname(expandTilde(xdgEnv1Val));
|
|
110
|
+
}
|
|
111
|
+
// env[2]: XDG_CONFIG_HOME → subdir
|
|
112
|
+
const xdgEnv2Val = env[configHome.env[2]];
|
|
113
|
+
if (configHome.env[2] && xdgEnv2Val) {
|
|
114
|
+
return node_path_1.default.join(expandTilde(xdgEnv2Val), configHome.name);
|
|
115
|
+
}
|
|
116
|
+
return node_path_1.default.join(home, '.config', configHome.name);
|
|
117
|
+
}
|
|
118
|
+
case 'generic-agents-root': {
|
|
119
|
+
// env override
|
|
120
|
+
const garEnv0Val = env[configHome.env[0]];
|
|
121
|
+
if (configHome.env[0] && garEnv0Val) {
|
|
122
|
+
return expandTilde(garEnv0Val);
|
|
123
|
+
}
|
|
124
|
+
// probe each candidate; return first where probeExists subpath exists
|
|
125
|
+
for (const candidate of configHome.probe) {
|
|
126
|
+
const resolved = expandTildeWithHome(candidate, home);
|
|
127
|
+
if (existsSyncFn(node_path_1.default.join(resolved, configHome.probeExists))) {
|
|
128
|
+
return resolved;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// fallback: first probe candidate
|
|
132
|
+
return expandTildeWithHome(configHome.probe[0], home);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Expand ~ using an explicit home directory (for hermetic testing).
|
|
138
|
+
*/
|
|
139
|
+
function expandTildeWithHome(p, home) {
|
|
140
|
+
if (!p)
|
|
141
|
+
return p;
|
|
142
|
+
if (p.startsWith('~/') || p === '~')
|
|
143
|
+
return node_path_1.default.join(home, p.slice(1));
|
|
144
|
+
return p;
|
|
145
|
+
}
|
|
41
146
|
/**
|
|
42
147
|
* Resolve Antigravity global config dir across 1.x and 2.x layouts.
|
|
148
|
+
*
|
|
149
|
+
* Thin wrapper delegating to resolveConfigHomeFromDescriptor with the
|
|
150
|
+
* antigravity descriptor shape. Preserved for external callers and tests.
|
|
43
151
|
*/
|
|
44
152
|
function resolveAntigravityGlobalDir(opts = {}) {
|
|
45
153
|
const env = opts.env ?? process.env;
|
|
46
154
|
const home = opts.home ?? node_os_1.default.homedir();
|
|
47
155
|
const existsSyncFn = opts.existsSync ?? node_fs_1.default.existsSync;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
156
|
+
return resolveConfigHomeFromDescriptor({
|
|
157
|
+
kind: 'dot-home-nested',
|
|
158
|
+
name: 'antigravity',
|
|
159
|
+
parent: '.gemini',
|
|
160
|
+
env: ['ANTIGRAVITY_CONFIG_DIR'],
|
|
161
|
+
probe: ['antigravity', 'antigravity-ide', 'antigravity-cli'],
|
|
162
|
+
}, { env, home, existsSync: existsSyncFn });
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Resolve Kimi's generic user root using Kimi CLI's documented first-existing
|
|
166
|
+
* generic skills directory policy:
|
|
167
|
+
*
|
|
168
|
+
* 1. ~/.config/agents/skills (recommended)
|
|
169
|
+
* 2. ~/.agents/skills
|
|
170
|
+
*
|
|
171
|
+
* If neither generic skills directory exists yet, install to the recommended
|
|
172
|
+
* ~/.config/agents root so the generated skills become the first generic
|
|
173
|
+
* candidate Kimi discovers.
|
|
174
|
+
*
|
|
175
|
+
* KIMI_CONFIG_DIR is a GSD installer write-location override. It is not Kimi's
|
|
176
|
+
* upstream data-root variable, and arbitrary roots are discoverable by Kimi only
|
|
177
|
+
* when the user also configures Kimi --skills-dir or extra_skill_dirs.
|
|
178
|
+
*
|
|
179
|
+
* Thin wrapper delegating to resolveConfigHomeFromDescriptor with the
|
|
180
|
+
* kimi descriptor shape. Preserved for external callers and tests.
|
|
181
|
+
*/
|
|
182
|
+
function resolveKimiGlobalDir(opts = {}) {
|
|
183
|
+
const env = opts.env ?? process.env;
|
|
184
|
+
const home = opts.home ?? node_os_1.default.homedir();
|
|
185
|
+
const existsSyncFn = opts.existsSync ?? node_fs_1.default.existsSync;
|
|
186
|
+
return resolveConfigHomeFromDescriptor({
|
|
187
|
+
kind: 'generic-agents-root',
|
|
188
|
+
name: 'agents',
|
|
189
|
+
env: ['KIMI_CONFIG_DIR'],
|
|
190
|
+
probe: ['~/.config/agents', '~/.agents'],
|
|
191
|
+
probeExists: 'skills',
|
|
192
|
+
}, { env, home, existsSync: existsSyncFn });
|
|
61
193
|
}
|
|
62
194
|
/**
|
|
63
195
|
* Return the global config base directory for the given runtime.
|
|
@@ -71,81 +203,25 @@ function resolveAntigravityGlobalDir(opts = {}) {
|
|
|
71
203
|
function getGlobalConfigDir(runtime, explicitDir) {
|
|
72
204
|
if (explicitDir)
|
|
73
205
|
return expandTilde(explicitDir);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
case 'claude':
|
|
79
|
-
return env['CLAUDE_CONFIG_DIR'] ? expandTilde(env['CLAUDE_CONFIG_DIR']) : node_path_1.default.join(home, '.claude');
|
|
80
|
-
// ── Cursor ───────────────────────────────────────────────────────────────
|
|
81
|
-
case 'cursor':
|
|
82
|
-
return env['CURSOR_CONFIG_DIR'] ? expandTilde(env['CURSOR_CONFIG_DIR']) : node_path_1.default.join(home, '.cursor');
|
|
83
|
-
// ── Gemini CLI ───────────────────────────────────────────────────────────
|
|
84
|
-
case 'gemini':
|
|
85
|
-
return env['GEMINI_CONFIG_DIR'] ? expandTilde(env['GEMINI_CONFIG_DIR']) : node_path_1.default.join(home, '.gemini');
|
|
86
|
-
// ── Codex ────────────────────────────────────────────────────────────────
|
|
87
|
-
case 'codex':
|
|
88
|
-
return env['CODEX_HOME'] ? expandTilde(env['CODEX_HOME']) : node_path_1.default.join(home, '.codex');
|
|
89
|
-
// ── Grok Build ───────────────────────────────────────────────────────────
|
|
90
|
-
case 'grok':
|
|
91
|
-
return env['GROK_AGENTS_HOME'] ? expandTilde(env['GROK_AGENTS_HOME']) : node_path_1.default.join(home, '.agents');
|
|
92
|
-
// ── Copilot (VS Code) ────────────────────────────────────────────────────
|
|
93
|
-
case 'copilot':
|
|
94
|
-
if (env['COPILOT_CONFIG_DIR'])
|
|
95
|
-
return expandTilde(env['COPILOT_CONFIG_DIR']);
|
|
96
|
-
if (env['COPILOT_HOME'])
|
|
97
|
-
return expandTilde(env['COPILOT_HOME']);
|
|
98
|
-
return node_path_1.default.join(home, '.copilot');
|
|
99
|
-
// ── Antigravity ──────────────────────────────────────────────────────────
|
|
100
|
-
case 'antigravity':
|
|
101
|
-
return resolveAntigravityGlobalDir({ env, home });
|
|
102
|
-
// ── Windsurf ─────────────────────────────────────────────────────────────
|
|
103
|
-
case 'windsurf':
|
|
104
|
-
return env['WINDSURF_CONFIG_DIR']
|
|
105
|
-
? expandTilde(env['WINDSURF_CONFIG_DIR'])
|
|
106
|
-
: node_path_1.default.join(home, '.codeium', 'windsurf');
|
|
107
|
-
// ── Augment ──────────────────────────────────────────────────────────────
|
|
108
|
-
case 'augment':
|
|
109
|
-
return env['AUGMENT_CONFIG_DIR'] ? expandTilde(env['AUGMENT_CONFIG_DIR']) : node_path_1.default.join(home, '.augment');
|
|
110
|
-
// ── Trae ─────────────────────────────────────────────────────────────────
|
|
111
|
-
case 'trae':
|
|
112
|
-
return env['TRAE_CONFIG_DIR'] ? expandTilde(env['TRAE_CONFIG_DIR']) : node_path_1.default.join(home, '.trae');
|
|
113
|
-
// ── Qwen Code ────────────────────────────────────────────────────────────
|
|
114
|
-
case 'qwen':
|
|
115
|
-
return env['QWEN_CONFIG_DIR'] ? expandTilde(env['QWEN_CONFIG_DIR']) : node_path_1.default.join(home, '.qwen');
|
|
116
|
-
// ── Hermes Agent ─────────────────────────────────────────────────────────
|
|
117
|
-
case 'hermes':
|
|
118
|
-
return env['HERMES_HOME'] ? expandTilde(env['HERMES_HOME']) : node_path_1.default.join(home, '.hermes');
|
|
119
|
-
// ── CodeBuddy ────────────────────────────────────────────────────────────
|
|
120
|
-
case 'codebuddy':
|
|
121
|
-
return env['CODEBUDDY_CONFIG_DIR'] ? expandTilde(env['CODEBUDDY_CONFIG_DIR']) : node_path_1.default.join(home, '.codebuddy');
|
|
122
|
-
// ── Cline ────────────────────────────────────────────────────────────────
|
|
123
|
-
case 'cline':
|
|
124
|
-
return env['CLINE_CONFIG_DIR'] ? expandTilde(env['CLINE_CONFIG_DIR']) : node_path_1.default.join(home, '.cline');
|
|
125
|
-
// ── OpenCode (XDG) ───────────────────────────────────────────────────────
|
|
126
|
-
case 'opencode': {
|
|
127
|
-
if (env['OPENCODE_CONFIG_DIR'])
|
|
128
|
-
return expandTilde(env['OPENCODE_CONFIG_DIR']);
|
|
129
|
-
if (env['OPENCODE_CONFIG'])
|
|
130
|
-
return node_path_1.default.dirname(expandTilde(env['OPENCODE_CONFIG']));
|
|
131
|
-
if (env['XDG_CONFIG_HOME'])
|
|
132
|
-
return node_path_1.default.join(expandTilde(env['XDG_CONFIG_HOME']), 'opencode');
|
|
133
|
-
return node_path_1.default.join(home, '.config', 'opencode');
|
|
134
|
-
}
|
|
135
|
-
// ── Kilo (XDG) ───────────────────────────────────────────────────────────
|
|
136
|
-
case 'kilo': {
|
|
137
|
-
if (env['KILO_CONFIG_DIR'])
|
|
138
|
-
return expandTilde(env['KILO_CONFIG_DIR']);
|
|
139
|
-
if (env['KILO_CONFIG'])
|
|
140
|
-
return node_path_1.default.dirname(expandTilde(env['KILO_CONFIG']));
|
|
141
|
-
if (env['XDG_CONFIG_HOME'])
|
|
142
|
-
return node_path_1.default.join(expandTilde(env['XDG_CONFIG_HOME']), 'kilo');
|
|
143
|
-
return node_path_1.default.join(home, '.config', 'kilo');
|
|
144
|
-
}
|
|
145
|
-
// ── Default (Claude fallback) ─────────────────────────────────────────────
|
|
146
|
-
default:
|
|
147
|
-
return env['CLAUDE_CONFIG_DIR'] ? expandTilde(env['CLAUDE_CONFIG_DIR']) : node_path_1.default.join(home, '.claude');
|
|
206
|
+
// ── Grok: not in the registry — hardcoded branch ─────────────────────────
|
|
207
|
+
if (runtime === 'grok') {
|
|
208
|
+
const env = process.env;
|
|
209
|
+
return env['GROK_AGENTS_HOME'] ? expandTilde(env['GROK_AGENTS_HOME']) : node_path_1.default.join(node_os_1.default.homedir(), '.agents');
|
|
148
210
|
}
|
|
211
|
+
// ── Descriptor-driven: look up in capability-registry ────────────────────
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
213
|
+
const { runtimes } = require('./capability-registry.cjs');
|
|
214
|
+
const runtimeEntry = runtimes[runtime];
|
|
215
|
+
if (runtimeEntry?.runtime?.configHome) {
|
|
216
|
+
return resolveConfigHomeFromDescriptor(runtimeEntry.runtime.configHome, {
|
|
217
|
+
env: process.env,
|
|
218
|
+
home: node_os_1.default.homedir(),
|
|
219
|
+
existsSync: node_fs_1.default.existsSync,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// ── Default (unknown runtime → Claude fallback) ───────────────────────────
|
|
223
|
+
const env = process.env;
|
|
224
|
+
return env['CLAUDE_CONFIG_DIR'] ? expandTilde(env['CLAUDE_CONFIG_DIR']) : node_path_1.default.join(node_os_1.default.homedir(), '.claude');
|
|
149
225
|
}
|
|
150
226
|
/**
|
|
151
227
|
* Return the global skills base directory for the given runtime.
|