codealmanac 0.2.2 → 0.2.4
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 +19 -6
- package/dist/agents-4Y7X24WW.js +25 -0
- package/dist/chunk-BF2J4XTC.js +766 -0
- package/dist/chunk-BF2J4XTC.js.map +1 -0
- package/dist/{chunk-B2AGSRXL.js → chunk-CW4HRLMS.js} +88 -7
- package/dist/chunk-CW4HRLMS.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-MX2EW5MR.js → chunk-H6QKCB7M.js} +2 -2
- 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-ZDJSJIB6.js → chunk-QRK3JLFX.js} +131 -15
- package/dist/chunk-QRK3JLFX.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/chunk-UU6FBRQO.js +187 -0
- package/dist/chunk-UU6FBRQO.js.map +1 -0
- package/dist/{cli-3XAVBTYG.js → cli-MYMZ66EN.js} +123 -32
- package/dist/cli-MYMZ66EN.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/config-ML2RCR7J.js +16 -0
- package/dist/{doctor-3BYSF3JD.js → doctor-W5KQQLAX.js} +6 -6
- package/dist/{register-commands-7QCIENRZ.js → register-commands-XTK2G2FB.js} +293 -393
- package/dist/register-commands-XTK2G2FB.js.map +1 -0
- package/dist/{uninstall-FDIOBAAR.js → uninstall-N7JY7ZV2.js} +5 -5
- package/dist/{update-RAF7QRYF.js → update-P2IPG7RO.js} +3 -3
- package/guides/mini.md +1 -1
- package/guides/reference.md +68 -9
- package/package.json +1 -1
- package/dist/agents-A4II4YJC.js +0 -15
- package/dist/auth-S5DVUIUJ.js +0 -18
- package/dist/chunk-B2AGSRXL.js.map +0 -1
- package/dist/chunk-P3LDTCLB.js.map +0 -1
- package/dist/chunk-R3URPHGH.js +0 -194
- package/dist/chunk-R3URPHGH.js.map +0 -1
- package/dist/chunk-SSYMRT4I.js +0 -126
- package/dist/chunk-SSYMRT4I.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-ZDJSJIB6.js.map +0 -1
- package/dist/cli-3XAVBTYG.js.map +0 -1
- package/dist/register-commands-7QCIENRZ.js.map +0 -1
- /package/dist/{agents-A4II4YJC.js.map → agents-4Y7X24WW.js.map} +0 -0
- /package/dist/{chunk-MX2EW5MR.js.map → chunk-H6QKCB7M.js.map} +0 -0
- /package/dist/{auth-S5DVUIUJ.js.map → config-ML2RCR7J.js.map} +0 -0
- /package/dist/{doctor-3BYSF3JD.js.map → doctor-W5KQQLAX.js.map} +0 -0
- /package/dist/{uninstall-FDIOBAAR.js.map → uninstall-N7JY7ZV2.js.map} +0 -0
- /package/dist/{update-RAF7QRYF.js.map → update-P2IPG7RO.js.map} +0 -0
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
collectOption,
|
|
4
|
+
deprecationWarning,
|
|
4
5
|
emit,
|
|
5
6
|
parsePositiveInt,
|
|
6
|
-
readStdin
|
|
7
|
-
|
|
7
|
+
readStdin,
|
|
8
|
+
withWarning
|
|
9
|
+
} from "./chunk-H37GKBWI.js";
|
|
8
10
|
import {
|
|
9
|
-
|
|
11
|
+
runAgentsDoctor,
|
|
10
12
|
runAgentsList,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
runAgentsModel,
|
|
14
|
+
runAgentsUse,
|
|
15
|
+
runDeprecatedSetAgentModel,
|
|
16
|
+
runDeprecatedSetDefaultAgent
|
|
17
|
+
} from "./chunk-UU6FBRQO.js";
|
|
18
|
+
import {
|
|
19
|
+
runConfigGet,
|
|
20
|
+
runConfigList,
|
|
21
|
+
runConfigSet,
|
|
22
|
+
runConfigUnset
|
|
23
|
+
} from "./chunk-TT6ZP4GS.js";
|
|
14
24
|
import {
|
|
15
25
|
addEntry,
|
|
16
26
|
ancestorsInFile,
|
|
@@ -36,8 +46,8 @@ import {
|
|
|
36
46
|
} from "./chunk-KQUVMF27.js";
|
|
37
47
|
import {
|
|
38
48
|
runDoctor
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
49
|
+
} from "./chunk-CW4HRLMS.js";
|
|
50
|
+
import "./chunk-TILAKDN6.js";
|
|
41
51
|
import "./chunk-4CODZRHH.js";
|
|
42
52
|
import {
|
|
43
53
|
BLUE,
|
|
@@ -47,26 +57,30 @@ import {
|
|
|
47
57
|
} from "./chunk-FM3VRDK7.js";
|
|
48
58
|
import {
|
|
49
59
|
runUninstall
|
|
50
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-H6QKCB7M.js";
|
|
51
61
|
import {
|
|
52
62
|
runSetup
|
|
53
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-QRK3JLFX.js";
|
|
54
64
|
import {
|
|
55
65
|
runHookInstall,
|
|
56
66
|
runHookStatus,
|
|
57
67
|
runHookUninstall
|
|
58
68
|
} from "./chunk-447U3GQJ.js";
|
|
59
69
|
import {
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
DEFAULT_AGENT_MODEL,
|
|
71
|
+
assertAgentAuth,
|
|
72
|
+
getAgentProvider,
|
|
73
|
+
getProviderDefaultModel,
|
|
74
|
+
parseAgentSelection
|
|
75
|
+
} from "./chunk-BF2J4XTC.js";
|
|
62
76
|
import {
|
|
63
77
|
runUpdate
|
|
64
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-MRRX4UQB.js";
|
|
65
79
|
import "./chunk-F53U6JQG.js";
|
|
66
80
|
import {
|
|
67
81
|
isAgentProviderId,
|
|
68
82
|
readConfig
|
|
69
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-P5WGG4FJ.js";
|
|
70
84
|
import {
|
|
71
85
|
findNearestAlmanacDir,
|
|
72
86
|
getRepoAlmanacDir
|
|
@@ -1695,11 +1709,11 @@ function registerQueryCommands(program) {
|
|
|
1695
1709
|
"--mentions <path>",
|
|
1696
1710
|
"pages referencing this path; matches exact file, trailing-slash folders, and any file under a folder prefix"
|
|
1697
1711
|
).option("--since <duration>", "updated within duration, by file mtime (e.g. 2w, 30d)").option("--stale <duration>", "NOT updated within duration, by file mtime").option("--orphan", "pages with no topics").option("--include-archive", "include archived pages").option("--archived", "archived pages only").option("--wiki <name>", "target a specific registered wiki").option("--json", "emit structured JSON").option("--limit <n>", "cap results", parsePositiveInt).action(
|
|
1698
|
-
async (
|
|
1712
|
+
async (query, opts) => {
|
|
1699
1713
|
await autoRegisterIfNeeded(process.cwd());
|
|
1700
1714
|
const result = await runSearch({
|
|
1701
1715
|
cwd: process.cwd(),
|
|
1702
|
-
query
|
|
1716
|
+
query,
|
|
1703
1717
|
topics: opts.topic ?? [],
|
|
1704
1718
|
mentions: opts.mentions,
|
|
1705
1719
|
since: opts.since,
|
|
@@ -1714,7 +1728,7 @@ function registerQueryCommands(program) {
|
|
|
1714
1728
|
emit(result);
|
|
1715
1729
|
}
|
|
1716
1730
|
);
|
|
1717
|
-
program.command("show [slug]").description("print a page (metadata + body; flags to narrow)").option("--stdin", "read slugs from stdin (one per line)").option("--wiki <name>", "target a specific registered wiki").option("--json", "structured JSON (overrides other view/field flags)").option("--
|
|
1731
|
+
program.command("show [slug]").description("print a page (metadata + body; flags to narrow)").option("--stdin", "read slugs from stdin (one per line)").option("--wiki <name>", "target a specific registered wiki").option("--json", "structured JSON (overrides other view/field flags)").option("--body", "body only").option("--raw", "deprecated alias for --body").option("--meta", "metadata only, no body").option("--lead", "first paragraph of the body only").option("--title", "print title").option("--topics", "print topics").option("--files", "print file refs").option("--links", "print outgoing wikilinks").option("--backlinks", "print incoming wikilinks").option("--xwiki", "print cross-wiki links").option("--lineage", "print archived_at / supersedes / superseded_by").option("--updated", "print updated timestamp").option("--path", "print absolute file path").action(
|
|
1718
1732
|
async (slug, opts) => {
|
|
1719
1733
|
await autoRegisterIfNeeded(process.cwd());
|
|
1720
1734
|
const result = await runShow({
|
|
@@ -1737,7 +1751,10 @@ function registerQueryCommands(program) {
|
|
|
1737
1751
|
updated: opts.updated,
|
|
1738
1752
|
path: opts.path
|
|
1739
1753
|
});
|
|
1740
|
-
emit(
|
|
1754
|
+
emit(opts.raw === true ? withWarning(
|
|
1755
|
+
result,
|
|
1756
|
+
deprecationWarning("almanac show <slug> --raw", "almanac show <slug> --body")
|
|
1757
|
+
) : result);
|
|
1741
1758
|
}
|
|
1742
1759
|
);
|
|
1743
1760
|
program.command("health").description("report graph integrity problems").option("--topic <name>", "scope to a topic + its descendants").option("--stale <duration>", "stale threshold (default 90d)").option("--stdin", "read page slugs from stdin (limit to these pages)").option("--json", "emit structured JSON").option("--wiki <name>", "target a specific registered wiki").action(
|
|
@@ -1776,13 +1793,39 @@ function registerSetupCommands(program) {
|
|
|
1776
1793
|
agents.command("list").description("show Claude, Codex, and Cursor provider status").action(async () => {
|
|
1777
1794
|
emit(await runAgentsList());
|
|
1778
1795
|
});
|
|
1796
|
+
agents.command("doctor").description("diagnose supported AI agent providers").action(async () => {
|
|
1797
|
+
emit(await runAgentsDoctor());
|
|
1798
|
+
});
|
|
1799
|
+
agents.command("use").description("set the default AI agent provider").argument("<provider>", "claude, codex, cursor, or claude/<model>").action(async (provider) => {
|
|
1800
|
+
emit(await runAgentsUse({ provider }));
|
|
1801
|
+
});
|
|
1802
|
+
agents.command("model").description("set or reset a provider model").argument("<provider>", "claude, codex, or cursor").argument("[model]", "provider-specific model id").option("--default", "reset to provider default").action(async (provider, model, opts) => {
|
|
1803
|
+
emit(await runAgentsModel({
|
|
1804
|
+
provider,
|
|
1805
|
+
model,
|
|
1806
|
+
defaultModel: opts.default
|
|
1807
|
+
}));
|
|
1808
|
+
});
|
|
1809
|
+
const config = program.command("config").description("read and write codealmanac settings");
|
|
1810
|
+
config.command("list").description("show supported config keys").option("--json", "emit structured JSON").option("--show-origin", "show whether each value came from file or default").action(async (opts) => {
|
|
1811
|
+
emit(await runConfigList(opts));
|
|
1812
|
+
});
|
|
1813
|
+
config.command("get").description("print one config value").argument("<key>", "config key").option("--json", "emit structured JSON").option("--show-origin", "show whether the value came from file or default").action(async (key, opts) => {
|
|
1814
|
+
emit(await runConfigGet({ key, ...opts }));
|
|
1815
|
+
});
|
|
1816
|
+
config.command("set").description("set one config value").argument("<key>", "config key").argument("<value>", "config value").option("--project", "write .almanac/config.toml for this repo").action(async (key, value, opts) => {
|
|
1817
|
+
emit(await runConfigSet({ key, value, project: opts.project }));
|
|
1818
|
+
});
|
|
1819
|
+
config.command("unset").description("restore one config value to default").argument("<key>", "config key").option("--project", "remove from .almanac/config.toml for this repo").action(async (key, opts) => {
|
|
1820
|
+
emit(await runConfigUnset({ key, project: opts.project }));
|
|
1821
|
+
});
|
|
1779
1822
|
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
1823
|
if (key === "default-agent") {
|
|
1781
|
-
emit(await
|
|
1824
|
+
emit(await runDeprecatedSetDefaultAgent({ provider: value[0] ?? "" }));
|
|
1782
1825
|
return;
|
|
1783
1826
|
}
|
|
1784
1827
|
if (key === "model") {
|
|
1785
|
-
emit(await
|
|
1828
|
+
emit(await runDeprecatedSetAgentModel({
|
|
1786
1829
|
provider: value[0] ?? "",
|
|
1787
1830
|
model: value[1]
|
|
1788
1831
|
}));
|
|
@@ -1794,11 +1837,12 @@ function registerSetupCommands(program) {
|
|
|
1794
1837
|
exitCode: 1
|
|
1795
1838
|
});
|
|
1796
1839
|
});
|
|
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(
|
|
1840
|
+
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("--model <model>", "default model for the selected agent").option("--skip-hook", "opt out of the SessionEnd hook").option("--skip-guides", "opt out of the CLAUDE.md guides").action(
|
|
1798
1841
|
async (opts) => {
|
|
1799
1842
|
const result = await runSetup({
|
|
1800
1843
|
yes: opts.yes,
|
|
1801
1844
|
agent: opts.agent,
|
|
1845
|
+
model: opts.model,
|
|
1802
1846
|
skipHook: opts.skipHook,
|
|
1803
1847
|
skipGuides: opts.skipGuides
|
|
1804
1848
|
});
|
|
@@ -1821,10 +1865,10 @@ function registerSetupCommands(program) {
|
|
|
1821
1865
|
"silence the update banner for the current `latest_version` without installing"
|
|
1822
1866
|
).option("--check", "force a registry check now (bypasses the 24h cache); no install").option(
|
|
1823
1867
|
"--enable-notifier",
|
|
1824
|
-
"
|
|
1868
|
+
"deprecated: use `almanac config set update_notifier true`"
|
|
1825
1869
|
).option(
|
|
1826
1870
|
"--disable-notifier",
|
|
1827
|
-
"
|
|
1871
|
+
"deprecated: use `almanac config set update_notifier false`"
|
|
1828
1872
|
).action(
|
|
1829
1873
|
async (opts) => {
|
|
1830
1874
|
const result = await runUpdate({
|
|
@@ -1902,277 +1946,74 @@ async function loadPrompt(name) {
|
|
|
1902
1946
|
return readFile4(path.join(dir, `${name}.md`), "utf8");
|
|
1903
1947
|
}
|
|
1904
1948
|
|
|
1905
|
-
// src/agent/
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
const
|
|
1911
|
-
if (provider ===
|
|
1912
|
-
return
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
}
|
|
1917
|
-
return await runClaudeAgent(opts);
|
|
1918
|
-
}
|
|
1919
|
-
async function runClaudeAgent(opts) {
|
|
1920
|
-
const claudeExecutable = resolveClaudeExecutable();
|
|
1921
|
-
const q = query({
|
|
1922
|
-
prompt: opts.prompt,
|
|
1923
|
-
options: {
|
|
1924
|
-
systemPrompt: opts.systemPrompt,
|
|
1925
|
-
allowedTools: opts.allowedTools,
|
|
1926
|
-
agents: opts.agents ?? {},
|
|
1927
|
-
cwd: opts.cwd,
|
|
1928
|
-
model: opts.model ?? DEFAULT_AGENT_MODEL,
|
|
1929
|
-
maxTurns: opts.maxTurns ?? 100,
|
|
1930
|
-
...claudeExecutable !== void 0 ? { pathToClaudeCodeExecutable: claudeExecutable } : {},
|
|
1931
|
-
env: {
|
|
1932
|
-
...process.env,
|
|
1933
|
-
CODEALMANAC_INTERNAL_SESSION: "1"
|
|
1934
|
-
},
|
|
1935
|
-
// REQUIRED for streaming text deltas. Without it, `stream_event`
|
|
1936
|
-
// messages never fire and the CLI has no progress visibility during
|
|
1937
|
-
// long turns. See docs/research/agent-sdk.md §12 pitfall #1.
|
|
1938
|
-
includePartialMessages: true
|
|
1939
|
-
}
|
|
1940
|
-
});
|
|
1941
|
-
let cost = 0;
|
|
1942
|
-
let turns = 0;
|
|
1943
|
-
let result = "";
|
|
1944
|
-
let sessionId;
|
|
1945
|
-
let success = false;
|
|
1946
|
-
let errorMsg;
|
|
1947
|
-
try {
|
|
1948
|
-
for await (const msg of q) {
|
|
1949
|
-
opts.onMessage?.(msg);
|
|
1950
|
-
if (sessionId === void 0 && typeof msg.session_id === "string") {
|
|
1951
|
-
sessionId = msg.session_id;
|
|
1952
|
-
}
|
|
1953
|
-
if (msg.type === "result") {
|
|
1954
|
-
cost = msg.total_cost_usd;
|
|
1955
|
-
turns = msg.num_turns;
|
|
1956
|
-
if (msg.subtype === "success") {
|
|
1957
|
-
success = true;
|
|
1958
|
-
result = msg.result;
|
|
1959
|
-
} else {
|
|
1960
|
-
success = false;
|
|
1961
|
-
errorMsg = // `SDKResultError` variants don't carry a `result` string; the
|
|
1962
|
-
// useful detail lives in `errors` (array of strings) or the
|
|
1963
|
-
// subtype itself (e.g. "error_max_turns").
|
|
1964
|
-
(msg.errors?.join("; ") ?? "") || `agent error: ${msg.subtype}`;
|
|
1965
|
-
}
|
|
1966
|
-
}
|
|
1967
|
-
}
|
|
1968
|
-
} catch (err) {
|
|
1969
|
-
errorMsg = err instanceof Error ? err.message : String(err);
|
|
1970
|
-
success = false;
|
|
1949
|
+
// src/agent/selection.ts
|
|
1950
|
+
async function resolveAgentSelection(args) {
|
|
1951
|
+
const config = await readConfig({ cwd: args.cwd });
|
|
1952
|
+
const rawAgent = args.agent ?? process.env.ALMANAC_AGENT ?? config.agent.default;
|
|
1953
|
+
const agentSource = args.agent !== void 0 ? "flag" : process.env.ALMANAC_AGENT !== void 0 ? "env" : "config";
|
|
1954
|
+
const parsed = parseAgentSelection(rawAgent);
|
|
1955
|
+
if (parsed.provider === null || !isAgentProviderId(parsed.provider)) {
|
|
1956
|
+
return {
|
|
1957
|
+
ok: false,
|
|
1958
|
+
error: `unknown agent '${rawAgent}'. Expected one of: claude, codex, cursor.`
|
|
1959
|
+
};
|
|
1971
1960
|
}
|
|
1972
|
-
|
|
1961
|
+
const provider = parsed.provider;
|
|
1962
|
+
const configuredModel = config.agent.models[provider] ?? void 0;
|
|
1963
|
+
const model = args.model !== void 0 ? args.model : parsed.model !== void 0 && agentSource === "flag" ? parsed.model : process.env.ALMANAC_MODEL !== void 0 ? process.env.ALMANAC_MODEL : parsed.model !== void 0 ? parsed.model : configuredModel === null ? void 0 : configuredModel;
|
|
1964
|
+
return { ok: true, provider, model };
|
|
1973
1965
|
}
|
|
1974
|
-
function combinedPrompt(opts) {
|
|
1975
|
-
const reviewerFallback = buildReviewerFallback(opts);
|
|
1976
|
-
return `${opts.systemPrompt}${reviewerFallback}
|
|
1977
1966
|
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
}
|
|
1988
|
-
async function runCodexAgent(opts) {
|
|
1989
|
-
const args = [
|
|
1990
|
-
"exec",
|
|
1991
|
-
"--json",
|
|
1992
|
-
"--sandbox",
|
|
1993
|
-
"workspace-write",
|
|
1994
|
-
"--skip-git-repo-check",
|
|
1995
|
-
"-C",
|
|
1996
|
-
opts.cwd
|
|
1997
|
-
];
|
|
1998
|
-
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
1999
|
-
args.push("--model", opts.model);
|
|
2000
|
-
}
|
|
2001
|
-
args.push(combinedPrompt(opts));
|
|
2002
|
-
return await runJsonlCli({
|
|
2003
|
-
command: "codex",
|
|
2004
|
-
args,
|
|
2005
|
-
cwd: opts.cwd,
|
|
2006
|
-
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
2007
|
-
onMessage: opts.onMessage,
|
|
2008
|
-
parseFinal: parseCodexFinal
|
|
2009
|
-
});
|
|
2010
|
-
}
|
|
2011
|
-
async function runCursorAgent(opts) {
|
|
2012
|
-
const args = [
|
|
2013
|
-
"--print",
|
|
2014
|
-
"--output-format",
|
|
2015
|
-
"stream-json",
|
|
2016
|
-
"--stream-partial-output",
|
|
2017
|
-
"--trust",
|
|
2018
|
-
"--workspace",
|
|
2019
|
-
opts.cwd
|
|
2020
|
-
];
|
|
2021
|
-
if (opts.model !== void 0 && opts.model.length > 0) {
|
|
2022
|
-
args.push("--model", opts.model);
|
|
2023
|
-
}
|
|
2024
|
-
args.push(combinedPrompt(opts));
|
|
2025
|
-
return await runJsonlCli({
|
|
2026
|
-
command: "cursor-agent",
|
|
2027
|
-
args,
|
|
2028
|
-
cwd: opts.cwd,
|
|
2029
|
-
env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
|
|
2030
|
-
onMessage: opts.onMessage,
|
|
2031
|
-
parseFinal: parseCursorFinal
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2034
|
-
function runJsonlCli(opts) {
|
|
2035
|
-
return new Promise((resolve) => {
|
|
2036
|
-
const child = spawn(opts.command, opts.args, {
|
|
2037
|
-
cwd: opts.cwd,
|
|
2038
|
-
env: opts.env,
|
|
2039
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2040
|
-
});
|
|
2041
|
-
let stdoutBuf = "";
|
|
2042
|
-
let stderr = "";
|
|
2043
|
-
let cost = 0;
|
|
2044
|
-
let turns = 0;
|
|
2045
|
-
let result = "";
|
|
2046
|
-
let sessionId;
|
|
2047
|
-
let usage;
|
|
2048
|
-
let success = false;
|
|
2049
|
-
let finalSeen = false;
|
|
2050
|
-
let error;
|
|
2051
|
-
const observe = (msg) => {
|
|
2052
|
-
opts.onMessage?.(msg);
|
|
2053
|
-
if (sessionId === void 0 && typeof msg.session_id === "string" && msg.session_id.length > 0) {
|
|
2054
|
-
sessionId = msg.session_id;
|
|
2055
|
-
}
|
|
2056
|
-
if (sessionId === void 0 && typeof msg.thread_id === "string" && msg.thread_id.length > 0) {
|
|
2057
|
-
sessionId = msg.thread_id;
|
|
2058
|
-
}
|
|
2059
|
-
const final = opts.parseFinal(msg);
|
|
2060
|
-
if (final === null) return;
|
|
2061
|
-
finalSeen = true;
|
|
2062
|
-
if (final.cost !== void 0) cost = final.cost;
|
|
2063
|
-
if (final.turns !== void 0) turns = final.turns;
|
|
2064
|
-
if (final.result !== void 0) result = final.result;
|
|
2065
|
-
if (final.sessionId !== void 0) sessionId = final.sessionId;
|
|
2066
|
-
if (final.usage !== void 0) usage = final.usage;
|
|
2067
|
-
if (final.success !== void 0) success = final.success;
|
|
2068
|
-
if (final.error !== void 0) error = final.error;
|
|
2069
|
-
};
|
|
2070
|
-
const flushLines = () => {
|
|
2071
|
-
let idx = stdoutBuf.indexOf("\n");
|
|
2072
|
-
while (idx !== -1) {
|
|
2073
|
-
const rawLine = stdoutBuf.slice(0, idx);
|
|
2074
|
-
stdoutBuf = stdoutBuf.slice(idx + 1);
|
|
2075
|
-
const line = rawLine.trim();
|
|
2076
|
-
if (line.length > 0) {
|
|
2077
|
-
try {
|
|
2078
|
-
const parsed = JSON.parse(line);
|
|
2079
|
-
observe(parsed);
|
|
2080
|
-
} catch {
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
idx = stdoutBuf.indexOf("\n");
|
|
2084
|
-
}
|
|
1967
|
+
// src/cli/outcome.ts
|
|
1968
|
+
function renderOutcome(outcome, opts = {}) {
|
|
1969
|
+
const exitCode = opts.exitCode ?? defaultExitCode(outcome);
|
|
1970
|
+
if (opts.json === true) {
|
|
1971
|
+
return {
|
|
1972
|
+
stdout: `${JSON.stringify(outcome, null, 2)}
|
|
1973
|
+
`,
|
|
1974
|
+
stderr: "",
|
|
1975
|
+
exitCode
|
|
2085
1976
|
};
|
|
2086
|
-
child.stdout.on("data", (chunk) => {
|
|
2087
|
-
stdoutBuf += chunk.toString("utf8");
|
|
2088
|
-
flushLines();
|
|
2089
|
-
});
|
|
2090
|
-
child.stderr.on("data", (chunk) => {
|
|
2091
|
-
stderr += chunk.toString("utf8");
|
|
2092
|
-
});
|
|
2093
|
-
child.on("error", (err) => {
|
|
2094
|
-
resolve({
|
|
2095
|
-
success: false,
|
|
2096
|
-
cost,
|
|
2097
|
-
turns,
|
|
2098
|
-
result,
|
|
2099
|
-
sessionId,
|
|
2100
|
-
usage,
|
|
2101
|
-
error: err.code === "ENOENT" ? `${opts.command} not found on PATH` : err.message
|
|
2102
|
-
});
|
|
2103
|
-
});
|
|
2104
|
-
child.on("close", (code) => {
|
|
2105
|
-
flushLines();
|
|
2106
|
-
if (stdoutBuf.trim().length > 0) {
|
|
2107
|
-
try {
|
|
2108
|
-
observe(JSON.parse(stdoutBuf.trim()));
|
|
2109
|
-
} catch {
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
if (code === 0 && finalSeen && success) {
|
|
2113
|
-
resolve({ success, cost, turns, result, sessionId, usage });
|
|
2114
|
-
return;
|
|
2115
|
-
}
|
|
2116
|
-
const firstStderr = stderr.trim().split("\n")[0];
|
|
2117
|
-
resolve({
|
|
2118
|
-
success: false,
|
|
2119
|
-
cost,
|
|
2120
|
-
turns,
|
|
2121
|
-
result,
|
|
2122
|
-
sessionId,
|
|
2123
|
-
usage,
|
|
2124
|
-
error: error ?? (firstStderr !== void 0 && firstStderr.length > 0 ? firstStderr : `${opts.command} exited ${code ?? 1}`)
|
|
2125
|
-
});
|
|
2126
|
-
});
|
|
2127
|
-
});
|
|
2128
|
-
}
|
|
2129
|
-
function parseCodexFinal(msg) {
|
|
2130
|
-
if (msg.type === "item.completed") {
|
|
2131
|
-
const item = msg.item;
|
|
2132
|
-
if (item !== null && typeof item === "object") {
|
|
2133
|
-
const obj = item;
|
|
2134
|
-
if (obj.type === "agent_message" && typeof obj.text === "string") {
|
|
2135
|
-
return { result: obj.text };
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
return null;
|
|
2139
1977
|
}
|
|
2140
|
-
if (
|
|
2141
|
-
return {
|
|
1978
|
+
if (outcome.type === "needs-action") {
|
|
1979
|
+
return {
|
|
1980
|
+
stdout: opts.stdout ?? "",
|
|
1981
|
+
stderr: `almanac: ${outcome.message}
|
|
1982
|
+
${outcome.fix}
|
|
1983
|
+
`,
|
|
1984
|
+
exitCode
|
|
1985
|
+
};
|
|
2142
1986
|
}
|
|
2143
|
-
if (
|
|
1987
|
+
if (outcome.type === "error") {
|
|
2144
1988
|
return {
|
|
2145
|
-
|
|
2146
|
-
|
|
1989
|
+
stdout: opts.stdout ?? "",
|
|
1990
|
+
stderr: `almanac: ${outcome.message}
|
|
1991
|
+
`,
|
|
1992
|
+
exitCode
|
|
2147
1993
|
};
|
|
2148
1994
|
}
|
|
2149
|
-
return null;
|
|
2150
|
-
}
|
|
2151
|
-
function parseUsage(value) {
|
|
2152
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
2153
|
-
const obj = value;
|
|
2154
1995
|
return {
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
1996
|
+
stdout: opts.stdout ?? `${outcome.message}
|
|
1997
|
+
`,
|
|
1998
|
+
stderr: "",
|
|
1999
|
+
exitCode
|
|
2159
2000
|
};
|
|
2160
2001
|
}
|
|
2161
|
-
function
|
|
2162
|
-
|
|
2163
|
-
|
|
2002
|
+
function defaultExitCode(outcome) {
|
|
2003
|
+
switch (outcome.type) {
|
|
2004
|
+
case "success":
|
|
2005
|
+
case "noop":
|
|
2006
|
+
return 0;
|
|
2007
|
+
case "needs-action":
|
|
2008
|
+
case "error":
|
|
2009
|
+
return 1;
|
|
2010
|
+
}
|
|
2164
2011
|
}
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
turns: 1,
|
|
2171
|
-
result: typeof msg.result === "string" ? msg.result : "",
|
|
2172
|
-
sessionId: typeof msg.session_id === "string" ? msg.session_id : void 0,
|
|
2173
|
-
usage: parseUsage(msg.usage),
|
|
2174
|
-
error: isError ? typeof msg.result === "string" ? msg.result : `cursor result: ${String(msg.subtype ?? "error")}` : void 0
|
|
2175
|
-
};
|
|
2012
|
+
|
|
2013
|
+
// src/agent/sdk.ts
|
|
2014
|
+
async function runAgent(opts) {
|
|
2015
|
+
const provider = opts.provider ?? "claude";
|
|
2016
|
+
return await getAgentProvider(provider).run(opts);
|
|
2176
2017
|
}
|
|
2177
2018
|
|
|
2178
2019
|
// src/commands/init.ts
|
|
@@ -2318,42 +2159,47 @@ and optional \`files:\`. The rest is prose.
|
|
|
2318
2159
|
// src/commands/bootstrap.ts
|
|
2319
2160
|
var BOOTSTRAP_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash"];
|
|
2320
2161
|
async function runBootstrap(options) {
|
|
2162
|
+
const repoRoot = findNearestAlmanacDir(options.cwd) ?? options.cwd;
|
|
2321
2163
|
const providerResolution = await resolveAgentSelection({
|
|
2322
2164
|
agent: options.agent,
|
|
2323
|
-
model: options.model
|
|
2165
|
+
model: options.model,
|
|
2166
|
+
cwd: repoRoot
|
|
2324
2167
|
});
|
|
2325
2168
|
if (!providerResolution.ok) {
|
|
2326
|
-
return
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
exitCode: 1
|
|
2331
|
-
};
|
|
2169
|
+
return renderOutcome(
|
|
2170
|
+
{ type: "error", message: providerResolution.error },
|
|
2171
|
+
{ json: options.json }
|
|
2172
|
+
);
|
|
2332
2173
|
}
|
|
2333
2174
|
const { provider, model } = providerResolution;
|
|
2334
2175
|
try {
|
|
2335
2176
|
await assertAgentAuth({ provider, spawnCli: options.spawnCli });
|
|
2336
2177
|
} catch (err) {
|
|
2337
2178
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2338
|
-
return
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2179
|
+
return renderOutcome(
|
|
2180
|
+
{
|
|
2181
|
+
type: "needs-action",
|
|
2182
|
+
message: msg,
|
|
2183
|
+
fix: authFixFor(provider),
|
|
2184
|
+
data: { provider }
|
|
2185
|
+
},
|
|
2186
|
+
{ json: options.json }
|
|
2187
|
+
);
|
|
2344
2188
|
}
|
|
2345
|
-
const repoRoot = findNearestAlmanacDir(options.cwd) ?? options.cwd;
|
|
2346
2189
|
const almanacDir = getRepoAlmanacDir(repoRoot);
|
|
2347
2190
|
const pagesDir = join6(almanacDir, "pages");
|
|
2348
2191
|
if (options.force !== true && existsSync5(pagesDir)) {
|
|
2349
2192
|
const existing = await countMarkdownPages(pagesDir);
|
|
2350
2193
|
if (existing > 0) {
|
|
2351
|
-
return
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2194
|
+
return renderOutcome(
|
|
2195
|
+
{
|
|
2196
|
+
type: "needs-action",
|
|
2197
|
+
message: `.almanac/ already initialized with ${existing} page${existing === 1 ? "" : "s"}.`,
|
|
2198
|
+
fix: "run: almanac capture (or pass --force to overwrite)",
|
|
2199
|
+
data: { pages: existing }
|
|
2200
|
+
},
|
|
2201
|
+
{ json: options.json }
|
|
2202
|
+
);
|
|
2357
2203
|
}
|
|
2358
2204
|
}
|
|
2359
2205
|
if (!existsSync5(almanacDir)) {
|
|
@@ -2361,12 +2207,10 @@ async function runBootstrap(options) {
|
|
|
2361
2207
|
await initWiki({ cwd: repoRoot });
|
|
2362
2208
|
} catch (err) {
|
|
2363
2209
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2364
|
-
return
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
exitCode: 1
|
|
2369
|
-
};
|
|
2210
|
+
return renderOutcome(
|
|
2211
|
+
{ type: "error", message: `init failed during bootstrap: ${msg}` },
|
|
2212
|
+
{ json: options.json }
|
|
2213
|
+
);
|
|
2370
2214
|
}
|
|
2371
2215
|
}
|
|
2372
2216
|
const systemPrompt = await loadPrompt("bootstrap");
|
|
@@ -2379,7 +2223,7 @@ async function runBootstrap(options) {
|
|
|
2379
2223
|
const out = process.stdout;
|
|
2380
2224
|
const formatter = new StreamingFormatter({
|
|
2381
2225
|
write: (line) => {
|
|
2382
|
-
if (options.quiet !== true) out.write(line);
|
|
2226
|
+
if (options.quiet !== true && options.json !== true) out.write(line);
|
|
2383
2227
|
}
|
|
2384
2228
|
});
|
|
2385
2229
|
const onMessage = (msg) => {
|
|
@@ -2408,33 +2252,47 @@ async function runBootstrap(options) {
|
|
|
2408
2252
|
}
|
|
2409
2253
|
const finalLine = formatFinalLine(result, logPath, repoRoot);
|
|
2410
2254
|
if (result.success) {
|
|
2411
|
-
return
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2255
|
+
return renderOutcome(
|
|
2256
|
+
{
|
|
2257
|
+
type: "success",
|
|
2258
|
+
message: finalLine,
|
|
2259
|
+
data: runData(result, logPath, repoRoot)
|
|
2260
|
+
},
|
|
2261
|
+
{ json: options.json }
|
|
2262
|
+
);
|
|
2417
2263
|
}
|
|
2418
|
-
return
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2264
|
+
return renderOutcome(
|
|
2265
|
+
{
|
|
2266
|
+
type: "error",
|
|
2267
|
+
message: `bootstrap failed: ${result.error ?? "unknown error"}`,
|
|
2268
|
+
data: runData(result, logPath, repoRoot)
|
|
2269
|
+
},
|
|
2270
|
+
{
|
|
2271
|
+
json: options.json,
|
|
2272
|
+
stdout: options.quiet === true || options.json === true ? "" : `${finalLine}
|
|
2273
|
+
`
|
|
2274
|
+
}
|
|
2275
|
+
);
|
|
2425
2276
|
}
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2277
|
+
function authFixFor(provider) {
|
|
2278
|
+
switch (provider) {
|
|
2279
|
+
case "claude":
|
|
2280
|
+
return "run: claude auth login --claudeai (or export ANTHROPIC_API_KEY)";
|
|
2281
|
+
case "codex":
|
|
2282
|
+
return "run: codex login";
|
|
2283
|
+
case "cursor":
|
|
2284
|
+
return "run: cursor-agent login";
|
|
2285
|
+
default:
|
|
2286
|
+
return "run: almanac agents doctor";
|
|
2434
2287
|
}
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
return {
|
|
2288
|
+
}
|
|
2289
|
+
function runData(result, logPath, repoRoot) {
|
|
2290
|
+
return {
|
|
2291
|
+
transcript: relative(repoRoot, logPath),
|
|
2292
|
+
cost: result.cost,
|
|
2293
|
+
turns: result.turns,
|
|
2294
|
+
sessionId: result.sessionId
|
|
2295
|
+
};
|
|
2438
2296
|
}
|
|
2439
2297
|
function formatFinalLine(result, logPath, repoRoot) {
|
|
2440
2298
|
const status = result.success ? "done" : "failed";
|
|
@@ -2898,37 +2756,46 @@ var WRITER_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Agent"];
|
|
|
2898
2756
|
var REVIEWER_TOOLS = ["Read", "Grep", "Glob", "Bash"];
|
|
2899
2757
|
var REVIEWER_DESCRIPTION = "Reviews proposed wiki changes against the full knowledge base for cohesion, duplication, missing links, notability, and writing conventions.";
|
|
2900
2758
|
async function runCapture(options) {
|
|
2901
|
-
const
|
|
2759
|
+
const repoRoot = findNearestAlmanacDir(options.cwd);
|
|
2760
|
+
if (repoRoot === null) {
|
|
2761
|
+
return renderOutcome(
|
|
2762
|
+
{
|
|
2763
|
+
type: "needs-action",
|
|
2764
|
+
message: "no .almanac/ found in this directory or any parent.",
|
|
2765
|
+
fix: "run: almanac bootstrap"
|
|
2766
|
+
},
|
|
2767
|
+
{ json: options.json }
|
|
2768
|
+
);
|
|
2769
|
+
}
|
|
2770
|
+
const providerResolution = await resolveAgentSelection({
|
|
2902
2771
|
agent: options.agent,
|
|
2903
|
-
model: options.model
|
|
2772
|
+
model: options.model,
|
|
2773
|
+
cwd: repoRoot
|
|
2904
2774
|
});
|
|
2905
2775
|
if (!providerResolution.ok) {
|
|
2906
|
-
return
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
exitCode: 1
|
|
2911
|
-
};
|
|
2776
|
+
return renderOutcome(
|
|
2777
|
+
{ type: "error", message: providerResolution.error },
|
|
2778
|
+
{ json: options.json }
|
|
2779
|
+
);
|
|
2912
2780
|
}
|
|
2913
2781
|
const { provider, model } = providerResolution;
|
|
2782
|
+
const statusModel = model ?? getProviderDefaultModel(provider) ?? "provider default";
|
|
2914
2783
|
try {
|
|
2915
|
-
await
|
|
2784
|
+
await (options.assertAgentAuthFn ?? assertAgentAuth)({
|
|
2785
|
+
provider,
|
|
2786
|
+
spawnCli: options.spawnCli
|
|
2787
|
+
});
|
|
2916
2788
|
} catch (err) {
|
|
2917
2789
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2918
|
-
return
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
return {
|
|
2928
|
-
stdout: "",
|
|
2929
|
-
stderr: "almanac: no .almanac/ found in this directory or any parent. Run 'almanac bootstrap' first.\n",
|
|
2930
|
-
exitCode: 1
|
|
2931
|
-
};
|
|
2790
|
+
return renderOutcome(
|
|
2791
|
+
{
|
|
2792
|
+
type: "needs-action",
|
|
2793
|
+
message: msg,
|
|
2794
|
+
fix: authFixFor2(provider),
|
|
2795
|
+
data: { provider }
|
|
2796
|
+
},
|
|
2797
|
+
{ json: options.json }
|
|
2798
|
+
);
|
|
2932
2799
|
}
|
|
2933
2800
|
const almanacDir = getRepoAlmanacDir(repoRoot);
|
|
2934
2801
|
const pagesDir = join8(almanacDir, "pages");
|
|
@@ -2939,12 +2806,14 @@ async function runCapture(options) {
|
|
|
2939
2806
|
claudeProjectsDir: options.claudeProjectsDir
|
|
2940
2807
|
});
|
|
2941
2808
|
if (!transcriptResolution.ok) {
|
|
2942
|
-
return
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2809
|
+
return renderOutcome(
|
|
2810
|
+
{
|
|
2811
|
+
type: "needs-action",
|
|
2812
|
+
message: transcriptResolution.error,
|
|
2813
|
+
fix: transcriptFix(transcriptResolution.error)
|
|
2814
|
+
},
|
|
2815
|
+
{ json: options.json }
|
|
2816
|
+
);
|
|
2948
2817
|
}
|
|
2949
2818
|
const transcriptPath = transcriptResolution.path;
|
|
2950
2819
|
const snapshotBefore = await snapshotPages(pagesDir);
|
|
@@ -2970,7 +2839,7 @@ async function runCapture(options) {
|
|
|
2970
2839
|
stem: logStem,
|
|
2971
2840
|
sessionId: options.sessionId,
|
|
2972
2841
|
transcriptPath,
|
|
2973
|
-
model:
|
|
2842
|
+
model: statusModel,
|
|
2974
2843
|
startedAt
|
|
2975
2844
|
});
|
|
2976
2845
|
await writeCaptureRunRecord(statePath, stateRecord).catch(() => {
|
|
@@ -2979,7 +2848,7 @@ async function runCapture(options) {
|
|
|
2979
2848
|
const out = process.stdout;
|
|
2980
2849
|
const formatter = new StreamingFormatter({
|
|
2981
2850
|
write: (line) => {
|
|
2982
|
-
if (options.quiet !== true) out.write(line);
|
|
2851
|
+
if (options.quiet !== true && options.json !== true) out.write(line);
|
|
2983
2852
|
}
|
|
2984
2853
|
});
|
|
2985
2854
|
formatter.setAgent("writer");
|
|
@@ -3034,13 +2903,18 @@ Working directory: ${repoRoot}.`;
|
|
|
3034
2903
|
})
|
|
3035
2904
|
).catch(() => {
|
|
3036
2905
|
});
|
|
3037
|
-
return
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
`,
|
|
3042
|
-
|
|
3043
|
-
|
|
2906
|
+
return renderOutcome(
|
|
2907
|
+
{
|
|
2908
|
+
type: "error",
|
|
2909
|
+
message: `capture failed: ${result.error ?? "unknown error"}
|
|
2910
|
+
(transcript: ${relative3(repoRoot, logPath)})`,
|
|
2911
|
+
data: captureOutcomeData(result, delta, logPath, repoRoot)
|
|
2912
|
+
},
|
|
2913
|
+
{
|
|
2914
|
+
json: options.json,
|
|
2915
|
+
stdout: ""
|
|
2916
|
+
}
|
|
2917
|
+
);
|
|
3044
2918
|
}
|
|
3045
2919
|
await writeCaptureRunRecord(
|
|
3046
2920
|
statePath,
|
|
@@ -3053,25 +2927,46 @@ Working directory: ${repoRoot}.`;
|
|
|
3053
2927
|
).catch(() => {
|
|
3054
2928
|
});
|
|
3055
2929
|
const summary = formatSummary2(result, delta, logPath, repoRoot);
|
|
2930
|
+
return renderOutcome(
|
|
2931
|
+
{
|
|
2932
|
+
type: isNoopDelta(delta) ? "noop" : "success",
|
|
2933
|
+
message: summary,
|
|
2934
|
+
data: captureOutcomeData(result, delta, logPath, repoRoot)
|
|
2935
|
+
},
|
|
2936
|
+
{ json: options.json }
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
function transcriptFix(error) {
|
|
2940
|
+
if (error.includes("transcript not found")) {
|
|
2941
|
+
return "pass a valid <transcript-path>";
|
|
2942
|
+
}
|
|
2943
|
+
return "pass --session <id> or <transcript-path>";
|
|
2944
|
+
}
|
|
2945
|
+
function authFixFor2(provider) {
|
|
2946
|
+
switch (provider) {
|
|
2947
|
+
case "claude":
|
|
2948
|
+
return "run: claude auth login --claudeai (or export ANTHROPIC_API_KEY)";
|
|
2949
|
+
case "codex":
|
|
2950
|
+
return "run: codex login";
|
|
2951
|
+
case "cursor":
|
|
2952
|
+
return "run: cursor-agent login";
|
|
2953
|
+
default:
|
|
2954
|
+
return "run: almanac agents doctor";
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
function captureOutcomeData(result, delta, logPath, repoRoot) {
|
|
3056
2958
|
return {
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
2959
|
+
transcript: relative3(repoRoot, logPath),
|
|
2960
|
+
updated: delta.updated,
|
|
2961
|
+
created: delta.created,
|
|
2962
|
+
archived: delta.archived,
|
|
2963
|
+
cost: result.cost,
|
|
2964
|
+
turns: result.turns,
|
|
2965
|
+
sessionId: result.sessionId
|
|
3061
2966
|
};
|
|
3062
2967
|
}
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
const rawProvider = args.agent ?? config.agent.default;
|
|
3066
|
-
if (!isAgentProviderId(rawProvider)) {
|
|
3067
|
-
return {
|
|
3068
|
-
ok: false,
|
|
3069
|
-
error: `unknown agent '${rawProvider}'. Expected one of: claude, codex, cursor.`
|
|
3070
|
-
};
|
|
3071
|
-
}
|
|
3072
|
-
const configuredModel = config.agent.models[rawProvider] ?? void 0;
|
|
3073
|
-
const model = args.model !== void 0 ? args.model : configuredModel === null ? void 0 : configuredModel;
|
|
3074
|
-
return { ok: true, provider: rawProvider, model };
|
|
2968
|
+
function isNoopDelta(delta) {
|
|
2969
|
+
return delta.created === 0 && delta.updated === 0 && delta.archived === 0;
|
|
3075
2970
|
}
|
|
3076
2971
|
async function resolveTranscript(args) {
|
|
3077
2972
|
if (args.explicit !== void 0 && args.explicit.length > 0) {
|
|
@@ -3251,19 +3146,20 @@ async function runReindex(options) {
|
|
|
3251
3146
|
function registerWikiLifecycleCommands(program) {
|
|
3252
3147
|
program.command("bootstrap").description(
|
|
3253
3148
|
"scaffold a wiki in this repo via an AI agent (requires ANTHROPIC_API_KEY or Claude subscription)"
|
|
3254
|
-
).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(
|
|
3149
|
+
).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)").option("--json", "emit structured CommandOutcome JSON").action(
|
|
3255
3150
|
async (opts) => {
|
|
3256
3151
|
const result = await runBootstrap({
|
|
3257
3152
|
cwd: process.cwd(),
|
|
3258
3153
|
quiet: opts.quiet,
|
|
3259
3154
|
agent: opts.agent,
|
|
3260
3155
|
model: opts.model,
|
|
3261
|
-
force: opts.force
|
|
3156
|
+
force: opts.force,
|
|
3157
|
+
json: opts.json
|
|
3262
3158
|
});
|
|
3263
3159
|
emit(result);
|
|
3264
3160
|
}
|
|
3265
3161
|
);
|
|
3266
|
-
const capture = program.command("capture [transcript]").alias("c").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(
|
|
3162
|
+
const capture = program.command("capture [transcript]").alias("c").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").option("--json", "emit structured CommandOutcome JSON").action(
|
|
3267
3163
|
async (transcript, opts) => {
|
|
3268
3164
|
await autoRegisterIfNeeded(process.cwd());
|
|
3269
3165
|
const result = await runCapture({
|
|
@@ -3272,7 +3168,8 @@ function registerWikiLifecycleCommands(program) {
|
|
|
3272
3168
|
sessionId: opts.session,
|
|
3273
3169
|
quiet: opts.quiet,
|
|
3274
3170
|
agent: opts.agent,
|
|
3275
|
-
model: opts.model
|
|
3171
|
+
model: opts.model,
|
|
3172
|
+
json: opts.json
|
|
3276
3173
|
});
|
|
3277
3174
|
emit(result);
|
|
3278
3175
|
}
|
|
@@ -3285,13 +3182,16 @@ function registerWikiLifecycleCommands(program) {
|
|
|
3285
3182
|
});
|
|
3286
3183
|
emit(result);
|
|
3287
3184
|
});
|
|
3288
|
-
program.command("ps").description("
|
|
3185
|
+
program.command("ps").description("deprecated alias for capture status").option("--json", "emit structured JSON").action(async (opts) => {
|
|
3289
3186
|
await autoRegisterIfNeeded(process.cwd());
|
|
3290
3187
|
const result = await runCaptureStatus({
|
|
3291
3188
|
cwd: process.cwd(),
|
|
3292
3189
|
json: opts.json
|
|
3293
3190
|
});
|
|
3294
|
-
emit(
|
|
3191
|
+
emit(withWarning(
|
|
3192
|
+
result,
|
|
3193
|
+
deprecationWarning("almanac ps", "almanac capture status")
|
|
3194
|
+
));
|
|
3295
3195
|
});
|
|
3296
3196
|
const hook = program.command("hook").description("manage the SessionEnd auto-capture hook");
|
|
3297
3197
|
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) => {
|
|
@@ -3335,4 +3235,4 @@ function registerCommands(program) {
|
|
|
3335
3235
|
export {
|
|
3336
3236
|
registerCommands
|
|
3337
3237
|
};
|
|
3338
|
-
//# sourceMappingURL=register-commands-
|
|
3238
|
+
//# sourceMappingURL=register-commands-XTK2G2FB.js.map
|