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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
removeImportLine,
|
|
4
|
+
runUninstall
|
|
5
|
+
} from "./chunk-H6QKCB7M.js";
|
|
6
|
+
import "./chunk-QRK3JLFX.js";
|
|
7
|
+
import "./chunk-447U3GQJ.js";
|
|
8
|
+
import "./chunk-BF2J4XTC.js";
|
|
9
|
+
import "./chunk-P5WGG4FJ.js";
|
|
10
|
+
import "./chunk-7JUX4ADQ.js";
|
|
11
|
+
export {
|
|
12
|
+
removeImportLine,
|
|
13
|
+
runUninstall
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=uninstall-N7JY7ZV2.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runUpdate
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MRRX4UQB.js";
|
|
5
5
|
import "./chunk-F53U6JQG.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-P5WGG4FJ.js";
|
|
7
7
|
import "./chunk-7JUX4ADQ.js";
|
|
8
8
|
export {
|
|
9
9
|
runUpdate
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=update-
|
|
11
|
+
//# sourceMappingURL=update-P2IPG7RO.js.map
|
package/guides/mini.md
CHANGED
|
@@ -69,7 +69,7 @@ Returns slugs, one per line. Pipe-friendly. Filters AND-intersect.
|
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
71
|
almanac show checkout-flow # metadata header + body (default)
|
|
72
|
-
almanac show checkout-flow --
|
|
72
|
+
almanac show checkout-flow --body # body only
|
|
73
73
|
almanac show checkout-flow --meta # metadata only
|
|
74
74
|
almanac show checkout-flow --lead # first paragraph (cheap preview)
|
|
75
75
|
almanac show checkout-flow --backlinks # pages linking TO this one
|
package/guides/reference.md
CHANGED
|
@@ -49,7 +49,8 @@ Unified reader. Absorbs the old `info` and `path` commands — pick fields with
|
|
|
49
49
|
| `--stdin` | false | Read slugs from stdin, one per line. JSON Lines output for `--json` mode. |
|
|
50
50
|
| `--wiki <name>` | current repo | Target a specific registered wiki. |
|
|
51
51
|
| `--json` | false | Structured JSON. Overrides every view/field flag. |
|
|
52
|
-
| `--
|
|
52
|
+
| `--body` | false | Body only. Guarantees exactly one trailing newline — shell redirect produces a well-formed file. |
|
|
53
|
+
| `--raw` | false | Deprecated alias for `--body`; still accepted for compatibility. |
|
|
53
54
|
| `--meta` | false | Metadata header only, no body. |
|
|
54
55
|
| `--lead` | false | First paragraph of the body only (cheap preview). |
|
|
55
56
|
| `--title` | false | Print title. |
|
|
@@ -117,7 +118,7 @@ All topic subcommands accept `--wiki <name>`. `list` / `show` accept `--json`.
|
|
|
117
118
|
|
|
118
119
|
#### `almanac bootstrap`
|
|
119
120
|
|
|
120
|
-
Spawns an agent to create initial wiki stubs. Requires
|
|
121
|
+
Spawns an agent to create initial wiki stubs. Requires the selected provider to be installed and logged in. `--quiet` suppresses per-tool streaming. `--agent <provider>` overrides the provider for this run. `--model <model>` overrides the provider-local model. `--json` emits a structured `CommandOutcome` and suppresses streaming. `--force` overwrites an existing populated wiki. Writes `.almanac/logs/.bootstrap-<timestamp>.log`.
|
|
121
122
|
|
|
122
123
|
Bootstrap is the scaffolding path — it creates `.almanac/pages/`, `.almanac/topics.yaml`, `.almanac/README.md`, and stub entity pages based on what the agent reads in the repo.
|
|
123
124
|
|
|
@@ -130,7 +131,9 @@ Run the writer/reviewer pipeline on a Claude Code session transcript. Usually au
|
|
|
130
131
|
| `[transcript]` | Explicit path. Falls back to `--session` match or most-recent-by-cwd. |
|
|
131
132
|
| `--session <id>` | Target a specific session by ID. Matches filename under `~/.claude/projects/`. |
|
|
132
133
|
| `--quiet` | Suppress per-tool streaming; print only the final summary. |
|
|
134
|
+
| `--agent <provider>` | Override the configured provider for this run. |
|
|
133
135
|
| `--model <model>` | Override the agent model. |
|
|
136
|
+
| `--json` | Emit a structured `CommandOutcome`; suppresses streaming so stdout is parseable. |
|
|
134
137
|
|
|
135
138
|
Writes SDK transcript to `.almanac/logs/.capture-<session-id>.jsonl` (one JSON message per line). When invoked manually without `--session`, falls back to `.capture-<timestamp>.jsonl` so repeated runs don't clobber each other. A writer subagent drafts pages; a reviewer subagent enforces notability + writing conventions (§9) before drafts land.
|
|
136
139
|
|
|
@@ -153,10 +156,12 @@ Install the SessionEnd hook + the two CLAUDE.md guides (`codealmanac.md`, `codea
|
|
|
153
156
|
| Flag | Semantics |
|
|
154
157
|
|---|---|
|
|
155
158
|
| `-y, --yes` | Skip prompts; install everything. |
|
|
159
|
+
| `--agent <agent>` | Set the default provider. Accepts `claude`, `codex`, `cursor`, or optional shorthand like `claude/opus`. |
|
|
160
|
+
| `--model <model>` | Set the provider-local model during setup. Non-interactive equivalent of the model picker. |
|
|
156
161
|
| `--skip-hook` | Opt out of the SessionEnd hook. |
|
|
157
162
|
| `--skip-guides` | Opt out of the CLAUDE.md guides. |
|
|
158
163
|
|
|
159
|
-
Both `almanac setup` and bare `codealmanac` route here. `codealmanac --yes`, `codealmanac --skip-hook`, and `codealmanac --skip-guides` are the typical first-run invocations. Passing `--skip-hook --skip-guides` together short-circuits with a terse line — nothing was installed, no banner drawn.
|
|
164
|
+
Both `almanac setup` and bare `codealmanac` route here. Interactive setup chooses provider first, then provider-local model. `codealmanac --yes`, `codealmanac --agent codex --model gpt-5.3-codex`, `codealmanac --skip-hook`, and `codealmanac --skip-guides` are the typical first-run invocations. Passing `--skip-hook --skip-guides` together short-circuits with a terse line — nothing was installed, no banner drawn.
|
|
160
165
|
|
|
161
166
|
#### `almanac uninstall`
|
|
162
167
|
|
|
@@ -190,6 +195,23 @@ Read-only install + current-wiki health report. Every check reports a state; non
|
|
|
190
195
|
{ "key": "install.guides", "status": "ok", "message": "..." },
|
|
191
196
|
{ "key": "install.import", "status": "ok", "message": "..." }
|
|
192
197
|
],
|
|
198
|
+
"agents": [
|
|
199
|
+
{
|
|
200
|
+
"id": "claude",
|
|
201
|
+
"label": "Claude",
|
|
202
|
+
"status": "ok",
|
|
203
|
+
"readiness": "ready",
|
|
204
|
+
"selected": true,
|
|
205
|
+
"recommended": true,
|
|
206
|
+
"installed": true,
|
|
207
|
+
"authenticated": true,
|
|
208
|
+
"model": "claude-sonnet-4-6",
|
|
209
|
+
"providerDefaultModel": "claude-sonnet-4-6",
|
|
210
|
+
"configuredModel": null,
|
|
211
|
+
"account": "rohan@example.com",
|
|
212
|
+
"detail": "rohan@example.com"
|
|
213
|
+
}
|
|
214
|
+
],
|
|
193
215
|
"wiki": [
|
|
194
216
|
{ "key": "wiki.repo", "status": "info", "message": "repo: /abs/path" },
|
|
195
217
|
{ "key": "wiki.registered", "status": "ok", "message": "registered as '...'" },
|
|
@@ -206,6 +228,43 @@ Each check has a stable `key` safe for scripting. ✗ entries include a `fix` fi
|
|
|
206
228
|
|
|
207
229
|
The report also includes an `## Updates` section (`updates: Check[]` in `--json`) with keys `update.status`, `update.last_check`, `update.notifier`, and `update.dismissed`. `update.status === "problem"` when a new version is available — mirrors the pre-command banner.
|
|
208
230
|
|
|
231
|
+
#### `almanac agents`
|
|
232
|
+
|
|
233
|
+
Provider-focused settings and readiness.
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
almanac agents list
|
|
237
|
+
almanac agents doctor
|
|
238
|
+
almanac agents use claude
|
|
239
|
+
almanac agents model claude claude-opus-4-6
|
|
240
|
+
almanac agents model claude --default
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`agents use` writes the default provider. `agents model` writes the provider-local model override; `--default`, `default`, or `null` resets the provider to its own default. The older `almanac set default-agent ...` and `almanac set model ...` commands remain compatibility aliases and print deprecation warnings.
|
|
244
|
+
|
|
245
|
+
`bootstrap` and `capture` resolve provider settings in this order:
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
--agent flag > ALMANAC_AGENT env > config.agent.default > built-in default
|
|
249
|
+
--model flag > ALMANAC_MODEL env > config.agent.models[provider] > provider default
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### `almanac config`
|
|
253
|
+
|
|
254
|
+
Low-level scriptable settings surface.
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
almanac config list
|
|
258
|
+
almanac config list --show-origin
|
|
259
|
+
almanac config get agent.default
|
|
260
|
+
almanac config set agent.models.claude claude-opus-4-6
|
|
261
|
+
almanac config set --project agent.default codex
|
|
262
|
+
almanac config unset agent.models.claude
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Supported keys: `update_notifier`, `agent.default`, `agent.models.claude`, `agent.models.codex`, and `agent.models.cursor`.
|
|
266
|
+
User config is stored at `~/.almanac/config.toml`. Project config lives at `.almanac/config.toml` and can override agent provider/model settings for a repo; `update_notifier` remains user-level only because it controls a global pre-command banner. Effective precedence is flag, environment, project config, user config, provider default.
|
|
267
|
+
|
|
209
268
|
#### `almanac update`
|
|
210
269
|
|
|
211
270
|
Upgrade command + the controls for the nag banner. See §11 for the full update-notifier architecture.
|
|
@@ -215,8 +274,8 @@ Upgrade command + the controls for the nag banner. See §11 for the full update-
|
|
|
215
274
|
| (none) | Run `npm i -g codealmanac@latest` synchronously in the foreground. Inherits stdio so you see npm's progress bar, permission prompts, and peer-dep warnings verbatim. |
|
|
216
275
|
| `--dismiss` | Mark the current `latest_version` as "don't nag". No install. Banner is suppressed until a newer version ships. |
|
|
217
276
|
| `--check` | Force a registry query now, bypassing the 24h cache. Prints the result. No install. |
|
|
218
|
-
| `--enable-notifier` |
|
|
219
|
-
| `--disable-notifier` |
|
|
277
|
+
| `--enable-notifier` | Deprecated alias for `almanac config set update_notifier true`. |
|
|
278
|
+
| `--disable-notifier` | Deprecated alias for `almanac config set update_notifier false`. |
|
|
220
279
|
|
|
221
280
|
**Exit codes:** `0` on successful install / check / dismiss / toggle. Install propagates npm's exit code on failure. `--check` exits `1` when the registry is unreachable.
|
|
222
281
|
|
|
@@ -297,7 +356,7 @@ inventory lock row to Supabase, returns the PI client secret. See
|
|
|
297
356
|
[[inventory-lock-gotcha]] for the deadlock we hit in March.
|
|
298
357
|
```
|
|
299
358
|
|
|
300
|
-
CRLF-terminated files are handled transparently — `show --
|
|
359
|
+
CRLF-terminated files are handled transparently — `show --body` strips frontmatter without leaving a stray `\r` at the body head.
|
|
301
360
|
|
|
302
361
|
---
|
|
303
362
|
|
|
@@ -432,7 +491,7 @@ almanac search --orphan | almanac show --stdin --path | xargs -n 1 "$EDITOR"
|
|
|
432
491
|
|
|
433
492
|
**Export a page's body to a standalone markdown file:**
|
|
434
493
|
```bash
|
|
435
|
-
almanac show checkout-flow --
|
|
494
|
+
almanac show checkout-flow --body > checkout-flow.md # exactly one trailing \n
|
|
436
495
|
```
|
|
437
496
|
|
|
438
497
|
**Doctor a flaky install in CI:**
|
|
@@ -722,7 +781,7 @@ command runs
|
|
|
722
781
|
### State files
|
|
723
782
|
|
|
724
783
|
- **`~/.almanac/update-state.json`** — written by the background worker + `almanac update`. Shape: `{last_check_at, installed_version, latest_version, dismissed_versions[], last_fetch_failed_at?}`. `last_check_at` is epoch seconds; `dismissed_versions` is a list of version strings the user muted via `--dismiss`. Missing / malformed → all read paths return defaults. Never break the CLI.
|
|
725
|
-
- **`~/.almanac/config.
|
|
784
|
+
- **`~/.almanac/config.toml`** — contains `update_notifier` plus user-level agent defaults. Toggles whether the banner ever prints. Default `true`. Flip via `almanac config set update_notifier true` / `false`. Legacy `~/.almanac/config.json` is migrated on normal config reads.
|
|
726
785
|
|
|
727
786
|
### Cache behavior
|
|
728
787
|
|
|
@@ -733,7 +792,7 @@ command runs
|
|
|
733
792
|
|
|
734
793
|
### Dismissal semantics
|
|
735
794
|
|
|
736
|
-
`almanac update --dismiss` appends the current `latest_version` to `dismissed_versions[]`. The banner suppresses **only that specific version** — when a newer one ships, `latest_version` moves on and the banner reappears. Multiple consecutive dismissals accumulate; `dismissed_versions` is never trimmed automatically. If you find yourself dismissing every release, `almanac
|
|
795
|
+
`almanac update --dismiss` appends the current `latest_version` to `dismissed_versions[]`. The banner suppresses **only that specific version** — when a newer one ships, `latest_version` moves on and the banner reappears. Multiple consecutive dismissals accumulate; `dismissed_versions` is never trimmed automatically. If you find yourself dismissing every release, `almanac config set update_notifier false` is the right tool instead.
|
|
737
796
|
|
|
738
797
|
Dismissal does NOT prevent `almanac update` from installing. It only silences the banner.
|
|
739
798
|
|
package/package.json
CHANGED
package/dist/agents-RVYQ44DB.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runAgentsList,
|
|
4
|
-
runSetAgentModel,
|
|
5
|
-
runSetDefaultAgent
|
|
6
|
-
} from "./chunk-PIYJQE4Z.js";
|
|
7
|
-
import "./chunk-TWM7I2LU.js";
|
|
8
|
-
import "./chunk-SSYMRT4I.js";
|
|
9
|
-
import "./chunk-WRUSDYYE.js";
|
|
10
|
-
import "./chunk-7JUX4ADQ.js";
|
|
11
|
-
export {
|
|
12
|
-
runAgentsList,
|
|
13
|
-
runSetAgentModel,
|
|
14
|
-
runSetDefaultAgent
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=agents-RVYQ44DB.js.map
|
package/dist/auth-S5DVUIUJ.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
UNAUTHENTICATED_MESSAGE,
|
|
4
|
-
assertClaudeAuth,
|
|
5
|
-
checkClaudeAuth,
|
|
6
|
-
defaultSpawnCli,
|
|
7
|
-
legacySdkSpawnCli,
|
|
8
|
-
resolveClaudeExecutable
|
|
9
|
-
} from "./chunk-SSYMRT4I.js";
|
|
10
|
-
export {
|
|
11
|
-
UNAUTHENTICATED_MESSAGE,
|
|
12
|
-
assertClaudeAuth,
|
|
13
|
-
checkClaudeAuth,
|
|
14
|
-
defaultSpawnCli,
|
|
15
|
-
legacySdkSpawnCli,
|
|
16
|
-
resolveClaudeExecutable
|
|
17
|
-
};
|
|
18
|
-
//# sourceMappingURL=auth-S5DVUIUJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/doctor-checks/format.ts","../src/commands/doctor-checks/install.ts","../src/commands/doctor-checks/probes.ts","../src/commands/doctor-checks/updates.ts","../src/commands/doctor.ts"],"sourcesContent":["import { BLUE, BOLD, DIM, GREEN, RED, RST } from \"../../ansi.js\";\nimport type { Check, CheckStatus, DoctorOptions, DoctorReport } from \"./types.js\";\n\nexport function formatReport(\n report: DoctorReport,\n options: DoctorOptions,\n): string {\n const color = options.stdout === undefined && process.stdout.isTTY === true;\n const lines: string[] = [];\n lines.push(`codealmanac v${report.version}`);\n lines.push(\"\");\n if (report.install.length > 0) {\n lines.push(color ? `${BOLD}## Install${RST}` : \"## Install\");\n for (const c of report.install) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n if (report.updates.length > 0) {\n lines.push(color ? `${BOLD}## Updates${RST}` : \"## Updates\");\n for (const c of report.updates) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n if (report.wiki.length > 0) {\n lines.push(color ? `${BOLD}## Current wiki${RST}` : \"## Current wiki\");\n for (const c of report.wiki) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction formatCheck(c: Check, color: boolean): string {\n const { icon, tint } = iconFor(c.status, color);\n const head = ` ${tint}${icon}${color ? RST : \"\"} ${c.message}`;\n if (c.fix === undefined) return head;\n const fixLine = color\n ? ` ${DIM}${c.fix}${RST}`\n : ` ${c.fix}`;\n return `${head}\\n${fixLine}`;\n}\n\nfunction iconFor(\n status: CheckStatus,\n color: boolean,\n): { icon: string; tint: string } {\n switch (status) {\n case \"ok\":\n return { icon: \"\\u2713\", tint: color ? GREEN : \"\" };\n case \"problem\":\n return { icon: \"\\u2717\", tint: color ? RED : \"\" };\n case \"info\":\n return { icon: \"\\u25c7\", tint: color ? BLUE : \"\" };\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\nimport type { ClaudeAuthStatus } from \"../../agent/auth.js\";\nimport { IMPORT_LINE } from \"../setup.js\";\nimport {\n classifyInstallPath,\n detectInstallPath,\n probeBetterSqlite3,\n safeCheckAuth,\n} from \"./probes.js\";\nimport type { Check, DoctorOptions } from \"./types.js\";\n\nexport async function gatherInstallChecks(\n options: DoctorOptions,\n): Promise<Check[]> {\n const checks: Check[] = [];\n\n const rawPath = options.installPath ?? detectInstallPath();\n const { installPath, isEphemeral } = classifyInstallPath(rawPath);\n checks.push(describeInstallPath(installPath, isEphemeral));\n\n const nodeVersion = options.nodeVersion ?? process.version;\n const sqlite = options.sqliteProbe ?? probeBetterSqlite3();\n checks.push({\n status: sqlite.ok ? \"ok\" : \"problem\",\n key: \"install.sqlite\",\n message: sqlite.ok\n ? `better-sqlite3 native binding OK (Node ${nodeVersion})`\n : `better-sqlite3 native binding failed: ${sqlite.summary}`,\n fix: sqlite.ok\n ? undefined\n : \"run: npm rebuild better-sqlite3 (in the install directory)\",\n });\n\n const auth = await safeCheckAuth(options.spawnCli);\n checks.push(describeAuth(auth));\n\n const settingsPath =\n options.settingsPath ?? path.join(homedir(), \".claude\", \"settings.json\");\n checks.push(await describeHook(settingsPath));\n\n const claudeDir = options.claudeDir ?? path.join(homedir(), \".claude\");\n checks.push(describeGuides(claudeDir));\n checks.push(await describeImportLine(claudeDir));\n\n return checks;\n}\n\nfunction describeInstallPath(\n installPath: string | null,\n isEphemeral: boolean,\n): Check {\n if (installPath === null) {\n return {\n status: \"problem\",\n key: \"install.path\",\n message: \"could not detect codealmanac install path\",\n fix: \"reinstall with: npm install -g codealmanac\",\n };\n }\n return {\n status: isEphemeral ? \"info\" : \"ok\",\n key: \"install.path\",\n message: isEphemeral\n ? `codealmanac running from ephemeral npx location: ${installPath}`\n : `codealmanac installed at ${installPath}`,\n fix: isEphemeral\n ? \"run: npm install -g codealmanac (to make the install permanent)\"\n : undefined,\n };\n}\n\nfunction describeAuth(auth: ClaudeAuthStatus): Check {\n if (auth.loggedIn) {\n if (auth.authMethod === \"apiKey\") {\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: \"claude auth: ANTHROPIC_API_KEY set\",\n };\n }\n const who = auth.email ?? \"Claude account\";\n const plan =\n auth.subscriptionType !== undefined\n ? ` (${auth.subscriptionType} subscription)`\n : \"\";\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: `claude auth: ${who}${plan}`,\n };\n }\n if (\n process.env.ANTHROPIC_API_KEY !== undefined &&\n process.env.ANTHROPIC_API_KEY.length > 0\n ) {\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: \"claude auth: ANTHROPIC_API_KEY set\",\n };\n }\n return {\n status: \"problem\",\n key: \"install.auth\",\n message: \"claude auth: not signed in\",\n fix: \"run: claude auth login --claudeai (or export ANTHROPIC_API_KEY)\",\n };\n}\n\nasync function describeHook(settingsPath: string): Promise<Check> {\n if (!existsSync(settingsPath)) {\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: \"SessionEnd hook not installed\",\n fix: \"run: almanac setup --yes\",\n };\n }\n try {\n const raw = await readFile(settingsPath, \"utf8\");\n const parsed = JSON.parse(raw) as {\n hooks?: {\n SessionEnd?: {\n command?: string;\n hooks?: { command?: string }[];\n }[];\n };\n };\n const entries = parsed.hooks?.SessionEnd ?? [];\n const found = entries.some((e) => {\n if (\n typeof e?.command === \"string\" &&\n e.command.endsWith(\"almanac-capture.sh\")\n ) {\n return true;\n }\n if (Array.isArray(e?.hooks)) {\n return e.hooks.some(\n (h) =>\n typeof h?.command === \"string\" &&\n h.command.endsWith(\"almanac-capture.sh\"),\n );\n }\n return false;\n });\n if (!found) {\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: \"SessionEnd hook not installed\",\n fix: \"run: almanac setup --yes\",\n };\n }\n return {\n status: \"ok\",\n key: \"install.hook\",\n message: `SessionEnd hook installed at ${settingsPath}`,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: `could not read ${settingsPath}: ${msg}`,\n fix: \"check the file for malformed JSON\",\n };\n }\n}\n\nfunction describeGuides(claudeDir: string): Check {\n const mini = path.join(claudeDir, \"codealmanac.md\");\n const ref = path.join(claudeDir, \"codealmanac-reference.md\");\n const haveMini = existsSync(mini);\n const haveRef = existsSync(ref);\n if (haveMini && haveRef) {\n return {\n status: \"ok\",\n key: \"install.guides\",\n message: `Agent guides installed (${path.basename(mini)}, ${path.basename(ref)})`,\n };\n }\n const missing = [\n haveMini ? null : \"codealmanac.md\",\n haveRef ? null : \"codealmanac-reference.md\",\n ].filter((s): s is string => s !== null);\n return {\n status: \"problem\",\n key: \"install.guides\",\n message: `Agent guides missing (${missing.join(\", \")})`,\n fix: \"run: almanac setup --yes\",\n };\n}\n\nasync function describeImportLine(claudeDir: string): Promise<Check> {\n const claudeMd = path.join(claudeDir, \"CLAUDE.md\");\n if (!existsSync(claudeMd)) {\n return {\n status: \"problem\",\n key: \"install.import\",\n message: \"CLAUDE.md import not present (no ~/.claude/CLAUDE.md)\",\n fix: \"run: almanac setup --yes\",\n };\n }\n try {\n const contents = await readFile(claudeMd, \"utf8\");\n const lines = contents.split(/\\r?\\n/).map((l) => l.trim());\n const present = lines.some((line) => {\n if (line === IMPORT_LINE) return true;\n if (!line.startsWith(IMPORT_LINE)) return false;\n const next = line[IMPORT_LINE.length];\n return next === \" \" || next === \"\\t\";\n });\n if (present) {\n return {\n status: \"ok\",\n key: \"install.import\",\n message: \"CLAUDE.md import present\",\n };\n }\n return {\n status: \"problem\",\n key: \"install.import\",\n message: \"CLAUDE.md import line missing\",\n fix: \"run: almanac setup --yes\",\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"install.import\",\n message: `could not read ${claudeMd}: ${msg}`,\n };\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { checkClaudeAuth, type ClaudeAuthStatus, type SpawnCliFn } from \"../../agent/auth.js\";\nimport type { SqliteProbeResult } from \"./types.js\";\n\n// Single `createRequire` instance — used by package/binding probes.\nconst req = createRequire(import.meta.url);\n\n/**\n * Detect where codealmanac is installed by walking up from the running\n * module until we find a `package.json` whose `name` is `codealmanac`.\n */\nexport function detectInstallPath(): string | null {\n try {\n const here = fileURLToPath(import.meta.url);\n let dir = path.dirname(here);\n for (let i = 0; i < 6; i++) {\n const pkgPath = path.join(dir, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const raw = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(raw) as { name?: unknown };\n if (pkg.name === \"codealmanac\") return dir;\n } catch {\n // ignore — keep walking\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Classify the detected install path as permanent or ephemeral.\n * Ephemeral locations (npm npx cache, pnpm dlx cache, /tmp/) are valid\n * installs but will disappear when the cache is evicted or the machine\n * reboots. Doctor reports them as `info` rather than `ok`.\n */\nexport function classifyInstallPath(\n raw: string | null,\n): { installPath: string | null; isEphemeral: boolean } {\n if (raw === null) return { installPath: null, isEphemeral: false };\n const home = homedir();\n const ephemeralPrefixes = [\n path.join(home, \".npm\", \"_npx\"),\n path.join(home, \".local\", \"share\", \"pnpm\", \"dlx\"),\n \"/tmp/\",\n \"/var/folders/\",\n ];\n const isEphemeral = ephemeralPrefixes.some((p) => raw.startsWith(p));\n return { installPath: raw, isEphemeral };\n}\n\n/**\n * Probe the better-sqlite3 native binding by opening an in-memory DB.\n */\nexport function probeBetterSqlite3(): SqliteProbeResult {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const Database = req(\"better-sqlite3\") as typeof import(\"better-sqlite3\");\n const db = new Database(\":memory:\");\n db.close();\n return { ok: true, summary: \"native binding loads cleanly\" };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n const firstLine = msg.split(\"\\n\")[0] ?? msg;\n return { ok: false, summary: firstLine };\n }\n}\n\nexport async function safeCheckAuth(\n spawnCli?: SpawnCliFn,\n): Promise<ClaudeAuthStatus> {\n try {\n return await checkClaudeAuth(spawnCli);\n } catch {\n return { loggedIn: false };\n }\n}\n\nexport function readPackageVersion(): string | null {\n const candidates = [\n \"../../../package.json\",\n \"../../package.json\",\n \"../package.json\",\n ];\n for (const candidate of candidates) {\n try {\n const pkg = req(candidate) as { version?: unknown };\n if (typeof pkg.version === \"string\" && pkg.version.length > 0) {\n return pkg.version;\n }\n } catch {\n // Fall through to the next runtime layout candidate.\n }\n }\n return null;\n}\n","import { readConfig } from \"../../update/config.js\";\nimport { readStateForDoctor } from \"../../update/schedule.js\";\nimport { isNewer } from \"../../update/semver.js\";\nimport { formatDuration } from \"./duration.js\";\nimport type { Check, DoctorOptions } from \"./types.js\";\n\nexport async function gatherUpdateChecks(\n options: DoctorOptions,\n installedVersion: string,\n): Promise<Check[]> {\n const checks: Check[] = [];\n const state = readStateForDoctor(options.updateStatePath);\n const config = await readConfig(options.updateConfigPath);\n\n if (state === null || state.latest_version.length === 0) {\n checks.push({\n status: \"info\",\n key: \"update.status\",\n message: `on ${installedVersion}; no update check has run yet`,\n fix: \"run: almanac update --check\",\n });\n } else if (isNewer(state.latest_version, installedVersion)) {\n const dismissed = state.dismissed_versions.includes(state.latest_version)\n ? \" (dismissed — run `almanac update` to install anyway)\"\n : \"\";\n checks.push({\n status: \"problem\",\n key: \"update.status\",\n message:\n `${state.latest_version} available (you're on ${installedVersion})${dismissed}`,\n fix: \"run: almanac update\",\n });\n } else {\n checks.push({\n status: \"ok\",\n key: \"update.status\",\n message: `on latest (${installedVersion})`,\n });\n }\n\n if (state !== null && state.last_check_at > 0) {\n const now = (options.now?.() ?? new Date()).getTime();\n const ageMs = now - state.last_check_at * 1000;\n const failedSuffix =\n state.last_fetch_failed_at !== undefined &&\n state.last_fetch_failed_at === state.last_check_at\n ? \" (last attempt failed — will retry next invocation)\"\n : \"\";\n checks.push({\n status: \"info\",\n key: \"update.last_check\",\n message: `last checked: ${formatDuration(ageMs)} ago${failedSuffix}`,\n });\n } else {\n checks.push({\n status: \"info\",\n key: \"update.last_check\",\n message: \"last checked: never\",\n });\n }\n\n checks.push({\n status: \"info\",\n key: \"update.notifier\",\n message: `update notifier: ${config.update_notifier ? \"enabled\" : \"disabled\"}`,\n fix: config.update_notifier\n ? undefined\n : \"run: almanac update --enable-notifier\",\n });\n\n if (state !== null && state.dismissed_versions.length > 0) {\n checks.push({\n status: \"info\",\n key: \"update.dismissed\",\n message: `dismissed versions: ${state.dismissed_versions.join(\", \")}`,\n });\n }\n\n return checks;\n}\n","import { formatReport } from \"./doctor-checks/format.js\";\nimport { gatherInstallChecks } from \"./doctor-checks/install.js\";\nimport { readPackageVersion } from \"./doctor-checks/probes.js\";\nimport type {\n Check,\n CheckStatus,\n DoctorOptions,\n DoctorReport,\n DoctorResult,\n SqliteProbeResult,\n} from \"./doctor-checks/types.js\";\nimport { gatherUpdateChecks } from \"./doctor-checks/updates.js\";\n\nexport type {\n Check,\n CheckStatus,\n DoctorOptions,\n DoctorReport,\n DoctorResult,\n SqliteProbeResult,\n};\n\n/**\n * `almanac doctor` — install + wiki health report.\n *\n * Separate from `almanac health` (which checks graph integrity of a\n * specific wiki). `doctor` answers the \"is this install even set up\n * correctly?\" question that users hit when first trying the tool or when\n * sessions silently stop getting captured.\n *\n * This file is the command composition root. The section-specific probes\n * and formatting live in `doctor-checks/` so each durable fact has one\n * obvious owner.\n */\nexport async function runDoctor(\n options: DoctorOptions,\n): Promise<DoctorResult> {\n const version =\n options.versionOverride ?? readPackageVersion() ?? \"unknown\";\n\n const install: Check[] = options.wikiOnly === true\n ? []\n : await gatherInstallChecks(options);\n\n const updates: Check[] = options.wikiOnly === true\n ? []\n : await gatherUpdateChecks(options, version);\n\n const wiki: Check[] = options.installOnly === true\n ? []\n : await safeGatherWikiChecks(options);\n\n const report: DoctorReport = { version, install, updates, wiki };\n\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify(report, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n return {\n stdout: formatReport(report, options),\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nasync function safeGatherWikiChecks(\n options: DoctorOptions,\n): Promise<Check[]> {\n try {\n const { gatherWikiChecks } = await import(\"./doctor-checks/wiki.js\");\n return await gatherWikiChecks(options);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return [\n {\n status: \"problem\",\n key: \"wiki.checks\",\n message: `could not run wiki checks: ${msg.split(\"\\n\")[0] ?? msg}`,\n fix: \"run: npm rebuild better-sqlite3 (in the install directory)\",\n },\n ];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGO,SAAS,aACd,QACA,SACQ;AACR,QAAM,QAAQ,QAAQ,WAAW,UAAa,QAAQ,OAAO,UAAU;AACvE,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,gBAAgB,OAAO,OAAO,EAAE;AAC3C,QAAM,KAAK,EAAE;AACb,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,QAAQ,GAAG,IAAI,aAAa,GAAG,KAAK,YAAY;AAC3D,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,KAAK,YAAY,GAAG,KAAK,CAAC;AAAA,IAClC;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,QAAQ,GAAG,IAAI,aAAa,GAAG,KAAK,YAAY;AAC3D,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,KAAK,YAAY,GAAG,KAAK,CAAC;AAAA,IAClC;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,MAAI,OAAO,KAAK,SAAS,GAAG;AAC1B,UAAM,KAAK,QAAQ,GAAG,IAAI,kBAAkB,GAAG,KAAK,iBAAiB;AACrE,eAAW,KAAK,OAAO,MAAM;AAC3B,YAAM,KAAK,YAAY,GAAG,KAAK,CAAC;AAAA,IAClC;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;AAEA,SAAS,YAAY,GAAU,OAAwB;AACrD,QAAM,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,QAAQ,KAAK;AAC9C,QAAM,OAAO,KAAK,IAAI,GAAG,IAAI,GAAG,QAAQ,MAAM,EAAE,IAAI,EAAE,OAAO;AAC7D,MAAI,EAAE,QAAQ,OAAW,QAAO;AAChC,QAAM,UAAU,QACZ,OAAO,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,KACxB,OAAO,EAAE,GAAG;AAChB,SAAO,GAAG,IAAI;AAAA,EAAK,OAAO;AAC5B;AAEA,SAAS,QACP,QACA,OACgC;AAChC,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,MAAM,QAAQ,QAAQ,GAAG;AAAA,IACpD,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,MAAM,QAAQ,MAAM,GAAG;AAAA,IAClD,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,MAAM,QAAQ,OAAO,GAAG;AAAA,EACrD;AACF;;;ACzDA,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,WAAAC,gBAAe;AACxB,OAAOC,WAAU;;;ACHjB,SAAS,YAAY,oBAAoB;AACzC,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAM9B,IAAM,MAAM,cAAc,YAAY,GAAG;AAMlC,SAAS,oBAAmC;AACjD,MAAI;AACF,UAAM,OAAO,cAAc,YAAY,GAAG;AAC1C,QAAI,MAAM,KAAK,QAAQ,IAAI;AAC3B,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,UAAU,KAAK,KAAK,KAAK,cAAc;AAC7C,UAAI,WAAW,OAAO,GAAG;AACvB,YAAI;AACF,gBAAM,MAAM,aAAa,SAAS,OAAO;AACzC,gBAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,cAAI,IAAI,SAAS,cAAe,QAAO;AAAA,QACzC,QAAQ;AAAA,QAER;AAAA,MACF;AACA,YAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,UAAI,WAAW,IAAK;AACpB,YAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,oBACd,KACsD;AACtD,MAAI,QAAQ,KAAM,QAAO,EAAE,aAAa,MAAM,aAAa,MAAM;AACjE,QAAM,OAAO,QAAQ;AACrB,QAAM,oBAAoB;AAAA,IACxB,KAAK,KAAK,MAAM,QAAQ,MAAM;AAAA,IAC9B,KAAK,KAAK,MAAM,UAAU,SAAS,QAAQ,KAAK;AAAA,IAChD;AAAA,IACA;AAAA,EACF;AACA,QAAM,cAAc,kBAAkB,KAAK,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC;AACnE,SAAO,EAAE,aAAa,KAAK,YAAY;AACzC;AAKO,SAAS,qBAAwC;AACtD,MAAI;AAEF,UAAM,WAAW,IAAI,gBAAgB;AACrC,UAAM,KAAK,IAAI,SAAS,UAAU;AAClC,OAAG,MAAM;AACT,WAAO,EAAE,IAAI,MAAM,SAAS,+BAA+B;AAAA,EAC7D,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAM,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC,KAAK;AACxC,WAAO,EAAE,IAAI,OAAO,SAAS,UAAU;AAAA,EACzC;AACF;AAEA,eAAsB,cACpB,UAC2B;AAC3B,MAAI;AACF,WAAO,MAAM,gBAAgB,QAAQ;AAAA,EACvC,QAAQ;AACN,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AACF;AAEO,SAAS,qBAAoC;AAClD,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,YAAM,MAAM,IAAI,SAAS;AACzB,UAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,GAAG;AAC7D,eAAO,IAAI;AAAA,MACb;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;;;AD3FA,eAAsB,oBACpB,SACkB;AAClB,QAAM,SAAkB,CAAC;AAEzB,QAAM,UAAU,QAAQ,eAAe,kBAAkB;AACzD,QAAM,EAAE,aAAa,YAAY,IAAI,oBAAoB,OAAO;AAChE,SAAO,KAAK,oBAAoB,aAAa,WAAW,CAAC;AAEzD,QAAM,cAAc,QAAQ,eAAe,QAAQ;AACnD,QAAM,SAAS,QAAQ,eAAe,mBAAmB;AACzD,SAAO,KAAK;AAAA,IACV,QAAQ,OAAO,KAAK,OAAO;AAAA,IAC3B,KAAK;AAAA,IACL,SAAS,OAAO,KACZ,0CAA0C,WAAW,MACrD,yCAAyC,OAAO,OAAO;AAAA,IAC3D,KAAK,OAAO,KACR,SACA;AAAA,EACN,CAAC;AAED,QAAM,OAAO,MAAM,cAAc,QAAQ,QAAQ;AACjD,SAAO,KAAK,aAAa,IAAI,CAAC;AAE9B,QAAM,eACJ,QAAQ,gBAAgBC,MAAK,KAAKC,SAAQ,GAAG,WAAW,eAAe;AACzE,SAAO,KAAK,MAAM,aAAa,YAAY,CAAC;AAE5C,QAAM,YAAY,QAAQ,aAAaD,MAAK,KAAKC,SAAQ,GAAG,SAAS;AACrE,SAAO,KAAK,eAAe,SAAS,CAAC;AACrC,SAAO,KAAK,MAAM,mBAAmB,SAAS,CAAC;AAE/C,SAAO;AACT;AAEA,SAAS,oBACP,aACA,aACO;AACP,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,MACT,KAAK;AAAA,IACP;AAAA,EACF;AACA,SAAO;AAAA,IACL,QAAQ,cAAc,SAAS;AAAA,IAC/B,KAAK;AAAA,IACL,SAAS,cACL,oDAAoD,WAAW,KAC/D,4BAA4B,WAAW;AAAA,IAC3C,KAAK,cACD,qEACA;AAAA,EACN;AACF;AAEA,SAAS,aAAa,MAA+B;AACnD,MAAI,KAAK,UAAU;AACjB,QAAI,KAAK,eAAe,UAAU;AAChC,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,SAAS;AAAA,MACX;AAAA,IACF;AACA,UAAM,MAAM,KAAK,SAAS;AAC1B,UAAM,OACJ,KAAK,qBAAqB,SACtB,KAAK,KAAK,gBAAgB,mBAC1B;AACN,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,gBAAgB,GAAG,GAAG,IAAI;AAAA,IACrC;AAAA,EACF;AACA,MACE,QAAQ,IAAI,sBAAsB,UAClC,QAAQ,IAAI,kBAAkB,SAAS,GACvC;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,SAAS;AAAA,IACT,KAAK;AAAA,EACP;AACF;AAEA,eAAe,aAAa,cAAsC;AAChE,MAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,MACT,KAAK;AAAA,IACP;AAAA,EACF;AACA,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,MAAM;AAC/C,UAAM,SAAS,KAAK,MAAM,GAAG;AAQ7B,UAAM,UAAU,OAAO,OAAO,cAAc,CAAC;AAC7C,UAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM;AAChC,UACE,OAAO,GAAG,YAAY,YACtB,EAAE,QAAQ,SAAS,oBAAoB,GACvC;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,QAAQ,GAAG,KAAK,GAAG;AAC3B,eAAO,EAAE,MAAM;AAAA,UACb,CAAC,MACC,OAAO,GAAG,YAAY,YACtB,EAAE,QAAQ,SAAS,oBAAoB;AAAA,QAC3C;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AACD,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,SAAS;AAAA,QACT,KAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,gCAAgC,YAAY;AAAA,IACvD;AAAA,EACF,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,kBAAkB,YAAY,KAAK,GAAG;AAAA,MAC/C,KAAK;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,eAAe,WAA0B;AAChD,QAAM,OAAOF,MAAK,KAAK,WAAW,gBAAgB;AAClD,QAAM,MAAMA,MAAK,KAAK,WAAW,0BAA0B;AAC3D,QAAM,WAAWE,YAAW,IAAI;AAChC,QAAM,UAAUA,YAAW,GAAG;AAC9B,MAAI,YAAY,SAAS;AACvB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,2BAA2BF,MAAK,SAAS,IAAI,CAAC,KAAKA,MAAK,SAAS,GAAG,CAAC;AAAA,IAChF;AAAA,EACF;AACA,QAAM,UAAU;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,UAAU,OAAO;AAAA,EACnB,EAAE,OAAO,CAAC,MAAmB,MAAM,IAAI;AACvC,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,SAAS,yBAAyB,QAAQ,KAAK,IAAI,CAAC;AAAA,IACpD,KAAK;AAAA,EACP;AACF;AAEA,eAAe,mBAAmB,WAAmC;AACnE,QAAM,WAAWA,MAAK,KAAK,WAAW,WAAW;AACjD,MAAI,CAACE,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,MACT,KAAK;AAAA,IACP;AAAA,EACF;AACA,MAAI;AACF,UAAM,WAAW,MAAM,SAAS,UAAU,MAAM;AAChD,UAAM,QAAQ,SAAS,MAAM,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACzD,UAAM,UAAU,MAAM,KAAK,CAAC,SAAS;AACnC,UAAI,SAAS,YAAa,QAAO;AACjC,UAAI,CAAC,KAAK,WAAW,WAAW,EAAG,QAAO;AAC1C,YAAM,OAAO,KAAK,YAAY,MAAM;AACpC,aAAO,SAAS,OAAO,SAAS;AAAA,IAClC,CAAC;AACD,QAAI,SAAS;AACX,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,MACT,KAAK;AAAA,IACP;AAAA,EACF,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,kBAAkB,QAAQ,KAAK,GAAG;AAAA,IAC7C;AAAA,EACF;AACF;;;AEvOA,eAAsB,mBACpB,SACA,kBACkB;AAClB,QAAM,SAAkB,CAAC;AACzB,QAAM,QAAQ,mBAAmB,QAAQ,eAAe;AACxD,QAAM,SAAS,MAAM,WAAW,QAAQ,gBAAgB;AAExD,MAAI,UAAU,QAAQ,MAAM,eAAe,WAAW,GAAG;AACvD,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,MAAM,gBAAgB;AAAA,MAC/B,KAAK;AAAA,IACP,CAAC;AAAA,EACH,WAAW,QAAQ,MAAM,gBAAgB,gBAAgB,GAAG;AAC1D,UAAM,YAAY,MAAM,mBAAmB,SAAS,MAAM,cAAc,IACpE,+DACA;AACJ,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SACE,GAAG,MAAM,cAAc,yBAAyB,gBAAgB,IAAI,SAAS;AAAA,MAC/E,KAAK;AAAA,IACP,CAAC;AAAA,EACH,OAAO;AACL,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,cAAc,gBAAgB;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,MAAI,UAAU,QAAQ,MAAM,gBAAgB,GAAG;AAC7C,UAAM,OAAO,QAAQ,MAAM,KAAK,oBAAI,KAAK,GAAG,QAAQ;AACpD,UAAM,QAAQ,MAAM,MAAM,gBAAgB;AAC1C,UAAM,eACJ,MAAM,yBAAyB,UAC/B,MAAM,yBAAyB,MAAM,gBACjC,6DACA;AACN,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,iBAAiB,eAAe,KAAK,CAAC,OAAO,YAAY;AAAA,IACpE,CAAC;AAAA,EACH,OAAO;AACL,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO,KAAK;AAAA,IACV,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,SAAS,oBAAoB,OAAO,kBAAkB,YAAY,UAAU;AAAA,IAC5E,KAAK,OAAO,kBACR,SACA;AAAA,EACN,CAAC;AAED,MAAI,UAAU,QAAQ,MAAM,mBAAmB,SAAS,GAAG;AACzD,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,SAAS,uBAAuB,MAAM,mBAAmB,KAAK,IAAI,CAAC;AAAA,IACrE,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC7CA,eAAsB,UACpB,SACuB;AACvB,QAAM,UACJ,QAAQ,mBAAmB,mBAAmB,KAAK;AAErD,QAAM,UAAmB,QAAQ,aAAa,OAC1C,CAAC,IACD,MAAM,oBAAoB,OAAO;AAErC,QAAM,UAAmB,QAAQ,aAAa,OAC1C,CAAC,IACD,MAAM,mBAAmB,SAAS,OAAO;AAE7C,QAAM,OAAgB,QAAQ,gBAAgB,OAC1C,CAAC,IACD,MAAM,qBAAqB,OAAO;AAEtC,QAAM,SAAuB,EAAE,SAAS,SAAS,SAAS,KAAK;AAE/D,MAAI,QAAQ,SAAS,MAAM;AACzB,WAAO;AAAA,MACL,QAAQ,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,MAC1C,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,aAAa,QAAQ,OAAO;AAAA,IACpC,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEA,eAAe,qBACb,SACkB;AAClB,MAAI;AACF,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,oBAAyB;AACnE,WAAO,MAAM,iBAAiB,OAAO;AAAA,EACvC,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL;AAAA,QACE,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,SAAS,8BAA8B,IAAI,MAAM,IAAI,EAAE,CAAC,KAAK,GAAG;AAAA,QAChE,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;","names":["existsSync","homedir","path","path","homedir","existsSync"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/helpers.ts"],"sourcesContent":["export interface CommandResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport function emit(result: CommandResult): void {\n if (result.stderr.length > 0) process.stderr.write(result.stderr);\n if (result.stdout.length > 0) process.stdout.write(result.stdout);\n if (result.exitCode !== 0) process.exitCode = result.exitCode;\n}\n\nexport function collectOption(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport function parsePositiveInt(value: string): number {\n const n = Number.parseInt(value, 10);\n if (!Number.isFinite(n) || n < 0) {\n throw new Error(`invalid --limit \"${value}\" (expected a non-negative integer)`);\n }\n return n;\n}\n\nexport async function readStdin(): Promise<string> {\n if (process.stdin.isTTY === true) return \"\";\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n"],"mappings":";;;AAMO,SAAS,KAAK,QAA6B;AAChD,MAAI,OAAO,OAAO,SAAS,EAAG,SAAQ,OAAO,MAAM,OAAO,MAAM;AAChE,MAAI,OAAO,OAAO,SAAS,EAAG,SAAQ,OAAO,MAAM,OAAO,MAAM;AAChE,MAAI,OAAO,aAAa,EAAG,SAAQ,WAAW,OAAO;AACvD;AAEO,SAAS,cAAc,OAAe,UAA8B;AACzE,SAAO,CAAC,GAAG,UAAU,KAAK;AAC5B;AAEO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,IAAI,OAAO,SAAS,OAAO,EAAE;AACnC,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,GAAG;AAChC,UAAM,IAAI,MAAM,oBAAoB,KAAK,qCAAqC;AAAA,EAChF;AACA,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,MAAI,QAAQ,MAAM,UAAU,KAAM,QAAO;AACzC,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ,OAAO;AACvC,WAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK,CAAC;AAAA,EACjE;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAC9C;","names":[]}
|
package/dist/chunk-PIYJQE4Z.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
assertAgentAuth,
|
|
4
|
-
listProviderStatuses
|
|
5
|
-
} from "./chunk-TWM7I2LU.js";
|
|
6
|
-
import {
|
|
7
|
-
isAgentProviderId,
|
|
8
|
-
readConfig,
|
|
9
|
-
writeConfig
|
|
10
|
-
} from "./chunk-WRUSDYYE.js";
|
|
11
|
-
|
|
12
|
-
// src/commands/agents.ts
|
|
13
|
-
async function runAgentsList() {
|
|
14
|
-
const config = await readConfig();
|
|
15
|
-
const statuses = await listProviderStatuses();
|
|
16
|
-
const lines = ["codealmanac agents\n"];
|
|
17
|
-
for (const status of statuses) {
|
|
18
|
-
const selected = status.id === config.agent.default ? "*" : " ";
|
|
19
|
-
const auth = status.authenticated ? "ready" : "not ready";
|
|
20
|
-
const installed = status.installed ? "installed" : "missing";
|
|
21
|
-
lines.push(
|
|
22
|
-
`${selected} ${status.id.padEnd(6)} ${installed.padEnd(9)} ${auth.padEnd(9)} ${status.detail}`
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
lines.push("\nChange default with: almanac set default-agent <claude|codex|cursor>");
|
|
26
|
-
return { stdout: `${lines.join("\n")}
|
|
27
|
-
`, stderr: "", exitCode: 0 };
|
|
28
|
-
}
|
|
29
|
-
async function runSetDefaultAgent(opts) {
|
|
30
|
-
if (!isAgentProviderId(opts.provider)) {
|
|
31
|
-
return {
|
|
32
|
-
stdout: "",
|
|
33
|
-
stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
|
|
34
|
-
`,
|
|
35
|
-
exitCode: 1
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
await assertAgentAuth({ provider: opts.provider });
|
|
40
|
-
} catch (err) {
|
|
41
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
42
|
-
return {
|
|
43
|
-
stdout: "",
|
|
44
|
-
stderr: `almanac: ${msg}
|
|
45
|
-
Run \`almanac agents list\` to see provider readiness.
|
|
46
|
-
`,
|
|
47
|
-
exitCode: 1
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
const config = await readConfig();
|
|
51
|
-
const next = {
|
|
52
|
-
...config,
|
|
53
|
-
agent: {
|
|
54
|
-
...config.agent,
|
|
55
|
-
default: opts.provider
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
await writeConfig(next);
|
|
59
|
-
return {
|
|
60
|
-
stdout: `codealmanac: default agent set to ${opts.provider}.
|
|
61
|
-
`,
|
|
62
|
-
stderr: "",
|
|
63
|
-
exitCode: 0
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
async function runSetAgentModel(opts) {
|
|
67
|
-
if (!isAgentProviderId(opts.provider)) {
|
|
68
|
-
return {
|
|
69
|
-
stdout: "",
|
|
70
|
-
stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
|
|
71
|
-
`,
|
|
72
|
-
exitCode: 1
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
const provider = opts.provider;
|
|
76
|
-
const config = await readConfig();
|
|
77
|
-
const model = opts.model !== void 0 && opts.model.length > 0 ? opts.model : null;
|
|
78
|
-
await writeConfig({
|
|
79
|
-
...config,
|
|
80
|
-
agent: {
|
|
81
|
-
...config.agent,
|
|
82
|
-
models: {
|
|
83
|
-
...config.agent.models,
|
|
84
|
-
[provider]: model
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
return {
|
|
89
|
-
stdout: model === null ? `codealmanac: ${provider} model reset to provider default.
|
|
90
|
-
` : `codealmanac: ${provider} model set to ${model}.
|
|
91
|
-
`,
|
|
92
|
-
stderr: "",
|
|
93
|
-
exitCode: 0
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export {
|
|
98
|
-
runAgentsList,
|
|
99
|
-
runSetDefaultAgent,
|
|
100
|
-
runSetAgentModel
|
|
101
|
-
};
|
|
102
|
-
//# sourceMappingURL=chunk-PIYJQE4Z.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/agents.ts"],"sourcesContent":["import { assertAgentAuth, listProviderStatuses } from \"../agent/providers.js\";\nimport {\n isAgentProviderId,\n readConfig,\n writeConfig,\n type AgentProviderId,\n} from \"../update/config.js\";\n\nexport interface AgentsResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport async function runAgentsList(): Promise<AgentsResult> {\n const config = await readConfig();\n const statuses = await listProviderStatuses();\n const lines = [\"codealmanac agents\\n\"];\n for (const status of statuses) {\n const selected = status.id === config.agent.default ? \"*\" : \" \";\n const auth = status.authenticated ? \"ready\" : \"not ready\";\n const installed = status.installed ? \"installed\" : \"missing\";\n lines.push(\n `${selected} ${status.id.padEnd(6)} ${installed.padEnd(9)} ${auth.padEnd(9)} ${status.detail}`,\n );\n }\n lines.push(\"\\nChange default with: almanac set default-agent <claude|codex|cursor>\");\n return { stdout: `${lines.join(\"\\n\")}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport interface SetDefaultAgentOptions {\n provider: string;\n}\n\nexport async function runSetDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n if (!isAgentProviderId(opts.provider)) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n \"Expected one of: claude, codex, cursor.\\n\",\n exitCode: 1,\n };\n }\n try {\n await assertAgentAuth({ provider: opts.provider });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n stdout: \"\",\n stderr:\n `almanac: ${msg}\\n` +\n \"Run `almanac agents list` to see provider readiness.\\n\",\n exitCode: 1,\n };\n }\n const config = await readConfig();\n const next = {\n ...config,\n agent: {\n ...config.agent,\n default: opts.provider,\n },\n };\n await writeConfig(next);\n return {\n stdout: `codealmanac: default agent set to ${opts.provider}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nexport async function runSetAgentModel(opts: {\n provider: string;\n model?: string;\n}): Promise<AgentsResult> {\n if (!isAgentProviderId(opts.provider)) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n \"Expected one of: claude, codex, cursor.\\n\",\n exitCode: 1,\n };\n }\n const provider = opts.provider as AgentProviderId;\n const config = await readConfig();\n const model =\n opts.model !== undefined && opts.model.length > 0 ? opts.model : null;\n await writeConfig({\n ...config,\n agent: {\n ...config.agent,\n models: {\n ...config.agent.models,\n [provider]: model,\n },\n },\n });\n return {\n stdout:\n model === null\n ? `codealmanac: ${provider} model reset to provider default.\\n`\n : `codealmanac: ${provider} model set to ${model}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n"],"mappings":";;;;;;;;;;;;AAcA,eAAsB,gBAAuC;AAC3D,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,WAAW,MAAM,qBAAqB;AAC5C,QAAM,QAAQ,CAAC,sBAAsB;AACrC,aAAW,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,OAAO,OAAO,MAAM,UAAU,MAAM;AAC5D,UAAM,OAAO,OAAO,gBAAgB,UAAU;AAC9C,UAAM,YAAY,OAAO,YAAY,cAAc;AACnD,UAAM;AAAA,MACJ,GAAG,QAAQ,IAAI,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,UAAU,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,IAAI,OAAO,MAAM;AAAA,IAC9F;AAAA,EACF;AACA,QAAM,KAAK,wEAAwE;AACnF,SAAO,EAAE,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA,GAAM,QAAQ,IAAI,UAAU,EAAE;AACpE;AAMA,eAAsB,mBACpB,MACuB;AACvB,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ;AAAA;AAAA,MAE1C,UAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI;AACF,UAAM,gBAAgB,EAAE,UAAU,KAAK,SAAS,CAAC;AAAA,EACnD,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,YAAY,GAAG;AAAA;AAAA;AAAA,MAEjB,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACA,QAAM,YAAY,IAAI;AACtB,SAAO;AAAA,IACL,QAAQ,qCAAqC,KAAK,QAAQ;AAAA;AAAA,IAC1D,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEA,eAAsB,iBAAiB,MAGb;AACxB,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ;AAAA;AAAA,MAE1C,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,WAAW,KAAK;AACtB,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,QACJ,KAAK,UAAU,UAAa,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ;AACnE,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,QAAQ;AAAA,QACN,GAAG,OAAO,MAAM;AAAA,QAChB,CAAC,QAAQ,GAAG;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,QACE,UAAU,OACN,gBAAgB,QAAQ;AAAA,IACxB,gBAAgB,QAAQ,iBAAiB,KAAK;AAAA;AAAA,IACpD,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;","names":[]}
|
package/dist/chunk-SSYMRT4I.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/agent/auth.ts
|
|
4
|
-
import { spawn, spawnSync } from "child_process";
|
|
5
|
-
import { createRequire } from "module";
|
|
6
|
-
import { dirname, join } from "path";
|
|
7
|
-
var AUTH_TIMEOUT_MS = 1e4;
|
|
8
|
-
function resolveClaudeExecutable() {
|
|
9
|
-
const result = spawnSync("sh", ["-lc", "command -v claude"], {
|
|
10
|
-
encoding: "utf8"
|
|
11
|
-
});
|
|
12
|
-
if (result.status !== 0) return void 0;
|
|
13
|
-
const found = result.stdout.trim().split("\n")[0]?.trim();
|
|
14
|
-
return found !== void 0 && found.length > 0 ? found : void 0;
|
|
15
|
-
}
|
|
16
|
-
function resolveCliJsPath() {
|
|
17
|
-
const require2 = createRequire(import.meta.url);
|
|
18
|
-
const entry = require2.resolve("@anthropic-ai/claude-agent-sdk");
|
|
19
|
-
return join(dirname(entry), "cli.js");
|
|
20
|
-
}
|
|
21
|
-
var defaultSpawnCli = (args) => {
|
|
22
|
-
const command = resolveClaudeExecutable() ?? "claude";
|
|
23
|
-
const child = spawn(command, args, {
|
|
24
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
25
|
-
});
|
|
26
|
-
return child;
|
|
27
|
-
};
|
|
28
|
-
var legacySdkSpawnCli = (args) => {
|
|
29
|
-
const cliPath = resolveCliJsPath();
|
|
30
|
-
const child = spawn(process.execPath, [cliPath, ...args], {
|
|
31
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
32
|
-
});
|
|
33
|
-
return child;
|
|
34
|
-
};
|
|
35
|
-
async function checkClaudeAuth(spawnCli = defaultSpawnCli) {
|
|
36
|
-
if (spawnCli === defaultSpawnCli) {
|
|
37
|
-
const status = await checkClaudeAuthWith(defaultSpawnCli);
|
|
38
|
-
if (status.loggedIn) return status;
|
|
39
|
-
return await checkClaudeAuthWith(legacySdkSpawnCli);
|
|
40
|
-
}
|
|
41
|
-
return await checkClaudeAuthWith(spawnCli);
|
|
42
|
-
}
|
|
43
|
-
async function checkClaudeAuthWith(spawnCli) {
|
|
44
|
-
let child;
|
|
45
|
-
try {
|
|
46
|
-
child = spawnCli(["auth", "status", "--json"]);
|
|
47
|
-
} catch {
|
|
48
|
-
return { loggedIn: false };
|
|
49
|
-
}
|
|
50
|
-
return new Promise((resolve) => {
|
|
51
|
-
let stdout = "";
|
|
52
|
-
let stderr = "";
|
|
53
|
-
let settled = false;
|
|
54
|
-
const settle = (value) => {
|
|
55
|
-
if (settled) return;
|
|
56
|
-
settled = true;
|
|
57
|
-
clearTimeout(timer);
|
|
58
|
-
resolve(value);
|
|
59
|
-
};
|
|
60
|
-
const timer = setTimeout(() => {
|
|
61
|
-
try {
|
|
62
|
-
child.kill("SIGTERM");
|
|
63
|
-
} catch {
|
|
64
|
-
}
|
|
65
|
-
settle({ loggedIn: false });
|
|
66
|
-
}, AUTH_TIMEOUT_MS);
|
|
67
|
-
child.stdout.on("data", (data) => {
|
|
68
|
-
stdout += data.toString();
|
|
69
|
-
});
|
|
70
|
-
child.stderr.on("data", (data) => {
|
|
71
|
-
stderr += data.toString();
|
|
72
|
-
});
|
|
73
|
-
child.on("error", () => {
|
|
74
|
-
settle({ loggedIn: false });
|
|
75
|
-
});
|
|
76
|
-
child.on("close", (code) => {
|
|
77
|
-
if (code !== 0 && stdout.trim().length === 0) {
|
|
78
|
-
void stderr;
|
|
79
|
-
settle({ loggedIn: false });
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
settle(parseClaudeAuthStatus(stdout.trim()));
|
|
84
|
-
} catch {
|
|
85
|
-
settle({ loggedIn: false });
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
function parseClaudeAuthStatus(raw) {
|
|
91
|
-
const parsed = JSON.parse(raw);
|
|
92
|
-
const loggedIn = parsed.loggedIn === true;
|
|
93
|
-
const out = { loggedIn };
|
|
94
|
-
if (typeof parsed.email === "string") out.email = parsed.email;
|
|
95
|
-
if (typeof parsed.subscriptionType === "string") {
|
|
96
|
-
out.subscriptionType = parsed.subscriptionType;
|
|
97
|
-
}
|
|
98
|
-
if (typeof parsed.authMethod === "string") {
|
|
99
|
-
out.authMethod = parsed.authMethod;
|
|
100
|
-
}
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
var UNAUTHENTICATED_MESSAGE = "not authenticated to Claude.\n\nOption 1 \u2014 use your Claude subscription (Pro/Max):\n claude auth login --claudeai\n\nOption 2 \u2014 use a pay-per-token API key:\n Get one at https://console.anthropic.com\n export ANTHROPIC_API_KEY=sk-ant-...\n\nVerify with: claude auth status";
|
|
104
|
-
async function assertClaudeAuth(spawnCli = defaultSpawnCli) {
|
|
105
|
-
const status = await checkClaudeAuth(spawnCli);
|
|
106
|
-
if (status.loggedIn) {
|
|
107
|
-
return status;
|
|
108
|
-
}
|
|
109
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
110
|
-
if (apiKey !== void 0 && apiKey.length > 0) {
|
|
111
|
-
return { loggedIn: true, authMethod: "apiKey" };
|
|
112
|
-
}
|
|
113
|
-
const err = new Error(UNAUTHENTICATED_MESSAGE);
|
|
114
|
-
err.code = "CLAUDE_AUTH_MISSING";
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export {
|
|
119
|
-
resolveClaudeExecutable,
|
|
120
|
-
defaultSpawnCli,
|
|
121
|
-
legacySdkSpawnCli,
|
|
122
|
-
checkClaudeAuth,
|
|
123
|
-
UNAUTHENTICATED_MESSAGE,
|
|
124
|
-
assertClaudeAuth
|
|
125
|
-
};
|
|
126
|
-
//# sourceMappingURL=chunk-SSYMRT4I.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent/auth.ts"],"sourcesContent":["import { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Claude auth gate — accepts either an active Claude subscription login\n * OR an `ANTHROPIC_API_KEY` environment variable.\n *\n * Claude Code owns subscription OAuth credentials. Users who are logged in\n * via `claude auth login --claudeai` should be able to run bootstrap/capture\n * without exporting an API key. Conversely, users on pay-per-token API keys\n * shouldn't be required to go through the OAuth flow.\n *\n * Current Claude Agent SDK packages no longer ship the old private\n * `cli.js` entrypoint, so the primary probe is the public Claude Code CLI:\n * `claude auth status --json`. We keep the SDK `cli.js` probe as a legacy\n * fallback for older SDK layouts.\n */\n\nexport interface ClaudeAuthStatus {\n loggedIn: boolean;\n email?: string;\n subscriptionType?: string;\n authMethod?: string;\n}\n\nexport interface SpawnedProcess {\n stdout: { on: (event: \"data\", cb: (data: Buffer | string) => void) => void };\n stderr: { on: (event: \"data\", cb: (data: Buffer | string) => void) => void };\n on: (event: \"close\" | \"error\", cb: (arg: number | null | Error) => void) => void;\n kill: (signal?: string) => void;\n}\n\n/**\n * The subprocess spawner is injectable so tests can replace it with a\n * fake that emits canned JSON without touching the filesystem.\n */\nexport type SpawnCliFn = (args: string[]) => SpawnedProcess;\n\nconst AUTH_TIMEOUT_MS = 10_000;\n\n/**\n * Resolve the installed Claude Code executable from PATH. The Agent SDK can\n * accept this path via `pathToClaudeCodeExecutable`, and the auth probe uses\n * the same binary so CodeAlmanac agrees with `claude auth status`.\n */\nexport function resolveClaudeExecutable(): string | undefined {\n const result = spawnSync(\"sh\", [\"-lc\", \"command -v claude\"], {\n encoding: \"utf8\",\n });\n if (result.status !== 0) return undefined;\n const found = result.stdout.trim().split(\"\\n\")[0]?.trim();\n return found !== undefined && found.length > 0 ? found : undefined;\n}\n\n/**\n * Resolve legacy `cli.js` from older `@anthropic-ai/claude-agent-sdk`\n * installs. SDK 0.2.129+ no longer ships this file; callers must treat\n * failure as expected and fall back to the public `claude` binary.\n */\nfunction resolveCliJsPath(): string {\n const require = createRequire(import.meta.url);\n const entry = require.resolve(\"@anthropic-ai/claude-agent-sdk\");\n return join(dirname(entry), \"cli.js\");\n}\n\n/**\n * Default subprocess spawner for production use — invokes the installed\n * Claude Code CLI.\n */\nexport const defaultSpawnCli: SpawnCliFn = (args: string[]) => {\n const command = resolveClaudeExecutable() ?? \"claude\";\n const child = spawn(command, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return child as unknown as SpawnedProcess;\n};\n\nexport const legacySdkSpawnCli: SpawnCliFn = (args: string[]) => {\n const cliPath = resolveCliJsPath();\n const child = spawn(process.execPath, [cliPath, ...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return child as unknown as SpawnedProcess;\n};\n\n/**\n * Check whether the user is authenticated via Claude subscription OAuth.\n *\n * Spawns `claude auth status --json`, falling back to the legacy SDK CLI\n * layout when available. On any failure (spawn error, non-JSON stdout,\n * non-zero exit, timeout) we return `{ loggedIn: false }` rather than\n * propagating the error — the caller will fall back to the\n * `ANTHROPIC_API_KEY` path and, if that's also missing, produce a clean\n * two-option error message.\n *\n * The 10s timeout guards against the CLI hanging on a broken network or\n * keychain prompt. In practice `auth status` is a cheap local read.\n */\nexport async function checkClaudeAuth(\n spawnCli: SpawnCliFn = defaultSpawnCli,\n): Promise<ClaudeAuthStatus> {\n if (spawnCli === defaultSpawnCli) {\n const status = await checkClaudeAuthWith(defaultSpawnCli);\n if (status.loggedIn) return status;\n return await checkClaudeAuthWith(legacySdkSpawnCli);\n }\n return await checkClaudeAuthWith(spawnCli);\n}\n\nasync function checkClaudeAuthWith(\n spawnCli: SpawnCliFn,\n): Promise<ClaudeAuthStatus> {\n let child: SpawnedProcess;\n try {\n child = spawnCli([\"auth\", \"status\", \"--json\"]);\n } catch {\n return { loggedIn: false };\n }\n\n return new Promise<ClaudeAuthStatus>((resolve) => {\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n const settle = (value: ClaudeAuthStatus): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(value);\n };\n\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGTERM\");\n } catch {\n // Kill can fail if the process already exited; nothing we can do.\n }\n settle({ loggedIn: false });\n }, AUTH_TIMEOUT_MS);\n\n child.stdout.on(\"data\", (data) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data) => {\n stderr += data.toString();\n });\n\n child.on(\"error\", () => {\n settle({ loggedIn: false });\n });\n\n child.on(\"close\", (code) => {\n // The SDK writes `{\"loggedIn\": false, ...}` to stdout with a zero\n // exit code when the user isn't signed in, so we only reject on\n // non-zero + empty stdout. An empty stdout with zero exit (shouldn't\n // happen in practice) also fails safely to `loggedIn: false`.\n if (code !== 0 && stdout.trim().length === 0) {\n // `stderr` isn't surfaced to the user here — the caller's error\n // message covers both auth paths — but it would be captured by\n // `stderr` if we ever wanted to log it for debugging.\n void stderr;\n settle({ loggedIn: false });\n return;\n }\n try {\n settle(parseClaudeAuthStatus(stdout.trim()));\n } catch {\n settle({ loggedIn: false });\n }\n });\n });\n}\n\nfunction parseClaudeAuthStatus(raw: string): ClaudeAuthStatus {\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n const loggedIn = parsed.loggedIn === true;\n const out: ClaudeAuthStatus = { loggedIn };\n if (typeof parsed.email === \"string\") out.email = parsed.email;\n if (typeof parsed.subscriptionType === \"string\") {\n out.subscriptionType = parsed.subscriptionType;\n }\n if (typeof parsed.authMethod === \"string\") {\n out.authMethod = parsed.authMethod;\n }\n return out;\n}\n\n/**\n * Human-readable error when neither auth path is available. The text is\n * deliberately verbose — users hitting this wall for the first time\n * deserve both options in front of them, not a terse hint.\n */\nexport const UNAUTHENTICATED_MESSAGE =\n \"not authenticated to Claude.\\n\\n\" +\n \"Option 1 — use your Claude subscription (Pro/Max):\\n\" +\n \" claude auth login --claudeai\\n\\n\" +\n \"Option 2 — use a pay-per-token API key:\\n\" +\n \" Get one at https://console.anthropic.com\\n\" +\n \" export ANTHROPIC_API_KEY=sk-ant-...\\n\\n\" +\n \"Verify with: claude auth status\";\n\n/**\n * Assert that at least one auth path is satisfied. Prefers subscription\n * auth (fewer surprises for Claude Pro/Max users) but accepts\n * `ANTHROPIC_API_KEY` as a fallback. On failure throws with\n * `code = \"CLAUDE_AUTH_MISSING\"` so callers can distinguish this from\n * other errors if they ever want to.\n *\n * Returns the resolved auth status so callers that want to display the\n * logged-in email in a preamble can do so without a second subprocess.\n */\nexport async function assertClaudeAuth(\n spawnCli: SpawnCliFn = defaultSpawnCli,\n): Promise<ClaudeAuthStatus> {\n const status = await checkClaudeAuth(spawnCli);\n if (status.loggedIn) {\n return status;\n }\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (apiKey !== undefined && apiKey.length > 0) {\n // Signal to callers that we're on the API-key path. Not \"loggedIn\"\n // in the OAuth sense, but the SDK will pick up the env var and\n // succeed — so we return a status that tells bootstrap/capture the\n // gate is open.\n return { loggedIn: true, authMethod: \"apiKey\" };\n }\n const err = new Error(UNAUTHENTICATED_MESSAGE);\n (err as { code?: string }).code = \"CLAUDE_AUTH_MISSING\";\n throw err;\n}\n\n// Internal re-export — helps keep the public type surface minimal while\n// still letting tests import the `ChildProcess` shape when needed.\nexport type { ChildProcess };\n"],"mappings":"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","names":["require"]}
|