ikarmic-forge 0.0.0-stage → 4.5.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 +62 -2
- package/dist/acp/server.d.ts +55 -0
- package/dist/acp/server.d.ts.map +1 -0
- package/dist/acp/server.js +276 -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 +786 -0
- package/dist/bin/forge.js.map +1 -0
- package/dist/chat-files.d.ts +45 -0
- package/dist/chat-files.d.ts.map +1 -0
- package/dist/chat-files.js +189 -0
- package/dist/chat-files.js.map +1 -0
- package/dist/clipboard.d.ts +38 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +63 -0
- package/dist/clipboard.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/memory.d.ts +10 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +77 -0
- package/dist/commands/memory.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 +23 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +147 -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 +39 -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 +449 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +871 -0
- package/dist/options.js.map +1 -0
- package/dist/repl-commands.d.ts +92 -0
- package/dist/repl-commands.d.ts.map +1 -0
- package/dist/repl-commands.js +228 -0
- package/dist/repl-commands.js.map +1 -0
- package/dist/repl-extras.d.ts +39 -0
- package/dist/repl-extras.d.ts.map +1 -0
- package/dist/repl-extras.js +120 -0
- package/dist/repl-extras.js.map +1 -0
- package/dist/repl.d.ts +76 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +1507 -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,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge checkpoint …` subcommand: list / show / restore / prune
|
|
3
|
+
* the per-turn file snapshots the agent captures automatically.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the other soft-prefix subcommands (`session`, `skill`,
|
|
6
|
+
* `hook`, `mcp`): no AI provider required, exits 0/1/2.
|
|
7
|
+
*/
|
|
8
|
+
import process from 'node:process';
|
|
9
|
+
import { compareWorktreeContexts, defaultSessionDir, listSessions, snapshotWorktreeContext, } from '@ikarmic/forge-core';
|
|
10
|
+
import { sessionCheckpointStore } from '../session-checkpoints.js';
|
|
11
|
+
export async function handleCheckpointCommand(cmd, cwd) {
|
|
12
|
+
// Checkpoints are per-session (`<sessions>/<id>/checkpoints`). Without
|
|
13
|
+
// --session, default to the most recently updated session.
|
|
14
|
+
const sessionsDir = defaultSessionDir();
|
|
15
|
+
const sessionId = cmd.sessionId ?? (await listSessions(sessionsDir))[0]?.id;
|
|
16
|
+
if (!sessionId) {
|
|
17
|
+
process.stdout.write('(no sessions found: checkpoints appear after the first file-mutating tool call)\n');
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
const store = sessionCheckpointStore(sessionsDir, sessionId, cwd);
|
|
21
|
+
if (cmd.list) {
|
|
22
|
+
return listCheckpoints(store, cmd.list.limit ?? undefined);
|
|
23
|
+
}
|
|
24
|
+
if (cmd.show) {
|
|
25
|
+
return showCheckpoint(store, cmd.show.id);
|
|
26
|
+
}
|
|
27
|
+
if (cmd.restore) {
|
|
28
|
+
return restoreCheckpoint(store, cmd.restore.id, cmd.restore.yes);
|
|
29
|
+
}
|
|
30
|
+
if (cmd.prune) {
|
|
31
|
+
return pruneCheckpoints(store, cmd.prune.keep ?? undefined);
|
|
32
|
+
}
|
|
33
|
+
process.stderr.write('forge checkpoint: expected one of list|show|restore|prune. Try `forge checkpoint --help` (not yet implemented; read the README).\n');
|
|
34
|
+
return 2;
|
|
35
|
+
}
|
|
36
|
+
async function listCheckpoints(store, limit) {
|
|
37
|
+
const all = await store.list();
|
|
38
|
+
const items = typeof limit === 'number' ? all.slice(-limit) : all;
|
|
39
|
+
if (items.length === 0) {
|
|
40
|
+
process.stdout.write('(no checkpoints found: they appear after the first file-mutating tool call)\n');
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
process.stdout.write('id turn trigger files size when\n');
|
|
44
|
+
process.stdout.write('────────────────────────────────────────────────────────────────────\n');
|
|
45
|
+
for (const cp of items) {
|
|
46
|
+
const id = cp.id.length > 24 ? cp.id.slice(0, 23) + '…' : cp.id.padEnd(24);
|
|
47
|
+
const turn = String(cp.turnIndex).padEnd(5);
|
|
48
|
+
const trigger = cp.trigger.padEnd(15);
|
|
49
|
+
const files = String(cp.fileCount).padEnd(6);
|
|
50
|
+
const size = formatBytes(cp.totalBytes).padEnd(10);
|
|
51
|
+
const when = cp.createdAt.replace('T', ' ').slice(0, 19);
|
|
52
|
+
process.stdout.write(`${id} ${turn} ${trigger} ${files} ${size} ${when}\n`);
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
async function showCheckpoint(store, id) {
|
|
57
|
+
const cp = await store.get(id);
|
|
58
|
+
if (!cp) {
|
|
59
|
+
process.stderr.write(`forge checkpoint: no checkpoint with id "${id}"\n`);
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write(`Checkpoint ${cp.id}\n`);
|
|
63
|
+
process.stdout.write(` turn: ${cp.turnIndex}\n`);
|
|
64
|
+
process.stdout.write(` trigger: ${cp.trigger}\n`);
|
|
65
|
+
process.stdout.write(` when: ${cp.createdAt}\n`);
|
|
66
|
+
process.stdout.write(` description: ${cp.description}\n`);
|
|
67
|
+
if (cp.toolName)
|
|
68
|
+
process.stdout.write(` tool: ${cp.toolName}\n`);
|
|
69
|
+
process.stdout.write(` files: ${cp.files.length} (${formatBytes(cp.totalBytes)})\n`);
|
|
70
|
+
for (const f of cp.files) {
|
|
71
|
+
process.stdout.write(` [${f.status.padEnd(8)}] ${f.path}`);
|
|
72
|
+
if (f.status !== 'deleted')
|
|
73
|
+
process.stdout.write(` (${formatBytes(f.size)})`);
|
|
74
|
+
process.stdout.write('\n');
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
async function restoreCheckpoint(store, id, yes) {
|
|
79
|
+
const cp = await store.get(id);
|
|
80
|
+
if (!cp) {
|
|
81
|
+
process.stderr.write(`forge checkpoint: no checkpoint with id "${id}"\n`);
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
// v2.12: worktree-aware restore warning. When the checkpoint was
|
|
85
|
+
// captured inside a different git worktree (or a different repo
|
|
86
|
+
// entirely), surface that to the user before we go overwriting
|
|
87
|
+
// files. The store still operates on cwd-relative paths, so the
|
|
88
|
+
// restore would silently succeed: just on the wrong tree.
|
|
89
|
+
//
|
|
90
|
+
// We probe the current cwd's worktree context on demand (cheap,
|
|
91
|
+
// and skipped when not in a git repo). Best-effort: if the probe
|
|
92
|
+
// fails, we proceed without a warning rather than blocking the
|
|
93
|
+
// restore.
|
|
94
|
+
let mismatch = null;
|
|
95
|
+
try {
|
|
96
|
+
const currentSnap = await snapshotWorktreeContext(store.cwdPath());
|
|
97
|
+
mismatch = compareWorktreeContexts(cp.worktreeContext, currentSnap);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// ignore: proceed without warning
|
|
101
|
+
}
|
|
102
|
+
const worktreeWarning = mismatch?.message ?? null;
|
|
103
|
+
if (!yes) {
|
|
104
|
+
process.stderr.write(`About to restore ${cp.files.length} file${cp.files.length === 1 ? '' : 's'} from checkpoint "${cp.id}".\n`);
|
|
105
|
+
if (worktreeWarning) {
|
|
106
|
+
// Prefix with a clear marker so users (and CI logs) can grep
|
|
107
|
+
// for the warning class.
|
|
108
|
+
process.stderr.write(` ⚠ worktree mismatch (${mismatch.kind}): ${worktreeWarning}\n`);
|
|
109
|
+
}
|
|
110
|
+
process.stderr.write('Re-run with --yes to confirm. Refusing to overwrite uncommitted work without an explicit flag.\n');
|
|
111
|
+
return 2;
|
|
112
|
+
}
|
|
113
|
+
// Even with --yes, print the worktree warning before proceeding so
|
|
114
|
+
// it's visible in logs / transcripts. Users can redirect to a
|
|
115
|
+
// file to suppress the visual but the warning still surfaces.
|
|
116
|
+
if (worktreeWarning) {
|
|
117
|
+
process.stderr.write(`⚠ ${worktreeWarning}\n`);
|
|
118
|
+
}
|
|
119
|
+
const result = await store.restore(id);
|
|
120
|
+
if (!result) {
|
|
121
|
+
process.stderr.write(`forge checkpoint: failed to restore "${id}"\n`);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
const parts = [];
|
|
125
|
+
if (result.restored.length > 0)
|
|
126
|
+
parts.push(`${result.restored.length} restored`);
|
|
127
|
+
if (result.modified.length > 0)
|
|
128
|
+
parts.push(`${result.modified.length} modified`);
|
|
129
|
+
if (result.removed.length > 0)
|
|
130
|
+
parts.push(`${result.removed.length} removed`);
|
|
131
|
+
if (result.unchanged.length > 0)
|
|
132
|
+
parts.push(`${result.unchanged.length} unchanged`);
|
|
133
|
+
process.stdout.write(`restored ${id}: ${parts.join(', ') || 'no changes'}\n`);
|
|
134
|
+
if (result.modified.length > 0) {
|
|
135
|
+
process.stdout.write(' modified:\n');
|
|
136
|
+
for (const f of result.modified)
|
|
137
|
+
process.stdout.write(` ${f}\n`);
|
|
138
|
+
}
|
|
139
|
+
if (result.restored.length > 0) {
|
|
140
|
+
process.stdout.write(' restored:\n');
|
|
141
|
+
for (const f of result.restored)
|
|
142
|
+
process.stdout.write(` ${f}\n`);
|
|
143
|
+
}
|
|
144
|
+
if (result.removed.length > 0) {
|
|
145
|
+
process.stdout.write(' removed:\n');
|
|
146
|
+
for (const f of result.removed)
|
|
147
|
+
process.stdout.write(` ${f}\n`);
|
|
148
|
+
}
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
async function pruneCheckpoints(store, keep) {
|
|
152
|
+
const result = await store.prune(keep);
|
|
153
|
+
process.stdout.write(`pruned: kept ${result.kept}, removed ${result.removed}, freed ${formatBytes(result.bytesFreed)}\n`);
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
function formatBytes(n) {
|
|
157
|
+
if (n < 1024)
|
|
158
|
+
return `${n}B`;
|
|
159
|
+
if (n < 1024 * 1024)
|
|
160
|
+
return `${(n / 1024).toFixed(1)}KB`;
|
|
161
|
+
return `${(n / (1024 * 1024)).toFixed(2)}MB`;
|
|
162
|
+
}
|
|
163
|
+
// Late import: keeps the file-relative path resolution at function call
|
|
164
|
+
// time (we already use the function above). The import is at the bottom
|
|
165
|
+
// so it doesn't disturb the soft-prefix handler shape.
|
|
166
|
+
import path from 'node:path';
|
|
167
|
+
void path;
|
|
168
|
+
//# sourceMappingURL=checkpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/commands/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAEL,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAA4B,EAC5B,GAAW;IAEX,uEAAuE;IACvE,2DAA2D;IAC3D,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC5E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mFAAmF,CAAC,CAAC;QAC1G,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,sBAAsB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IAElE,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAChB,OAAO,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oIAAoI,CACrI,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAAsB,EAAE,KAAc;IACnE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+EAA+E,CAChF,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;IACjG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC/F,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,KAAsB,EAAE,EAAU;IAC9D,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;QAC1E,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,WAAW,IAAI,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,QAAQ;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC3F,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,KAAsB,EAAE,EAAU,EAAE,GAAY;IAC/E,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;QAC1E,OAAO,CAAC,CAAC;IACX,CAAC;IAED,iEAAiE;IACjE,gEAAgE;IAChE,+DAA+D;IAC/D,gEAAgE;IAChE,0DAA0D;IAC1D,EAAE;IACF,gEAAgE;IAChE,iEAAiE;IACjE,+DAA+D;IAC/D,WAAW;IACX,IAAI,QAAQ,GAAoD,IAAI,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,QAAQ,GAAG,uBAAuB,CAAC,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;IACD,MAAM,eAAe,GAAG,QAAQ,EAAE,OAAO,IAAI,IAAI,CAAC;IAElD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,EAAE,CAAC,KAAK,CAAC,MAAM,QAAQ,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,qBAAqB,EAAE,CAAC,EAAE,MAAM,CAC5G,CAAC;QACF,IAAI,eAAe,EAAE,CAAC;YACpB,6DAA6D;YAC7D,yBAAyB;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,QAAS,CAAC,IAAI,MAAM,eAAe,IAAI,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kGAAkG,CAAC,CAAC;QACzH,OAAO,CAAC,CAAC;IACX,CAAC;IAED,mEAAmE;IACnE,8DAA8D;IAC9D,8DAA8D;IAC9D,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,eAAe,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QACtE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;IACjF,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;IACjF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC,CAAC;IACpF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACrC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,KAAsB,EAAE,IAAa;IACnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,MAAM,CAAC,IAAI,aAAa,MAAM,CAAC,OAAO,WAAW,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CACpG,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACzD,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED,wEAAwE;AACxE,wEAAwE;AACxE,uDAAuD;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,KAAK,IAAI,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { loadForgeConfigFile as coreLoad, saveForgeConfigFile as coreSave } from '@ikarmic/forge-core';
|
|
3
|
+
import type { CredentialStore } from '@ikarmic/forge-core';
|
|
4
|
+
export interface ConfigWizardProps {
|
|
5
|
+
loadForgeConfigFile: typeof coreLoad;
|
|
6
|
+
saveForgeConfigFile: typeof coreSave;
|
|
7
|
+
credentialStore: CredentialStore;
|
|
8
|
+
onExit: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function ConfigWizard(props: ConfigWizardProps): React.ReactElement;
|
|
11
|
+
/** Renders the wizard and resolves once the user finishes. */
|
|
12
|
+
export declare function runConfigWizard(deps: {
|
|
13
|
+
credentialStore: CredentialStore;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAMnD,OAAO,EAOL,mBAAmB,IAAI,QAAQ,EAE/B,mBAAmB,IAAI,QAAQ,EAGhC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAA0E,MAAM,qBAAqB,CAAC;AAEnI,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,OAAO,QAAQ,CAAC;IACrC,mBAAmB,EAAE,OAAO,QAAQ,CAAC;IACrC,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CA2NzE;AAED,8DAA8D;AAC9D,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,eAAe,EAAE,eAAe,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/F"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Box, Text, render, useApp } from 'ink';
|
|
3
|
+
import SelectInput from 'ink-select-input';
|
|
4
|
+
import TextInput from 'ink-text-input';
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
import { BUILTIN_TOOLS, MODEL_CATALOG, SUPPORTED_PROVIDERS, exportSettings, importSettings, listSpecialists, loadForgeConfigFile as coreLoad, loadToolSandboxConfig, saveForgeConfigFile as coreSave, saveSpecialistsToConfig, saveToolSandboxConfig, } from '@ikarmic/forge-core';
|
|
7
|
+
export function ConfigWizard(props) {
|
|
8
|
+
const { exit } = useApp();
|
|
9
|
+
const [step, setStep] = useState('provider');
|
|
10
|
+
const [provider, setProvider] = useState(null);
|
|
11
|
+
const [keyInput, setKeyInput] = useState('');
|
|
12
|
+
const [agents, setAgents] = useState(() => [...listSpecialists()]);
|
|
13
|
+
const [agentError, setAgentError] = useState(null);
|
|
14
|
+
const [exportImportMsg, setExportImportMsg] = useState(null);
|
|
15
|
+
const [denyTools, setDenyTools] = useState([]);
|
|
16
|
+
const [permissionsMsg, setPermissionsMsg] = useState(null);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
loadToolSandboxConfig(process.cwd(), { trustedProjectSettings: false }).then(({ sandbox }) => {
|
|
19
|
+
setDenyTools(sandbox.denyTools ?? []);
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
22
|
+
if (step === 'provider') {
|
|
23
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
24
|
+
React.createElement(Text, { bold: true }, "Provider"),
|
|
25
|
+
React.createElement(SelectInput, { items: SUPPORTED_PROVIDERS.map((p) => ({ label: p, value: p })), onSelect: (item) => {
|
|
26
|
+
setProvider(item.value);
|
|
27
|
+
setStep('model');
|
|
28
|
+
} })));
|
|
29
|
+
}
|
|
30
|
+
if (step === 'model' && provider) {
|
|
31
|
+
const entries = MODEL_CATALOG[provider];
|
|
32
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
33
|
+
React.createElement(Text, { bold: true },
|
|
34
|
+
"Model (",
|
|
35
|
+
provider,
|
|
36
|
+
")"),
|
|
37
|
+
React.createElement(SelectInput, { items: entries.map((e) => ({ label: e.label, value: e.id })), onSelect: async (item) => {
|
|
38
|
+
await props.saveForgeConfigFile({ provider, model: item.value });
|
|
39
|
+
setStep('reasoningEffort');
|
|
40
|
+
} })));
|
|
41
|
+
}
|
|
42
|
+
if (step === 'reasoningEffort') {
|
|
43
|
+
const options = [
|
|
44
|
+
{ label: '(provider default)', value: '' },
|
|
45
|
+
{ label: 'None', value: 'none' },
|
|
46
|
+
{ label: 'Minimal', value: 'minimal' },
|
|
47
|
+
{ label: 'Low', value: 'low' },
|
|
48
|
+
{ label: 'Medium', value: 'medium' },
|
|
49
|
+
{ label: 'High', value: 'high' },
|
|
50
|
+
{ label: 'Extra high', value: 'xhigh' },
|
|
51
|
+
];
|
|
52
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
53
|
+
React.createElement(Text, { bold: true }, "Reasoning effort"),
|
|
54
|
+
React.createElement(SelectInput, { items: options, onSelect: async (item) => {
|
|
55
|
+
await props.saveForgeConfigFile({
|
|
56
|
+
...(item.value ? { reasoningEffort: item.value } : {}),
|
|
57
|
+
});
|
|
58
|
+
setStep('apiKey');
|
|
59
|
+
} })));
|
|
60
|
+
}
|
|
61
|
+
if (step === 'apiKey' && provider) {
|
|
62
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
63
|
+
React.createElement(Text, { bold: true },
|
|
64
|
+
"API key for ",
|
|
65
|
+
provider),
|
|
66
|
+
React.createElement(TextInput, { value: keyInput, onChange: setKeyInput, mask: "*", onSubmit: async (value) => {
|
|
67
|
+
if (value)
|
|
68
|
+
await props.credentialStore.set(provider, value);
|
|
69
|
+
setStep('agents');
|
|
70
|
+
} }),
|
|
71
|
+
React.createElement(Text, { color: "gray" }, "Press Enter to skip")));
|
|
72
|
+
}
|
|
73
|
+
if (step === 'agents') {
|
|
74
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
75
|
+
React.createElement(Text, { bold: true },
|
|
76
|
+
"Agents (",
|
|
77
|
+
agents.length,
|
|
78
|
+
" custom)"),
|
|
79
|
+
agents.map((a) => (React.createElement(Text, { key: a.id },
|
|
80
|
+
"- ",
|
|
81
|
+
a.id,
|
|
82
|
+
": ",
|
|
83
|
+
a.description))),
|
|
84
|
+
agentError && React.createElement(Text, { color: "red" }, agentError),
|
|
85
|
+
React.createElement(SelectInput, { items: [
|
|
86
|
+
{ label: 'Save and continue', value: 'save' },
|
|
87
|
+
{ label: 'Skip (no changes)', value: 'skip' },
|
|
88
|
+
], onSelect: async (item) => {
|
|
89
|
+
if (item.value === 'save') {
|
|
90
|
+
try {
|
|
91
|
+
await saveSpecialistsToConfig(agents);
|
|
92
|
+
setStep('permissions');
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
setAgentError(err.message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
setStep('permissions');
|
|
100
|
+
}
|
|
101
|
+
} })));
|
|
102
|
+
}
|
|
103
|
+
if (step === 'permissions') {
|
|
104
|
+
const items = BUILTIN_TOOLS.map((t) => ({
|
|
105
|
+
label: (denyTools.includes(t.name) ? '[x] ' : '[ ] ') + t.name,
|
|
106
|
+
value: t.name,
|
|
107
|
+
}));
|
|
108
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
109
|
+
React.createElement(Text, { bold: true }, "Permissions: toggle tools to deny (Enter to toggle, select \"Done\" to save)"),
|
|
110
|
+
permissionsMsg && React.createElement(Text, { color: "green" }, permissionsMsg),
|
|
111
|
+
React.createElement(SelectInput, { items: [...items, { label: 'Done', value: '__done__' }], onSelect: async (item) => {
|
|
112
|
+
if (item.value === '__done__') {
|
|
113
|
+
const sandbox = denyTools.length > 0 ? { denyTools } : {};
|
|
114
|
+
await saveToolSandboxConfig(sandbox);
|
|
115
|
+
setPermissionsMsg('Saved.');
|
|
116
|
+
setStep('display');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
setDenyTools((prev) => prev.includes(item.value) ? prev.filter((t) => t !== item.value) : [...prev, item.value]);
|
|
120
|
+
} })));
|
|
121
|
+
}
|
|
122
|
+
if (step === 'display') {
|
|
123
|
+
const options = [
|
|
124
|
+
{ label: 'Review first (expanded blocks, reasoning shown)', value: 'review' },
|
|
125
|
+
{ label: 'High autonomy (collapsed blocks, reasoning hidden)', value: 'autonomy' },
|
|
126
|
+
{ label: 'Continue without changing', value: 'skip' },
|
|
127
|
+
];
|
|
128
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
129
|
+
React.createElement(Text, { bold: true }, "Display"),
|
|
130
|
+
React.createElement(SelectInput, { items: options, onSelect: async (item) => {
|
|
131
|
+
if (item.value === 'review') {
|
|
132
|
+
await props.saveForgeConfigFile({ display: { detail: 'full', showReasoning: true } });
|
|
133
|
+
}
|
|
134
|
+
else if (item.value === 'autonomy') {
|
|
135
|
+
await props.saveForgeConfigFile({ display: { detail: 'compact', showReasoning: false } });
|
|
136
|
+
}
|
|
137
|
+
setStep('exportImport');
|
|
138
|
+
} })));
|
|
139
|
+
}
|
|
140
|
+
if (step === 'exportImport') {
|
|
141
|
+
const options = [
|
|
142
|
+
{ label: 'Export settings to ./forge-settings.json', value: 'export' },
|
|
143
|
+
{ label: 'Import settings from ./forge-settings.json', value: 'import' },
|
|
144
|
+
{ label: 'Done', value: 'done' },
|
|
145
|
+
];
|
|
146
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
147
|
+
React.createElement(Text, { bold: true }, "Export / Import"),
|
|
148
|
+
exportImportMsg && React.createElement(Text, { color: "green" }, exportImportMsg),
|
|
149
|
+
React.createElement(SelectInput, { items: options, onSelect: async (item) => {
|
|
150
|
+
if (item.value === 'export') {
|
|
151
|
+
const data = await exportSettings({});
|
|
152
|
+
await writeFile('./forge-settings.json', JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
153
|
+
setExportImportMsg('Exported to ./forge-settings.json');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (item.value === 'import') {
|
|
157
|
+
try {
|
|
158
|
+
const raw = await readFile('./forge-settings.json', 'utf8');
|
|
159
|
+
await importSettings(JSON.parse(raw), {});
|
|
160
|
+
setExportImportMsg('Imported from ./forge-settings.json');
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
setExportImportMsg('Import failed: ' + err.message);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
setStep('done');
|
|
168
|
+
props.onExit();
|
|
169
|
+
exit();
|
|
170
|
+
} })));
|
|
171
|
+
}
|
|
172
|
+
return (React.createElement(Box, null,
|
|
173
|
+
React.createElement(Text, { color: "green" }, "Saved.")));
|
|
174
|
+
}
|
|
175
|
+
/** Renders the wizard and resolves once the user finishes. */
|
|
176
|
+
export async function runConfigWizard(deps) {
|
|
177
|
+
const { waitUntilExit } = render(React.createElement(ConfigWizard, { loadForgeConfigFile: coreLoad, saveForgeConfigFile: coreSave, credentialStore: deps.credentialStore, onExit: () => { } }));
|
|
178
|
+
await waitUntilExit();
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge diff <file1> <file2>` subcommand: print a unified diff between
|
|
3
|
+
* two files (or a file and stdin). Pure CLI surface over the
|
|
4
|
+
* {@link computeUnifiedDiff} core helper; no AI provider needed.
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* forge diff before.txt after.txt
|
|
8
|
+
* forge diff --from-stdin package.json < updated-package.json
|
|
9
|
+
* forge diff --context 5 src/old.ts src/new.ts
|
|
10
|
+
*
|
|
11
|
+
* The output is pipe-friendly: same format as `git diff`, so it
|
|
12
|
+
* composes with `less`, `diff-so-fancy`, etc.
|
|
13
|
+
*/
|
|
14
|
+
export interface DiffCommandOptions {
|
|
15
|
+
fileA: string;
|
|
16
|
+
fileB?: string;
|
|
17
|
+
contextLines?: number;
|
|
18
|
+
fromStdin?: boolean;
|
|
19
|
+
/** When set, only print the one-line summary (no diff text). */
|
|
20
|
+
summaryOnly?: boolean;
|
|
21
|
+
cwd?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run the `forge diff` subcommand. Resolves file paths relative to
|
|
25
|
+
* `cwd` and prints the unified diff (or summary) to stdout. Returns
|
|
26
|
+
* the shell exit code: 0 = files identical, 1 = files differ, 2 = error.
|
|
27
|
+
*/
|
|
28
|
+
export declare function handleDiffCommand(opts: DiffCommandOptions): number;
|
|
29
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA6ClE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge diff <file1> <file2>` subcommand: print a unified diff between
|
|
3
|
+
* two files (or a file and stdin). Pure CLI surface over the
|
|
4
|
+
* {@link computeUnifiedDiff} core helper; no AI provider needed.
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* forge diff before.txt after.txt
|
|
8
|
+
* forge diff --from-stdin package.json < updated-package.json
|
|
9
|
+
* forge diff --context 5 src/old.ts src/new.ts
|
|
10
|
+
*
|
|
11
|
+
* The output is pipe-friendly: same format as `git diff`, so it
|
|
12
|
+
* composes with `less`, `diff-so-fancy`, etc.
|
|
13
|
+
*/
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
import process from 'node:process';
|
|
16
|
+
import { computeDiffSummary, computeUnifiedDiff } from '@ikarmic/forge-core';
|
|
17
|
+
/**
|
|
18
|
+
* Run the `forge diff` subcommand. Resolves file paths relative to
|
|
19
|
+
* `cwd` and prints the unified diff (or summary) to stdout. Returns
|
|
20
|
+
* the shell exit code: 0 = files identical, 1 = files differ, 2 = error.
|
|
21
|
+
*/
|
|
22
|
+
export function handleDiffCommand(opts) {
|
|
23
|
+
let before;
|
|
24
|
+
let after;
|
|
25
|
+
try {
|
|
26
|
+
before = readFileSync(resolvePath(opts.cwd ?? process.cwd(), opts.fileA), 'utf8');
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
process.stderr.write(`forge diff: failed to read ${opts.fileA}: ${err.message}\n`);
|
|
30
|
+
return 2;
|
|
31
|
+
}
|
|
32
|
+
if (opts.fromStdin) {
|
|
33
|
+
try {
|
|
34
|
+
after = readStdinSync();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
process.stderr.write(`forge diff: failed to read stdin: ${err.message}\n`);
|
|
38
|
+
return 2;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const fileB = opts.fileB;
|
|
43
|
+
if (!fileB) {
|
|
44
|
+
process.stderr.write('forge diff: missing <fileB> (or pass --from-stdin)\n');
|
|
45
|
+
return 2;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
after = readFileSync(resolvePath(opts.cwd ?? process.cwd(), fileB), 'utf8');
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
process.stderr.write(`forge diff: failed to read ${fileB}: ${err.message}\n`);
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const diffOpts = {
|
|
56
|
+
filePath: opts.fileB ?? opts.fileA,
|
|
57
|
+
...(opts.contextLines !== undefined ? { contextLines: opts.contextLines } : {}),
|
|
58
|
+
};
|
|
59
|
+
const result = computeUnifiedDiff(before, after, diffOpts);
|
|
60
|
+
if (opts.summaryOnly) {
|
|
61
|
+
const summary = computeDiffSummary(before, after, diffOpts);
|
|
62
|
+
process.stdout.write(`${summary.summary}\n`);
|
|
63
|
+
}
|
|
64
|
+
else if (!result.unchanged) {
|
|
65
|
+
process.stdout.write(result.text);
|
|
66
|
+
if (!result.text.endsWith('\n'))
|
|
67
|
+
process.stdout.write('\n');
|
|
68
|
+
}
|
|
69
|
+
return result.unchanged ? 0 : 1;
|
|
70
|
+
}
|
|
71
|
+
function resolvePath(cwd, p) {
|
|
72
|
+
// Simple path resolver: accepts absolute paths as-is, otherwise
|
|
73
|
+
// joins with cwd. Node's path.resolve would also normalize `..` but
|
|
74
|
+
// we keep it minimal here. Also recognizes Windows UNC paths
|
|
75
|
+
// (`\\server\share\file`) as absolute.
|
|
76
|
+
if (p.startsWith('/') || p.startsWith('\\\\') || /^[a-zA-Z]:[\\/]/.test(p))
|
|
77
|
+
return p;
|
|
78
|
+
return `${cwd}/${p}`;
|
|
79
|
+
}
|
|
80
|
+
function readStdinSync() {
|
|
81
|
+
// Node 18+ exposes fs.readFileSync('/dev/stdin') as a synchronous
|
|
82
|
+
// stdin read. On Windows this falls back to reading 0 via `readFileSync`
|
|
83
|
+
// which works for short inputs. Errors (e.g. a known partial-read/EAGAIN
|
|
84
|
+
// behavior on non-regular-file descriptors for large piped input on
|
|
85
|
+
// Windows) propagate to the caller rather than being swallowed into ''
|
|
86
|
+
//: silently treating a read failure as empty stdin would make `forge
|
|
87
|
+
// diff --from-stdin` claim the whole file was deleted with no warning.
|
|
88
|
+
return readFileSync(0, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge hook …` subcommand: list, test, log hooks.
|
|
3
|
+
*
|
|
4
|
+
* Hooks are loaded from `~/.forge/settings.json` + `.forge/settings.json`
|
|
5
|
+
* exactly the way the agent does, so what you see here matches what the
|
|
6
|
+
* agent runs.
|
|
7
|
+
*/
|
|
8
|
+
import type { ParsedHookCommand } from '../options.js';
|
|
9
|
+
export declare function handleHookCommand(cmd: ParsedHookCommand, cwd: string): Promise<number>;
|
|
10
|
+
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa5F"}
|