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