codealmanac 0.1.10 → 0.2.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/README.md +36 -21
- package/dist/agents-A4II4YJC.js +15 -0
- package/dist/auth-S5DVUIUJ.js +18 -0
- package/dist/{chunk-Z4MWLVS2.js → chunk-447U3GQJ.js} +162 -5
- package/dist/chunk-447U3GQJ.js.map +1 -0
- package/dist/{chunk-QLHJP2XK.js → chunk-D3B2EEHL.js} +12 -8
- package/dist/{chunk-QLHJP2XK.js.map → chunk-D3B2EEHL.js.map} +1 -1
- package/dist/{chunk-AXFPUHBN.js → chunk-F53U6JQG.js} +8 -49
- package/dist/chunk-F53U6JQG.js.map +1 -0
- package/dist/{chunk-BJVZLP6O.js → chunk-MX2EW5MR.js} +3 -3
- package/dist/{chunk-Z6MBJ3D2.js → chunk-QQHIVTXT.js} +6 -4
- package/dist/{chunk-Z6MBJ3D2.js.map → chunk-QQHIVTXT.js.map} +1 -1
- package/dist/chunk-R3URPHGH.js +194 -0
- package/dist/chunk-R3URPHGH.js.map +1 -0
- package/dist/chunk-SSYMRT4I.js +126 -0
- package/dist/chunk-SSYMRT4I.js.map +1 -0
- package/dist/{chunk-QHQ6YH7U.js → chunk-V3QOQSXI.js} +5 -3
- package/dist/{chunk-QHQ6YH7U.js.map → chunk-V3QOQSXI.js.map} +1 -1
- package/dist/chunk-WRUSDYYE.js +97 -0
- package/dist/chunk-WRUSDYYE.js.map +1 -0
- package/dist/{chunk-3LC55TG6.js → chunk-ZDJSJIB6.js} +77 -126
- package/dist/chunk-ZDJSJIB6.js.map +1 -0
- package/dist/{cli-W3OYVJYH.js → cli-CMGYLJSN.js} +52 -13
- package/dist/cli-CMGYLJSN.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/doctor-BTH7GCFV.js +17 -0
- package/dist/{hook-CRJMWSSO.js → hook-2NP3UE7U.js} +2 -2
- package/dist/{register-commands-JHC2OFKM.js → register-commands-7SKQLQW4.js} +330 -32
- package/dist/register-commands-7SKQLQW4.js.map +1 -0
- package/dist/uninstall-FDIOBAAR.js +15 -0
- package/dist/uninstall-FDIOBAAR.js.map +1 -0
- package/dist/update-RAF7QRYF.js +11 -0
- package/dist/update-RAF7QRYF.js.map +1 -0
- package/hooks/almanac-capture.sh +40 -7
- package/package.json +1 -1
- package/dist/chunk-3LC55TG6.js.map +0 -1
- package/dist/chunk-AXFPUHBN.js.map +0 -1
- package/dist/chunk-Z4MWLVS2.js.map +0 -1
- package/dist/cli-W3OYVJYH.js.map +0 -1
- package/dist/doctor-ODFNJUKH.js +0 -15
- package/dist/register-commands-JHC2OFKM.js.map +0 -1
- package/dist/uninstall-HE2Z2LN2.js +0 -12
- package/dist/update-IL243I4E.js +0 -10
- /package/dist/{doctor-ODFNJUKH.js.map → agents-A4II4YJC.js.map} +0 -0
- /package/dist/{hook-CRJMWSSO.js.map → auth-S5DVUIUJ.js.map} +0 -0
- /package/dist/{chunk-BJVZLP6O.js.map → chunk-MX2EW5MR.js.map} +0 -0
- /package/dist/{uninstall-HE2Z2LN2.js.map → doctor-BTH7GCFV.js.map} +0 -0
- /package/dist/{update-IL243I4E.js.map → hook-2NP3UE7U.js.map} +0 -0
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
collectOption,
|
|
4
|
+
emit,
|
|
5
|
+
parsePositiveInt,
|
|
6
|
+
readStdin
|
|
7
|
+
} from "./chunk-P3LDTCLB.js";
|
|
8
|
+
import {
|
|
9
|
+
assertAgentAuth,
|
|
10
|
+
runAgentsList,
|
|
11
|
+
runSetAgentModel,
|
|
12
|
+
runSetDefaultAgent
|
|
13
|
+
} from "./chunk-R3URPHGH.js";
|
|
2
14
|
import {
|
|
3
15
|
addEntry,
|
|
4
16
|
ancestorsInFile,
|
|
@@ -24,21 +36,9 @@ import {
|
|
|
24
36
|
} from "./chunk-3C5SY5SE.js";
|
|
25
37
|
import {
|
|
26
38
|
runDoctor
|
|
27
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-D3B2EEHL.js";
|
|
40
|
+
import "./chunk-V3QOQSXI.js";
|
|
28
41
|
import "./chunk-4CODZRHH.js";
|
|
29
|
-
import {
|
|
30
|
-
runUninstall
|
|
31
|
-
} from "./chunk-BJVZLP6O.js";
|
|
32
|
-
import {
|
|
33
|
-
runUpdate
|
|
34
|
-
} from "./chunk-Z6MBJ3D2.js";
|
|
35
|
-
import {
|
|
36
|
-
collectOption,
|
|
37
|
-
emit,
|
|
38
|
-
parsePositiveInt,
|
|
39
|
-
readStdin
|
|
40
|
-
} from "./chunk-P3LDTCLB.js";
|
|
41
|
-
import "./chunk-QHQ6YH7U.js";
|
|
42
42
|
import {
|
|
43
43
|
BLUE,
|
|
44
44
|
BOLD,
|
|
@@ -46,16 +46,27 @@ import {
|
|
|
46
46
|
RST
|
|
47
47
|
} from "./chunk-FM3VRDK7.js";
|
|
48
48
|
import {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
runUninstall
|
|
50
|
+
} from "./chunk-MX2EW5MR.js";
|
|
51
|
+
import {
|
|
51
52
|
runSetup
|
|
52
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-ZDJSJIB6.js";
|
|
53
54
|
import {
|
|
54
55
|
runHookInstall,
|
|
55
56
|
runHookStatus,
|
|
56
57
|
runHookUninstall
|
|
57
|
-
} from "./chunk-
|
|
58
|
-
import
|
|
58
|
+
} from "./chunk-447U3GQJ.js";
|
|
59
|
+
import {
|
|
60
|
+
resolveClaudeExecutable
|
|
61
|
+
} from "./chunk-SSYMRT4I.js";
|
|
62
|
+
import {
|
|
63
|
+
runUpdate
|
|
64
|
+
} from "./chunk-QQHIVTXT.js";
|
|
65
|
+
import "./chunk-F53U6JQG.js";
|
|
66
|
+
import {
|
|
67
|
+
isAgentProviderId,
|
|
68
|
+
readConfig
|
|
69
|
+
} from "./chunk-WRUSDYYE.js";
|
|
59
70
|
import {
|
|
60
71
|
findNearestAlmanacDir,
|
|
61
72
|
getRepoAlmanacDir
|
|
@@ -1761,10 +1772,33 @@ function registerQueryCommands(program) {
|
|
|
1761
1772
|
|
|
1762
1773
|
// src/cli/register-setup-commands.ts
|
|
1763
1774
|
function registerSetupCommands(program) {
|
|
1764
|
-
program.command("
|
|
1775
|
+
const agents = program.command("agents").description("list supported AI agent providers and readiness");
|
|
1776
|
+
agents.command("list").description("show Claude, Codex, and Cursor provider status").action(async () => {
|
|
1777
|
+
emit(await runAgentsList());
|
|
1778
|
+
});
|
|
1779
|
+
program.command("set").description("configure codealmanac defaults").argument("<key>", "setting key, e.g. default-agent or model").argument("[value...]", "setting value").action(async (key, value) => {
|
|
1780
|
+
if (key === "default-agent") {
|
|
1781
|
+
emit(await runSetDefaultAgent({ provider: value[0] ?? "" }));
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
if (key === "model") {
|
|
1785
|
+
emit(await runSetAgentModel({
|
|
1786
|
+
provider: value[0] ?? "",
|
|
1787
|
+
model: value[1]
|
|
1788
|
+
}));
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
emit({
|
|
1792
|
+
stdout: "",
|
|
1793
|
+
stderr: "almanac: unknown setting. Use `default-agent` or `model`.\n",
|
|
1794
|
+
exitCode: 1
|
|
1795
|
+
});
|
|
1796
|
+
});
|
|
1797
|
+
program.command("setup").description("install the hook + CLAUDE.md guides (bare codealmanac alias)").option("-y, --yes", "skip prompts; install everything").option("--agent <agent>", "default agent: claude, codex, or cursor").option("--skip-hook", "opt out of the SessionEnd hook").option("--skip-guides", "opt out of the CLAUDE.md guides").action(
|
|
1765
1798
|
async (opts) => {
|
|
1766
1799
|
const result = await runSetup({
|
|
1767
1800
|
yes: opts.yes,
|
|
1801
|
+
agent: opts.agent,
|
|
1768
1802
|
skipHook: opts.skipHook,
|
|
1769
1803
|
skipGuides: opts.skipGuides
|
|
1770
1804
|
});
|
|
@@ -1869,8 +1903,19 @@ async function loadPrompt(name) {
|
|
|
1869
1903
|
}
|
|
1870
1904
|
|
|
1871
1905
|
// src/agent/sdk.ts
|
|
1906
|
+
import { spawn } from "child_process";
|
|
1872
1907
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
1873
1908
|
async function runAgent(opts) {
|
|
1909
|
+
const provider = opts.provider ?? "claude";
|
|
1910
|
+
if (provider === "codex") {
|
|
1911
|
+
return await runCodexAgent(opts);
|
|
1912
|
+
}
|
|
1913
|
+
if (provider === "cursor") {
|
|
1914
|
+
return await runCursorAgent(opts);
|
|
1915
|
+
}
|
|
1916
|
+
return await runClaudeAgent(opts);
|
|
1917
|
+
}
|
|
1918
|
+
async function runClaudeAgent(opts) {
|
|
1874
1919
|
const claudeExecutable = resolveClaudeExecutable();
|
|
1875
1920
|
const q = query({
|
|
1876
1921
|
prompt: opts.prompt,
|
|
@@ -1925,6 +1970,186 @@ async function runAgent(opts) {
|
|
|
1925
1970
|
}
|
|
1926
1971
|
return { success, cost, turns, result, sessionId, error: errorMsg };
|
|
1927
1972
|
}
|
|
1973
|
+
function combinedPrompt(opts) {
|
|
1974
|
+
const reviewerFallback = buildReviewerFallback(opts);
|
|
1975
|
+
return `${opts.systemPrompt}${reviewerFallback}
|
|
1976
|
+
|
|
1977
|
+
---
|
|
1978
|
+
|
|
1979
|
+
${opts.prompt}`;
|
|
1980
|
+
}
|
|
1981
|
+
function buildReviewerFallback(opts) {
|
|
1982
|
+
if ((opts.provider ?? "claude") === "claude") return "";
|
|
1983
|
+
const reviewer = opts.agents?.reviewer;
|
|
1984
|
+
if (reviewer === void 0) return "";
|
|
1985
|
+
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;
|
|
1986
|
+
}
|
|
1987
|
+
async function runCodexAgent(opts) {
|
|
1988
|
+
const args = [
|
|
1989
|
+
"exec",
|
|
1990
|
+
"--json",
|
|
1991
|
+
"--sandbox",
|
|
1992
|
+
"workspace-write",
|
|
1993
|
+
"--skip-git-repo-check",
|
|
1994
|
+
"-C",
|
|
1995
|
+
opts.cwd
|
|
1996
|
+
];
|
|
1997
|
+
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
1998
|
+
args.push("--model", opts.model);
|
|
1999
|
+
}
|
|
2000
|
+
args.push(combinedPrompt(opts));
|
|
2001
|
+
return await runJsonlCli({
|
|
2002
|
+
command: "codex",
|
|
2003
|
+
args,
|
|
2004
|
+
cwd: opts.cwd,
|
|
2005
|
+
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
2006
|
+
onMessage: opts.onMessage,
|
|
2007
|
+
parseFinal: parseCodexFinal
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
async function runCursorAgent(opts) {
|
|
2011
|
+
const args = [
|
|
2012
|
+
"--print",
|
|
2013
|
+
"--output-format",
|
|
2014
|
+
"stream-json",
|
|
2015
|
+
"--stream-partial-output",
|
|
2016
|
+
"--trust",
|
|
2017
|
+
"--workspace",
|
|
2018
|
+
opts.cwd
|
|
2019
|
+
];
|
|
2020
|
+
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
2021
|
+
args.push("--model", opts.model);
|
|
2022
|
+
}
|
|
2023
|
+
args.push(combinedPrompt(opts));
|
|
2024
|
+
return await runJsonlCli({
|
|
2025
|
+
command: "cursor-agent",
|
|
2026
|
+
args,
|
|
2027
|
+
cwd: opts.cwd,
|
|
2028
|
+
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
2029
|
+
onMessage: opts.onMessage,
|
|
2030
|
+
parseFinal: parseCursorFinal
|
|
2031
|
+
});
|
|
2032
|
+
}
|
|
2033
|
+
function runJsonlCli(opts) {
|
|
2034
|
+
return new Promise((resolve) => {
|
|
2035
|
+
const child = spawn(opts.command, opts.args, {
|
|
2036
|
+
cwd: opts.cwd,
|
|
2037
|
+
env: opts.env,
|
|
2038
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2039
|
+
});
|
|
2040
|
+
let stdoutBuf = "";
|
|
2041
|
+
let stderr = "";
|
|
2042
|
+
let cost = 0;
|
|
2043
|
+
let turns = 0;
|
|
2044
|
+
let result = "";
|
|
2045
|
+
let sessionId;
|
|
2046
|
+
let success = false;
|
|
2047
|
+
let finalSeen = false;
|
|
2048
|
+
let error;
|
|
2049
|
+
const observe = (msg) => {
|
|
2050
|
+
opts.onMessage?.(msg);
|
|
2051
|
+
if (sessionId === void 0 && typeof msg.session_id === "string" && msg.session_id.length > 0) {
|
|
2052
|
+
sessionId = msg.session_id;
|
|
2053
|
+
}
|
|
2054
|
+
const final = opts.parseFinal(msg);
|
|
2055
|
+
if (final === null) return;
|
|
2056
|
+
finalSeen = true;
|
|
2057
|
+
if (final.cost !== void 0) cost = final.cost;
|
|
2058
|
+
if (final.turns !== void 0) turns = final.turns;
|
|
2059
|
+
if (final.result !== void 0) result = final.result;
|
|
2060
|
+
if (final.sessionId !== void 0) sessionId = final.sessionId;
|
|
2061
|
+
if (final.success !== void 0) success = final.success;
|
|
2062
|
+
if (final.error !== void 0) error = final.error;
|
|
2063
|
+
};
|
|
2064
|
+
const flushLines = () => {
|
|
2065
|
+
let idx = stdoutBuf.indexOf("\n");
|
|
2066
|
+
while (idx !== -1) {
|
|
2067
|
+
const rawLine = stdoutBuf.slice(0, idx);
|
|
2068
|
+
stdoutBuf = stdoutBuf.slice(idx + 1);
|
|
2069
|
+
const line = rawLine.trim();
|
|
2070
|
+
if (line.length > 0) {
|
|
2071
|
+
try {
|
|
2072
|
+
const parsed = JSON.parse(line);
|
|
2073
|
+
observe(parsed);
|
|
2074
|
+
} catch {
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
idx = stdoutBuf.indexOf("\n");
|
|
2078
|
+
}
|
|
2079
|
+
};
|
|
2080
|
+
child.stdout.on("data", (chunk) => {
|
|
2081
|
+
stdoutBuf += chunk.toString("utf8");
|
|
2082
|
+
flushLines();
|
|
2083
|
+
});
|
|
2084
|
+
child.stderr.on("data", (chunk) => {
|
|
2085
|
+
stderr += chunk.toString("utf8");
|
|
2086
|
+
});
|
|
2087
|
+
child.on("error", (err) => {
|
|
2088
|
+
resolve({
|
|
2089
|
+
success: false,
|
|
2090
|
+
cost,
|
|
2091
|
+
turns,
|
|
2092
|
+
result,
|
|
2093
|
+
sessionId,
|
|
2094
|
+
error: err.code === "ENOENT" ? `${opts.command} not found on PATH` : err.message
|
|
2095
|
+
});
|
|
2096
|
+
});
|
|
2097
|
+
child.on("close", (code) => {
|
|
2098
|
+
flushLines();
|
|
2099
|
+
if (stdoutBuf.trim().length > 0) {
|
|
2100
|
+
try {
|
|
2101
|
+
observe(JSON.parse(stdoutBuf.trim()));
|
|
2102
|
+
} catch {
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
if (code === 0 && finalSeen && success) {
|
|
2106
|
+
resolve({ success, cost, turns, result, sessionId });
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
const firstStderr = stderr.trim().split("\n")[0];
|
|
2110
|
+
resolve({
|
|
2111
|
+
success: false,
|
|
2112
|
+
cost,
|
|
2113
|
+
turns,
|
|
2114
|
+
result,
|
|
2115
|
+
sessionId,
|
|
2116
|
+
error: error ?? (firstStderr !== void 0 && firstStderr.length > 0 ? firstStderr : `${opts.command} exited ${code ?? 1}`)
|
|
2117
|
+
});
|
|
2118
|
+
});
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
function parseCodexFinal(msg) {
|
|
2122
|
+
if (msg.type === "item.completed") {
|
|
2123
|
+
const item = msg.item;
|
|
2124
|
+
if (item !== null && typeof item === "object") {
|
|
2125
|
+
const obj = item;
|
|
2126
|
+
if (obj.type === "agent_message" && typeof obj.text === "string") {
|
|
2127
|
+
return { result: obj.text };
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
return null;
|
|
2131
|
+
}
|
|
2132
|
+
if (msg.type === "turn.completed") {
|
|
2133
|
+
return { success: true };
|
|
2134
|
+
}
|
|
2135
|
+
if (msg.type === "turn.failed" || msg.type === "error") {
|
|
2136
|
+
return {
|
|
2137
|
+
success: false,
|
|
2138
|
+
error: typeof msg.message === "string" ? msg.message : typeof msg.error === "string" ? msg.error : "codex turn failed"
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
return null;
|
|
2142
|
+
}
|
|
2143
|
+
function parseCursorFinal(msg) {
|
|
2144
|
+
if (msg.type !== "result") return null;
|
|
2145
|
+
const isError = msg.is_error === true || msg.subtype !== "success";
|
|
2146
|
+
return {
|
|
2147
|
+
success: !isError,
|
|
2148
|
+
result: typeof msg.result === "string" ? msg.result : "",
|
|
2149
|
+
sessionId: typeof msg.session_id === "string" ? msg.session_id : void 0,
|
|
2150
|
+
error: isError ? typeof msg.result === "string" ? msg.result : `cursor result: ${String(msg.subtype ?? "error")}` : void 0
|
|
2151
|
+
};
|
|
2152
|
+
}
|
|
1928
2153
|
|
|
1929
2154
|
// src/commands/init.ts
|
|
1930
2155
|
import { existsSync as existsSync4 } from "fs";
|
|
@@ -2069,8 +2294,21 @@ and optional \`files:\`. The rest is prose.
|
|
|
2069
2294
|
// src/commands/bootstrap.ts
|
|
2070
2295
|
var BOOTSTRAP_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash"];
|
|
2071
2296
|
async function runBootstrap(options) {
|
|
2297
|
+
const providerResolution = await resolveAgentSelection({
|
|
2298
|
+
agent: options.agent,
|
|
2299
|
+
model: options.model
|
|
2300
|
+
});
|
|
2301
|
+
if (!providerResolution.ok) {
|
|
2302
|
+
return {
|
|
2303
|
+
stdout: "",
|
|
2304
|
+
stderr: `almanac: ${providerResolution.error}
|
|
2305
|
+
`,
|
|
2306
|
+
exitCode: 1
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
const { provider, model } = providerResolution;
|
|
2072
2310
|
try {
|
|
2073
|
-
await
|
|
2311
|
+
await assertAgentAuth({ provider, spawnCli: options.spawnCli });
|
|
2074
2312
|
} catch (err) {
|
|
2075
2313
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2076
2314
|
return {
|
|
@@ -2137,7 +2375,8 @@ async function runBootstrap(options) {
|
|
|
2137
2375
|
prompt: userPrompt,
|
|
2138
2376
|
allowedTools: BOOTSTRAP_TOOLS,
|
|
2139
2377
|
cwd: repoRoot,
|
|
2140
|
-
|
|
2378
|
+
provider,
|
|
2379
|
+
model,
|
|
2141
2380
|
onMessage
|
|
2142
2381
|
});
|
|
2143
2382
|
} finally {
|
|
@@ -2160,6 +2399,19 @@ async function runBootstrap(options) {
|
|
|
2160
2399
|
exitCode: 1
|
|
2161
2400
|
};
|
|
2162
2401
|
}
|
|
2402
|
+
async function resolveAgentSelection(args) {
|
|
2403
|
+
const config = await readConfig();
|
|
2404
|
+
const rawProvider = args.agent ?? config.agent.default;
|
|
2405
|
+
if (!isAgentProviderId(rawProvider)) {
|
|
2406
|
+
return {
|
|
2407
|
+
ok: false,
|
|
2408
|
+
error: `unknown agent '${rawProvider}'. Expected one of: claude, codex, cursor.`
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
const configuredModel = config.agent.models[rawProvider] ?? void 0;
|
|
2412
|
+
const model = args.model !== void 0 ? args.model : configuredModel === null ? void 0 : configuredModel;
|
|
2413
|
+
return { ok: true, provider: rawProvider, model };
|
|
2414
|
+
}
|
|
2163
2415
|
function formatFinalLine(result, logPath, repoRoot) {
|
|
2164
2416
|
const status = result.success ? "done" : "failed";
|
|
2165
2417
|
const rel = relative(repoRoot, logPath);
|
|
@@ -2210,17 +2462,23 @@ var StreamingFormatter = class {
|
|
|
2210
2462
|
this.currentAgent = name;
|
|
2211
2463
|
}
|
|
2212
2464
|
handle(msg) {
|
|
2213
|
-
if (msg
|
|
2465
|
+
if (!isRecord(msg)) return;
|
|
2466
|
+
if (msg.type === "assistant" && isRecord(msg.message)) {
|
|
2467
|
+
const content = msg.message.content;
|
|
2468
|
+
if (!Array.isArray(content)) return;
|
|
2214
2469
|
for (const block of msg.message.content) {
|
|
2215
|
-
if (block.type !== "tool_use") continue;
|
|
2470
|
+
if (!isRecord(block) || block.type !== "tool_use") continue;
|
|
2471
|
+
if (typeof block.name !== "string") continue;
|
|
2216
2472
|
this.handleToolUse(block.name, block.input);
|
|
2217
2473
|
}
|
|
2218
2474
|
return;
|
|
2219
2475
|
}
|
|
2220
2476
|
if (msg.type === "result") {
|
|
2221
2477
|
const status = msg.subtype === "success" ? "done" : `failed (${msg.subtype})`;
|
|
2478
|
+
const cost = typeof msg.total_cost_usd === "number" ? msg.total_cost_usd : 0;
|
|
2479
|
+
const turns = typeof msg.num_turns === "number" ? msg.num_turns : 0;
|
|
2222
2480
|
this.sink.write(
|
|
2223
|
-
`[${status}] cost: $${
|
|
2481
|
+
`[${status}] cost: $${cost.toFixed(3)}, turns: ${turns}
|
|
2224
2482
|
`
|
|
2225
2483
|
);
|
|
2226
2484
|
return;
|
|
@@ -2292,6 +2550,9 @@ function stringField(input, key) {
|
|
|
2292
2550
|
const value = input[key];
|
|
2293
2551
|
return typeof value === "string" ? value : void 0;
|
|
2294
2552
|
}
|
|
2553
|
+
function isRecord(value) {
|
|
2554
|
+
return value !== null && typeof value === "object";
|
|
2555
|
+
}
|
|
2295
2556
|
|
|
2296
2557
|
// src/commands/capture.ts
|
|
2297
2558
|
import { createHash } from "crypto";
|
|
@@ -2307,8 +2568,21 @@ var WRITER_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Agent"];
|
|
|
2307
2568
|
var REVIEWER_TOOLS = ["Read", "Grep", "Glob", "Bash"];
|
|
2308
2569
|
var REVIEWER_DESCRIPTION = "Reviews proposed wiki changes against the full knowledge base for cohesion, duplication, missing links, notability, and writing conventions.";
|
|
2309
2570
|
async function runCapture(options) {
|
|
2571
|
+
const providerResolution = await resolveAgentSelection2({
|
|
2572
|
+
agent: options.agent,
|
|
2573
|
+
model: options.model
|
|
2574
|
+
});
|
|
2575
|
+
if (!providerResolution.ok) {
|
|
2576
|
+
return {
|
|
2577
|
+
stdout: "",
|
|
2578
|
+
stderr: `almanac: ${providerResolution.error}
|
|
2579
|
+
`,
|
|
2580
|
+
exitCode: 1
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
const { provider, model } = providerResolution;
|
|
2310
2584
|
try {
|
|
2311
|
-
await
|
|
2585
|
+
await assertAgentAuth({ provider, spawnCli: options.spawnCli });
|
|
2312
2586
|
} catch (err) {
|
|
2313
2587
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2314
2588
|
return {
|
|
@@ -2387,7 +2661,8 @@ Working directory: ${repoRoot}.`;
|
|
|
2387
2661
|
allowedTools: WRITER_TOOLS,
|
|
2388
2662
|
agents,
|
|
2389
2663
|
cwd: repoRoot,
|
|
2390
|
-
|
|
2664
|
+
provider,
|
|
2665
|
+
model,
|
|
2391
2666
|
// Capture sessions can touch many pages; give it more headroom than
|
|
2392
2667
|
// bootstrap. The SDK treats `maxTurns` as a hard stop — better to
|
|
2393
2668
|
// overshoot than to cut off mid-review.
|
|
@@ -2416,6 +2691,19 @@ Working directory: ${repoRoot}.`;
|
|
|
2416
2691
|
exitCode: 0
|
|
2417
2692
|
};
|
|
2418
2693
|
}
|
|
2694
|
+
async function resolveAgentSelection2(args) {
|
|
2695
|
+
const config = await readConfig();
|
|
2696
|
+
const rawProvider = args.agent ?? config.agent.default;
|
|
2697
|
+
if (!isAgentProviderId(rawProvider)) {
|
|
2698
|
+
return {
|
|
2699
|
+
ok: false,
|
|
2700
|
+
error: `unknown agent '${rawProvider}'. Expected one of: claude, codex, cursor.`
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
const configuredModel = config.agent.models[rawProvider] ?? void 0;
|
|
2704
|
+
const model = args.model !== void 0 ? args.model : configuredModel === null ? void 0 : configuredModel;
|
|
2705
|
+
return { ok: true, provider: rawProvider, model };
|
|
2706
|
+
}
|
|
2419
2707
|
async function resolveTranscript(args) {
|
|
2420
2708
|
if (args.explicit !== void 0 && args.explicit.length > 0) {
|
|
2421
2709
|
if (!existsSync6(args.explicit)) {
|
|
@@ -2594,18 +2882,19 @@ async function runReindex(options) {
|
|
|
2594
2882
|
function registerWikiLifecycleCommands(program) {
|
|
2595
2883
|
program.command("bootstrap").description(
|
|
2596
2884
|
"scaffold a wiki in this repo via an AI agent (requires ANTHROPIC_API_KEY or Claude subscription)"
|
|
2597
|
-
).option("--quiet", "suppress per-tool streaming; print only the final line").option("--model <model>", "override the agent model").option("--force", "overwrite an existing populated wiki (default: refuse)").action(
|
|
2885
|
+
).option("--quiet", "suppress per-tool streaming; print only the final line").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").option("--force", "overwrite an existing populated wiki (default: refuse)").action(
|
|
2598
2886
|
async (opts) => {
|
|
2599
2887
|
const result = await runBootstrap({
|
|
2600
2888
|
cwd: process.cwd(),
|
|
2601
2889
|
quiet: opts.quiet,
|
|
2890
|
+
agent: opts.agent,
|
|
2602
2891
|
model: opts.model,
|
|
2603
2892
|
force: opts.force
|
|
2604
2893
|
});
|
|
2605
2894
|
emit(result);
|
|
2606
2895
|
}
|
|
2607
2896
|
);
|
|
2608
|
-
program.command("capture [transcript]").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--model <model>", "override the agent model").action(
|
|
2897
|
+
program.command("capture [transcript]").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").action(
|
|
2609
2898
|
async (transcript, opts) => {
|
|
2610
2899
|
await autoRegisterIfNeeded(process.cwd());
|
|
2611
2900
|
const result = await runCapture({
|
|
@@ -2613,14 +2902,17 @@ function registerWikiLifecycleCommands(program) {
|
|
|
2613
2902
|
transcriptPath: transcript,
|
|
2614
2903
|
sessionId: opts.session,
|
|
2615
2904
|
quiet: opts.quiet,
|
|
2905
|
+
agent: opts.agent,
|
|
2616
2906
|
model: opts.model
|
|
2617
2907
|
});
|
|
2618
2908
|
emit(result);
|
|
2619
2909
|
}
|
|
2620
2910
|
);
|
|
2621
2911
|
const hook = program.command("hook").description("manage the SessionEnd auto-capture hook");
|
|
2622
|
-
hook.command("install").description("add a SessionEnd entry that runs 'almanac capture' on session end").action(async () => {
|
|
2623
|
-
const result = await runHookInstall(
|
|
2912
|
+
hook.command("install").description("add a SessionEnd entry that runs 'almanac capture' on session end").option("--source <source>", "claude, codex, cursor, or all").action(async (opts) => {
|
|
2913
|
+
const result = await runHookInstall({
|
|
2914
|
+
source: normalizeHookSource(opts.source)
|
|
2915
|
+
});
|
|
2624
2916
|
emit(result);
|
|
2625
2917
|
});
|
|
2626
2918
|
hook.command("uninstall").description("remove codealmanac's SessionEnd entry; leaves foreign entries alone").action(async () => {
|
|
@@ -2641,6 +2933,12 @@ function registerWikiLifecycleCommands(program) {
|
|
|
2641
2933
|
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
2642
2934
|
});
|
|
2643
2935
|
}
|
|
2936
|
+
function normalizeHookSource(source) {
|
|
2937
|
+
if (source === "claude" || source === "codex" || source === "cursor" || source === "all") {
|
|
2938
|
+
return source;
|
|
2939
|
+
}
|
|
2940
|
+
return void 0;
|
|
2941
|
+
}
|
|
2644
2942
|
|
|
2645
2943
|
// src/cli/register-commands.ts
|
|
2646
2944
|
function registerCommands(program) {
|
|
@@ -2652,4 +2950,4 @@ function registerCommands(program) {
|
|
|
2652
2950
|
export {
|
|
2653
2951
|
registerCommands
|
|
2654
2952
|
};
|
|
2655
|
-
//# sourceMappingURL=register-commands-
|
|
2953
|
+
//# sourceMappingURL=register-commands-7SKQLQW4.js.map
|