codealmanac 0.2.5 → 0.2.6

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.
Files changed (53) hide show
  1. package/COMMERCIAL.md +9 -0
  2. package/LICENSE +133 -21
  3. package/README.md +11 -11
  4. package/dist/{agents-RVTQYE6A.js → agents-HYRWRHRX.js} +4 -4
  5. package/dist/{chunk-TT6ZP4GS.js → chunk-2BNDNGUR.js} +8 -4
  6. package/dist/{chunk-TT6ZP4GS.js.map → chunk-2BNDNGUR.js.map} +1 -1
  7. package/dist/{chunk-P5WGG4FJ.js → chunk-3E7JNMTZ.js} +28 -3
  8. package/dist/chunk-3E7JNMTZ.js.map +1 -0
  9. package/dist/{chunk-SMIK2YLU.js → chunk-DW32TL5W.js} +117 -83
  10. package/dist/chunk-DW32TL5W.js.map +1 -0
  11. package/dist/{chunk-6BJUYZ43.js → chunk-GPFVEF6V.js} +28 -18
  12. package/dist/chunk-GPFVEF6V.js.map +1 -0
  13. package/dist/{chunk-TILAKDN6.js → chunk-HJ3WREGP.js} +2 -2
  14. package/dist/{chunk-BGUID5BS.js → chunk-J7DNV2DH.js} +219 -26
  15. package/dist/chunk-J7DNV2DH.js.map +1 -0
  16. package/dist/{chunk-DL5BXZCX.js → chunk-K2JBCB7R.js} +40 -54
  17. package/dist/chunk-K2JBCB7R.js.map +1 -0
  18. package/dist/{chunk-MRRX4UQB.js → chunk-ODJAAJGZ.js} +2 -2
  19. package/dist/{chunk-447U3GQJ.js → chunk-PDFS5VFE.js} +17 -5
  20. package/dist/chunk-PDFS5VFE.js.map +1 -0
  21. package/dist/{chunk-GFUB57IT.js → chunk-VXDPUOQ5.js} +384 -207
  22. package/dist/chunk-VXDPUOQ5.js.map +1 -0
  23. package/dist/{cli-CL4ID7EO.js → cli-MKXCNEMW.js} +14 -14
  24. package/dist/codealmanac.js +1 -1
  25. package/dist/{config-ML2RCR7J.js → config-F7FKEQ7F.js} +3 -3
  26. package/dist/doctor-37UH3HT5.js +17 -0
  27. package/dist/{hook-2NP3UE7U.js → hook-4SVX446M.js} +4 -2
  28. package/dist/{register-commands-FBJ6XQ3L.js → register-commands-2F6SXLDI.js} +30 -21
  29. package/dist/register-commands-2F6SXLDI.js.map +1 -0
  30. package/dist/uninstall-C62ZOK32.js +17 -0
  31. package/dist/{update-P2IPG7RO.js → update-2UGOFN5C.js} +3 -3
  32. package/guides/mini.md +3 -3
  33. package/guides/reference.md +7 -7
  34. package/package.json +4 -3
  35. package/dist/chunk-447U3GQJ.js.map +0 -1
  36. package/dist/chunk-6BJUYZ43.js.map +0 -1
  37. package/dist/chunk-BGUID5BS.js.map +0 -1
  38. package/dist/chunk-DL5BXZCX.js.map +0 -1
  39. package/dist/chunk-GFUB57IT.js.map +0 -1
  40. package/dist/chunk-P5WGG4FJ.js.map +0 -1
  41. package/dist/chunk-SMIK2YLU.js.map +0 -1
  42. package/dist/doctor-DOLJRGS4.js +0 -17
  43. package/dist/register-commands-FBJ6XQ3L.js.map +0 -1
  44. package/dist/uninstall-DX6LFKMX.js +0 -15
  45. /package/dist/{agents-RVTQYE6A.js.map → agents-HYRWRHRX.js.map} +0 -0
  46. /package/dist/{chunk-TILAKDN6.js.map → chunk-HJ3WREGP.js.map} +0 -0
  47. /package/dist/{chunk-MRRX4UQB.js.map → chunk-ODJAAJGZ.js.map} +0 -0
  48. /package/dist/{cli-CL4ID7EO.js.map → cli-MKXCNEMW.js.map} +0 -0
  49. /package/dist/{config-ML2RCR7J.js.map → config-F7FKEQ7F.js.map} +0 -0
  50. /package/dist/{doctor-DOLJRGS4.js.map → doctor-37UH3HT5.js.map} +0 -0
  51. /package/dist/{hook-2NP3UE7U.js.map → hook-4SVX446M.js.map} +0 -0
  52. /package/dist/{uninstall-DX6LFKMX.js.map → uninstall-C62ZOK32.js.map} +0 -0
  53. /package/dist/{update-P2IPG7RO.js.map → update-2UGOFN5C.js.map} +0 -0
