ikarmic-forge 0.0.0-stage → 4.4.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 +21 -0
- package/README.md +58 -2
- package/dist/acp/server.d.ts +53 -0
- package/dist/acp/server.d.ts.map +1 -0
- package/dist/acp/server.js +235 -0
- package/dist/acp/server.js.map +1 -0
- package/dist/app.d.ts +22 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +159 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/forge.d.ts +3 -0
- package/dist/bin/forge.d.ts.map +1 -0
- package/dist/bin/forge.js +747 -0
- package/dist/bin/forge.js.map +1 -0
- package/dist/chat-files.d.ts +37 -0
- package/dist/chat-files.d.ts.map +1 -0
- package/dist/chat-files.js +152 -0
- package/dist/chat-files.js.map +1 -0
- package/dist/commands/acp.d.ts +4 -0
- package/dist/commands/acp.d.ts.map +1 -0
- package/dist/commands/acp.js +36 -0
- package/dist/commands/acp.js.map +1 -0
- package/dist/commands/ai-comments.d.ts +9 -0
- package/dist/commands/ai-comments.d.ts.map +1 -0
- package/dist/commands/ai-comments.js +43 -0
- package/dist/commands/ai-comments.js.map +1 -0
- package/dist/commands/architect.d.ts +9 -0
- package/dist/commands/architect.d.ts.map +1 -0
- package/dist/commands/architect.js +27 -0
- package/dist/commands/architect.js.map +1 -0
- package/dist/commands/checkpoint.d.ts +10 -0
- package/dist/commands/checkpoint.d.ts.map +1 -0
- package/dist/commands/checkpoint.js +168 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/config.d.ts +15 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +180 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/diff.d.ts +29 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +90 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/hook.d.ts +10 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +121 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/mcp.d.ts +10 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +110 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/orchestrator.d.ts +22 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +113 -0
- package/dist/commands/orchestrator.js.map +1 -0
- package/dist/commands/plugin.d.ts +3 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +62 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/policy.d.ts +2 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +21 -0
- package/dist/commands/policy.js.map +1 -0
- package/dist/commands/skill.d.ts +13 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +194 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/spec.d.ts +13 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +76 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/watch.d.ts +15 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +83 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/worktree.d.ts +22 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +187 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/components/Approval.d.ts +9 -0
- package/dist/components/Approval.d.ts.map +1 -0
- package/dist/components/Approval.js +37 -0
- package/dist/components/Approval.js.map +1 -0
- package/dist/components/Footer.d.ts +22 -0
- package/dist/components/Footer.d.ts.map +1 -0
- package/dist/components/Footer.js +59 -0
- package/dist/components/Footer.js.map +1 -0
- package/dist/components/Header.d.ts +11 -0
- package/dist/components/Header.d.ts.map +1 -0
- package/dist/components/Header.js +23 -0
- package/dist/components/Header.js.map +1 -0
- package/dist/components/Spinner.d.ts +3 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +8 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Stream.d.ts +10 -0
- package/dist/components/Stream.d.ts.map +1 -0
- package/dist/components/Stream.js +13 -0
- package/dist/components/Stream.js.map +1 -0
- package/dist/components/ToolEvent.d.ts +13 -0
- package/dist/components/ToolEvent.d.ts.map +1 -0
- package/dist/components/ToolEvent.js +54 -0
- package/dist/components/ToolEvent.js.map +1 -0
- package/dist/credential-store.d.ts +8 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/credential-store.js +37 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/git-workflow.d.ts +16 -0
- package/dist/git-workflow.d.ts.map +1 -0
- package/dist/git-workflow.js +38 -0
- package/dist/git-workflow.js.map +1 -0
- package/dist/mcp-loader.d.ts +25 -0
- package/dist/mcp-loader.d.ts.map +1 -0
- package/dist/mcp-loader.js +99 -0
- package/dist/mcp-loader.js.map +1 -0
- package/dist/notify.d.ts +12 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +47 -0
- package/dist/notify.js.map +1 -0
- package/dist/options.d.ts +407 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +792 -0
- package/dist/options.js.map +1 -0
- package/dist/repl-commands.d.ts +53 -0
- package/dist/repl-commands.d.ts.map +1 -0
- package/dist/repl-commands.js +141 -0
- package/dist/repl-commands.js.map +1 -0
- package/dist/repl.d.ts +52 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +1174 -0
- package/dist/repl.js.map +1 -0
- package/dist/runner.d.ts +64 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +61 -0
- package/dist/runner.js.map +1 -0
- package/dist/session-checkpoints.d.ts +6 -0
- package/dist/session-checkpoints.d.ts.map +1 -0
- package/dist/session-checkpoints.js +25 -0
- package/dist/session-checkpoints.js.map +1 -0
- package/dist/specialists-loader.d.ts +22 -0
- package/dist/specialists-loader.d.ts.map +1 -0
- package/dist/specialists-loader.js +38 -0
- package/dist/specialists-loader.js.map +1 -0
- package/dist/tool-display.d.ts +19 -0
- package/dist/tool-display.d.ts.map +1 -0
- package/dist/tool-display.js +57 -0
- package/dist/tool-display.js.map +1 -0
- package/package.json +70 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge orchestrator …` subcommand: multi-agent routing.
|
|
3
|
+
*
|
|
4
|
+
* `forge orchestrator list`: show available specialists
|
|
5
|
+
* `forge orchestrator run "<task>"`: dispatch the task via the orchestrator
|
|
6
|
+
* `forge orchestrator plan "<task>"`: preview the routing plan without running it
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the other soft-prefix subcommands: no special parsing,
|
|
9
|
+
* exits 0/1/2.
|
|
10
|
+
*/
|
|
11
|
+
import type { ParsedOrchestratorCommand } from '../options.js';
|
|
12
|
+
export declare function handleOrchestratorCommand(cmd: ParsedOrchestratorCommand, cwd: string, model: {
|
|
13
|
+
provider: string;
|
|
14
|
+
model: string;
|
|
15
|
+
}, options?: {
|
|
16
|
+
worktrees?: 'auto' | 'always' | 'never';
|
|
17
|
+
/** v2.14: delete orchestrator-created branches alongside their worktrees. */
|
|
18
|
+
cleanupBranches?: boolean;
|
|
19
|
+
/** Commit worktree specialists' edits onto kept branches. */
|
|
20
|
+
commitChanges?: boolean;
|
|
21
|
+
}): Promise<number>;
|
|
22
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/commands/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE/D,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,yBAAyB,EAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC1C,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge orchestrator …` subcommand: multi-agent routing.
|
|
3
|
+
*
|
|
4
|
+
* `forge orchestrator list`: show available specialists
|
|
5
|
+
* `forge orchestrator run "<task>"`: dispatch the task via the orchestrator
|
|
6
|
+
* `forge orchestrator plan "<task>"`: preview the routing plan without running it
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the other soft-prefix subcommands: no special parsing,
|
|
9
|
+
* exits 0/1/2.
|
|
10
|
+
*/
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
import { BUILTIN_SPECIALISTS, listSpecialists, parseRouterOutput, runOrchestrator, runRouter, } from '@ikarmic/forge-core';
|
|
13
|
+
export async function handleOrchestratorCommand(cmd, cwd, model, options = {}) {
|
|
14
|
+
if (cmd.list) {
|
|
15
|
+
return printSpecialistsList();
|
|
16
|
+
}
|
|
17
|
+
if (cmd.run) {
|
|
18
|
+
return runOrchestratorCli(cmd.run.task, cwd, model, {
|
|
19
|
+
preview: false,
|
|
20
|
+
worktrees: options.worktrees ?? 'auto',
|
|
21
|
+
cleanupBranches: options.cleanupBranches ?? true,
|
|
22
|
+
commitChanges: options.commitChanges ?? false,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (cmd.plan) {
|
|
26
|
+
return runOrchestratorCli(cmd.plan.task, cwd, model, { preview: true });
|
|
27
|
+
}
|
|
28
|
+
process.stderr.write('forge orchestrator: expected one of list|run|plan. Try `forge orchestrator --help` (not yet implemented; read docs/ORCHESTRATOR.md).\n');
|
|
29
|
+
return 2;
|
|
30
|
+
}
|
|
31
|
+
async function printSpecialistsList() {
|
|
32
|
+
const builtinIds = new Set(BUILTIN_SPECIALISTS.map((s) => s.id));
|
|
33
|
+
const all = listSpecialists();
|
|
34
|
+
process.stdout.write('Available specialists:\n');
|
|
35
|
+
for (const s of all) {
|
|
36
|
+
const tag = builtinIds.has(s.id) ? 'core' : 'custom';
|
|
37
|
+
process.stdout.write(` ${s.id.padEnd(8)} ${tag.padEnd(6)} ${s.description}\n`);
|
|
38
|
+
}
|
|
39
|
+
const customCount = all.length - BUILTIN_SPECIALISTS.length;
|
|
40
|
+
if (customCount > 0) {
|
|
41
|
+
process.stdout.write(`\n${customCount} custom specialist${customCount === 1 ? '' : 's'} loaded from ~/.forge/specialists.json\n`);
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
async function runOrchestratorCli(task, cwd, model, opts) {
|
|
46
|
+
try {
|
|
47
|
+
if (opts.preview) {
|
|
48
|
+
const result = await runRouter({
|
|
49
|
+
task,
|
|
50
|
+
model: model,
|
|
51
|
+
cwd,
|
|
52
|
+
auto: true,
|
|
53
|
+
maxIterations: 5,
|
|
54
|
+
});
|
|
55
|
+
const plan = parseRouterOutput(result.finalText, task);
|
|
56
|
+
process.stdout.write(`Plan:\n rationale: ${plan.rationale ?? '(none)'}\n`);
|
|
57
|
+
for (let i = 0; i < plan.steps.length; i++) {
|
|
58
|
+
const step = plan.steps[i];
|
|
59
|
+
process.stdout.write(` ${i + 1}. [${step.specialist}] ${step.task}${step.parallelGroup ? ` (group: ${step.parallelGroup})` : ''}\n`);
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
const result = await runOrchestrator({
|
|
64
|
+
task,
|
|
65
|
+
model: model,
|
|
66
|
+
cwd,
|
|
67
|
+
auto: true,
|
|
68
|
+
worktrees: opts.worktrees ?? 'auto',
|
|
69
|
+
// v2.14: delete auto-created branches (default true). Mirror
|
|
70
|
+
// the user's CLI flag via the dispatchOpts field below.
|
|
71
|
+
...(opts.cleanupBranches !== undefined
|
|
72
|
+
? { cleanupBranches: opts.cleanupBranches }
|
|
73
|
+
: {}),
|
|
74
|
+
...(opts.commitChanges ? { commitChanges: true } : {}),
|
|
75
|
+
onWorktreeEvent: (event) => {
|
|
76
|
+
// Surface worktree lifecycle in stderr (so it doesn't pollute
|
|
77
|
+
// the plan/results output). Cheap progress signal.
|
|
78
|
+
process.stderr.write(`forge orchestrator: ${event.kind} worktree ${event.path} (${event.branch})\n`);
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
process.stdout.write(`Plan (${result.plan.rationale ?? 'no rationale'}):\n`);
|
|
82
|
+
for (let i = 0; i < result.steps.length; i++) {
|
|
83
|
+
const s = result.steps[i];
|
|
84
|
+
const wtInfo = s.worktreePath
|
|
85
|
+
? ` worktree=${s.worktreeBranch}`
|
|
86
|
+
: '';
|
|
87
|
+
process.stdout.write(` ${i + 1}. [${s.step.specialist}] ${s.reason} (${s.durationMs}ms)${wtInfo}${s.error ? ` ERROR: ${s.error}` : ''}\n`);
|
|
88
|
+
if (s.finalText) {
|
|
89
|
+
const preview = s.finalText.length > 200 ? s.finalText.slice(0, 200) + '…' : s.finalText;
|
|
90
|
+
process.stdout.write(` → ${preview.replace(/\n/g, ' ')}\n`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const kept = result.steps.filter((s) => s.worktreeCommit && s.worktreeBranch);
|
|
94
|
+
if (kept.length > 0) {
|
|
95
|
+
process.stdout.write('\nBranches with committed work (review, then merge or delete):\n');
|
|
96
|
+
for (const s of kept) {
|
|
97
|
+
process.stdout.write(` ${s.worktreeBranch} (${s.changedFiles?.length ?? 0} file${s.changedFiles?.length === 1 ? '' : 's'})\n` +
|
|
98
|
+
` review: git diff HEAD...${s.worktreeBranch}\n` +
|
|
99
|
+
` merge: git merge --no-ff ${s.worktreeBranch}\n` +
|
|
100
|
+
` drop: git branch -D ${s.worktreeBranch}\n`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
process.stdout.write(`\ntotal: ${result.durationMs}ms, ${result.totalInputTokens} in / ${result.totalOutputTokens} out tokens` +
|
|
104
|
+
(result.costKnown ? `, $${result.totalCostUsd.toFixed(4)}` : '') +
|
|
105
|
+
'\n');
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
process.stderr.write(`forge orchestrator: ${err.message}\n`);
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/commands/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAQzD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6ChG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge plugin …` subcommand: list, show, install, remove plugin bundles.
|
|
3
|
+
* No AI provider required. Exit codes: 0 ok, 2 user error, 1 unexpected.
|
|
4
|
+
*/
|
|
5
|
+
import { discoverPlugins, installPlugin, removePlugin } from '@ikarmic/forge-core';
|
|
6
|
+
function counts(p) {
|
|
7
|
+
const hookCount = Object.values(p.hooks).reduce((n, entries) => n + (entries?.length ?? 0), 0);
|
|
8
|
+
const mcpCount = Object.keys(p.mcpServers).length;
|
|
9
|
+
return `skills: ${p.skillsDir ? 'yes' : 'no'}, hook entries: ${hookCount}, mcp servers: ${mcpCount}`;
|
|
10
|
+
}
|
|
11
|
+
export async function handlePluginCommand(cmd, cwd) {
|
|
12
|
+
const out = (s) => process.stdout.write(`${s}\n`);
|
|
13
|
+
const err = (s) => process.stderr.write(`${s}\n`);
|
|
14
|
+
try {
|
|
15
|
+
if (cmd.list) {
|
|
16
|
+
const plugins = await discoverPlugins(cwd);
|
|
17
|
+
if (plugins.length === 0)
|
|
18
|
+
out('(no plugins installed)');
|
|
19
|
+
for (const p of plugins)
|
|
20
|
+
out(`${p.name}${p.version ? `@${p.version}` : ''} [${p.scope}] ${counts(p)}${p.description ? `\n ${p.description}` : ''}`);
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
if (cmd.show) {
|
|
24
|
+
const plugin = (await discoverPlugins(cwd)).find((p) => p.name === cmd.show.name);
|
|
25
|
+
if (!plugin) {
|
|
26
|
+
err(`forge plugin: "${cmd.show.name}" is not installed`);
|
|
27
|
+
return 2;
|
|
28
|
+
}
|
|
29
|
+
out(`${plugin.name}${plugin.version ? `@${plugin.version}` : ''} [${plugin.scope}]\n${plugin.root}\n${counts(plugin)}`);
|
|
30
|
+
for (const w of plugin.warnings)
|
|
31
|
+
out(`warning: ${w}`);
|
|
32
|
+
if (plugin.scope === 'project')
|
|
33
|
+
out('note: project plugins run hooks only after the project is trusted; their MCP servers are not started.');
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (cmd.install) {
|
|
37
|
+
const plugin = await installPlugin(cmd.install.source, {
|
|
38
|
+
scope: cmd.install.project ? 'project' : 'global',
|
|
39
|
+
cwd,
|
|
40
|
+
overwrite: cmd.install.overwrite,
|
|
41
|
+
});
|
|
42
|
+
out(`installed ${plugin.name}${plugin.version ? `@${plugin.version}` : ''} → ${plugin.root}\n${counts(plugin)}`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
if (cmd.remove) {
|
|
46
|
+
const removed = await removePlugin(cmd.remove.name, { scope: cmd.remove.project ? 'project' : 'global', cwd });
|
|
47
|
+
if (!removed) {
|
|
48
|
+
err(`forge plugin: "${cmd.remove.name}" is not installed in that scope`);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
out(`removed ${cmd.remove.name}`);
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
err(`forge plugin: ${e.message}`);
|
|
57
|
+
return 2;
|
|
58
|
+
}
|
|
59
|
+
err('forge plugin: expected one of list|show <name>|install <source>|remove <name>');
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/commands/policy.ts"],"names":[],"mappings":"AAOA,wBAAgB,mBAAmB,IAAI,MAAM,CAa5C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge policy`: show which organization policy (if any) applies on this machine.
|
|
3
|
+
*/
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import { PolicyError, getOrgPolicy, managedPolicyPath } from '@ikarmic/forge-core';
|
|
6
|
+
export function handlePolicyCommand() {
|
|
7
|
+
try {
|
|
8
|
+
const loaded = getOrgPolicy();
|
|
9
|
+
if (!loaded) {
|
|
10
|
+
process.stdout.write(`No organization policy is active.\n(Looked for ${process.env.FORGE_POLICY_FILE ?? managedPolicyPath()})\n`);
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
process.stdout.write(`Organization policy: ${loaded.source}\n\n${JSON.stringify(loaded.policy, null, 2)}\n`);
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
process.stderr.write(`forge: ${err.message}\n`);
|
|
18
|
+
return err instanceof PolicyError ? 2 : 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/commands/policy.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kDAAkD,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,iBAAiB,EAAE,KAAK,CAAC,CAAC;YAClI,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,MAAM,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7G,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAW,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QAC3D,OAAO,GAAG,YAAY,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge skill …` subcommand: list, show, install, search, browse skills.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors how `forge session …` works: no AI provider required, exits
|
|
5
|
+
* with code 0 on success / 2 on user error / 1 on unexpected failure.
|
|
6
|
+
*
|
|
7
|
+
* v2.1: `install <name>` consults the marketplace catalog first; falls
|
|
8
|
+
* back to the GitHub-URL / shorthand path when the name isn't found.
|
|
9
|
+
* `search <query>` fetches + filters the catalog.
|
|
10
|
+
*/
|
|
11
|
+
import type { ParsedSkillCommand } from '../options.js';
|
|
12
|
+
export declare function handleSkillCommand(cmd: ParsedSkillCommand, cwd: string): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAWxD,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB9F"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge skill …` subcommand: list, show, install, search, browse skills.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors how `forge session …` works: no AI provider required, exits
|
|
5
|
+
* with code 0 on success / 2 on user error / 1 on unexpected failure.
|
|
6
|
+
*
|
|
7
|
+
* v2.1: `install <name>` consults the marketplace catalog first; falls
|
|
8
|
+
* back to the GitHub-URL / shorthand path when the name isn't found.
|
|
9
|
+
* `search <query>` fetches + filters the catalog.
|
|
10
|
+
*/
|
|
11
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { DEFAULT_SKILL_CATALOG_URL, discoverSkills, fetchSkillsCatalog, installSkillFromCatalog, loadSkillsRegistryAsync, searchSkills, } from '@ikarmic/forge-core';
|
|
14
|
+
/**
|
|
15
|
+
* Skill marketplace catalog URL. The default URL points at a public
|
|
16
|
+
* JSON document hosted on GitHub raw content. Operators can override
|
|
17
|
+
* via `FORGE_SKILL_CATALOG_URL`.
|
|
18
|
+
*/
|
|
19
|
+
function catalogUrl() {
|
|
20
|
+
return process.env.FORGE_SKILL_CATALOG_URL ?? DEFAULT_SKILL_CATALOG_URL;
|
|
21
|
+
}
|
|
22
|
+
export async function handleSkillCommand(cmd, cwd) {
|
|
23
|
+
if (cmd.list) {
|
|
24
|
+
return listSkills(cwd);
|
|
25
|
+
}
|
|
26
|
+
if (cmd.show) {
|
|
27
|
+
return showSkill(cwd, cmd.show.name);
|
|
28
|
+
}
|
|
29
|
+
if (cmd.install) {
|
|
30
|
+
return installFromSource(cmd.install.url, cwd);
|
|
31
|
+
}
|
|
32
|
+
if (cmd.search) {
|
|
33
|
+
return searchCatalog(cmd.search.query, cmd.search.limit ?? undefined);
|
|
34
|
+
}
|
|
35
|
+
if (cmd.browse) {
|
|
36
|
+
return browseMarketplace();
|
|
37
|
+
}
|
|
38
|
+
process.stderr.write('forge skill: expected one of list|show|install|search|browse. Try `forge skill --help` (not yet implemented; read the README).\n');
|
|
39
|
+
return 2;
|
|
40
|
+
}
|
|
41
|
+
async function listSkills(cwd) {
|
|
42
|
+
const skills = await discoverSkills(cwd);
|
|
43
|
+
if (skills.length === 0) {
|
|
44
|
+
process.stdout.write(`(no skills found in ${cwd})\n`);
|
|
45
|
+
process.stdout.write('Discovery roots: ./skills/ ./.forge/skills/ ~/.forge/skills/\n');
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
for (const skill of skills) {
|
|
49
|
+
const ver = skill.version ? ` v${skill.version}` : '';
|
|
50
|
+
process.stdout.write(`${skill.name}${ver} [${skill.source.kind}] ${skill.source.path}\n`);
|
|
51
|
+
if (skill.description) {
|
|
52
|
+
process.stdout.write(` ${skill.description}\n`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
async function showSkill(cwd, name) {
|
|
58
|
+
const registry = await loadSkillsRegistryAsync(cwd);
|
|
59
|
+
const skill = registry.get(name);
|
|
60
|
+
if (!skill) {
|
|
61
|
+
process.stderr.write(`forge skill: no skill named "${name}"\n`);
|
|
62
|
+
return 2;
|
|
63
|
+
}
|
|
64
|
+
process.stdout.write(`# ${skill.name}\n`);
|
|
65
|
+
if (skill.version)
|
|
66
|
+
process.stdout.write(`version: ${skill.version}\n`);
|
|
67
|
+
process.stdout.write(`source: ${skill.source.kind} ${skill.source.path}\n`);
|
|
68
|
+
if (skill.description)
|
|
69
|
+
process.stdout.write(`description: ${skill.description}\n`);
|
|
70
|
+
if (skill.allowedTools && skill.allowedTools.length > 0) {
|
|
71
|
+
process.stdout.write(`allowed-tools: ${skill.allowedTools.join(', ')}\n`);
|
|
72
|
+
}
|
|
73
|
+
process.stdout.write('\n');
|
|
74
|
+
process.stdout.write(skill.body);
|
|
75
|
+
if (!skill.body.endsWith('\n'))
|
|
76
|
+
process.stdout.write('\n');
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
async function installFromSource(source, cwd) {
|
|
80
|
+
// v2.1: try the marketplace catalog first when `source` looks like a
|
|
81
|
+
// name (no `/`, no scheme, no `.git`). Falls back to GitHub URL /
|
|
82
|
+
// shorthand handling when the catalog fetch fails or the name isn't
|
|
83
|
+
// found.
|
|
84
|
+
if (looksLikeSkillName(source)) {
|
|
85
|
+
const catalog = await fetchSkillsCatalog(catalogUrl());
|
|
86
|
+
if (catalog) {
|
|
87
|
+
const entry = catalog.skills.find((s) => s.name === source);
|
|
88
|
+
if (entry) {
|
|
89
|
+
const result = await installSkillFromCatalog({
|
|
90
|
+
name: source,
|
|
91
|
+
catalog,
|
|
92
|
+
});
|
|
93
|
+
if (result) {
|
|
94
|
+
process.stdout.write(`installed ${result.path}\n`);
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
process.stderr.write(`forge skill install: failed to fetch ${entry.github}: falling back\n`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
process.stderr.write(`forge skill install: "${source}" not in marketplace: falling back\n`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
process.stderr.write(`forge skill install: could not load marketplace catalog (${catalogUrl()}): falling back to URL stub\n`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Fallback: scaffold a SKILL.md stub (the v1.1 behavior).
|
|
108
|
+
const targetDir = path.resolve(cwd, 'skills');
|
|
109
|
+
await mkdir(targetDir, { recursive: true });
|
|
110
|
+
const slug = slugFromUrl(source);
|
|
111
|
+
const skillPath = path.join(targetDir, `${slug}.md`);
|
|
112
|
+
const content = `---
|
|
113
|
+
name: ${slug}
|
|
114
|
+
description: Skill installed from ${source}. Edit this description so the activator picks it up for matching tasks.
|
|
115
|
+
version: 1.0.0
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
# ${slug}
|
|
119
|
+
|
|
120
|
+
This skill was installed by \`forge skill install ${source}\`.
|
|
121
|
+
|
|
122
|
+
Replace this body with your own instructions. The activator matches on the
|
|
123
|
+
\`description\` field above: keep it focused (1-2 sentences) and free of
|
|
124
|
+
generic words ("the", "and", "use", "tool") so description-scoring
|
|
125
|
+
selects it for the right tasks.
|
|
126
|
+
|
|
127
|
+
Upstream: ${source}
|
|
128
|
+
`;
|
|
129
|
+
await writeFile(skillPath, content, 'utf8');
|
|
130
|
+
process.stdout.write(`installed ${skillPath}\n`);
|
|
131
|
+
process.stdout.write(`Next: edit ${skillPath} and write your skill body.\n`);
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
/** Heuristic: does `source` look like a skill name (vs a URL)? */
|
|
135
|
+
function looksLikeSkillName(source) {
|
|
136
|
+
if (!source)
|
|
137
|
+
return false;
|
|
138
|
+
if (source.includes('/') || source.includes('\\'))
|
|
139
|
+
return false;
|
|
140
|
+
if (/^[a-z]+:\/\//i.test(source))
|
|
141
|
+
return false;
|
|
142
|
+
if (source.includes('.'))
|
|
143
|
+
return false; // skip .git, .com, etc.
|
|
144
|
+
return /^[a-z0-9_-]+$/i.test(source);
|
|
145
|
+
}
|
|
146
|
+
async function searchCatalog(query, limit) {
|
|
147
|
+
const catalog = await fetchSkillsCatalog(catalogUrl());
|
|
148
|
+
if (!catalog) {
|
|
149
|
+
process.stderr.write(`forge skill search: could not load marketplace catalog (${catalogUrl()})\n` +
|
|
150
|
+
`Set FORGE_SKILL_CATALOG_URL to override.\n`);
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
const result = searchSkills(catalog, query, limit);
|
|
154
|
+
if (result.matches.length === 0) {
|
|
155
|
+
process.stdout.write(`(no skills match "${query}" in ${result.totalScanned} catalog entries)\n`);
|
|
156
|
+
return 0;
|
|
157
|
+
}
|
|
158
|
+
for (const skill of result.matches) {
|
|
159
|
+
const ver = skill.version ? ` v${skill.version}` : '';
|
|
160
|
+
process.stdout.write(`${skill.name}${ver} · ${skill.displayName}\n`);
|
|
161
|
+
if (skill.description)
|
|
162
|
+
process.stdout.write(` ${skill.description}\n`);
|
|
163
|
+
if (skill.tags && skill.tags.length > 0) {
|
|
164
|
+
process.stdout.write(` tags: ${skill.tags.join(', ')}\n`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
process.stdout.write(`\n${result.matches.length} of ${result.totalScanned} entries matched.\n`);
|
|
168
|
+
process.stdout.write(`Install with: forge skill install <name>\n`);
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
function slugFromUrl(url) {
|
|
172
|
+
try {
|
|
173
|
+
const u = new URL(url);
|
|
174
|
+
const segs = u.pathname.split('/').filter((s) => s.length > 0);
|
|
175
|
+
const last = segs[segs.length - 1] ?? 'external-skill';
|
|
176
|
+
return last
|
|
177
|
+
.toLowerCase()
|
|
178
|
+
.replace(/\.git$/, '')
|
|
179
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
180
|
+
.replace(/^-+|-+$/g, '') || 'external-skill';
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return 'external-skill';
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function browseMarketplace() {
|
|
187
|
+
process.stdout.write(`IKarmic Forge Skills Marketplace (catalog):\n ${catalogUrl()}\n\n`);
|
|
188
|
+
process.stdout.write('Browse community skills there. To install one:\n');
|
|
189
|
+
process.stdout.write(' forge skill install <github-url> # any GitHub repo with SKILL.md\n');
|
|
190
|
+
process.stdout.write(' forge skill install <name> # from the marketplace catalog\n');
|
|
191
|
+
process.stdout.write(' forge skill search <query> # find skills by keyword\n');
|
|
192
|
+
return 0;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge spec …` subcommand: list / show / cancel already-approved
|
|
3
|
+
* spec-driven-planning-mode output (`.forge/specs/<id>/`).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `commands/checkpoint.ts`'s soft-prefix shape: no AI provider
|
|
6
|
+
* required, exits 0/1/2. Generation itself happens via `--spec "<task>"`
|
|
7
|
+
* (one-shot) or `/spec <task>` (REPL): see `options.ts`'s header
|
|
8
|
+
* comment on `ParsedSpecCommand` for why "approve" isn't a subcommand
|
|
9
|
+
* here.
|
|
10
|
+
*/
|
|
11
|
+
import type { ParsedSpecCommand } from '../options.js';
|
|
12
|
+
export declare function handleSpecCommand(cmd: ParsedSpecCommand, cwd: string): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5F"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge spec …` subcommand: list / show / cancel already-approved
|
|
3
|
+
* spec-driven-planning-mode output (`.forge/specs/<id>/`).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `commands/checkpoint.ts`'s soft-prefix shape: no AI provider
|
|
6
|
+
* required, exits 0/1/2. Generation itself happens via `--spec "<task>"`
|
|
7
|
+
* (one-shot) or `/spec <task>` (REPL): see `options.ts`'s header
|
|
8
|
+
* comment on `ParsedSpecCommand` for why "approve" isn't a subcommand
|
|
9
|
+
* here.
|
|
10
|
+
*/
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
import { readFile } from 'node:fs/promises';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { SpecStore } from '@ikarmic/forge-core';
|
|
15
|
+
export async function handleSpecCommand(cmd, cwd) {
|
|
16
|
+
const store = new SpecStore(cwd);
|
|
17
|
+
if (cmd.list) {
|
|
18
|
+
return listSpecs(store);
|
|
19
|
+
}
|
|
20
|
+
if (cmd.show) {
|
|
21
|
+
return showSpec(store, cmd.show.id);
|
|
22
|
+
}
|
|
23
|
+
if (cmd.cancel) {
|
|
24
|
+
return cancelSpec(store, cmd.cancel.id, cmd.cancel.yes);
|
|
25
|
+
}
|
|
26
|
+
process.stderr.write('forge spec: expected one of list|show|cancel. Generate a new spec with `forge --spec "<task>"` or `/spec <task>` in the REPL.\n');
|
|
27
|
+
return 2;
|
|
28
|
+
}
|
|
29
|
+
async function listSpecs(store) {
|
|
30
|
+
const all = await store.list();
|
|
31
|
+
if (all.length === 0) {
|
|
32
|
+
process.stdout.write('(no approved specs found: generate one with `forge --spec "<task>"` or `/spec <task>` in the REPL)\n');
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
process.stdout.write('id task when\n');
|
|
36
|
+
process.stdout.write('────────────────────────────────────────────────────────────────────────\n');
|
|
37
|
+
for (const s of all) {
|
|
38
|
+
const id = s.id.length > 36 ? s.id.slice(0, 35) + '…' : s.id.padEnd(36);
|
|
39
|
+
const task = s.task.length > 30 ? s.task.slice(0, 29) + '…' : s.task.padEnd(30);
|
|
40
|
+
const when = s.approvedAt.replace('T', ' ').slice(0, 19);
|
|
41
|
+
process.stdout.write(`${id} ${task} ${when}\n`);
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
async function showSpec(store, id) {
|
|
46
|
+
const summary = await store.get(id);
|
|
47
|
+
if (!summary) {
|
|
48
|
+
process.stderr.write(`forge spec: no spec with id "${id}"\n`);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
process.stdout.write(`Spec ${summary.id}\n`);
|
|
52
|
+
process.stdout.write(` task: ${summary.task}\n`);
|
|
53
|
+
process.stdout.write(` approved: ${summary.approvedAt}\n`);
|
|
54
|
+
process.stdout.write(` dir: ${summary.dir}\n\n`);
|
|
55
|
+
for (const file of ['requirements.md', 'design.md', 'tasks.md']) {
|
|
56
|
+
const content = await readFile(path.join(summary.dir, file), 'utf8');
|
|
57
|
+
process.stdout.write(`── ${file} ──\n${content}\n\n`);
|
|
58
|
+
}
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
async function cancelSpec(store, id, yes) {
|
|
62
|
+
const summary = await store.get(id);
|
|
63
|
+
if (!summary) {
|
|
64
|
+
process.stderr.write(`forge spec: no spec with id "${id}"\n`);
|
|
65
|
+
return 2;
|
|
66
|
+
}
|
|
67
|
+
if (!yes) {
|
|
68
|
+
process.stderr.write(`About to permanently delete spec "${id}" (${summary.dir}).\n` +
|
|
69
|
+
'Re-run with --yes to confirm. Refusing to delete without an explicit flag.\n');
|
|
70
|
+
return 2;
|
|
71
|
+
}
|
|
72
|
+
const removed = await store.delete(id);
|
|
73
|
+
process.stdout.write(removed ? `deleted spec ${id}\n` : `forge spec: failed to delete "${id}"\n`);
|
|
74
|
+
return removed ? 0 : 1;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge watch`: runs a filesystem watcher that dispatches FileChanged
|
|
3
|
+
* hook events independent of any active Agent.run(). Runs until
|
|
4
|
+
* SIGINT (Ctrl+C). No agent loop involved.
|
|
5
|
+
*
|
|
6
|
+
* Loads hooks config exactly the way toAgentConfig does elsewhere
|
|
7
|
+
* (loadHooksConfig -> new HooksBus). trustedProjectHooks is never set
|
|
8
|
+
* to true here, same as every other CLI call site: project-level
|
|
9
|
+
* FileChanged hooks stay blocked by default.
|
|
10
|
+
*/
|
|
11
|
+
import { type ModelConfig } from '@ikarmic/forge-core';
|
|
12
|
+
export declare function handleWatchCommand(cwd: string, resolveModel?: () => ModelConfig, watchOptions?: {
|
|
13
|
+
aiComments?: boolean;
|
|
14
|
+
}): Promise<number>;
|
|
15
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAM7B,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,WAAW,EAChC,YAAY,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,OAAO,CAAC,MAAM,CAAC,CA4DjB"}
|