codealmanac 0.2.3 → 0.2.5
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/README.md +27 -14
- package/dist/agents-RVTQYE6A.js +25 -0
- package/dist/chunk-6BJUYZ43.js +195 -0
- package/dist/chunk-6BJUYZ43.js.map +1 -0
- package/dist/chunk-BGUID5BS.js +766 -0
- package/dist/chunk-BGUID5BS.js.map +1 -0
- package/dist/{chunk-NBVIEZZQ.js → chunk-DL5BXZCX.js} +53 -3
- package/dist/chunk-DL5BXZCX.js.map +1 -0
- package/dist/{chunk-XNTNXEWY.js → chunk-GFUB57IT.js} +243 -83
- package/dist/chunk-GFUB57IT.js.map +1 -0
- package/dist/{chunk-P3LDTCLB.js → chunk-H37GKBWI.js} +13 -1
- package/dist/chunk-H37GKBWI.js.map +1 -0
- package/dist/{chunk-QQHIVTXT.js → chunk-MRRX4UQB.js} +4 -4
- package/dist/{chunk-QQHIVTXT.js.map → chunk-MRRX4UQB.js.map} +1 -1
- package/dist/chunk-P5WGG4FJ.js +359 -0
- package/dist/chunk-P5WGG4FJ.js.map +1 -0
- package/dist/{chunk-HNVOYWC2.js → chunk-SMIK2YLU.js} +165 -76
- package/dist/chunk-SMIK2YLU.js.map +1 -0
- package/dist/{chunk-V3QOQSXI.js → chunk-TILAKDN6.js} +14 -8
- package/dist/chunk-TILAKDN6.js.map +1 -0
- package/dist/chunk-TT6ZP4GS.js +282 -0
- package/dist/chunk-TT6ZP4GS.js.map +1 -0
- package/dist/{cli-6BOB6KAN.js → cli-CL4ID7EO.js} +123 -33
- package/dist/cli-CL4ID7EO.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/config-ML2RCR7J.js +16 -0
- package/dist/doctor-DOLJRGS4.js +17 -0
- package/dist/{register-commands-IXYE5CNZ.js → register-commands-FBJ6XQ3L.js} +296 -398
- package/dist/register-commands-FBJ6XQ3L.js.map +1 -0
- package/dist/uninstall-DX6LFKMX.js +15 -0
- package/dist/{update-RAF7QRYF.js → update-P2IPG7RO.js} +3 -3
- package/guides/mini.md +4 -4
- package/guides/reference.md +75 -16
- package/package.json +1 -1
- package/dist/agents-RVYQ44DB.js +0 -16
- package/dist/auth-S5DVUIUJ.js +0 -18
- package/dist/chunk-HNVOYWC2.js.map +0 -1
- package/dist/chunk-NBVIEZZQ.js.map +0 -1
- package/dist/chunk-P3LDTCLB.js.map +0 -1
- package/dist/chunk-PIYJQE4Z.js +0 -102
- package/dist/chunk-PIYJQE4Z.js.map +0 -1
- package/dist/chunk-SSYMRT4I.js +0 -126
- package/dist/chunk-SSYMRT4I.js.map +0 -1
- package/dist/chunk-TWM7I2LU.js +0 -116
- package/dist/chunk-TWM7I2LU.js.map +0 -1
- package/dist/chunk-V3QOQSXI.js.map +0 -1
- package/dist/chunk-WRUSDYYE.js +0 -97
- package/dist/chunk-WRUSDYYE.js.map +0 -1
- package/dist/chunk-XNTNXEWY.js.map +0 -1
- package/dist/cli-6BOB6KAN.js.map +0 -1
- package/dist/doctor-DD7EQGCA.js +0 -18
- package/dist/register-commands-IXYE5CNZ.js.map +0 -1
- package/dist/uninstall-OBV4Z3JE.js +0 -16
- /package/dist/{agents-RVYQ44DB.js.map → agents-RVTQYE6A.js.map} +0 -0
- /package/dist/{auth-S5DVUIUJ.js.map → config-ML2RCR7J.js.map} +0 -0
- /package/dist/{doctor-DD7EQGCA.js.map → doctor-DOLJRGS4.js.map} +0 -0
- /package/dist/{uninstall-OBV4Z3JE.js.map → uninstall-DX6LFKMX.js.map} +0 -0
- /package/dist/{update-RAF7QRYF.js.map → update-P2IPG7RO.js.map} +0 -0
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
AGENT_PROVIDER_IDS,
|
|
4
|
+
isAgentProviderId,
|
|
5
|
+
readConfig
|
|
6
|
+
} from "./chunk-P5WGG4FJ.js";
|
|
7
|
+
|
|
8
|
+
// src/agent/providers/claude/index.ts
|
|
9
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
10
|
+
|
|
11
|
+
// src/agent/providers/claude/auth.ts
|
|
12
|
+
import { spawn, spawnSync } from "child_process";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
import { dirname, join } from "path";
|
|
15
|
+
var AUTH_TIMEOUT_MS = 1e4;
|
|
16
|
+
function resolveClaudeExecutable() {
|
|
17
|
+
const result = spawnSync("sh", ["-lc", "command -v claude"], {
|
|
18
|
+
encoding: "utf8"
|
|
19
|
+
});
|
|
20
|
+
if (result.status !== 0) return void 0;
|
|
21
|
+
const found = result.stdout.trim().split("\n")[0]?.trim();
|
|
22
|
+
return found !== void 0 && found.length > 0 ? found : void 0;
|
|
23
|
+
}
|
|
24
|
+
function resolveCliJsPath() {
|
|
25
|
+
const require2 = createRequire(import.meta.url);
|
|
26
|
+
const entry = require2.resolve("@anthropic-ai/claude-agent-sdk");
|
|
27
|
+
return join(dirname(entry), "cli.js");
|
|
28
|
+
}
|
|
29
|
+
var defaultSpawnCli = (args) => {
|
|
30
|
+
const command = resolveClaudeExecutable() ?? "claude";
|
|
31
|
+
const child = spawn(command, args, {
|
|
32
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
33
|
+
});
|
|
34
|
+
return child;
|
|
35
|
+
};
|
|
36
|
+
var legacySdkSpawnCli = (args) => {
|
|
37
|
+
const cliPath = resolveCliJsPath();
|
|
38
|
+
const child = spawn(process.execPath, [cliPath, ...args], {
|
|
39
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
40
|
+
});
|
|
41
|
+
return child;
|
|
42
|
+
};
|
|
43
|
+
async function checkClaudeAuth(spawnCli = defaultSpawnCli) {
|
|
44
|
+
if (spawnCli === defaultSpawnCli) {
|
|
45
|
+
const status = await checkClaudeAuthWith(defaultSpawnCli);
|
|
46
|
+
if (status.loggedIn) return status;
|
|
47
|
+
return await checkClaudeAuthWith(legacySdkSpawnCli);
|
|
48
|
+
}
|
|
49
|
+
return await checkClaudeAuthWith(spawnCli);
|
|
50
|
+
}
|
|
51
|
+
async function checkClaudeAuthWith(spawnCli) {
|
|
52
|
+
let child;
|
|
53
|
+
try {
|
|
54
|
+
child = spawnCli(["auth", "status", "--json"]);
|
|
55
|
+
} catch {
|
|
56
|
+
return { loggedIn: false };
|
|
57
|
+
}
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
let stdout = "";
|
|
60
|
+
let stderr = "";
|
|
61
|
+
let settled = false;
|
|
62
|
+
const settle = (value) => {
|
|
63
|
+
if (settled) return;
|
|
64
|
+
settled = true;
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
resolve(value);
|
|
67
|
+
};
|
|
68
|
+
const timer = setTimeout(() => {
|
|
69
|
+
try {
|
|
70
|
+
child.kill("SIGTERM");
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
settle({ loggedIn: false });
|
|
74
|
+
}, AUTH_TIMEOUT_MS);
|
|
75
|
+
child.stdout.on("data", (data) => {
|
|
76
|
+
stdout += data.toString();
|
|
77
|
+
});
|
|
78
|
+
child.stderr.on("data", (data) => {
|
|
79
|
+
stderr += data.toString();
|
|
80
|
+
});
|
|
81
|
+
child.on("error", () => {
|
|
82
|
+
settle({ loggedIn: false });
|
|
83
|
+
});
|
|
84
|
+
child.on("close", (code) => {
|
|
85
|
+
if (code !== 0 && stdout.trim().length === 0) {
|
|
86
|
+
void stderr;
|
|
87
|
+
settle({ loggedIn: false });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
settle(parseClaudeAuthStatus(stdout.trim()));
|
|
92
|
+
} catch {
|
|
93
|
+
settle({ loggedIn: false });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function parseClaudeAuthStatus(raw) {
|
|
99
|
+
const parsed = JSON.parse(raw);
|
|
100
|
+
const loggedIn = parsed.loggedIn === true;
|
|
101
|
+
const out = { loggedIn };
|
|
102
|
+
if (typeof parsed.email === "string") out.email = parsed.email;
|
|
103
|
+
if (typeof parsed.subscriptionType === "string") {
|
|
104
|
+
out.subscriptionType = parsed.subscriptionType;
|
|
105
|
+
}
|
|
106
|
+
if (typeof parsed.authMethod === "string") {
|
|
107
|
+
out.authMethod = parsed.authMethod;
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
var UNAUTHENTICATED_MESSAGE = "not authenticated to Claude.\n\nOption 1 \u2014 use your Claude subscription (Pro/Max):\n claude auth login --claudeai\n\nOption 2 \u2014 use a pay-per-token API key:\n Get one at https://console.anthropic.com\n export ANTHROPIC_API_KEY=sk-ant-...\n\nVerify with: claude auth status";
|
|
112
|
+
async function assertClaudeAuth(spawnCli = defaultSpawnCli) {
|
|
113
|
+
const status = await checkClaudeAuth(spawnCli);
|
|
114
|
+
if (status.loggedIn) {
|
|
115
|
+
return status;
|
|
116
|
+
}
|
|
117
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
118
|
+
if (apiKey !== void 0 && apiKey.length > 0) {
|
|
119
|
+
return { loggedIn: true, authMethod: "apiKey" };
|
|
120
|
+
}
|
|
121
|
+
const err = new Error(UNAUTHENTICATED_MESSAGE);
|
|
122
|
+
err.code = "CLAUDE_AUTH_MISSING";
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/agent/providers/claude/index.ts
|
|
127
|
+
var DEFAULT_AGENT_MODEL = "claude-sonnet-4-6";
|
|
128
|
+
var metadata = {
|
|
129
|
+
id: "claude",
|
|
130
|
+
displayName: "Claude",
|
|
131
|
+
defaultModel: DEFAULT_AGENT_MODEL,
|
|
132
|
+
executable: "claude",
|
|
133
|
+
capabilities: {
|
|
134
|
+
transport: "sdk",
|
|
135
|
+
writesFiles: true,
|
|
136
|
+
supportsModelOverride: true,
|
|
137
|
+
supportsStreaming: true,
|
|
138
|
+
supportsSessionId: true,
|
|
139
|
+
supportsUsage: false,
|
|
140
|
+
supportsCost: true,
|
|
141
|
+
supportsProviderReportedTurns: true,
|
|
142
|
+
supportsProgrammaticSubagents: true,
|
|
143
|
+
supportsStrictToolAllowlist: false
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
var claudeProvider = {
|
|
147
|
+
metadata,
|
|
148
|
+
checkStatus,
|
|
149
|
+
assertReady,
|
|
150
|
+
run
|
|
151
|
+
};
|
|
152
|
+
async function run(opts) {
|
|
153
|
+
const claudeExecutable = resolveClaudeExecutable();
|
|
154
|
+
const q = query({
|
|
155
|
+
prompt: opts.prompt,
|
|
156
|
+
options: {
|
|
157
|
+
systemPrompt: opts.systemPrompt,
|
|
158
|
+
allowedTools: opts.allowedTools,
|
|
159
|
+
agents: opts.agents ?? {},
|
|
160
|
+
cwd: opts.cwd,
|
|
161
|
+
model: opts.model ?? metadata.defaultModel ?? void 0,
|
|
162
|
+
maxTurns: opts.maxTurns ?? 100,
|
|
163
|
+
...claudeExecutable !== void 0 ? { pathToClaudeCodeExecutable: claudeExecutable } : {},
|
|
164
|
+
env: {
|
|
165
|
+
...process.env,
|
|
166
|
+
CODEALMANAC_INTERNAL_SESSION: "1"
|
|
167
|
+
},
|
|
168
|
+
includePartialMessages: true
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
let cost = 0;
|
|
172
|
+
let turns = 0;
|
|
173
|
+
let result = "";
|
|
174
|
+
let sessionId;
|
|
175
|
+
let success = false;
|
|
176
|
+
let errorMsg;
|
|
177
|
+
try {
|
|
178
|
+
for await (const msg of q) {
|
|
179
|
+
opts.onMessage?.(msg);
|
|
180
|
+
if (sessionId === void 0 && typeof msg.session_id === "string") {
|
|
181
|
+
sessionId = msg.session_id;
|
|
182
|
+
}
|
|
183
|
+
if (msg.type === "result") {
|
|
184
|
+
cost = msg.total_cost_usd;
|
|
185
|
+
turns = msg.num_turns;
|
|
186
|
+
if (msg.subtype === "success") {
|
|
187
|
+
success = true;
|
|
188
|
+
result = msg.result;
|
|
189
|
+
} else {
|
|
190
|
+
success = false;
|
|
191
|
+
errorMsg = (msg.errors?.join("; ") ?? "") || `agent error: ${msg.subtype}`;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch (err) {
|
|
196
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
197
|
+
success = false;
|
|
198
|
+
}
|
|
199
|
+
return { success, cost, turns, result, sessionId, error: errorMsg };
|
|
200
|
+
}
|
|
201
|
+
async function checkStatus(spawnCli) {
|
|
202
|
+
let auth = { loggedIn: false };
|
|
203
|
+
try {
|
|
204
|
+
auth = await checkClaudeAuth(spawnCli);
|
|
205
|
+
} catch {
|
|
206
|
+
auth = { loggedIn: false };
|
|
207
|
+
}
|
|
208
|
+
const hasApiKey = process.env.ANTHROPIC_API_KEY !== void 0 && process.env.ANTHROPIC_API_KEY.length > 0;
|
|
209
|
+
const installed = resolveClaudeExecutable() !== void 0;
|
|
210
|
+
const authenticated = auth.loggedIn || hasApiKey;
|
|
211
|
+
const detail = authenticated ? auth.email ?? (hasApiKey ? "ANTHROPIC_API_KEY set" : "logged in") : installed ? "not logged in" : `${metadata.executable} not found on PATH`;
|
|
212
|
+
return { id: metadata.id, installed, authenticated, detail };
|
|
213
|
+
}
|
|
214
|
+
async function assertReady(spawnCli) {
|
|
215
|
+
await assertClaudeAuth(spawnCli);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/agent/providers/cli-status.ts
|
|
219
|
+
import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
220
|
+
var STATUS_TIMEOUT_MS = 3e3;
|
|
221
|
+
function commandExists(command) {
|
|
222
|
+
const result = spawnSync2("sh", ["-lc", `command -v ${command}`], {
|
|
223
|
+
encoding: "utf8"
|
|
224
|
+
});
|
|
225
|
+
return result.status === 0 && result.stdout.trim().length > 0;
|
|
226
|
+
}
|
|
227
|
+
function runStatusCommand(command, args) {
|
|
228
|
+
return new Promise((resolve) => {
|
|
229
|
+
let stdout = "";
|
|
230
|
+
let stderr = "";
|
|
231
|
+
let child;
|
|
232
|
+
let settled = false;
|
|
233
|
+
const settle = (value) => {
|
|
234
|
+
if (settled) return;
|
|
235
|
+
settled = true;
|
|
236
|
+
clearTimeout(timer);
|
|
237
|
+
resolve(value);
|
|
238
|
+
};
|
|
239
|
+
try {
|
|
240
|
+
child = spawn2(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
241
|
+
} catch (err) {
|
|
242
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
243
|
+
resolve({ ok: false, detail: msg });
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const timer = setTimeout(() => {
|
|
247
|
+
try {
|
|
248
|
+
child.kill("SIGTERM");
|
|
249
|
+
setTimeout(() => {
|
|
250
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
251
|
+
try {
|
|
252
|
+
child.kill("SIGKILL");
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}, 500).unref();
|
|
257
|
+
} catch {
|
|
258
|
+
}
|
|
259
|
+
settle({ ok: false, detail: `${command} status timed out` });
|
|
260
|
+
}, STATUS_TIMEOUT_MS);
|
|
261
|
+
child.stdout?.on("data", (chunk) => {
|
|
262
|
+
stdout += chunk.toString("utf8");
|
|
263
|
+
});
|
|
264
|
+
child.stderr?.on("data", (chunk) => {
|
|
265
|
+
stderr += chunk.toString("utf8");
|
|
266
|
+
});
|
|
267
|
+
child.on("error", (err) => {
|
|
268
|
+
settle({ ok: false, detail: err.message });
|
|
269
|
+
});
|
|
270
|
+
child.on("close", (code) => {
|
|
271
|
+
const text = `${stdout}
|
|
272
|
+
${stderr}`.trim();
|
|
273
|
+
settle({
|
|
274
|
+
ok: code === 0,
|
|
275
|
+
detail: text.split("\n").find((line) => line.trim().length > 0)?.trim() ?? (code === 0 ? "ready" : `${command} exited ${code ?? 1}`)
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/agent/providers/jsonl-cli.ts
|
|
282
|
+
import { spawn as spawn3 } from "child_process";
|
|
283
|
+
function runJsonlCli(opts) {
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
const child = spawn3(opts.command, opts.args, {
|
|
286
|
+
cwd: opts.cwd,
|
|
287
|
+
env: opts.env,
|
|
288
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
289
|
+
});
|
|
290
|
+
let stdoutBuf = "";
|
|
291
|
+
let stderr = "";
|
|
292
|
+
let cost = 0;
|
|
293
|
+
let turns = 0;
|
|
294
|
+
let result = "";
|
|
295
|
+
let sessionId;
|
|
296
|
+
let usage;
|
|
297
|
+
let success = false;
|
|
298
|
+
let finalSeen = false;
|
|
299
|
+
let error;
|
|
300
|
+
const observe = (msg) => {
|
|
301
|
+
opts.onMessage?.(msg);
|
|
302
|
+
if (sessionId === void 0 && typeof msg.session_id === "string" && msg.session_id.length > 0) {
|
|
303
|
+
sessionId = msg.session_id;
|
|
304
|
+
}
|
|
305
|
+
if (sessionId === void 0 && typeof msg.thread_id === "string" && msg.thread_id.length > 0) {
|
|
306
|
+
sessionId = msg.thread_id;
|
|
307
|
+
}
|
|
308
|
+
const final = opts.parseFinal(msg);
|
|
309
|
+
if (final === null) return;
|
|
310
|
+
finalSeen = true;
|
|
311
|
+
if (final.cost !== void 0) cost = final.cost;
|
|
312
|
+
if (final.turns !== void 0) turns = final.turns;
|
|
313
|
+
if (final.result !== void 0) result = final.result;
|
|
314
|
+
if (final.sessionId !== void 0) sessionId = final.sessionId;
|
|
315
|
+
if (final.usage !== void 0) usage = final.usage;
|
|
316
|
+
if (final.success !== void 0) success = final.success;
|
|
317
|
+
if (final.error !== void 0) error = final.error;
|
|
318
|
+
};
|
|
319
|
+
const flushLines = () => {
|
|
320
|
+
let idx = stdoutBuf.indexOf("\n");
|
|
321
|
+
while (idx !== -1) {
|
|
322
|
+
const rawLine = stdoutBuf.slice(0, idx);
|
|
323
|
+
stdoutBuf = stdoutBuf.slice(idx + 1);
|
|
324
|
+
const line = rawLine.trim();
|
|
325
|
+
if (line.length > 0) {
|
|
326
|
+
try {
|
|
327
|
+
observe(JSON.parse(line));
|
|
328
|
+
} catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
idx = stdoutBuf.indexOf("\n");
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
child.stdout.on("data", (chunk) => {
|
|
335
|
+
stdoutBuf += chunk.toString("utf8");
|
|
336
|
+
flushLines();
|
|
337
|
+
});
|
|
338
|
+
child.stderr.on("data", (chunk) => {
|
|
339
|
+
stderr += chunk.toString("utf8");
|
|
340
|
+
});
|
|
341
|
+
child.on("error", (err) => {
|
|
342
|
+
resolve({
|
|
343
|
+
success: false,
|
|
344
|
+
cost,
|
|
345
|
+
turns,
|
|
346
|
+
result,
|
|
347
|
+
sessionId,
|
|
348
|
+
usage,
|
|
349
|
+
error: err.code === "ENOENT" ? `${opts.command} not found on PATH` : err.message
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
child.on("close", (code) => {
|
|
353
|
+
flushLines();
|
|
354
|
+
if (stdoutBuf.trim().length > 0) {
|
|
355
|
+
try {
|
|
356
|
+
observe(JSON.parse(stdoutBuf.trim()));
|
|
357
|
+
} catch {
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (code === 0 && finalSeen && success) {
|
|
361
|
+
resolve({ success, cost, turns, result, sessionId, usage });
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const firstStderr = stderr.trim().split("\n")[0];
|
|
365
|
+
resolve({
|
|
366
|
+
success: false,
|
|
367
|
+
cost,
|
|
368
|
+
turns,
|
|
369
|
+
result,
|
|
370
|
+
sessionId,
|
|
371
|
+
usage,
|
|
372
|
+
error: error ?? (firstStderr !== void 0 && firstStderr.length > 0 ? firstStderr : `${opts.command} exited ${code ?? 1}`)
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
function parseUsage(value) {
|
|
378
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
379
|
+
const obj = value;
|
|
380
|
+
return {
|
|
381
|
+
inputTokens: numberField(obj, "input_tokens") ?? numberField(obj, "inputTokens"),
|
|
382
|
+
cachedInputTokens: numberField(obj, "cached_input_tokens") ?? numberField(obj, "cachedInputTokens") ?? numberField(obj, "cacheReadTokens"),
|
|
383
|
+
outputTokens: numberField(obj, "output_tokens") ?? numberField(obj, "outputTokens"),
|
|
384
|
+
reasoningOutputTokens: numberField(obj, "reasoning_output_tokens") ?? numberField(obj, "reasoningOutputTokens")
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function numberField(input, key) {
|
|
388
|
+
const value = input[key];
|
|
389
|
+
return typeof value === "number" ? value : void 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/agent/providers/prompt.ts
|
|
393
|
+
function combinedPrompt(opts, metadata4) {
|
|
394
|
+
const reviewerFallback = buildReviewerFallback(opts, metadata4);
|
|
395
|
+
return `${opts.systemPrompt}${reviewerFallback}
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
${opts.prompt}`;
|
|
400
|
+
}
|
|
401
|
+
function buildReviewerFallback(opts, metadata4) {
|
|
402
|
+
if (metadata4.capabilities.supportsProgrammaticSubagents) return "";
|
|
403
|
+
const reviewer = opts.agents?.reviewer;
|
|
404
|
+
if (reviewer === void 0) return "";
|
|
405
|
+
return "\n\nNon-Claude provider note: this runtime does not receive Claude's nested Agent tool contract. When the writer prompt asks you to invoke the reviewer subagent, perform that review pass yourself before final wiki edits. Treat this reviewer prompt as read-only review guidance:\n\n" + reviewer.prompt;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/agent/providers/codex-cli.ts
|
|
409
|
+
var metadata2 = {
|
|
410
|
+
id: "codex",
|
|
411
|
+
displayName: "Codex",
|
|
412
|
+
defaultModel: null,
|
|
413
|
+
executable: "codex",
|
|
414
|
+
capabilities: {
|
|
415
|
+
transport: "cli-jsonl",
|
|
416
|
+
writesFiles: true,
|
|
417
|
+
supportsModelOverride: true,
|
|
418
|
+
supportsStreaming: true,
|
|
419
|
+
supportsSessionId: false,
|
|
420
|
+
supportsUsage: true,
|
|
421
|
+
supportsCost: false,
|
|
422
|
+
supportsProviderReportedTurns: false,
|
|
423
|
+
supportsProgrammaticSubagents: false,
|
|
424
|
+
supportsStrictToolAllowlist: false
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
var codexProvider = {
|
|
428
|
+
metadata: metadata2,
|
|
429
|
+
checkStatus: checkStatus2,
|
|
430
|
+
assertReady: assertReady2,
|
|
431
|
+
run: run2
|
|
432
|
+
};
|
|
433
|
+
async function run2(opts) {
|
|
434
|
+
const args = [
|
|
435
|
+
"exec",
|
|
436
|
+
"--json",
|
|
437
|
+
"--sandbox",
|
|
438
|
+
"workspace-write",
|
|
439
|
+
"--skip-git-repo-check",
|
|
440
|
+
"-C",
|
|
441
|
+
opts.cwd
|
|
442
|
+
];
|
|
443
|
+
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
444
|
+
args.push("--model", opts.model);
|
|
445
|
+
}
|
|
446
|
+
args.push(combinedPrompt({ ...opts, provider: "codex" }, metadata2));
|
|
447
|
+
return await runJsonlCli({
|
|
448
|
+
command: metadata2.executable,
|
|
449
|
+
args,
|
|
450
|
+
cwd: opts.cwd,
|
|
451
|
+
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
452
|
+
onMessage: opts.onMessage,
|
|
453
|
+
parseFinal: parseCodexFinal
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
async function checkStatus2() {
|
|
457
|
+
if (!commandExists(metadata2.executable)) {
|
|
458
|
+
return {
|
|
459
|
+
id: metadata2.id,
|
|
460
|
+
installed: false,
|
|
461
|
+
authenticated: false,
|
|
462
|
+
detail: `${metadata2.executable} not found on PATH`
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
const auth = await runStatusCommand(metadata2.executable, ["login", "status"]);
|
|
466
|
+
return {
|
|
467
|
+
id: metadata2.id,
|
|
468
|
+
installed: true,
|
|
469
|
+
authenticated: auth.ok,
|
|
470
|
+
detail: auth.detail
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function assertReady2() {
|
|
474
|
+
const status = await checkStatus2();
|
|
475
|
+
if (!status.installed || !status.authenticated) {
|
|
476
|
+
const err = new Error(`${status.id} not ready: ${status.detail}`);
|
|
477
|
+
err.code = "AGENT_AUTH_MISSING";
|
|
478
|
+
throw err;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
function parseCodexFinal(msg) {
|
|
482
|
+
if (msg.type === "item.completed") {
|
|
483
|
+
const item = msg.item;
|
|
484
|
+
if (item !== null && typeof item === "object") {
|
|
485
|
+
const obj = item;
|
|
486
|
+
if (obj.type === "agent_message" && typeof obj.text === "string") {
|
|
487
|
+
return { result: obj.text };
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
if (msg.type === "turn.completed") {
|
|
493
|
+
return { success: true, turns: 1, usage: parseUsage(msg.usage) };
|
|
494
|
+
}
|
|
495
|
+
if (msg.type === "turn.failed" || msg.type === "error") {
|
|
496
|
+
return {
|
|
497
|
+
success: false,
|
|
498
|
+
error: typeof msg.message === "string" ? msg.message : typeof msg.error === "string" ? msg.error : "codex turn failed"
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// src/agent/providers/cursor-cli.ts
|
|
505
|
+
var metadata3 = {
|
|
506
|
+
id: "cursor",
|
|
507
|
+
displayName: "Cursor",
|
|
508
|
+
defaultModel: null,
|
|
509
|
+
executable: "cursor-agent",
|
|
510
|
+
capabilities: {
|
|
511
|
+
transport: "cli-jsonl",
|
|
512
|
+
writesFiles: true,
|
|
513
|
+
supportsModelOverride: true,
|
|
514
|
+
supportsStreaming: true,
|
|
515
|
+
supportsSessionId: true,
|
|
516
|
+
supportsUsage: true,
|
|
517
|
+
supportsCost: false,
|
|
518
|
+
supportsProviderReportedTurns: false,
|
|
519
|
+
supportsProgrammaticSubagents: false,
|
|
520
|
+
supportsStrictToolAllowlist: false
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
var cursorProvider = {
|
|
524
|
+
metadata: metadata3,
|
|
525
|
+
checkStatus: checkStatus3,
|
|
526
|
+
assertReady: assertReady3,
|
|
527
|
+
run: run3
|
|
528
|
+
};
|
|
529
|
+
async function run3(opts) {
|
|
530
|
+
const args = [
|
|
531
|
+
"--print",
|
|
532
|
+
"--output-format",
|
|
533
|
+
"stream-json",
|
|
534
|
+
"--stream-partial-output",
|
|
535
|
+
"--trust",
|
|
536
|
+
"--workspace",
|
|
537
|
+
opts.cwd
|
|
538
|
+
];
|
|
539
|
+
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
540
|
+
args.push("--model", opts.model);
|
|
541
|
+
}
|
|
542
|
+
args.push(combinedPrompt({ ...opts, provider: "cursor" }, metadata3));
|
|
543
|
+
return await runJsonlCli({
|
|
544
|
+
command: metadata3.executable,
|
|
545
|
+
args,
|
|
546
|
+
cwd: opts.cwd,
|
|
547
|
+
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
548
|
+
onMessage: opts.onMessage,
|
|
549
|
+
parseFinal: parseCursorFinal
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
async function checkStatus3() {
|
|
553
|
+
if (!commandExists(metadata3.executable)) {
|
|
554
|
+
return {
|
|
555
|
+
id: metadata3.id,
|
|
556
|
+
installed: false,
|
|
557
|
+
authenticated: false,
|
|
558
|
+
detail: `${metadata3.executable} not found on PATH`
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
const auth = await runStatusCommand(metadata3.executable, ["status"]);
|
|
562
|
+
return {
|
|
563
|
+
id: metadata3.id,
|
|
564
|
+
installed: true,
|
|
565
|
+
authenticated: auth.ok,
|
|
566
|
+
detail: auth.detail
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
async function assertReady3() {
|
|
570
|
+
const status = await checkStatus3();
|
|
571
|
+
if (!status.installed || !status.authenticated) {
|
|
572
|
+
const err = new Error(`${status.id} not ready: ${status.detail}`);
|
|
573
|
+
err.code = "AGENT_AUTH_MISSING";
|
|
574
|
+
throw err;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function parseCursorFinal(msg) {
|
|
578
|
+
if (msg.type !== "result") return null;
|
|
579
|
+
const isError = msg.is_error === true || msg.subtype !== "success";
|
|
580
|
+
return {
|
|
581
|
+
success: !isError,
|
|
582
|
+
turns: 1,
|
|
583
|
+
result: typeof msg.result === "string" ? msg.result : "",
|
|
584
|
+
sessionId: typeof msg.session_id === "string" ? msg.session_id : void 0,
|
|
585
|
+
usage: parseUsage(msg.usage),
|
|
586
|
+
error: isError ? typeof msg.result === "string" ? msg.result : `cursor result: ${String(msg.subtype ?? "error")}` : void 0
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// src/agent/providers/status.ts
|
|
591
|
+
async function assertAgentAuth(args) {
|
|
592
|
+
await getAgentProvider(args.provider).assertReady(args.spawnCli);
|
|
593
|
+
}
|
|
594
|
+
async function listProviderStatuses(spawnCli) {
|
|
595
|
+
const out = [];
|
|
596
|
+
for (const id of AGENT_PROVIDER_IDS) {
|
|
597
|
+
out.push(await getAgentProvider(id).checkStatus(spawnCli));
|
|
598
|
+
}
|
|
599
|
+
return out;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/agent/providers/index.ts
|
|
603
|
+
var AGENT_PROVIDERS = {
|
|
604
|
+
claude: claudeProvider,
|
|
605
|
+
codex: codexProvider,
|
|
606
|
+
cursor: cursorProvider
|
|
607
|
+
};
|
|
608
|
+
function getAgentProvider(id) {
|
|
609
|
+
return AGENT_PROVIDERS[id];
|
|
610
|
+
}
|
|
611
|
+
var AGENT_PROVIDER_METADATA = {
|
|
612
|
+
claude: claudeProvider.metadata,
|
|
613
|
+
codex: codexProvider.metadata,
|
|
614
|
+
cursor: cursorProvider.metadata
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
// src/agent/provider-view.ts
|
|
618
|
+
var LOGIN_FIXES = {
|
|
619
|
+
claude: "run: claude auth login --claudeai",
|
|
620
|
+
codex: "run: codex login",
|
|
621
|
+
cursor: "run: cursor-agent login"
|
|
622
|
+
};
|
|
623
|
+
var INSTALL_FIXES = {
|
|
624
|
+
claude: "install Claude Code, then run: claude auth login --claudeai",
|
|
625
|
+
codex: "install Codex CLI, then run: codex login",
|
|
626
|
+
cursor: "install cursor-agent, then run: cursor-agent login"
|
|
627
|
+
};
|
|
628
|
+
function getProviderLabel(id) {
|
|
629
|
+
return AGENT_PROVIDER_METADATA[id].displayName;
|
|
630
|
+
}
|
|
631
|
+
function getProviderDefaultModel(id) {
|
|
632
|
+
return AGENT_PROVIDER_METADATA[id].defaultModel;
|
|
633
|
+
}
|
|
634
|
+
async function buildProviderSetupView(opts = {}) {
|
|
635
|
+
const config = opts.config ?? await readConfig();
|
|
636
|
+
const statuses = opts.statuses ?? await listProviderStatuses(opts.spawnCli);
|
|
637
|
+
const statusById = new Map(statuses.map((status) => [status.id, status]));
|
|
638
|
+
const recommendedProvider = chooseRecommendedProvider(statuses);
|
|
639
|
+
const choices = AGENT_PROVIDER_IDS.map((id) => {
|
|
640
|
+
const status = statusById.get(id) ?? missingStatus(id);
|
|
641
|
+
const readiness = getReadiness(status);
|
|
642
|
+
const configuredModel = normalizeModel(config.agent.models[id]);
|
|
643
|
+
const providerDefaultModel = getProviderDefaultModel(id);
|
|
644
|
+
const effectiveModel = configuredModel ?? providerDefaultModel;
|
|
645
|
+
return {
|
|
646
|
+
id,
|
|
647
|
+
label: getProviderLabel(id),
|
|
648
|
+
selected: id === config.agent.default,
|
|
649
|
+
recommended: id === recommendedProvider,
|
|
650
|
+
readiness,
|
|
651
|
+
ready: readiness === "ready",
|
|
652
|
+
installed: status.installed,
|
|
653
|
+
authenticated: status.authenticated,
|
|
654
|
+
effectiveModel,
|
|
655
|
+
providerDefaultModel,
|
|
656
|
+
configuredModel,
|
|
657
|
+
account: status.authenticated ? accountFromDetail(status.detail) : null,
|
|
658
|
+
detail: status.detail,
|
|
659
|
+
fixCommand: fixFor(id, readiness),
|
|
660
|
+
modelChoices: buildProviderModelChoices(id, configuredModel)
|
|
661
|
+
};
|
|
662
|
+
});
|
|
663
|
+
return {
|
|
664
|
+
defaultProvider: config.agent.default,
|
|
665
|
+
recommendedProvider,
|
|
666
|
+
choices
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function buildProviderModelChoices(id, configuredModel = null) {
|
|
670
|
+
const choices = [];
|
|
671
|
+
if (configuredModel !== null) {
|
|
672
|
+
choices.push({
|
|
673
|
+
value: configuredModel,
|
|
674
|
+
label: configuredModel,
|
|
675
|
+
recommended: false,
|
|
676
|
+
source: "configured"
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
const providerDefault = getProviderDefaultModel(id);
|
|
680
|
+
if (providerDefault !== null) {
|
|
681
|
+
if (!choices.some((choice) => choice.value === providerDefault)) {
|
|
682
|
+
choices.push({
|
|
683
|
+
value: providerDefault,
|
|
684
|
+
label: providerDefault,
|
|
685
|
+
recommended: true,
|
|
686
|
+
source: "provider-default"
|
|
687
|
+
});
|
|
688
|
+
} else {
|
|
689
|
+
choices[0] = { ...choices[0], recommended: true };
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
choices.push({
|
|
693
|
+
value: null,
|
|
694
|
+
label: "provider default",
|
|
695
|
+
recommended: true,
|
|
696
|
+
source: "provider-default"
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
choices.push({
|
|
700
|
+
value: "__custom__",
|
|
701
|
+
label: "custom model id",
|
|
702
|
+
recommended: false,
|
|
703
|
+
source: "custom"
|
|
704
|
+
});
|
|
705
|
+
return choices;
|
|
706
|
+
}
|
|
707
|
+
function chooseRecommendedProvider(statuses) {
|
|
708
|
+
const ready = statuses.filter((status) => status.installed && status.authenticated).map((status) => status.id);
|
|
709
|
+
if (ready.includes("claude")) return "claude";
|
|
710
|
+
for (const id of AGENT_PROVIDER_IDS) {
|
|
711
|
+
if (ready.includes(id)) return id;
|
|
712
|
+
}
|
|
713
|
+
return "claude";
|
|
714
|
+
}
|
|
715
|
+
function parseAgentSelection(value) {
|
|
716
|
+
const [rawProvider, ...modelParts] = value.split("/");
|
|
717
|
+
if (rawProvider === void 0 || !isAgentProviderId(rawProvider)) {
|
|
718
|
+
return { provider: null };
|
|
719
|
+
}
|
|
720
|
+
const model = modelParts.join("/");
|
|
721
|
+
return {
|
|
722
|
+
provider: rawProvider,
|
|
723
|
+
model: model.length > 0 ? model : void 0
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
function getReadiness(status) {
|
|
727
|
+
if (!status.installed) return "missing";
|
|
728
|
+
if (!status.authenticated) return "not-authenticated";
|
|
729
|
+
return "ready";
|
|
730
|
+
}
|
|
731
|
+
function fixFor(id, readiness) {
|
|
732
|
+
if (readiness === "ready") return null;
|
|
733
|
+
if (readiness === "missing") return INSTALL_FIXES[id];
|
|
734
|
+
return LOGIN_FIXES[id];
|
|
735
|
+
}
|
|
736
|
+
function accountFromDetail(detail) {
|
|
737
|
+
const clean = detail.trim();
|
|
738
|
+
if (clean.length === 0 || clean === "ready" || clean === "logged in" || clean === "ANTHROPIC_API_KEY set") {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
return clean;
|
|
742
|
+
}
|
|
743
|
+
function normalizeModel(value) {
|
|
744
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
745
|
+
}
|
|
746
|
+
function missingStatus(id) {
|
|
747
|
+
return {
|
|
748
|
+
id,
|
|
749
|
+
installed: false,
|
|
750
|
+
authenticated: false,
|
|
751
|
+
detail: "provider status unavailable"
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export {
|
|
756
|
+
checkClaudeAuth,
|
|
757
|
+
DEFAULT_AGENT_MODEL,
|
|
758
|
+
assertAgentAuth,
|
|
759
|
+
getAgentProvider,
|
|
760
|
+
getProviderLabel,
|
|
761
|
+
getProviderDefaultModel,
|
|
762
|
+
buildProviderSetupView,
|
|
763
|
+
buildProviderModelChoices,
|
|
764
|
+
parseAgentSelection
|
|
765
|
+
};
|
|
766
|
+
//# sourceMappingURL=chunk-BGUID5BS.js.map
|