package/COMMERCIAL.md ADDED
@@ -0,0 +1,9 @@
1
+ # Commercial License
2
+
3
+ codealmanac is free for noncommercial use under the
4
+ [PolyForm Noncommercial License 1.0.0](./LICENSE).
5
+
6
+ Commercial use requires a separate paid commercial license from the copyright
7
+ holder.
8
+
9
+ To request a commercial license, contact Rohan Sheth.
package/LICENSE CHANGED
@@ -1,21 +1,133 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Rohan Sheth
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ # PolyForm Noncommercial License 1.0.0
2
+
3
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
4
+
5
+ Required Notice: Copyright (c) 2026 Rohan Sheth
6
+
7
+ ## Acceptance
8
+
9
+ In order to get any license under these terms, you must agree
10
+ to them as both strict obligations and conditions to all
11
+ your licenses.
12
+
13
+ ## Copyright License
14
+
15
+ The licensor grants you a copyright license for the
16
+ software to do everything you might do with the software
17
+ that would otherwise infringe the licensor's copyright
18
+ in it for any permitted purpose. However, you may
19
+ only distribute the software according to [Distribution
20
+ License](#distribution-license) and make changes or new works
21
+ based on the software according to [Changes and New Works
22
+ License](#changes-and-new-works-license).
23
+
24
+ ## Distribution License
25
+
26
+ The licensor grants you an additional copyright license
27
+ to distribute copies of the software. Your license
28
+ to distribute covers distributing the software with
29
+ changes and new works permitted by [Changes and New Works
30
+ License](#changes-and-new-works-license).
31
+
32
+ ## Notices
33
+
34
+ You must ensure that anyone who gets a copy of any part of
35
+ the software from you also gets a copy of these terms or the
36
+ URL for them above, as well as copies of any plain-text lines
37
+ beginning with `Required Notice:` that the licensor provided
38
+ with the software. For example:
39
+
40
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
41
+
42
+ ## Changes and New Works License
43
+
44
+ The licensor grants you an additional copyright license to
45
+ make changes and new works based on the software for any
46
+ permitted purpose.
47
+
48
+ ## Patent License
49
+
50
+ The licensor grants you a patent license for the software that
51
+ covers patent claims the licensor can license, or becomes able
52
+ to license, that you would infringe by using the software.
53
+
54
+ ## Noncommercial Purposes
55
+
56
+ Any noncommercial purpose is a permitted purpose.
57
+
58
+ ## Personal Uses
59
+
60
+ Personal use for research, experiment, and testing for
61
+ the benefit of public knowledge, personal study, private
62
+ entertainment, hobby projects, amateur pursuits, or religious
63
+ observance, without any anticipated commercial application,
64
+ is use for a permitted purpose.
65
+
66
+ ## Noncommercial Organizations
67
+
68
+ Use by any charitable organization, educational institution,
69
+ public research organization, public safety or health
70
+ organization, environmental protection organization,
71
+ or government institution is use for a permitted purpose
72
+ regardless of the source of funding or obligations resulting
73
+ from the funding.
74
+
75
+ ## Fair Use
76
+
77
+ You may have "fair use" rights for the software under the
78
+ law. These terms do not limit them.
79
+
80
+ ## No Other Rights
81
+
82
+ These terms do not allow you to sublicense or transfer any of
83
+ your licenses to anyone else, or prevent the licensor from
84
+ granting licenses to anyone else. These terms do not imply
85
+ any other licenses.
86
+
87
+ ## Patent Defense
88
+
89
+ If you make any written claim that the software infringes or
90
+ contributes to infringement of any patent, your patent license
91
+ for the software granted under these terms ends immediately. If
92
+ your company makes such a claim, your patent license ends
93
+ immediately for work on behalf of your company.
94
+
95
+ ## Violations
96
+
97
+ The first time you are notified in writing that you have
98
+ violated any of these terms, or done anything with the software
99
+ not covered by your licenses, your licenses can nonetheless
100
+ continue if you come into full compliance with these terms,
101
+ and take practical steps to correct past violations, within
102
+ 32 days of receiving notice. Otherwise, all your licenses
103
+ end immediately.
104
+
105
+ ## No Liability
106
+
107
+ ***As far as the law allows, the software comes as is, without
108
+ any warranty or condition, and the licensor will not be liable
109
+ to you for any damages arising out of these terms or the use
110
+ or nature of the software, under any kind of legal claim.***
111
+
112
+ ## Definitions
113
+
114
+ The **licensor** is the individual or entity offering these
115
+ terms, and the **software** is the software the licensor makes
116
+ available under these terms.
117
+
118
+ **You** refers to the individual or entity agreeing to these
119
+ terms.
120
+
121
+ **Your company** is any legal entity, sole proprietorship,
122
+ or other kind of organization that you work for, plus all
123
+ organizations that have control over, are under the control of,
124
+ or are under common control with that organization. **Control**
125
+ means ownership of substantially all the assets of an entity,
126
+ or the power to direct its management and policies by vote,
127
+ contract, or otherwise. Control can be direct or indirect.
128
+
129
+ **Your licenses** are all the licenses granted to you for the
130
+ software under these terms.
131
+
132
+ **Use** means anything you do with the software requiring one
133
+ of your licenses.
package/README.md CHANGED
@@ -42,17 +42,18 @@ codealmanac --yes
42
42
  ```
43
43
 
44
44
  `codealmanac` (the bare invocation) routes to a setup wizard that:
45
- - lets you choose a default provider: Claude, Codex, or Cursor,
46
- - lets you choose a provider-local model or inherit the provider default,
47
- - reports local provider readiness,
48
- - installs auto-capture hooks for supported agents,
49
- - installs the codealmanac guide into the selected provider's instruction surface: Claude uses `~/.claude/CLAUDE.md`, Codex uses `~/.codex/AGENTS.md`, and Cursor uses `.cursor/rules/codealmanac.mdc`.
45
+ - lets you choose a default agent: Claude, Codex, or Cursor,
46
+ - lets you choose a provider model or inherit the provider default,
47
+ - checks local agent readiness,
48
+ - installs auto-capture hooks for Claude, Codex, and Cursor,
49
+ - drops two agent guides into `~/.claude/` (`codealmanac.md` mini, `codealmanac-reference.md` full),
50
+ - appends `@~/.claude/codealmanac.md` to `~/.claude/CLAUDE.md` so every Claude Code session loads the mini guide.
50
51
 
51
52
  The setup is idempotent — safe to re-run. Opt out with `--skip-hook` or `--skip-guides`. Later, `almanac uninstall` reverses it.
52
53
 
53
54
  Two binaries ship, both pointing at the same entry: `codealmanac` (install surface) and `almanac` (day-to-day). Requires Node 20 or 22.
54
55
 
55
- `bootstrap` and `capture` invoke your configured default provider. Claude uses the bundled Claude Agent SDK, Codex uses `codex exec --json`, and Cursor uses `cursor-agent --print --output-format stream-json`. The query commands (`search`, `show`, `health`, `topics`) need no credentials at all.
56
+ `bootstrap` and `capture` invoke your configured default agent. Claude uses the bundled Claude Agent SDK, Codex uses `codex exec --json`, and Cursor uses `cursor-agent --print --output-format stream-json`. The query commands (`search`, `show`, `health`, `topics`) need no credentials at all.
56
57
 
57
58
  ## Authentication
58
59
 
@@ -98,7 +99,7 @@ codealmanac # interactive setup wizard; choose provider + mode
98
99
  # (or: codealmanac --yes)
99
100
 
100
101
  cd your-repo
101
- almanac bootstrap # default provider reads the repo and seeds pages + topic DAG
102
+ almanac bootstrap # default agent reads the repo and seeds pages + topic DAG
102
103
 
103
104
  almanac search "auth" # full-text search across pages
104
105
  almanac show checkout-flow # read a page
@@ -138,10 +139,9 @@ almanac capture --json <transcript> # structured CommandOutcome output
138
139
  almanac hook install --source all # auto-capture for Claude/Codex/Cursor
139
140
 
140
141
  # Setup & diagnose
141
- almanac agents list # provider readiness + current model
142
+ almanac agents list # provider readiness + default
142
143
  almanac agents use codex # change default provider
143
144
  almanac agents model claude claude-opus-4-6 # set provider model
144
- almanac agents model claude --default # inherit provider default
145
145
  almanac config list --show-origin # scriptable settings view
146
146
  almanac doctor # check install + wiki health
147
147
  almanac update # update to latest version
@@ -195,7 +195,7 @@ Intelligence lives in the prompt, not in the pipeline. Whenever a task calls for
195
195
 
196
196
  ## Contributing
197
197
 
198
- codealmanac is open source under the MIT license. To set up a development environment:
198
+ codealmanac is source-available for noncommercial use under the PolyForm Noncommercial License 1.0.0. Commercial use requires a separate paid commercial license; see [COMMERCIAL.md](./COMMERCIAL.md). To set up a development environment:
199
199
 
200
200
  ```bash
201
201
  git clone https://github.com/AlmanacCode/codealmanac.git
@@ -238,4 +238,4 @@ codealmanac is part of the [OpenAlmanac](https://www.openalmanac.org) family. Op
238
238
 
239
239
  ## License
240
240
 
241
- MIT. Copyright (c) 2026 Rohan Sheth. See [LICENSE](./LICENSE).
241
+ PolyForm Noncommercial License 1.0.0. Commercial use requires a separate paid commercial license; see [COMMERCIAL.md](./COMMERCIAL.md). Copyright (c) 2026 Rohan Sheth. See [LICENSE](./LICENSE).
@@ -8,9 +8,9 @@ import {
8
8
  runDeprecatedSetDefaultAgent,
9
9
  runSetAgentModel,
10
10
  runSetDefaultAgent
11
- } from "./chunk-6BJUYZ43.js";
12
- import "./chunk-BGUID5BS.js";
13
- import "./chunk-P5WGG4FJ.js";
11
+ } from "./chunk-GPFVEF6V.js";
12
+ import "./chunk-J7DNV2DH.js";
13
+ import "./chunk-3E7JNMTZ.js";
14
14
  import "./chunk-7JUX4ADQ.js";
15
15
  export {
16
16
  runAgentsDoctor,
@@ -22,4 +22,4 @@ export {
22
22
  runSetAgentModel,
23
23
  runSetDefaultAgent
24
24
  };
25
- //# sourceMappingURL=agents-RVTQYE6A.js.map
25
+ //# sourceMappingURL=agents-HYRWRHRX.js.map
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AGENT_PROVIDER_IDS,
4
+ formatEnabledAgentProviderList,
4
5
  getConfigPath,
5
6
  getProjectConfigPath,
6
7
  isAgentProviderId,
8
+ isEnabledAgentProviderId,
7
9
  parseConfigText,
8
10
  readConfig,
9
11
  readConfigWithOrigins,
10
12
  serializeConfig
11
- } from "./chunk-P5WGG4FJ.js";
13
+ } from "./chunk-3E7JNMTZ.js";
12
14
 
13
15
  // src/commands/config.ts
14
16
  import { mkdir, readFile, rename, writeFile } from "fs/promises";
@@ -42,8 +44,10 @@ function setConfigValue(config, key, rawValue) {
42
44
  };
43
45
  }
44
46
  if (key === "agent.default") {
45
- if (rawValue === null || !isAgentProviderId(rawValue)) {
46
- throw new Error("agent.default must be one of: claude, codex, cursor");
47
+ if (rawValue === null || !isAgentProviderId(rawValue) || !isEnabledAgentProviderId(rawValue)) {
48
+ throw new Error(
49
+ `agent.default must be one of: ${formatEnabledAgentProviderList()}`
50
+ );
47
51
  }
48
52
  return {
49
53
  ...config,
@@ -279,4 +283,4 @@ export {
279
283
  runConfigSet,
280
284
  runConfigUnset
281
285
  };
282
- //# sourceMappingURL=chunk-TT6ZP4GS.js.map
286
+ //# sourceMappingURL=chunk-2BNDNGUR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/config.ts","../src/commands/config-keys.ts"],"sourcesContent":["import { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport {\n CONFIG_KEYS,\n configEntries,\n formatConfigValue,\n getConfigValue,\n parseConfigKey,\n setConfigValue,\n type ConfigKey,\n} from \"./config-keys.js\";\nimport {\n getConfigPath,\n getProjectConfigPath,\n parseConfigText,\n readConfig,\n readConfigWithOrigins,\n serializeConfig,\n} from \"../update/config.js\";\n\nexport interface ConfigResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport async function runConfigList(opts: {\n json?: boolean;\n showOrigin?: boolean;\n} = {}): Promise<ConfigResult> {\n const { config, origins } = await readConfigWithOrigins({ cwd: process.cwd() });\n const rows = configEntries(config).map((entry) => ({\n ...entry,\n origin: origins[entry.key] ?? \"default\",\n }));\n if (opts.json === true) {\n return ok(`${JSON.stringify(rows, null, 2)}\\n`);\n }\n const lines = rows.map((row) => {\n const value = formatConfigValue(row.value);\n return opts.showOrigin === true\n ? `${row.key.padEnd(20)} ${value.padEnd(24)} ${row.origin}`\n : `${row.key.padEnd(20)} ${value}`;\n });\n return ok(`${lines.join(\"\\n\")}\\n`);\n}\n\nexport async function runConfigGet(opts: {\n key: string;\n json?: boolean;\n showOrigin?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n const { config, origins } = await readConfigWithOrigins({ cwd: process.cwd() });\n const value = getConfigValue(config, key);\n const origin = origins[key] ?? \"default\";\n if (opts.json === true) {\n return ok(`${JSON.stringify({ key, value, origin }, null, 2)}\\n`);\n }\n const rendered = formatConfigValue(value);\n return ok(\n opts.showOrigin === true\n ? `${key}=${rendered} (${origin})\\n`\n : `${rendered}\\n`,\n );\n}\n\nexport async function runConfigSet(opts: {\n key: string;\n value?: string;\n project?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n if (opts.project === true && key === \"update_notifier\") {\n return {\n stdout: \"\",\n stderr: \"almanac: update_notifier is user-level only.\\n\",\n exitCode: 1,\n };\n }\n if (opts.value === undefined) {\n return {\n stdout: \"\",\n stderr: `almanac: missing value for ${key}.\\n`,\n exitCode: 1,\n };\n }\n try {\n const file = targetConfigPath(opts.project === true);\n if (file === null) {\n return {\n stdout: \"\",\n stderr: \"almanac: no .almanac/ found for project config.\\n\",\n exitCode: 1,\n };\n }\n const next = setConfigValue(await readConfig({ cwd: process.cwd() }), key, opts.value);\n const raw = ensureRawObject(await readRawConfig(file));\n setRawConfigValue(raw, key, getConfigValue(next, key));\n await writeRawConfig(raw, file);\n return ok(\n `codealmanac: set ${key}=${formatConfigValue(getConfigValue(next, key))}` +\n `${opts.project === true ? \" in project config\" : \"\"}.\\n`,\n );\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return { stdout: \"\", stderr: `almanac: ${msg}\\n`, exitCode: 1 };\n }\n}\n\nexport async function runConfigUnset(opts: {\n key: string;\n project?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n if (opts.project === true && key === \"update_notifier\") {\n return {\n stdout: \"\",\n stderr: \"almanac: update_notifier is user-level only.\\n\",\n exitCode: 1,\n };\n }\n const file = targetConfigPath(opts.project === true);\n if (file === null) {\n return {\n stdout: \"\",\n stderr: \"almanac: no .almanac/ found for project config.\\n\",\n exitCode: 1,\n };\n }\n const raw = ensureRawObject(await readRawConfig(file));\n deleteRawConfigValue(raw, key);\n await writeRawConfig(raw, file);\n return ok(\n `codealmanac: unset ${key}${opts.project === true ? \" in project config\" : \"\"}.\\n`,\n );\n}\n\nfunction unknownKey(key: string): ConfigResult {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown config key '${key}'. ` +\n `Expected one of: ${CONFIG_KEYS.join(\", \")}.\\n`,\n exitCode: 1,\n };\n}\n\nfunction ok(stdout: string): ConfigResult {\n return { stdout, stderr: \"\", exitCode: 0 };\n}\n\nfunction targetConfigPath(project: boolean): string | null {\n return project ? getProjectConfigPath(process.cwd()) : getConfigPath();\n}\n\nasync function readRawConfig(file = getConfigPath()): Promise<unknown> {\n try {\n return parseConfigText(await readFile(file, \"utf8\"), file);\n } catch {\n return null;\n }\n}\n\nasync function writeRawConfig(\n raw: Record<string, unknown>,\n file = getConfigPath(),\n): Promise<void> {\n await mkdir(dirname(file), { recursive: true });\n const tmp = `${file}.tmp`;\n await writeFile(tmp, serializeConfig(raw, file), \"utf8\");\n await rename(tmp, file);\n}\n\nfunction ensureRawObject(raw: unknown): Record<string, unknown> {\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n return {};\n}\n\nfunction setRawConfigValue(\n raw: Record<string, unknown>,\n key: ConfigKey,\n value: string | boolean | null,\n): void {\n const parts = key.split(\".\");\n let cursor = raw;\n for (const part of parts.slice(0, -1)) {\n const next = cursor[part];\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\n cursor[part] = {};\n }\n cursor = cursor[part] as Record<string, unknown>;\n }\n const leaf = parts[parts.length - 1];\n if (leaf !== undefined) cursor[leaf] = value;\n}\n\nfunction deleteRawConfigValue(raw: Record<string, unknown>, key: ConfigKey): void {\n const parts = key.split(\".\");\n const parents: Array<{ object: Record<string, unknown>; key: string }> = [];\n let cursor: unknown = raw;\n for (const part of parts.slice(0, -1)) {\n if (cursor === null || typeof cursor !== \"object\" || Array.isArray(cursor)) {\n return;\n }\n const object = cursor as Record<string, unknown>;\n parents.push({ object, key: part });\n cursor = object[part];\n }\n if (cursor === null || typeof cursor !== \"object\" || Array.isArray(cursor)) {\n return;\n }\n const leaf = parts[parts.length - 1];\n if (leaf === undefined) return;\n delete (cursor as Record<string, unknown>)[leaf];\n\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = parents[i];\n if (parent === undefined) continue;\n const value = parent.object[parent.key];\n if (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0\n ) {\n delete parent.object[parent.key];\n }\n }\n}\n","import {\n AGENT_PROVIDER_IDS,\n isAgentProviderId,\n type AgentProviderId,\n type GlobalConfig,\n} from \"../update/config.js\";\n\nexport type ConfigKey =\n | \"update_notifier\"\n | \"agent.default\"\n | `agent.models.${AgentProviderId}`;\n\nexport interface ConfigEntry {\n key: ConfigKey;\n value: string | boolean | null;\n}\n\nexport const CONFIG_KEYS: ConfigKey[] = [\n \"update_notifier\",\n \"agent.default\",\n ...AGENT_PROVIDER_IDS.map((id) => `agent.models.${id}` as const),\n];\n\nexport function parseConfigKey(raw: string): ConfigKey | null {\n if (raw === \"update_notifier\" || raw === \"agent.default\") return raw;\n const prefix = \"agent.models.\";\n if (!raw.startsWith(prefix)) return null;\n const provider = raw.slice(prefix.length);\n if (!isAgentProviderId(provider)) return null;\n return `agent.models.${provider}`;\n}\n\nexport function getConfigValue(\n config: GlobalConfig,\n key: ConfigKey,\n): string | boolean | null {\n if (key === \"update_notifier\") return config.update_notifier;\n if (key === \"agent.default\") return config.agent.default;\n const provider = providerFromModelKey(key);\n return config.agent.models[provider] ?? null;\n}\n\nexport function setConfigValue(\n config: GlobalConfig,\n key: ConfigKey,\n rawValue: string | null,\n): GlobalConfig {\n if (key === \"update_notifier\") {\n return {\n ...config,\n update_notifier: parseBoolean(rawValue),\n };\n }\n if (key === \"agent.default\") {\n if (rawValue === null || !isAgentProviderId(rawValue)) {\n throw new Error(\"agent.default must be one of: claude, codex, cursor\");\n }\n return {\n ...config,\n agent: {\n ...config.agent,\n default: rawValue,\n },\n };\n }\n const provider = providerFromModelKey(key);\n const model = normalizeModel(rawValue);\n return {\n ...config,\n agent: {\n ...config.agent,\n models: {\n ...config.agent.models,\n [provider]: model,\n },\n },\n };\n}\n\nexport function configEntries(config: GlobalConfig): ConfigEntry[] {\n return CONFIG_KEYS.map((key) => ({\n key,\n value: getConfigValue(config, key),\n }));\n}\n\nexport function formatConfigValue(value: string | boolean | null): string {\n if (value === null) return \"default\";\n return String(value);\n}\n\nfunction providerFromModelKey(key: ConfigKey): AgentProviderId {\n const provider = key.slice(\"agent.models.\".length);\n if (!isAgentProviderId(provider)) {\n throw new Error(`not a model key: ${key}`);\n }\n return provider;\n}\n\nfunction parseBoolean(value: string | null): boolean {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw new Error(\"update_notifier must be true or false\");\n}\n\nfunction normalizeModel(value: string | null): string | null {\n if (value === null) return null;\n if (value === \"default\" || value === \"null\") return null;\n if (value.length === 0) {\n throw new Error(\"model must be non-empty, default, or null\");\n }\n return value;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/config.ts","../src/commands/config-keys.ts"],"sourcesContent":["import { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport {\n CONFIG_KEYS,\n configEntries,\n formatConfigValue,\n getConfigValue,\n parseConfigKey,\n setConfigValue,\n type ConfigKey,\n} from \"./config-keys.js\";\nimport {\n getConfigPath,\n getProjectConfigPath,\n parseConfigText,\n readConfig,\n readConfigWithOrigins,\n serializeConfig,\n} from \"../update/config.js\";\n\nexport interface ConfigResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport async function runConfigList(opts: {\n json?: boolean;\n showOrigin?: boolean;\n} = {}): Promise<ConfigResult> {\n const { config, origins } = await readConfigWithOrigins({ cwd: process.cwd() });\n const rows = configEntries(config).map((entry) => ({\n ...entry,\n origin: origins[entry.key] ?? \"default\",\n }));\n if (opts.json === true) {\n return ok(`${JSON.stringify(rows, null, 2)}\\n`);\n }\n const lines = rows.map((row) => {\n const value = formatConfigValue(row.value);\n return opts.showOrigin === true\n ? `${row.key.padEnd(20)} ${value.padEnd(24)} ${row.origin}`\n : `${row.key.padEnd(20)} ${value}`;\n });\n return ok(`${lines.join(\"\\n\")}\\n`);\n}\n\nexport async function runConfigGet(opts: {\n key: string;\n json?: boolean;\n showOrigin?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n const { config, origins } = await readConfigWithOrigins({ cwd: process.cwd() });\n const value = getConfigValue(config, key);\n const origin = origins[key] ?? \"default\";\n if (opts.json === true) {\n return ok(`${JSON.stringify({ key, value, origin }, null, 2)}\\n`);\n }\n const rendered = formatConfigValue(value);\n return ok(\n opts.showOrigin === true\n ? `${key}=${rendered} (${origin})\\n`\n : `${rendered}\\n`,\n );\n}\n\nexport async function runConfigSet(opts: {\n key: string;\n value?: string;\n project?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n if (opts.project === true && key === \"update_notifier\") {\n return {\n stdout: \"\",\n stderr: \"almanac: update_notifier is user-level only.\\n\",\n exitCode: 1,\n };\n }\n if (opts.value === undefined) {\n return {\n stdout: \"\",\n stderr: `almanac: missing value for ${key}.\\n`,\n exitCode: 1,\n };\n }\n try {\n const file = targetConfigPath(opts.project === true);\n if (file === null) {\n return {\n stdout: \"\",\n stderr: \"almanac: no .almanac/ found for project config.\\n\",\n exitCode: 1,\n };\n }\n const next = setConfigValue(await readConfig({ cwd: process.cwd() }), key, opts.value);\n const raw = ensureRawObject(await readRawConfig(file));\n setRawConfigValue(raw, key, getConfigValue(next, key));\n await writeRawConfig(raw, file);\n return ok(\n `codealmanac: set ${key}=${formatConfigValue(getConfigValue(next, key))}` +\n `${opts.project === true ? \" in project config\" : \"\"}.\\n`,\n );\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return { stdout: \"\", stderr: `almanac: ${msg}\\n`, exitCode: 1 };\n }\n}\n\nexport async function runConfigUnset(opts: {\n key: string;\n project?: boolean;\n}): Promise<ConfigResult> {\n const key = parseConfigKey(opts.key);\n if (key === null) return unknownKey(opts.key);\n if (opts.project === true && key === \"update_notifier\") {\n return {\n stdout: \"\",\n stderr: \"almanac: update_notifier is user-level only.\\n\",\n exitCode: 1,\n };\n }\n const file = targetConfigPath(opts.project === true);\n if (file === null) {\n return {\n stdout: \"\",\n stderr: \"almanac: no .almanac/ found for project config.\\n\",\n exitCode: 1,\n };\n }\n const raw = ensureRawObject(await readRawConfig(file));\n deleteRawConfigValue(raw, key);\n await writeRawConfig(raw, file);\n return ok(\n `codealmanac: unset ${key}${opts.project === true ? \" in project config\" : \"\"}.\\n`,\n );\n}\n\nfunction unknownKey(key: string): ConfigResult {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown config key '${key}'. ` +\n `Expected one of: ${CONFIG_KEYS.join(\", \")}.\\n`,\n exitCode: 1,\n };\n}\n\nfunction ok(stdout: string): ConfigResult {\n return { stdout, stderr: \"\", exitCode: 0 };\n}\n\nfunction targetConfigPath(project: boolean): string | null {\n return project ? getProjectConfigPath(process.cwd()) : getConfigPath();\n}\n\nasync function readRawConfig(file = getConfigPath()): Promise<unknown> {\n try {\n return parseConfigText(await readFile(file, \"utf8\"), file);\n } catch {\n return null;\n }\n}\n\nasync function writeRawConfig(\n raw: Record<string, unknown>,\n file = getConfigPath(),\n): Promise<void> {\n await mkdir(dirname(file), { recursive: true });\n const tmp = `${file}.tmp`;\n await writeFile(tmp, serializeConfig(raw, file), \"utf8\");\n await rename(tmp, file);\n}\n\nfunction ensureRawObject(raw: unknown): Record<string, unknown> {\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n return {};\n}\n\nfunction setRawConfigValue(\n raw: Record<string, unknown>,\n key: ConfigKey,\n value: string | boolean | null,\n): void {\n const parts = key.split(\".\");\n let cursor = raw;\n for (const part of parts.slice(0, -1)) {\n const next = cursor[part];\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\n cursor[part] = {};\n }\n cursor = cursor[part] as Record<string, unknown>;\n }\n const leaf = parts[parts.length - 1];\n if (leaf !== undefined) cursor[leaf] = value;\n}\n\nfunction deleteRawConfigValue(raw: Record<string, unknown>, key: ConfigKey): void {\n const parts = key.split(\".\");\n const parents: Array<{ object: Record<string, unknown>; key: string }> = [];\n let cursor: unknown = raw;\n for (const part of parts.slice(0, -1)) {\n if (cursor === null || typeof cursor !== \"object\" || Array.isArray(cursor)) {\n return;\n }\n const object = cursor as Record<string, unknown>;\n parents.push({ object, key: part });\n cursor = object[part];\n }\n if (cursor === null || typeof cursor !== \"object\" || Array.isArray(cursor)) {\n return;\n }\n const leaf = parts[parts.length - 1];\n if (leaf === undefined) return;\n delete (cursor as Record<string, unknown>)[leaf];\n\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = parents[i];\n if (parent === undefined) continue;\n const value = parent.object[parent.key];\n if (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0\n ) {\n delete parent.object[parent.key];\n }\n }\n}\n","import {\n AGENT_PROVIDER_IDS,\n formatEnabledAgentProviderList,\n isAgentProviderId,\n isEnabledAgentProviderId,\n type AgentProviderId,\n type GlobalConfig,\n} from \"../update/config.js\";\n\nexport type ConfigKey =\n | \"update_notifier\"\n | \"agent.default\"\n | `agent.models.${AgentProviderId}`;\n\nexport interface ConfigEntry {\n key: ConfigKey;\n value: string | boolean | null;\n}\n\nexport const CONFIG_KEYS: ConfigKey[] = [\n \"update_notifier\",\n \"agent.default\",\n ...AGENT_PROVIDER_IDS.map((id) => `agent.models.${id}` as const),\n];\n\nexport function parseConfigKey(raw: string): ConfigKey | null {\n if (raw === \"update_notifier\" || raw === \"agent.default\") return raw;\n const prefix = \"agent.models.\";\n if (!raw.startsWith(prefix)) return null;\n const provider = raw.slice(prefix.length);\n if (!isAgentProviderId(provider)) return null;\n return `agent.models.${provider}`;\n}\n\nexport function getConfigValue(\n config: GlobalConfig,\n key: ConfigKey,\n): string | boolean | null {\n if (key === \"update_notifier\") return config.update_notifier;\n if (key === \"agent.default\") return config.agent.default;\n const provider = providerFromModelKey(key);\n return config.agent.models[provider] ?? null;\n}\n\nexport function setConfigValue(\n config: GlobalConfig,\n key: ConfigKey,\n rawValue: string | null,\n): GlobalConfig {\n if (key === \"update_notifier\") {\n return {\n ...config,\n update_notifier: parseBoolean(rawValue),\n };\n }\n if (key === \"agent.default\") {\n if (\n rawValue === null ||\n !isAgentProviderId(rawValue) ||\n !isEnabledAgentProviderId(rawValue)\n ) {\n throw new Error(\n `agent.default must be one of: ${formatEnabledAgentProviderList()}`,\n );\n }\n return {\n ...config,\n agent: {\n ...config.agent,\n default: rawValue,\n },\n };\n }\n const provider = providerFromModelKey(key);\n const model = normalizeModel(rawValue);\n return {\n ...config,\n agent: {\n ...config.agent,\n models: {\n ...config.agent.models,\n [provider]: model,\n },\n },\n };\n}\n\nexport function configEntries(config: GlobalConfig): ConfigEntry[] {\n return CONFIG_KEYS.map((key) => ({\n key,\n value: getConfigValue(config, key),\n }));\n}\n\nexport function formatConfigValue(value: string | boolean | null): string {\n if (value === null) return \"default\";\n return String(value);\n}\n\nfunction providerFromModelKey(key: ConfigKey): AgentProviderId {\n const provider = key.slice(\"agent.models.\".length);\n if (!isAgentProviderId(provider)) {\n throw new Error(`not a model key: ${key}`);\n }\n return provider;\n}\n\nfunction parseBoolean(value: string | null): boolean {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw new Error(\"update_notifier must be true or false\");\n}\n\nfunction normalizeModel(value: string | null): string | null {\n if (value === null) return null;\n if (value === \"default\" || value === \"null\") return null;\n if (value.length === 0) {\n throw new Error(\"model must be non-empty, default, or null\");\n }\n return value;\n}\n"],"mappings":"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","names":[]}
@@ -9,9 +9,29 @@ import {
9
9
  import { existsSync } from "fs";
10
10
  import { mkdir, readFile, rename, writeFile } from "fs/promises";
11
11
  import { dirname, join } from "path";
12
- var AGENT_PROVIDER_IDS = ["claude", "codex", "cursor"];
12
+ var ALL_AGENT_PROVIDER_IDS = ["claude", "codex", "cursor"];
13
+ var AGENT_PROVIDER_IDS = ALL_AGENT_PROVIDER_IDS;
14
+ var DEFAULT_AGENT_PROVIDER_IDS = ["claude", "codex"];
15
+ function isCursorEnabled(env = process.env) {
16
+ return env.CODEALMANAC_ENABLE_CURSOR === "1";
17
+ }
18
+ function getEnabledAgentProviderIds(env = process.env) {
19
+ return isCursorEnabled(env) ? [...ALL_AGENT_PROVIDER_IDS] : [...DEFAULT_AGENT_PROVIDER_IDS];
20
+ }
21
+ function isEnabledAgentProviderId(value, env = process.env) {
22
+ return getEnabledAgentProviderIds(env).includes(value);
23
+ }
24
+ function formatEnabledAgentProviderList(env = process.env) {
25
+ return getEnabledAgentProviderIds(env).join(", ");
26
+ }
27
+ function disabledAgentProviderMessage(provider) {
28
+ if (provider === "cursor") {
29
+ return "cursor support is disabled. Set CODEALMANAC_ENABLE_CURSOR=1 to enable experimental Cursor support.";
30
+ }
31
+ return `${provider} support is disabled.`;
32
+ }
13
33
  function isAgentProviderId(value) {
14
- return AGENT_PROVIDER_IDS.includes(value);
34
+ return ALL_AGENT_PROVIDER_IDS.includes(value);
15
35
  }
16
36
  function defaultConfig() {
17
37
  return {
@@ -346,6 +366,11 @@ function pruneEmptyObjects(raw) {
346
366
 
347
367
  export {
348
368
  AGENT_PROVIDER_IDS,
369
+ isCursorEnabled,
370
+ getEnabledAgentProviderIds,
371
+ isEnabledAgentProviderId,
372
+ formatEnabledAgentProviderList,
373
+ disabledAgentProviderMessage,
349
374
  isAgentProviderId,
350
375
  getConfigPath,
351
376
  getLegacyConfigPath,
@@ -356,4 +381,4 @@ export {
356
381
  parseConfigText,
357
382
  serializeConfig
358
383
  };
359
- //# sourceMappingURL=chunk-P5WGG4FJ.js.map
384
+ //# sourceMappingURL=chunk-3E7JNMTZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/update/config.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n findNearestAlmanacDir,\n getGlobalAlmanacDir,\n getRepoAlmanacDir,\n} from \"../paths.js\";\n\nexport const ALL_AGENT_PROVIDER_IDS = [\"claude\", \"codex\", \"cursor\"] as const;\nexport type AgentProviderId = (typeof ALL_AGENT_PROVIDER_IDS)[number];\nexport const AGENT_PROVIDER_IDS = ALL_AGENT_PROVIDER_IDS;\nexport const DEFAULT_AGENT_PROVIDER_IDS = [\"claude\", \"codex\"] as const;\nexport type EnabledAgentProviderId =\n (typeof DEFAULT_AGENT_PROVIDER_IDS)[number] | AgentProviderId;\n\nexport function isCursorEnabled(env: NodeJS.ProcessEnv = process.env): boolean {\n return env.CODEALMANAC_ENABLE_CURSOR === \"1\";\n}\n\nexport function getEnabledAgentProviderIds(\n env: NodeJS.ProcessEnv = process.env,\n): AgentProviderId[] {\n return isCursorEnabled(env)\n ? [...ALL_AGENT_PROVIDER_IDS]\n : [...DEFAULT_AGENT_PROVIDER_IDS];\n}\n\nexport function isEnabledAgentProviderId(\n value: string,\n env: NodeJS.ProcessEnv = process.env,\n): value is AgentProviderId {\n return getEnabledAgentProviderIds(env).includes(value as AgentProviderId);\n}\n\nexport function formatEnabledAgentProviderList(\n env: NodeJS.ProcessEnv = process.env,\n): string {\n return getEnabledAgentProviderIds(env).join(\", \");\n}\n\nexport function disabledAgentProviderMessage(provider: string): string {\n if (provider === \"cursor\") {\n return \"cursor support is disabled. Set CODEALMANAC_ENABLE_CURSOR=1 to enable experimental Cursor support.\";\n }\n return `${provider} support is disabled.`;\n}\n\nexport function isAgentProviderId(value: string): value is AgentProviderId {\n return (ALL_AGENT_PROVIDER_IDS as readonly string[]).includes(value);\n}\n\nexport interface AgentConfig {\n /** Default provider for bootstrap/capture. Default: \"claude\". */\n default: AgentProviderId;\n /** Optional per-provider model override. `null` means provider default. */\n models: Partial<Record<AgentProviderId, string | null>>;\n}\n\n/**\n * `~/.almanac/config.toml` — global, cross-wiki configuration. Legacy\n * `config.json` is read and migrated forward on first normal access.\n *\n * Missing or malformed → defaults. Same tolerance as `UpdateState`:\n * the CLI must not be able to fail because this file drifted.\n */\nexport interface GlobalConfig {\n /** When `false`, suppress the pre-command update-nag banner. Default: true. */\n update_notifier: boolean;\n /** Agent-provider settings for bootstrap/capture. */\n agent: AgentConfig;\n}\n\nexport function defaultConfig(): GlobalConfig {\n return {\n update_notifier: true,\n agent: {\n default: \"claude\",\n models: {\n claude: null,\n codex: null,\n cursor: null,\n },\n },\n };\n}\n\nexport function getConfigPath(): string {\n return join(getGlobalAlmanacDir(), \"config.toml\");\n}\n\nexport function getLegacyConfigPath(): string {\n return join(getGlobalAlmanacDir(), \"config.json\");\n}\n\nexport function getProjectConfigPath(cwd: string): string | null {\n const repoRoot = findNearestAlmanacDir(cwd);\n return repoRoot === null ? null : join(getRepoAlmanacDir(repoRoot), \"config.toml\");\n}\n\nexport type ConfigOrigin = \"default\" | \"user\" | \"project\";\n\nexport interface ConfigReadOptions {\n path?: string;\n cwd?: string;\n}\n\nexport interface ConfigReadResult {\n config: GlobalConfig;\n origins: Record<string, ConfigOrigin>;\n raw: Record<string, unknown>;\n}\n\nexport async function readConfig(\n input?: string | ConfigReadOptions,\n): Promise<GlobalConfig> {\n return (await readConfigWithOrigins(input)).config;\n}\n\nexport async function readConfigWithOrigins(\n input?: string | ConfigReadOptions,\n): Promise<ConfigReadResult> {\n const opts = normalizeReadOptions(input);\n if (opts.path !== undefined) {\n const raw = await readRawConfigObject(opts.path);\n return {\n config: normalizeRawConfig(raw),\n origins: originsFromRaw(raw, \"user\"),\n raw,\n };\n }\n\n const file = getConfigPath();\n await migrateLegacyConfigIfNeeded(file);\n const userRaw = await readRawConfigObject(file);\n const mergedRaw = cloneJsonObject(userRaw);\n const origins = originsFromRaw(userRaw, \"user\");\n const projectPath = opts.cwd !== undefined ? getProjectConfigPath(opts.cwd) : null;\n if (projectPath !== null) {\n const projectRaw = await readRawConfigObject(projectPath);\n applyProjectConfig(mergedRaw, projectRaw);\n Object.assign(origins, originsFromRaw(projectRaw, \"project\", true));\n }\n return {\n config: normalizeRawConfig(mergedRaw),\n origins,\n raw: mergedRaw,\n };\n}\n\nfunction normalizeReadOptions(\n input?: string | ConfigReadOptions,\n): ConfigReadOptions {\n return typeof input === \"string\" ? { path: input } : input ?? {};\n}\n\nasync function migrateLegacyConfigIfNeeded(file: string): Promise<void> {\n if (existsSync(file)) return;\n const legacy = getLegacyConfigPath();\n if (!existsSync(legacy)) return;\n const raw = await readRawConfigObject(legacy);\n if (Object.keys(raw).length === 0) return;\n await writeConfig(normalizeRawConfig(raw), file);\n}\n\nfunction normalizeRawConfig(raw: Record<string, unknown>): GlobalConfig {\n const defaults = defaultConfig();\n const rawAgent =\n raw.agent !== undefined &&\n raw.agent !== null &&\n typeof raw.agent === \"object\" &&\n !Array.isArray(raw.agent)\n ? (raw.agent as Partial<AgentConfig>)\n : {};\n const rawDefault =\n typeof rawAgent.default === \"string\" &&\n isAgentProviderId(rawAgent.default)\n ? rawAgent.default\n : defaults.agent.default;\n const rawModels =\n rawAgent.models !== undefined &&\n rawAgent.models !== null &&\n typeof rawAgent.models === \"object\" &&\n !Array.isArray(rawAgent.models)\n ? (rawAgent.models as Record<string, unknown>)\n : {};\n const models: Partial<Record<AgentProviderId, string | null>> = {\n ...defaults.agent.models,\n };\n for (const id of AGENT_PROVIDER_IDS) {\n const value = rawModels[id];\n if (typeof value === \"string\" && value.length > 0) {\n models[id] = value === \"default\" || value === \"null\" ? null : value;\n } else if (value === null) {\n models[id] = null;\n }\n }\n return {\n update_notifier:\n typeof raw.update_notifier === \"boolean\"\n ? raw.update_notifier\n : defaults.update_notifier,\n agent: {\n default: rawDefault,\n models,\n },\n };\n}\n\nfunction applyProjectConfig(\n target: Record<string, unknown>,\n projectRaw: Record<string, unknown>,\n): void {\n const projectAgent =\n projectRaw.agent !== null &&\n typeof projectRaw.agent === \"object\" &&\n !Array.isArray(projectRaw.agent)\n ? projectRaw.agent as Record<string, unknown>\n : {};\n if (Object.keys(projectAgent).length === 0) return;\n const targetAgent =\n target.agent !== null &&\n typeof target.agent === \"object\" &&\n !Array.isArray(target.agent)\n ? target.agent as Record<string, unknown>\n : {};\n target.agent = targetAgent;\n if (typeof projectAgent.default === \"string\") {\n targetAgent.default = projectAgent.default;\n }\n const projectModels =\n projectAgent.models !== null &&\n typeof projectAgent.models === \"object\" &&\n !Array.isArray(projectAgent.models)\n ? projectAgent.models as Record<string, unknown>\n : {};\n if (Object.keys(projectModels).length === 0) return;\n const targetModels =\n targetAgent.models !== null &&\n typeof targetAgent.models === \"object\" &&\n !Array.isArray(targetAgent.models)\n ? targetAgent.models as Record<string, unknown>\n : {};\n targetAgent.models = targetModels;\n for (const id of AGENT_PROVIDER_IDS) {\n if (Object.prototype.hasOwnProperty.call(projectModels, id)) {\n targetModels[id] = projectModels[id];\n }\n }\n}\n\nfunction originsFromRaw(\n raw: Record<string, unknown>,\n origin: ConfigOrigin,\n agentOnly = false,\n): Record<string, ConfigOrigin> {\n const origins: Record<string, ConfigOrigin> = {};\n if (!agentOnly && Object.prototype.hasOwnProperty.call(raw, \"update_notifier\")) {\n origins.update_notifier = origin;\n }\n const agent =\n raw.agent !== null &&\n typeof raw.agent === \"object\" &&\n !Array.isArray(raw.agent)\n ? raw.agent as Record<string, unknown>\n : {};\n if (Object.prototype.hasOwnProperty.call(agent, \"default\")) {\n origins[\"agent.default\"] = origin;\n }\n const models =\n agent.models !== null &&\n typeof agent.models === \"object\" &&\n !Array.isArray(agent.models)\n ? agent.models as Record<string, unknown>\n : {};\n for (const id of AGENT_PROVIDER_IDS) {\n if (Object.prototype.hasOwnProperty.call(models, id)) {\n origins[`agent.models.${id}`] = origin;\n }\n }\n return origins;\n}\n\nasync function readSingleConfig(file: string): Promise<GlobalConfig> {\n let raw: string;\n try {\n raw = await readFile(file, \"utf8\");\n } catch {\n return defaultConfig();\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) return defaultConfig();\n try {\n return normalizeRawConfig(parseConfigText(trimmed, file));\n } catch {\n return defaultConfig();\n }\n}\n\nexport async function writeConfig(\n config: GlobalConfig | Partial<GlobalConfig>,\n path?: string,\n): Promise<void> {\n const file = path ?? getConfigPath();\n await mkdir(dirname(file), { recursive: true });\n const current = await readSingleConfig(file);\n const existingRaw = await readRawConfigObject(file);\n const stored = toStoredConfigPatch(config, current, existingRaw);\n const body = serializeConfig(stored, file);\n const tmp = `${file}.tmp`;\n await writeFile(tmp, body, \"utf8\");\n await rename(tmp, file);\n}\n\nfunction normalizeConfig(config: GlobalConfig | Partial<GlobalConfig>): GlobalConfig {\n const defaults = defaultConfig();\n return {\n update_notifier:\n typeof config.update_notifier === \"boolean\"\n ? config.update_notifier\n : defaults.update_notifier,\n agent: {\n default:\n config.agent !== undefined && isAgentProviderId(config.agent.default)\n ? config.agent.default\n : defaults.agent.default,\n models: {\n ...defaults.agent.models,\n ...(config.agent?.models ?? {}),\n },\n },\n };\n}\n\nasync function readRawConfigObject(\n path: string,\n): Promise<Record<string, unknown>> {\n try {\n return parseConfigText(await readFile(path, \"utf8\"), path);\n } catch {\n // Fall through to empty.\n }\n return {};\n}\n\nexport function parseConfigText(\n raw: string,\n path = \"config.toml\",\n): Record<string, unknown> {\n const trimmed = raw.trim();\n if (trimmed.length === 0) return {};\n if (path.endsWith(\".json\") || trimmed.startsWith(\"{\")) {\n const parsed = JSON.parse(trimmed) as unknown;\n return parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n }\n return parseTomlConfig(trimmed);\n}\n\nexport function serializeConfig(\n raw: Record<string, unknown>,\n path = \"config.toml\",\n): string {\n return path.endsWith(\".json\")\n ? `${JSON.stringify(raw, null, 2)}\\n`\n : serializeTomlConfig(raw);\n}\n\nfunction parseTomlConfig(raw: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n let section: string[] = [];\n for (const original of raw.split(/\\r?\\n/)) {\n const line = stripTomlComment(original).trim();\n if (line.length === 0) continue;\n const sectionMatch = line.match(/^\\[([A-Za-z0-9_.-]+)\\]$/);\n if (sectionMatch !== null) {\n section = sectionMatch[1]!.split(\".\");\n continue;\n }\n const eq = line.indexOf(\"=\");\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n const value = parseTomlValue(line.slice(eq + 1).trim());\n setObjectPath(result, [...section, key], value);\n }\n return result;\n}\n\nfunction serializeTomlConfig(raw: Record<string, unknown>): string {\n const lines: string[] = [];\n if (typeof raw.update_notifier === \"boolean\") {\n lines.push(`update_notifier = ${raw.update_notifier ? \"true\" : \"false\"}`);\n }\n const agent =\n raw.agent !== null &&\n typeof raw.agent === \"object\" &&\n !Array.isArray(raw.agent)\n ? raw.agent as Record<string, unknown>\n : {};\n if (typeof agent.default === \"string\") {\n if (lines.length > 0) lines.push(\"\");\n lines.push(\"[agent]\");\n lines.push(`default = ${tomlString(agent.default)}`);\n }\n const models =\n agent.models !== null &&\n typeof agent.models === \"object\" &&\n !Array.isArray(agent.models)\n ? agent.models as Record<string, unknown>\n : {};\n const modelLines: string[] = [];\n for (const id of AGENT_PROVIDER_IDS) {\n if (!Object.prototype.hasOwnProperty.call(models, id)) continue;\n const value = models[id] === null ? \"default\" : models[id];\n if (typeof value === \"string\" && value.length > 0) {\n modelLines.push(`${id} = ${tomlString(value)}`);\n }\n }\n if (modelLines.length > 0) {\n if (lines.length > 0) lines.push(\"\");\n lines.push(\"[agent.models]\", ...modelLines);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction stripTomlComment(line: string): string {\n let inString = false;\n let escaped = false;\n for (let i = 0; i < line.length; i++) {\n const ch = line[i];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n escaped = true;\n continue;\n }\n if (ch === \"\\\"\") inString = !inString;\n if (ch === \"#\" && !inString) return line.slice(0, i);\n }\n return line;\n}\n\nfunction parseTomlValue(raw: string): string | boolean {\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n if (raw.startsWith(\"\\\"\") && raw.endsWith(\"\\\"\")) {\n return JSON.parse(raw) as string;\n }\n return raw;\n}\n\nfunction tomlString(value: string): string {\n return JSON.stringify(value);\n}\n\nfunction setObjectPath(\n raw: Record<string, unknown>,\n path: string[],\n value: string | boolean,\n): void {\n let cursor = raw;\n for (const part of path.slice(0, -1)) {\n const next = cursor[part];\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\n cursor[part] = {};\n }\n cursor = cursor[part] as Record<string, unknown>;\n }\n const leaf = path[path.length - 1];\n if (leaf !== undefined) cursor[leaf] = value;\n}\n\nfunction toStoredConfigPatch(\n config: GlobalConfig | Partial<GlobalConfig>,\n current: GlobalConfig,\n raw: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized = normalizeConfig(config);\n const defaults = defaultConfig();\n const stored = cloneJsonObject(raw);\n\n if (\n config.update_notifier !== undefined &&\n normalized.update_notifier !== current.update_notifier\n ) {\n setStoredValue(\n stored,\n [\"update_notifier\"],\n normalized.update_notifier,\n defaults.update_notifier,\n );\n }\n\n if (config.agent !== undefined) {\n if (\n config.agent.default !== undefined &&\n normalized.agent.default !== current.agent.default\n ) {\n setStoredValue(\n stored,\n [\"agent\", \"default\"],\n normalized.agent.default,\n defaults.agent.default,\n );\n }\n\n const inputModels = config.agent.models ?? {};\n for (const id of AGENT_PROVIDER_IDS) {\n if (!Object.prototype.hasOwnProperty.call(inputModels, id)) continue;\n const value = normalized.agent.models[id] ?? null;\n const currentValue = current.agent.models[id] ?? null;\n const defaultValue = defaults.agent.models[id] ?? null;\n if (value !== currentValue) {\n setStoredValue(stored, [\"agent\", \"models\", id], value, defaultValue);\n }\n }\n }\n pruneEmptyObjects(stored);\n return stored;\n}\n\nfunction setStoredValue(\n raw: Record<string, unknown>,\n path: string[],\n value: string | boolean | null,\n defaultValue: string | boolean | null,\n): void {\n let cursor = raw;\n for (const part of path.slice(0, -1)) {\n const next = cursor[part];\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\n cursor[part] = {};\n }\n cursor = cursor[part] as Record<string, unknown>;\n }\n const leaf = path[path.length - 1];\n if (leaf === undefined) return;\n cursor[leaf] = value;\n if (value !== defaultValue) return;\n // Keep explicit defaults only when the caller changed the value to the\n // default. Unchanged explicit defaults are preserved by cloning `raw`.\n}\n\nfunction cloneJsonObject(raw: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(raw)) as Record<string, unknown>;\n}\n\nfunction pruneEmptyObjects(raw: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(raw)) {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n continue;\n }\n pruneEmptyObjects(value as Record<string, unknown>);\n if (Object.keys(value).length === 0) delete raw[key];\n }\n}\n"],"mappings":"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","names":[]}