@letrquan/book 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2747 -40
- package/README.md +132 -1311
- package/dist/additional-roots-H7UNAEHS.js +31 -0
- package/dist/{app-MOXXWEOY.js → app-GE4OHJOC.js} +5740 -4045
- package/dist/app-GE4OHJOC.js.map +1 -0
- package/dist/{chunk-5GDZ22YP.js → chunk-224FJZLH.js} +99 -108
- package/dist/chunk-224FJZLH.js.map +1 -0
- package/dist/chunk-2AAOF5B5.js +28 -0
- package/dist/chunk-2AAOF5B5.js.map +1 -0
- package/dist/{chunk-CAGOB2N4.js → chunk-4AS7LKKQ.js} +6 -4
- package/dist/chunk-4AS7LKKQ.js.map +1 -0
- package/dist/chunk-525CAZPY.js +120 -0
- package/dist/chunk-525CAZPY.js.map +1 -0
- package/dist/{chunk-URLQAXTR.js → chunk-56SIEMDX.js} +2 -2
- package/dist/chunk-56SIEMDX.js.map +1 -0
- package/dist/{chunk-XIFFTATU.js → chunk-5YHTKWJN.js} +5420 -4031
- package/dist/chunk-5YHTKWJN.js.map +1 -0
- package/dist/chunk-62QL5QUP.js +283 -0
- package/dist/chunk-62QL5QUP.js.map +1 -0
- package/dist/{chunk-KWHQ2XXL.js → chunk-67UZEWWF.js} +3 -3
- package/dist/chunk-67UZEWWF.js.map +1 -0
- package/dist/chunk-6OQQOMZR.js +785 -0
- package/dist/chunk-6OQQOMZR.js.map +1 -0
- package/dist/{chunk-GTVB4HEM.js → chunk-AQEQX4FF.js} +344 -315
- package/dist/chunk-AQEQX4FF.js.map +1 -0
- package/dist/chunk-C7ADUNPR.js +273 -0
- package/dist/chunk-C7ADUNPR.js.map +1 -0
- package/dist/{chunk-E75IPST5.js → chunk-EFJ2NH6E.js} +12 -58
- package/dist/chunk-EFJ2NH6E.js.map +1 -0
- package/dist/{chunk-5KLVH3PY.js → chunk-HQI7NYGX.js} +5 -3
- package/dist/chunk-HQI7NYGX.js.map +1 -0
- package/dist/chunk-IME7R2UI.js +6541 -0
- package/dist/chunk-IME7R2UI.js.map +1 -0
- package/dist/chunk-J4F2QLM2.js +273 -0
- package/dist/chunk-J4F2QLM2.js.map +1 -0
- package/dist/{chunk-MAQXCUR4.js → chunk-J62VZYOB.js} +444 -112
- package/dist/chunk-J62VZYOB.js.map +1 -0
- package/dist/chunk-JTPOI3KU.js +826 -0
- package/dist/chunk-JTPOI3KU.js.map +1 -0
- package/dist/{chunk-WKBO5R4O.js → chunk-KBQS35OV.js} +2 -2
- package/dist/chunk-KBQS35OV.js.map +1 -0
- package/dist/chunk-KXAYUIKP.js +90 -0
- package/dist/chunk-KXAYUIKP.js.map +1 -0
- package/dist/{chunk-VZQXX3WW.js → chunk-QYBD22H5.js} +1 -1
- package/dist/chunk-QYBD22H5.js.map +1 -0
- package/dist/{chunk-V4BOYR52.js → chunk-RFJ6Q6LE.js} +763 -198
- package/dist/chunk-RFJ6Q6LE.js.map +1 -0
- package/dist/{chunk-7N4J557C.js → chunk-RT5SATF7.js} +1 -1
- package/dist/chunk-RT5SATF7.js.map +1 -0
- package/dist/{chunk-C7D4NJ2D.js → chunk-S4JMID4G.js} +68 -26
- package/dist/chunk-S4JMID4G.js.map +1 -0
- package/dist/{chunk-ANSJPYGI.js → chunk-SOW4WRQP.js} +3 -3
- package/dist/chunk-SOW4WRQP.js.map +1 -0
- package/dist/{chunk-J7MIZ5CA.js → chunk-TLX3H2CL.js} +518 -79
- package/dist/chunk-TLX3H2CL.js.map +1 -0
- package/dist/{chunk-DGMQEI6Y.js → chunk-VPNLCMVR.js} +22 -9
- package/dist/chunk-VPNLCMVR.js.map +1 -0
- package/dist/{chunk-BTZZUCLI.js → chunk-W3XFHEF4.js} +173 -29
- package/dist/chunk-W3XFHEF4.js.map +1 -0
- package/dist/{chunk-574C6MQR.js → chunk-X4NJT436.js} +130 -60
- package/dist/chunk-X4NJT436.js.map +1 -0
- package/dist/chunk-X66I2NQO.js +137 -0
- package/dist/chunk-X66I2NQO.js.map +1 -0
- package/dist/chunk-XHAO3K7I.js +18 -0
- package/dist/chunk-XHAO3K7I.js.map +1 -0
- package/dist/{chunk-3U5IBM24.js → chunk-Y2VHN7TC.js} +2 -2
- package/dist/chunk-Y2VHN7TC.js.map +1 -0
- package/dist/chunk-YC6W4EJH.js +947 -0
- package/dist/chunk-YC6W4EJH.js.map +1 -0
- package/dist/{chunk-24AXE6SP.js → chunk-ZPSZZUWF.js} +1 -1
- package/dist/chunk-ZPSZZUWF.js.map +1 -0
- package/dist/{command-approvals-6Y57VCWZ.js → command-approvals-VBIU6BLM.js} +6 -5
- package/dist/context-CBOBDY5Q.js +38 -0
- package/dist/{hook-approvals-CTUFKEJT.js → hook-approvals-ZVT4V7IM.js} +5 -5
- package/dist/index.js +996 -155
- package/dist/index.js.map +1 -1
- package/dist/{interactive-assets-CCAAWVKH.js → interactive-assets-T4I4SEHU.js} +13 -9
- package/dist/interactive-assets-T4I4SEHU.js.map +1 -0
- package/dist/job-runner.js +159 -111
- package/dist/job-runner.js.map +1 -1
- package/dist/job-supervisor.d.ts +2 -0
- package/dist/job-supervisor.js +112 -0
- package/dist/job-supervisor.js.map +1 -0
- package/dist/loader-S77OVTHH.js +18 -0
- package/dist/{mcp-approvals-WNPH65BK.js → mcp-approvals-HJ2VDYMC.js} +5 -5
- package/dist/{mcp-config-YIJIES2C.js → mcp-config-RNB5LEVE.js} +3 -3
- package/dist/memory-store-DZUT5HUH.js +75 -0
- package/dist/{model-window-store-YFVNXCIP.js → model-window-store-MTSQ5JDJ.js} +8 -4
- package/dist/openai-compatible-2OB54YST.js +14 -0
- package/dist/{permission-approvals-76PVREFD.js → permission-approvals-YLV6UC5W.js} +5 -5
- package/dist/permissions-DHOKF3W2.js +45 -0
- package/dist/sandbox-WRYTZH3D.js +41 -0
- package/dist/{scrollback-LUKLIBVI.js → scrollback-35ME2GFX.js} +32 -22
- package/dist/scrollback-35ME2GFX.js.map +1 -0
- package/dist/sdk.d.ts +2219 -2361
- package/dist/sdk.js +53 -38
- package/dist/sdk.js.map +1 -1
- package/dist/settings-loader-JUNPGAAM.js +35 -0
- package/dist/settings-loader-JUNPGAAM.js.map +1 -0
- package/dist/{shell-selection-V6QAYXPX.js → shell-selection-CDHGJ4GC.js} +2 -2
- package/dist/shell-selection-CDHGJ4GC.js.map +1 -0
- package/package.json +23 -22
- package/dist/app-MOXXWEOY.js.map +0 -1
- package/dist/chunk-24AXE6SP.js.map +0 -1
- package/dist/chunk-3U5IBM24.js.map +0 -1
- package/dist/chunk-574C6MQR.js.map +0 -1
- package/dist/chunk-5GDZ22YP.js.map +0 -1
- package/dist/chunk-5KLVH3PY.js.map +0 -1
- package/dist/chunk-7N4J557C.js.map +0 -1
- package/dist/chunk-A7JLBK2Y.js +0 -3506
- package/dist/chunk-A7JLBK2Y.js.map +0 -1
- package/dist/chunk-ANSJPYGI.js.map +0 -1
- package/dist/chunk-BTZZUCLI.js.map +0 -1
- package/dist/chunk-C7D4NJ2D.js.map +0 -1
- package/dist/chunk-CAGOB2N4.js.map +0 -1
- package/dist/chunk-DGMQEI6Y.js.map +0 -1
- package/dist/chunk-E75IPST5.js.map +0 -1
- package/dist/chunk-EYGD6X2T.js +0 -180
- package/dist/chunk-EYGD6X2T.js.map +0 -1
- package/dist/chunk-GTVB4HEM.js.map +0 -1
- package/dist/chunk-J7MIZ5CA.js.map +0 -1
- package/dist/chunk-KWHQ2XXL.js.map +0 -1
- package/dist/chunk-L6LK2QIQ.js +0 -657
- package/dist/chunk-L6LK2QIQ.js.map +0 -1
- package/dist/chunk-MAQXCUR4.js.map +0 -1
- package/dist/chunk-S4XL7HOM.js +0 -402
- package/dist/chunk-S4XL7HOM.js.map +0 -1
- package/dist/chunk-URLQAXTR.js.map +0 -1
- package/dist/chunk-V4BOYR52.js.map +0 -1
- package/dist/chunk-VZQXX3WW.js.map +0 -1
- package/dist/chunk-WKBO5R4O.js.map +0 -1
- package/dist/chunk-XIFFTATU.js.map +0 -1
- package/dist/context-ZC5IFEAX.js +0 -25
- package/dist/interactive-assets-CCAAWVKH.js.map +0 -1
- package/dist/loader-4IDS2RIE.js +0 -15
- package/dist/openai-compatible-RHZUBHV6.js +0 -10
- package/dist/permissions-CHCKTFQQ.js +0 -28
- package/dist/sandbox-CNVAQDA7.js +0 -23
- package/dist/scrollback-LUKLIBVI.js.map +0 -1
- package/dist/settings-loader-M2QP5TX2.js +0 -21
- package/patches/ink+6.8.0.patch +0 -13
- package/scripts/apply-ink-patch.mjs +0 -29
- package/scripts/ink-patch.mjs +0 -59
- package/scripts/verify-ink-patch.mjs +0 -11
- /package/dist/{command-approvals-6Y57VCWZ.js.map → additional-roots-H7UNAEHS.js.map} +0 -0
- /package/dist/{context-ZC5IFEAX.js.map → command-approvals-VBIU6BLM.js.map} +0 -0
- /package/dist/{hook-approvals-CTUFKEJT.js.map → context-CBOBDY5Q.js.map} +0 -0
- /package/dist/{loader-4IDS2RIE.js.map → hook-approvals-ZVT4V7IM.js.map} +0 -0
- /package/dist/{mcp-approvals-WNPH65BK.js.map → loader-S77OVTHH.js.map} +0 -0
- /package/dist/{mcp-config-YIJIES2C.js.map → mcp-approvals-HJ2VDYMC.js.map} +0 -0
- /package/dist/{model-window-store-YFVNXCIP.js.map → mcp-config-RNB5LEVE.js.map} +0 -0
- /package/dist/{openai-compatible-RHZUBHV6.js.map → memory-store-DZUT5HUH.js.map} +0 -0
- /package/dist/{permission-approvals-76PVREFD.js.map → model-window-store-MTSQ5JDJ.js.map} +0 -0
- /package/dist/{permissions-CHCKTFQQ.js.map → openai-compatible-2OB54YST.js.map} +0 -0
- /package/dist/{sandbox-CNVAQDA7.js.map → permission-approvals-YLV6UC5W.js.map} +0 -0
- /package/dist/{settings-loader-M2QP5TX2.js.map → permissions-DHOKF3W2.js.map} +0 -0
- /package/dist/{shell-selection-V6QAYXPX.js.map → sandbox-WRYTZH3D.js.map} +0 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
// src/settings.ts
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
var permissionRuleSchema = z.string().min(1);
|
|
4
|
+
function unboundedInt() {
|
|
5
|
+
return z.number().check((ctx) => {
|
|
6
|
+
if (!Number.isInteger(ctx.value)) {
|
|
7
|
+
ctx.issues.push({ code: "invalid_type", expected: "int", input: ctx.value });
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
}
|
|
4
11
|
var sandboxSchema = z.object({
|
|
5
12
|
enabled: z.boolean().default(false),
|
|
6
13
|
failIfUnavailable: z.boolean().default(false),
|
|
@@ -11,11 +18,11 @@ var sandboxSchema = z.object({
|
|
|
11
18
|
allowWrite: z.array(z.string()).default([]),
|
|
12
19
|
denyWrite: z.array(z.string()).default([]),
|
|
13
20
|
denyRead: z.array(z.string()).default([])
|
|
14
|
-
}).
|
|
21
|
+
}).prefault({}),
|
|
15
22
|
network: z.object({
|
|
16
23
|
allowedDomains: z.array(z.string()).default([]),
|
|
17
24
|
deniedDomains: z.array(z.string()).default([])
|
|
18
|
-
}).
|
|
25
|
+
}).prefault({})
|
|
19
26
|
});
|
|
20
27
|
var projectAllowRuleChoiceSchema = z.enum(["approved", "rejected"]);
|
|
21
28
|
var permissionsSchema = z.object({
|
|
@@ -26,7 +33,7 @@ var permissionsSchema = z.object({
|
|
|
26
33
|
* Decisions about `allow` rules the project layer declared. A project rule
|
|
27
34
|
* with no `approved` entry here never reaches the resolved allow list.
|
|
28
35
|
*/
|
|
29
|
-
projectAllowRules: z.record(projectAllowRuleChoiceSchema).default({})
|
|
36
|
+
projectAllowRules: z.record(z.string(), projectAllowRuleChoiceSchema).default({})
|
|
30
37
|
});
|
|
31
38
|
var hookEntrySchema = z.object({
|
|
32
39
|
/** Tool(specifier) pattern to filter which events trigger this hook. */
|
|
@@ -34,7 +41,7 @@ var hookEntrySchema = z.object({
|
|
|
34
41
|
/** Shell command to run (passed through system shell). */
|
|
35
42
|
command: z.string().min(1),
|
|
36
43
|
/** Extra environment variables for this hook. */
|
|
37
|
-
env: z.record(z.string()).default({})
|
|
44
|
+
env: z.record(z.string(), z.string()).default({})
|
|
38
45
|
});
|
|
39
46
|
var projectHookChoiceSchema = z.enum(["approved", "rejected"]);
|
|
40
47
|
var HOOK_EVENTS = [
|
|
@@ -66,7 +73,7 @@ var hooksSchema = z.object({
|
|
|
66
73
|
* entry whose fingerprint has no `approved` record here never reaches the
|
|
67
74
|
* resolved hooks.
|
|
68
75
|
*/
|
|
69
|
-
projectEntries: z.record(projectHookChoiceSchema).default({})
|
|
76
|
+
projectEntries: z.record(z.string(), projectHookChoiceSchema).default({})
|
|
70
77
|
});
|
|
71
78
|
var retrySettingsSchema = z.object({
|
|
72
79
|
maxAttempts: z.number().int().min(0).max(15).default(10),
|
|
@@ -89,11 +96,15 @@ var retrySettingsSchema = z.object({
|
|
|
89
96
|
watchdog: z.boolean().default(false),
|
|
90
97
|
/**
|
|
91
98
|
* How many times a turn may be re-sent after a transport fault that left the
|
|
92
|
-
* work intact — a stalled stream, a dropped socket
|
|
99
|
+
* work intact — a stalled stream, a dropped socket — and how many times an
|
|
100
|
+
* empty completion may be re-asked. The two are counted separately per turn;
|
|
101
|
+
* this only says how many of each a turn gets.
|
|
93
102
|
*
|
|
94
103
|
* `maxAttempts` covers connection setup only; once a 200 response is streaming
|
|
95
104
|
* it is out of scope, so without this a single 20-second provider silence ended
|
|
96
|
-
* the run. Set to 0 to restore that behavior exactly.
|
|
105
|
+
* the run. Set to 0 to restore that behavior exactly for transport faults. An
|
|
106
|
+
* empty completion still gets one retry, the floor every earlier version spent,
|
|
107
|
+
* so a run does not end on the first blank answer.
|
|
97
108
|
*/
|
|
98
109
|
streamReissueAttempts: z.number().int().min(0).max(10).default(3),
|
|
99
110
|
/**
|
|
@@ -106,8 +117,8 @@ var retrySettingsSchema = z.object({
|
|
|
106
117
|
var effortLevelSchema = z.enum(["low", "medium", "high", "xhigh", "max"]);
|
|
107
118
|
var providerModelSchema = z.object({
|
|
108
119
|
label: z.string().optional(),
|
|
109
|
-
contextWindow:
|
|
110
|
-
maxOutputTokens:
|
|
120
|
+
contextWindow: unboundedInt().positive().optional(),
|
|
121
|
+
maxOutputTokens: unboundedInt().positive().optional(),
|
|
111
122
|
/** Whether this model accepts image input. Unknown models remain optimistic. */
|
|
112
123
|
vision: z.boolean().optional(),
|
|
113
124
|
/**
|
|
@@ -131,7 +142,7 @@ var providerConfigSchema = z.object({
|
|
|
131
142
|
baseURL: z.string().min(1).optional(),
|
|
132
143
|
baseUrl: z.string().min(1).optional(),
|
|
133
144
|
apiKey: z.string().min(1).optional(),
|
|
134
|
-
models: z.record(providerModelSchema).default({})
|
|
145
|
+
models: z.record(z.string(), providerModelSchema).default({})
|
|
135
146
|
});
|
|
136
147
|
var continuationSettingsSchema = z.object({
|
|
137
148
|
enabled: z.boolean().default(false),
|
|
@@ -150,9 +161,10 @@ var continuationSettingsSchema = z.object({
|
|
|
150
161
|
* predates continuation and needs no continuation to happen: a headless run in
|
|
151
162
|
* the default permission mode answers every prompt `deny`, so the model can
|
|
152
163
|
* re-issue a refused call forever while `toolCalls.length > 0` keeps the
|
|
153
|
-
* turn-end gate from ever firing. None of the existing anti-loop signals
|
|
154
|
-
* either — the repeated-failure breaker
|
|
155
|
-
* and `toolCallStats.failures` excludes
|
|
164
|
+
* turn-end gate from ever firing. None of the existing anti-loop signals stop it
|
|
165
|
+
* either — the repeated-failure breaker only annotates a repeated call and never
|
|
166
|
+
* sees the loop's own permission refusals, and `toolCallStats.failures` excludes
|
|
167
|
+
* `blocked` by construction.
|
|
156
168
|
*
|
|
157
169
|
* 0 disables the guard.
|
|
158
170
|
*/
|
|
@@ -160,12 +172,25 @@ var continuationSettingsSchema = z.object({
|
|
|
160
172
|
/** Turns between host-authored work-state messages; 0 disables them. */
|
|
161
173
|
planRefreshTurns: z.number().int().min(0).max(500).default(25),
|
|
162
174
|
/** Wall-clock ceiling for one continued run; 0 means no ceiling. */
|
|
163
|
-
maxWallClockMs:
|
|
175
|
+
maxWallClockMs: unboundedInt().min(0).default(0)
|
|
164
176
|
});
|
|
165
177
|
var memorySettingsSchema = z.object({
|
|
166
178
|
enabled: z.boolean().default(true),
|
|
167
179
|
autoSave: z.boolean().default(true),
|
|
168
|
-
requireApproval: z.boolean().default(
|
|
180
|
+
requireApproval: z.boolean().default(false),
|
|
181
|
+
quarantineExternal: z.boolean().default(true),
|
|
182
|
+
/**
|
|
183
|
+
* Phase 1b: at the next session start, extract memories the model missed from idle sessions.
|
|
184
|
+
* Off by default since 2026-10: on the owner's machine it wrote 8 of the 10 memories and all the
|
|
185
|
+
* wrong ones, copied from delegated spec runs; it stays available as an opt-in.
|
|
186
|
+
*/
|
|
187
|
+
extraction: z.object({
|
|
188
|
+
enabled: z.boolean().default(false),
|
|
189
|
+
idleHours: z.number().min(0).default(3),
|
|
190
|
+
minMessages: unboundedInt().min(1).default(10),
|
|
191
|
+
maxPerSession: z.number().int().min(1).max(20).default(5),
|
|
192
|
+
maxSessionsPerRun: z.number().int().min(1).max(20).default(3)
|
|
193
|
+
}).prefault({})
|
|
169
194
|
});
|
|
170
195
|
var agentSettingsSchema = z.object({
|
|
171
196
|
mode: z.enum(["adaptive", "manual", "off"]).default("adaptive"),
|
|
@@ -176,7 +201,7 @@ var agentSettingsSchema = z.object({
|
|
|
176
201
|
includeUntrackedInSnapshot: z.boolean().default(true),
|
|
177
202
|
telemetry: z.boolean().default(true),
|
|
178
203
|
retentionDays: z.number().int().min(1).max(3650).default(30),
|
|
179
|
-
checks: z.record(z.union([z.string().min(1), z.array(z.string().min(1)).min(1)])).default({}),
|
|
204
|
+
checks: z.record(z.string(), z.union([z.string().min(1), z.array(z.string().min(1)).min(1)])).default({}),
|
|
180
205
|
/**
|
|
181
206
|
* Wall-clock ceiling for one `Check` run. The 120s default suits a focused
|
|
182
207
|
* suite; a full `npm test` on a large repository routinely exceeds it, and a
|
|
@@ -184,6 +209,8 @@ var agentSettingsSchema = z.object({
|
|
|
184
209
|
* reported as a failing suite. Raise it per project rather than per invocation.
|
|
185
210
|
*/
|
|
186
211
|
checkTimeoutMs: z.number().int().min(1e3).max(72e5).default(12e4),
|
|
212
|
+
/** Ceiling on a foreground delegation via the Task tool; overrides the 1800s default. */
|
|
213
|
+
taskTimeoutMs: unboundedInt().min(1e3).optional(),
|
|
187
214
|
/**
|
|
188
215
|
* Simultaneous agent worktrees per repository; 0 disables the check.
|
|
189
216
|
*
|
|
@@ -209,20 +236,21 @@ var agentSettingsSchema = z.object({
|
|
|
209
236
|
* Worktrees share the filesystem with the workspace, so exhausting it breaks
|
|
210
237
|
* the root agent's own Edit and Bash, not just the child's.
|
|
211
238
|
*/
|
|
212
|
-
minFreeDiskBytes:
|
|
239
|
+
minFreeDiskBytes: unboundedInt().min(0).default(2 * 1024 * 1024 * 1024),
|
|
213
240
|
profiles: z.record(
|
|
241
|
+
z.string(),
|
|
214
242
|
z.object({
|
|
215
243
|
model: z.string().min(1).optional(),
|
|
216
244
|
effort: effortLevelSchema.optional(),
|
|
217
|
-
maxTurns:
|
|
245
|
+
maxTurns: unboundedInt().min(1).optional(),
|
|
218
246
|
color: z.string().optional()
|
|
219
247
|
})
|
|
220
248
|
).default({}),
|
|
221
|
-
ui: z.object({ enabled: z.boolean().default(true) }).
|
|
249
|
+
ui: z.object({ enabled: z.boolean().default(true) }).prefault({}),
|
|
222
250
|
routing: z.object({
|
|
223
251
|
inlineSearchBudget: z.number().int().min(1).max(20).default(3),
|
|
224
252
|
exploreReminder: z.boolean().default(true)
|
|
225
|
-
}).
|
|
253
|
+
}).prefault({}),
|
|
226
254
|
forwardTextEvents: z.boolean().default(false)
|
|
227
255
|
});
|
|
228
256
|
var toolDiscoverySettingsSchema = z.object({
|
|
@@ -256,7 +284,7 @@ var mcpSettingsSchema = z.object({
|
|
|
256
284
|
* Per-server trust decisions for workspace `.mcp.json` declarations.
|
|
257
285
|
* User-global servers (<BOOK_HOME>/.book/mcp.json) never require approval.
|
|
258
286
|
*/
|
|
259
|
-
projectServers: z.record(mcpProjectServerChoiceSchema).default({})
|
|
287
|
+
projectServers: z.record(z.string(), mcpProjectServerChoiceSchema).default({})
|
|
260
288
|
});
|
|
261
289
|
var projectCommandChoiceSchema = z.object({
|
|
262
290
|
/** Digest of the shell the body substitutes at decision time; a mismatch re-prompts. */
|
|
@@ -271,8 +299,9 @@ var commandSettingsSchema = z.object({
|
|
|
271
299
|
* needs a decision before it runs. User-global commands
|
|
272
300
|
* (<BOOK_HOME>/commands) were written by the user and never require one.
|
|
273
301
|
*/
|
|
274
|
-
projectCommands: z.record(projectCommandChoiceSchema).default({})
|
|
302
|
+
projectCommands: z.record(z.string(), projectCommandChoiceSchema).default({})
|
|
275
303
|
});
|
|
304
|
+
var projectDirectoryChoiceSchema = z.enum(["approved", "rejected"]);
|
|
276
305
|
var uiSettingsSchema = z.object({
|
|
277
306
|
/** Show provider-native and embedded model reasoning in the interactive transcript. */
|
|
278
307
|
showThinking: z.boolean().default(true),
|
|
@@ -285,9 +314,9 @@ var skillSettingsSchema = z.object({
|
|
|
285
314
|
/** Emergency switch that removes skill prompt and runtime effects without deleting packages. */
|
|
286
315
|
enabled: z.boolean().default(true),
|
|
287
316
|
/** Per-skill visibility overrides keyed by the skill's declared name. */
|
|
288
|
-
overrides: z.record(skillActivationSchema).default({}),
|
|
317
|
+
overrides: z.record(z.string(), skillActivationSchema).default({}),
|
|
289
318
|
/** Per-skill activation consent policy. Tool calls still use the normal permission system. */
|
|
290
|
-
execution: z.record(skillExecutionSchema).default({})
|
|
319
|
+
execution: z.record(z.string(), skillExecutionSchema).default({})
|
|
291
320
|
});
|
|
292
321
|
var compactStrategySchema = z.literal("summary");
|
|
293
322
|
var bookSettingsSchema = z.object({
|
|
@@ -296,11 +325,13 @@ var bookSettingsSchema = z.object({
|
|
|
296
325
|
compactStrategy: compactStrategySchema.optional(),
|
|
297
326
|
/** Optional model used only to generate historical conversation checkpoints. */
|
|
298
327
|
compactModel: z.string().min(1).optional(),
|
|
328
|
+
/** Reasoning effort for the compaction reducer; defaults to the session effort capped at medium. */
|
|
329
|
+
compactEffort: effortLevelSchema.optional(),
|
|
299
330
|
/** Max agent turns per user message. Omit for unlimited. */
|
|
300
|
-
maxTurns:
|
|
301
|
-
maxTokens:
|
|
331
|
+
maxTurns: unboundedInt().min(1).optional(),
|
|
332
|
+
maxTokens: unboundedInt().min(1e3).optional(),
|
|
302
333
|
effort: effortLevelSchema.optional(),
|
|
303
|
-
/** TUI color theme:
|
|
334
|
+
/** TUI color theme: rubric (default), folio, apple, or a custom theme filename. */
|
|
304
335
|
theme: z.string().min(1).optional(),
|
|
305
336
|
/**
|
|
306
337
|
* The shell the Bash tool spawns: `bash`, `pwsh`, `powershell`, `cmd`, `sh`,
|
|
@@ -309,27 +340,40 @@ var bookSettingsSchema = z.object({
|
|
|
309
340
|
* the program every command is handed to.
|
|
310
341
|
*/
|
|
311
342
|
shell: z.string().min(1).optional(),
|
|
312
|
-
ui: uiSettingsSchema.
|
|
313
|
-
skills: skillSettingsSchema.
|
|
343
|
+
ui: uiSettingsSchema.prefault({}),
|
|
344
|
+
skills: skillSettingsSchema.prefault({}),
|
|
314
345
|
autoCompactEnabled: z.boolean().optional(),
|
|
315
346
|
/** Permission mode used by each host when no invocation-specific mode is supplied. */
|
|
316
347
|
defaultMode: z.enum(["default", "acceptEdits", "plan", "auto", "dontAsk", "bypassPermissions"]).optional(),
|
|
317
348
|
disableBypassPermissionsMode: z.boolean().optional(),
|
|
349
|
+
/**
|
|
350
|
+
* Extra roots the file tools serve, for paths outside the workspace. An honored entry is a root
|
|
351
|
+
* for reads *and* writes: `Write`, `Edit`, `MultiEdit`, `ApplyPatch` and `NotebookEdit` accept an
|
|
352
|
+
* absolute path inside one and treat the entry as they would the workspace, while a relative path
|
|
353
|
+
* stays anchored to the workspace. A project-declared entry is withheld until `book trust dir`.
|
|
354
|
+
*/
|
|
318
355
|
additionalDirectories: z.array(z.string()).default([]),
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Decisions about `additionalDirectories` the project layer declared, keyed by the directory's
|
|
358
|
+
* real path (the declared text is only what the repository wrote; the path is what the file
|
|
359
|
+
* tools would serve). A project directory with no `approved` entry here is withheld, exactly
|
|
360
|
+
* as a project allow rule with no entry is.
|
|
361
|
+
*/
|
|
362
|
+
projectDirectories: z.record(z.string(), projectDirectoryChoiceSchema).default({}),
|
|
363
|
+
env: z.record(z.string(), z.string()).default({}),
|
|
364
|
+
provider: z.record(z.string(), providerConfigSchema).default({}),
|
|
365
|
+
permissions: permissionsSchema.prefault({}),
|
|
366
|
+
sandbox: sandboxSchema.prefault({}),
|
|
367
|
+
hooks: hooksSchema.prefault({}),
|
|
368
|
+
retry: retrySettingsSchema.prefault({}),
|
|
369
|
+
memory: memorySettingsSchema.prefault({}),
|
|
370
|
+
continuation: continuationSettingsSchema.prefault({}),
|
|
371
|
+
agents: agentSettingsSchema.prefault({}),
|
|
372
|
+
toolDiscovery: toolDiscoverySettingsSchema.prefault({}),
|
|
373
|
+
toolExecution: toolExecutionSettingsSchema.prefault({}),
|
|
374
|
+
observability: observabilitySettingsSchema.prefault({}),
|
|
375
|
+
mcp: mcpSettingsSchema.prefault({}),
|
|
376
|
+
commands: commandSettingsSchema.prefault({})
|
|
333
377
|
});
|
|
334
378
|
var DEFAULT_SETTINGS = {
|
|
335
379
|
compactStrategy: "summary",
|
|
@@ -358,6 +402,7 @@ var DEFAULT_SETTINGS = {
|
|
|
358
402
|
projectEntries: {}
|
|
359
403
|
},
|
|
360
404
|
additionalDirectories: [],
|
|
405
|
+
projectDirectories: {},
|
|
361
406
|
env: {},
|
|
362
407
|
provider: {},
|
|
363
408
|
ui: { showThinking: true, startupAnimation: true },
|
|
@@ -386,7 +431,15 @@ var DEFAULT_SETTINGS = {
|
|
|
386
431
|
memory: {
|
|
387
432
|
enabled: true,
|
|
388
433
|
autoSave: true,
|
|
389
|
-
requireApproval:
|
|
434
|
+
requireApproval: false,
|
|
435
|
+
quarantineExternal: true,
|
|
436
|
+
extraction: {
|
|
437
|
+
enabled: false,
|
|
438
|
+
idleHours: 3,
|
|
439
|
+
minMessages: 10,
|
|
440
|
+
maxPerSession: 5,
|
|
441
|
+
maxSessionsPerRun: 3
|
|
442
|
+
}
|
|
390
443
|
},
|
|
391
444
|
agents: {
|
|
392
445
|
mode: "adaptive",
|
|
@@ -429,21 +482,6 @@ var DEFAULT_SETTINGS = {
|
|
|
429
482
|
}
|
|
430
483
|
};
|
|
431
484
|
|
|
432
|
-
// src/settings-repository.ts
|
|
433
|
-
import {
|
|
434
|
-
closeSync,
|
|
435
|
-
existsSync,
|
|
436
|
-
fsyncSync,
|
|
437
|
-
mkdirSync,
|
|
438
|
-
openSync,
|
|
439
|
-
readFileSync,
|
|
440
|
-
renameSync,
|
|
441
|
-
statSync,
|
|
442
|
-
unlinkSync,
|
|
443
|
-
writeSync
|
|
444
|
-
} from "fs";
|
|
445
|
-
import { basename, dirname, join } from "path";
|
|
446
|
-
|
|
447
485
|
// src/cli/utils.ts
|
|
448
486
|
function getNestedValue(obj, path) {
|
|
449
487
|
const parts = path.split(".");
|
|
@@ -507,6 +545,35 @@ function parseNumericFlag(raw, flag, opts = {}) {
|
|
|
507
545
|
}
|
|
508
546
|
return value;
|
|
509
547
|
}
|
|
548
|
+
function resolvePrintPrompt(print, positional) {
|
|
549
|
+
if (positional === void 0) return { print };
|
|
550
|
+
if (print === void 0) {
|
|
551
|
+
return {
|
|
552
|
+
error: `unexpected argument '${positional}'. A prompt on the command line needs -p/--print (book -p "${positional}"); run book --help for the subcommands.`
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
if (typeof print === "string") {
|
|
556
|
+
return {
|
|
557
|
+
error: `the prompt was given twice: --print '${print}' and the argument '${positional}'. Pass it once, either as the --print value or as the argument.`
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
return { print: positional };
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/settings-repository.ts
|
|
564
|
+
import {
|
|
565
|
+
closeSync,
|
|
566
|
+
existsSync,
|
|
567
|
+
fsyncSync,
|
|
568
|
+
mkdirSync,
|
|
569
|
+
openSync,
|
|
570
|
+
readFileSync,
|
|
571
|
+
renameSync,
|
|
572
|
+
statSync,
|
|
573
|
+
unlinkSync,
|
|
574
|
+
writeSync
|
|
575
|
+
} from "fs";
|
|
576
|
+
import { basename, dirname, join } from "path";
|
|
510
577
|
|
|
511
578
|
// src/settings-redaction.ts
|
|
512
579
|
var REDACTED_SECRET = "*** (stored)";
|
|
@@ -719,6 +786,7 @@ function formatSettingsDiagnostics(diagnostics) {
|
|
|
719
786
|
}
|
|
720
787
|
|
|
721
788
|
export {
|
|
789
|
+
unboundedInt,
|
|
722
790
|
projectAllowRuleChoiceSchema,
|
|
723
791
|
projectHookChoiceSchema,
|
|
724
792
|
HOOK_EVENTS,
|
|
@@ -726,11 +794,13 @@ export {
|
|
|
726
794
|
providerConfigSchema,
|
|
727
795
|
mcpProjectServerChoiceSchema,
|
|
728
796
|
projectCommandChoiceSchema,
|
|
797
|
+
projectDirectoryChoiceSchema,
|
|
729
798
|
bookSettingsSchema,
|
|
730
799
|
DEFAULT_SETTINGS,
|
|
731
800
|
getNestedValue,
|
|
732
801
|
setNestedValue,
|
|
733
802
|
parseNumericFlag,
|
|
803
|
+
resolvePrintPrompt,
|
|
734
804
|
redactSettingValue,
|
|
735
805
|
redactSettingsForDisplay,
|
|
736
806
|
SETTINGS_TOP_LEVEL_KEYS,
|
|
@@ -740,4 +810,4 @@ export {
|
|
|
740
810
|
SettingsRepository,
|
|
741
811
|
formatSettingsDiagnostics
|
|
742
812
|
};
|
|
743
|
-
//# sourceMappingURL=chunk-
|
|
813
|
+
//# sourceMappingURL=chunk-X4NJT436.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/settings.ts","../src/cli/utils.ts","../src/settings-repository.ts","../src/settings-redaction.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Permission rule: \"Tool\" or \"Tool(specifier)\" where specifier is a glob pattern\n * matched against the tool's primary argument (e.g. bash command, file path).\n */\nexport const permissionRuleSchema = z.string().min(1);\n\n// An object schema defaulted to `{}` uses `.prefault({})`, not `.default({})`: Zod 4's `.default()`\n// returns its value without parsing it, so the object's own field defaults would never be applied.\n// Records and arrays keep `.default({})` / `.default([])`, whose values are already final.\n\n/**\n * An integer setting with no ceiling of its own.\n *\n * Zod 4's `.int()` also rejects anything above `Number.MAX_SAFE_INTEGER`, which Zod 3 accepted. A\n * settings file that loaded before the upgrade, such as one holding an \"effectively unlimited\"\n * `maxTurns`, must keep loading: an invalid document stops Book from starting. So these settings\n * check integrality themselves, reporting the same `invalid_type` issue `.int()` does. Bounded\n * ones keep `.int()`, since their `.max()` is far lower.\n */\nexport function unboundedInt() {\n return z.number().check((ctx) => {\n if (!Number.isInteger(ctx.value)) {\n ctx.issues.push({ code: 'invalid_type', expected: 'int', input: ctx.value });\n }\n });\n}\n\n/**\n * Bash sandbox configuration (matches CC's sandbox.* keys).\n */\nexport const sandboxSchema = z.object({\n enabled: z.boolean().default(false),\n failIfUnavailable: z.boolean().default(false),\n autoAllowBashIfSandboxed: z.boolean().default(true),\n excludedCommands: z.array(z.string()).default([]),\n allowUnsandboxedCommands: z.boolean().default(true),\n filesystem: z\n .object({\n allowWrite: z.array(z.string()).default([]),\n denyWrite: z.array(z.string()).default([]),\n denyRead: z.array(z.string()).default([]),\n })\n .prefault({}),\n network: z\n .object({\n allowedDomains: z.array(z.string()).default([]),\n deniedDomains: z.array(z.string()).default([]),\n })\n .prefault({}),\n});\n\n/**\n * Permission configuration (matches CC's permissions key).\n */\n/**\n * Per-rule trust decisions for `permissions.allow` entries declared by the\n * checked-in project layer.\n *\n * Unlike an MCP server, a permission rule *is* its own identity: change the\n * rule and it is a different key, so no fingerprint is needed to detect drift.\n * Decisions are stored per workspace in `.book/settings.local.json`, which the\n * repository cannot write.\n */\nexport const projectAllowRuleChoiceSchema = z.enum(['approved', 'rejected']);\n\nexport type ProjectAllowRuleChoice = z.infer<typeof projectAllowRuleChoiceSchema>;\n\nexport const permissionsSchema = z.object({\n allow: z.array(permissionRuleSchema).default([]),\n ask: z.array(permissionRuleSchema).default([]),\n deny: z.array(permissionRuleSchema).default([]),\n /**\n * Decisions about `allow` rules the project layer declared. A project rule\n * with no `approved` entry here never reaches the resolved allow list.\n */\n projectAllowRules: z.record(z.string(), projectAllowRuleChoiceSchema).default({}),\n});\n\n/**\n * Hook entry: a shell command that runs at a lifecycle event.\n * Matches Claude Code's hook configuration format.\n */\nexport const hookEntrySchema = z.object({\n /** Tool(specifier) pattern to filter which events trigger this hook. */\n matcher: z.string().optional(),\n /** Shell command to run (passed through system shell). */\n command: z.string().min(1),\n /** Extra environment variables for this hook. */\n env: z.record(z.string(), z.string()).default({}),\n});\n\nexport type HookEntry = z.infer<typeof hookEntrySchema>;\n\n/**\n * Per-entry trust decisions for hook entries declared by the checked-in project\n * layer, keyed by a fingerprint of `{ event, matcher, command, env }`.\n *\n * A hook is a shell command Book executes at lifecycle events, so a project\n * hook with no `approved` entry here never reaches the resolved hooks. Unlike\n * an MCP server record, a hook carries no name — the fingerprint is the key.\n */\nexport const projectHookChoiceSchema = z.enum(['approved', 'rejected']);\n\nexport type ProjectHookChoice = z.infer<typeof projectHookChoiceSchema>;\n\n/** Hook events supported by book. */\nexport const HOOK_EVENTS = [\n 'SessionStart',\n 'SessionEnd',\n 'UserPromptSubmit',\n 'PreToolUse',\n 'PostToolUse',\n 'Stop',\n 'PreCompact',\n 'PostCompact',\n 'SubagentStart',\n 'SubagentStop',\n /**\n * Something a human should know about while nobody is watching: a run parked on\n * a rejected credential, a budget crossing its ceiling, a refused spawn because\n * the disk is nearly full. Wire ntfy/Slack/SMS here as an ordinary shell hook.\n *\n * Only `severity: 'alarm'` is meant to wake anyone; everything else is a line to\n * tail. `hooksSchema` is generated from this array, so the schema cost is one\n * entry.\n */\n 'Notification',\n] as const;\n\nexport type HookEvent = (typeof HOOK_EVENTS)[number];\n\n/**\n * Hooks configuration — a map from event name to an array of hook entries.\n */\nexport const hooksSchema = z.object({\n ...(Object.fromEntries(HOOK_EVENTS.map((e) => [e, z.array(hookEntrySchema).default([])])) as {\n [K in HookEvent]: z.ZodDefault<z.ZodArray<typeof hookEntrySchema>>;\n }),\n /**\n * Decisions about hook entries the checked-in project layer declared. An\n * entry whose fingerprint has no `approved` record here never reaches the\n * resolved hooks.\n */\n projectEntries: z.record(z.string(), projectHookChoiceSchema).default({}),\n});\n\nexport type HooksConfig = z.infer<typeof hooksSchema>;\n\n/**\n * Retry configuration schema — mirrors Claude Code's retry tunables.\n */\nexport const retrySettingsSchema = z.object({\n maxAttempts: z.number().int().min(0).max(15).default(10),\n baseDelayMs: z.number().int().min(100).max(60000).default(1000),\n maxDelayMs: z.number().int().min(100).max(300000).default(30000),\n totalBudgetMs: z.number().int().min(0).max(600000).default(0),\n requestTimeoutMs: z.number().int().min(5000).max(600000).default(600000),\n streamStallTimeoutMs: z.number().int().min(5000).max(120000).default(20000),\n /**\n * Stall ceiling while the model is thinking, which is a different regime.\n *\n * `streamStallTimeoutMs` is tuned for a chat: 20s of silence means something\n * broke. But with adaptive thinking on — the default for every Opus and Sonnet\n * model here, at `high` effort unless told otherwise — a long quiet stretch\n * before the first token is the model working, not a fault. Applying the chat\n * timeout to it cancels a healthy request and reports `stream_stall`.\n */\n thinkingStallTimeoutMs: z.number().int().min(10_000).max(1_800_000).default(900_000),\n toolRetries: z.number().int().min(0).max(3).default(1),\n watchdog: z.boolean().default(false),\n /**\n * How many times a turn may be re-sent after a transport fault that left the\n * work intact — a stalled stream, a dropped socket — and how many times an\n * empty completion may be re-asked. The two are counted separately per turn;\n * this only says how many of each a turn gets.\n *\n * `maxAttempts` covers connection setup only; once a 200 response is streaming\n * it is out of scope, so without this a single 20-second provider silence ended\n * the run. Set to 0 to restore that behavior exactly for transport faults. An\n * empty completion still gets one retry, the floor every earlier version spent,\n * so a run does not end on the first blank answer.\n */\n streamReissueAttempts: z.number().int().min(0).max(10).default(3),\n /**\n * Separate allowance for continuing after the provider's output cap. A large\n * generated file legitimately hits the cap on consecutive turns, and sharing\n * the transport budget would leave nothing for a real socket drop afterwards.\n */\n outputCapContinuations: z.number().int().min(0).max(50).default(10),\n});\n\nexport type RetrySettings = z.infer<typeof retrySettingsSchema>;\n\nexport const effortLevelSchema = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);\n\nexport const providerModelSchema = z.object({\n label: z.string().optional(),\n contextWindow: unboundedInt().positive().optional(),\n maxOutputTokens: unboundedInt().positive().optional(),\n /** Whether this model accepts image input. Unknown models remain optimistic. */\n vision: z.boolean().optional(),\n /**\n * Entered by hand rather than returned by the endpoint's model-list API.\n * Refreshing the catalog keeps these, since they exist precisely because\n * discovery does not list them.\n */\n manual: z.boolean().optional(),\n /** Mutation-tool preference for this model; defaults to a family-level prior. */\n editFormat: z.enum(['patch', 'replace', 'whole']).optional(),\n effort: z\n .union([\n z.literal(false),\n z.object({\n default: effortLevelSchema.optional(),\n levels: z.array(effortLevelSchema).optional(),\n }),\n ])\n .optional(),\n});\n\nexport const providerConfigSchema = z.object({\n type: z.enum(['openai', 'anthropic']).default('openai'),\n baseURL: z.string().min(1).optional(),\n baseUrl: z.string().min(1).optional(),\n apiKey: z.string().min(1).optional(),\n models: z.record(z.string(), providerModelSchema).default({}),\n});\n\n/**\n * Continuation: whether a turn that stops with no tool calls may be re-driven.\n *\n * `runAgentLoop` ends as soon as a turn produces no tool calls, so one user\n * message is the whole run and a model that writes \"I've finished\" stops there.\n * Enabling this lets the loop append a host-authored user turn and keep going\n * while there is demonstrably work left.\n *\n * Off by default: it changes when a run ends, and continuation without the\n * no-progress brake below would let a stalled run spin and bill silently, where\n * today it stops and a human notices.\n */\nexport const continuationSettingsSchema = z.object({\n enabled: z.boolean().default(false),\n /** Consecutive host-authored continuations before the run stops regardless. */\n maxConsecutive: z.number().int().min(1).max(1000).default(50),\n /**\n * Identical progress witnesses in a row before the run stops as no-progress.\n * Minimum 1: a 0 here would fire on the first boundary, before any witness\n * exists, and label a run that never got a chance to spin as spinning.\n */\n noProgressLimit: z.number().int().min(1).max(20).default(3),\n /**\n * Consecutive turns in which EVERY tool call was refused before the run stops.\n *\n * Enforced even when `enabled` is false, deliberately. The spin it catches\n * predates continuation and needs no continuation to happen: a headless run in\n * the default permission mode answers every prompt `deny`, so the model can\n * re-issue a refused call forever while `toolCalls.length > 0` keeps the\n * turn-end gate from ever firing. None of the existing anti-loop signals stop it\n * either — the repeated-failure breaker only annotates a repeated call and never\n * sees the loop's own permission refusals, and `toolCallStats.failures` excludes\n * `blocked` by construction.\n *\n * 0 disables the guard.\n */\n blockedToolTurnLimit: z.number().int().min(0).max(100).default(3),\n /** Turns between host-authored work-state messages; 0 disables them. */\n planRefreshTurns: z.number().int().min(0).max(500).default(25),\n /** Wall-clock ceiling for one continued run; 0 means no ceiling. */\n maxWallClockMs: unboundedInt().min(0).default(0),\n});\n\nexport type ContinuationSettings = z.infer<typeof continuationSettingsSchema>;\n\nexport const memorySettingsSchema = z.object({\n enabled: z.boolean().default(true),\n autoSave: z.boolean().default(true),\n requireApproval: z.boolean().default(false),\n quarantineExternal: z.boolean().default(true),\n /**\n * Phase 1b: at the next session start, extract memories the model missed from idle sessions.\n * Off by default since 2026-10: on the owner's machine it wrote 8 of the 10 memories and all the\n * wrong ones, copied from delegated spec runs; it stays available as an opt-in.\n */\n extraction: z\n .object({\n enabled: z.boolean().default(false),\n idleHours: z.number().min(0).default(3),\n minMessages: unboundedInt().min(1).default(10),\n maxPerSession: z.number().int().min(1).max(20).default(5),\n maxSessionsPerRun: z.number().int().min(1).max(20).default(3),\n })\n .prefault({}),\n});\n\nexport const agentSettingsSchema = z.object({\n mode: z.enum(['adaptive', 'manual', 'off']).default('adaptive'),\n maxConcurrent: z.number().int().min(1).max(16).default(3),\n maxSpawned: z.number().int().min(1).max(64).default(8),\n maxDepth: z.literal(1).default(1),\n persist: z.boolean().default(true),\n includeUntrackedInSnapshot: z.boolean().default(true),\n telemetry: z.boolean().default(true),\n retentionDays: z.number().int().min(1).max(3650).default(30),\n checks: z\n .record(z.string(), z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]))\n .default({}),\n /**\n * Wall-clock ceiling for one `Check` run. The 120s default suits a focused\n * suite; a full `npm test` on a large repository routinely exceeds it, and a\n * check that always times out is worse than no check because the timeout was\n * reported as a failing suite. Raise it per project rather than per invocation.\n */\n checkTimeoutMs: z.number().int().min(1_000).max(7_200_000).default(120_000),\n /** Ceiling on a foreground delegation via the Task tool; overrides the 1800s default. */\n taskTimeoutMs: unboundedInt().min(1000).optional(),\n /**\n * Simultaneous agent worktrees per repository; 0 disables the check.\n *\n * Nothing reclaims a worktree automatically outside the TUI, and the store's\n * retention sweep runs once at startup with a 30-day default — so on a long\n * unattended run the count only grows. Sized above `maxConcurrent` so ordinary\n * fan-out is unaffected and only accumulation trips it.\n */\n maxWorktrees: z.number().int().min(0).max(256).default(24),\n /**\n * Re-drive agents that were interrupted by process death on the next start.\n *\n * A restart otherwise converts the whole pending backlog into terminal records\n * nothing picks up, silently losing hours of child work on a wide fan-out. The\n * re-drive is contained: explorers are read-only and patchers/validators run in\n * their own worktree, so nothing reaches the parent workspace without the usual\n * evidence gate. Only `process_exit` interruptions qualify — a user stop stays\n * stopped.\n */\n resumeInterrupted: z.boolean().default(true),\n /**\n * Refuse a new worktree when free disk would fall below this; 0 disables.\n * Worktrees share the filesystem with the workspace, so exhausting it breaks\n * the root agent's own Edit and Bash, not just the child's.\n */\n minFreeDiskBytes: unboundedInt()\n .min(0)\n .default(2 * 1024 * 1024 * 1024),\n profiles: z\n .record(\n z.string(),\n z.object({\n model: z.string().min(1).optional(),\n effort: effortLevelSchema.optional(),\n maxTurns: unboundedInt().min(1).optional(),\n color: z.string().optional(),\n }),\n )\n .default({}),\n ui: z.object({ enabled: z.boolean().default(true) }).prefault({}),\n routing: z\n .object({\n inlineSearchBudget: z.number().int().min(1).max(20).default(3),\n exploreReminder: z.boolean().default(true),\n })\n .prefault({}),\n forwardTextEvents: z.boolean().default(false),\n});\n\nexport const toolDiscoverySettingsSchema = z.object({\n mode: z.enum(['auto', 'eager', 'deferred']).default('auto'),\n eagerToolCount: z.number().int().min(1).max(100).default(10),\n schemaTokenBudget: z.number().int().min(1000).max(100000).default(8000),\n maxLoadedTools: z.number().int().min(1).max(100).default(15),\n searchLimit: z.number().int().min(1).max(5).default(5),\n});\n\nexport type ToolDiscoverySettings = z.infer<typeof toolDiscoverySettingsSchema>;\n\nexport const toolExecutionSettingsSchema = z.object({\n /** Shared across the root loop and managed children for parallel-safe tools. */\n maxConcurrent: z.number().int().min(1).max(8).default(4),\n});\n\nexport type ToolExecutionSettings = z.infer<typeof toolExecutionSettingsSchema>;\n\nexport const observabilitySettingsSchema = z.object({\n /** Persist a per-tool-call JSONL record for `book tool-stats`. */\n toolTelemetry: z.boolean().default(true),\n /**\n * Default reporting window (in days) for `book tool-stats` and the target for\n * `book tool-stats --prune`. Disk use is bounded by size-based log rotation;\n * records are only deleted when they rotate out or are explicitly pruned.\n */\n toolTelemetryRetentionDays: z.number().int().min(1).max(3650).default(30),\n});\n\nexport type ObservabilitySettings = z.infer<typeof observabilitySettingsSchema>;\n\nexport const mcpProjectServerChoiceSchema = z.object({\n /** Hash of the server's command/args/env at decision time; a mismatch re-prompts. */\n fingerprint: z.string().min(1),\n choice: z.enum(['approved', 'rejected']),\n});\n\nexport type McpProjectServerChoice = z.infer<typeof mcpProjectServerChoiceSchema>;\n\nexport const mcpSettingsSchema = z.object({\n /**\n * Per-server trust decisions for workspace `.mcp.json` declarations.\n * User-global servers (<BOOK_HOME>/.book/mcp.json) never require approval.\n */\n projectServers: z.record(z.string(), mcpProjectServerChoiceSchema).default({}),\n});\n\nexport type McpSettings = z.infer<typeof mcpSettingsSchema>;\n\nexport const projectCommandChoiceSchema = z.object({\n /** Digest of the shell the body substitutes at decision time; a mismatch re-prompts. */\n fingerprint: z.string().min(1),\n choice: z.enum(['approved', 'rejected']),\n});\n\nexport type ProjectCommandChoice = z.infer<typeof projectCommandChoiceSchema>;\n\nexport const commandSettingsSchema = z.object({\n /**\n * Per-command trust decisions for `<workspace>/.book/commands/*.md` files\n * that substitute shell into their prompt. That substitution runs outside the\n * permission system and outside the sandbox, so a repository-controlled file\n * needs a decision before it runs. User-global commands\n * (<BOOK_HOME>/commands) were written by the user and never require one.\n */\n projectCommands: z.record(z.string(), projectCommandChoiceSchema).default({}),\n});\n\nexport type CommandSettings = z.infer<typeof commandSettingsSchema>;\n\n/**\n * Per-directory trust decisions for `additionalDirectories` declared by the checked-in project\n * layer, keyed by the directory's real path.\n *\n * `additionalDirectories` widens the set of roots the file tools serve, so honouring one from a\n * clone would hand that clone a read (and a write path) over whatever the path resolves to. A\n * project directory with no `approved` entry here is withheld, exactly as a project allow rule\n * is. Unlike a rule, the key cannot be the declared text: a repository controls that text and\n * could declare a link, so the decision is recorded against where the path really goes.\n */\nexport const projectDirectoryChoiceSchema = z.enum(['approved', 'rejected']);\n\nexport type ProjectDirectoryChoice = z.infer<typeof projectDirectoryChoiceSchema>;\n\nexport const uiSettingsSchema = z.object({\n /** Show provider-native and embedded model reasoning in the interactive transcript. */\n showThinking: z.boolean().default(true),\n /** Play the full-screen fire sequence on a newly created interactive startup session. */\n startupAnimation: z.boolean().default(true),\n});\n\nexport type UiSettings = z.infer<typeof uiSettingsSchema>;\n\nexport const skillActivationSchema = z.enum(['auto', 'name-only', 'manual', 'off']);\nexport type SkillActivation = z.infer<typeof skillActivationSchema>;\n\nexport const skillExecutionSchema = z.enum(['inherit', 'ask', 'deny']);\nexport type SkillExecution = z.infer<typeof skillExecutionSchema>;\n\nexport const skillSettingsSchema = z.object({\n /** Emergency switch that removes skill prompt and runtime effects without deleting packages. */\n enabled: z.boolean().default(true),\n /** Per-skill visibility overrides keyed by the skill's declared name. */\n overrides: z.record(z.string(), skillActivationSchema).default({}),\n /** Per-skill activation consent policy. Tool calls still use the normal permission system. */\n execution: z.record(z.string(), skillExecutionSchema).default({}),\n});\n\nexport type SkillSettings = z.infer<typeof skillSettingsSchema>;\n\nexport type ProviderModelConfig = z.infer<typeof providerModelSchema>;\nexport type ProviderConfig = z.infer<typeof providerConfigSchema>;\n\n/** The supported production strategy. */\nexport const compactStrategySchema = z.literal('summary');\nexport type CompactStrategy = z.infer<typeof compactStrategySchema>;\n\n/**\n * Full settings.json schema — all keys that book supports.\n * New keys added in later milestones extend this schema.\n */\nexport const bookSettingsSchema = z.object({\n model: z.string().optional(),\n /** Default strategy used to reduce historical conversation context. */\n compactStrategy: compactStrategySchema.optional(),\n /** Optional model used only to generate historical conversation checkpoints. */\n compactModel: z.string().min(1).optional(),\n /** Reasoning effort for the compaction reducer; defaults to the session effort capped at medium. */\n compactEffort: effortLevelSchema.optional(),\n /** Max agent turns per user message. Omit for unlimited. */\n maxTurns: unboundedInt().min(1).optional(),\n maxTokens: unboundedInt().min(1000).optional(),\n effort: effortLevelSchema.optional(),\n /** TUI color theme: rubric (default), folio, apple, or a custom theme filename. */\n theme: z.string().min(1).optional(),\n /**\n * The shell the Bash tool spawns: `bash`, `pwsh`, `powershell`, `cmd`, `sh`,\n * or an executable path. Honoured from the user-global layer, an explicit\n * `--settings` document, or `BOOK_SHELL` only: a workspace file cannot pick\n * the program every command is handed to.\n */\n shell: z.string().min(1).optional(),\n ui: uiSettingsSchema.prefault({}),\n skills: skillSettingsSchema.prefault({}),\n autoCompactEnabled: z.boolean().optional(),\n /** Permission mode used by each host when no invocation-specific mode is supplied. */\n defaultMode: z\n .enum(['default', 'acceptEdits', 'plan', 'auto', 'dontAsk', 'bypassPermissions'])\n .optional(),\n disableBypassPermissionsMode: z.boolean().optional(),\n /**\n * Extra roots the file tools serve, for paths outside the workspace. An honored entry is a root\n * for reads *and* writes: `Write`, `Edit`, `MultiEdit`, `ApplyPatch` and `NotebookEdit` accept an\n * absolute path inside one and treat the entry as they would the workspace, while a relative path\n * stays anchored to the workspace. A project-declared entry is withheld until `book trust dir`.\n */\n additionalDirectories: z.array(z.string()).default([]),\n /**\n * Decisions about `additionalDirectories` the project layer declared, keyed by the directory's\n * real path (the declared text is only what the repository wrote; the path is what the file\n * tools would serve). A project directory with no `approved` entry here is withheld, exactly\n * as a project allow rule with no entry is.\n */\n projectDirectories: z.record(z.string(), projectDirectoryChoiceSchema).default({}),\n env: z.record(z.string(), z.string()).default({}),\n provider: z.record(z.string(), providerConfigSchema).default({}),\n permissions: permissionsSchema.prefault({}),\n sandbox: sandboxSchema.prefault({}),\n hooks: hooksSchema.prefault({}),\n retry: retrySettingsSchema.prefault({}),\n memory: memorySettingsSchema.prefault({}),\n continuation: continuationSettingsSchema.prefault({}),\n agents: agentSettingsSchema.prefault({}),\n toolDiscovery: toolDiscoverySettingsSchema.prefault({}),\n toolExecution: toolExecutionSettingsSchema.prefault({}),\n observability: observabilitySettingsSchema.prefault({}),\n mcp: mcpSettingsSchema.prefault({}),\n commands: commandSettingsSchema.prefault({}),\n});\n\nexport type BookSettings = z.infer<typeof bookSettingsSchema>;\n\n/**\n * Resolved settings after layering (all defaults filled).\n */\nexport type ResolvedSettings = Required<\n Omit<\n BookSettings,\n | 'model'\n | 'compactModel'\n | 'compactEffort'\n | 'maxTurns'\n | 'maxTokens'\n | 'effort'\n | 'theme'\n | 'shell'\n | 'autoCompactEnabled'\n | 'defaultMode'\n | 'disableBypassPermissionsMode'\n >\n> &\n Pick<\n BookSettings,\n | 'model'\n | 'compactModel'\n | 'compactEffort'\n | 'maxTurns'\n | 'maxTokens'\n | 'effort'\n | 'theme'\n | 'shell'\n | 'autoCompactEnabled'\n | 'defaultMode'\n | 'disableBypassPermissionsMode'\n >;\n\n/**\n * Default settings used as the base layer before user/project/local override.\n */\nexport const DEFAULT_SETTINGS: ResolvedSettings = {\n compactStrategy: 'summary',\n permissions: { allow: [], ask: [], deny: [], projectAllowRules: {} },\n sandbox: {\n enabled: false,\n failIfUnavailable: false,\n autoAllowBashIfSandboxed: true,\n excludedCommands: [],\n allowUnsandboxedCommands: true,\n filesystem: { allowWrite: [], denyWrite: [], denyRead: [] },\n network: { allowedDomains: [], deniedDomains: [] },\n },\n hooks: {\n SessionStart: [],\n SessionEnd: [],\n UserPromptSubmit: [],\n PreToolUse: [],\n PostToolUse: [],\n Stop: [],\n PreCompact: [],\n PostCompact: [],\n SubagentStart: [],\n SubagentStop: [],\n Notification: [],\n projectEntries: {},\n },\n additionalDirectories: [],\n projectDirectories: {},\n env: {},\n provider: {},\n ui: { showThinking: true, startupAnimation: true },\n skills: { enabled: true, overrides: {}, execution: {} },\n retry: {\n maxAttempts: 10,\n baseDelayMs: 1000,\n maxDelayMs: 30000,\n totalBudgetMs: 0,\n requestTimeoutMs: 600000,\n streamStallTimeoutMs: 20000,\n thinkingStallTimeoutMs: 900_000,\n toolRetries: 1,\n watchdog: false,\n streamReissueAttempts: 3,\n outputCapContinuations: 10,\n },\n continuation: {\n enabled: false,\n maxConsecutive: 50,\n noProgressLimit: 3,\n blockedToolTurnLimit: 3,\n planRefreshTurns: 25,\n maxWallClockMs: 0,\n },\n memory: {\n enabled: true,\n autoSave: true,\n requireApproval: false,\n quarantineExternal: true,\n extraction: {\n enabled: false,\n idleHours: 3,\n minMessages: 10,\n maxPerSession: 5,\n maxSessionsPerRun: 3,\n },\n },\n agents: {\n mode: 'adaptive',\n maxConcurrent: 3,\n maxSpawned: 8,\n maxDepth: 1,\n persist: true,\n includeUntrackedInSnapshot: true,\n telemetry: true,\n retentionDays: 30,\n checks: {},\n checkTimeoutMs: 120_000,\n maxWorktrees: 24,\n resumeInterrupted: true,\n minFreeDiskBytes: 2 * 1024 * 1024 * 1024,\n profiles: {},\n ui: { enabled: true },\n routing: { inlineSearchBudget: 3, exploreReminder: true },\n forwardTextEvents: false,\n },\n toolDiscovery: {\n mode: 'auto',\n eagerToolCount: 10,\n schemaTokenBudget: 8000,\n maxLoadedTools: 15,\n searchLimit: 5,\n },\n toolExecution: {\n maxConcurrent: 4,\n },\n observability: {\n toolTelemetry: true,\n toolTelemetryRetentionDays: 30,\n },\n mcp: {\n projectServers: {},\n },\n commands: {\n projectCommands: {},\n },\n};\n","/** Deeply nested value access by dot-separated key path. */\nexport function getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\n/** Deeply nested value setter, creating intermediate objects as needed. */\nexport function setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (\n !(parts[i] in current) ||\n typeof current[parts[i]] !== 'object' ||\n current[parts[i]] === null\n ) {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = value;\n}\n\n/** Delete a dot-path and prune only empty ancestor objects on that path. */\nexport function deleteNestedValue(\n obj: Record<string, unknown>,\n path: string | readonly string[],\n): boolean {\n const parts = typeof path === 'string' ? path.split('.') : [...path];\n const ancestors: Array<{ parent: Record<string, unknown>; key: string }> = [];\n let current = obj;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (!Object.prototype.hasOwnProperty.call(current, key)) return false;\n const next = current[key];\n if (typeof next !== 'object' || next === null || Array.isArray(next)) return false;\n ancestors.push({ parent: current, key });\n current = next as Record<string, unknown>;\n }\n\n const leaf = parts[parts.length - 1];\n if (!Object.prototype.hasOwnProperty.call(current, leaf)) return false;\n delete current[leaf];\n\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const { parent, key } = ancestors[i];\n const child = parent[key];\n if (\n typeof child === 'object' &&\n child !== null &&\n !Array.isArray(child) &&\n Object.keys(child).length === 0\n ) {\n delete parent[key];\n } else {\n break;\n }\n }\n return true;\n}\n\n/**\n * Parse a numeric CLI flag, refusing anything that is not a usable number.\n *\n * `parseInt('none', 10)` is `NaN`, and the old guard was truthiness — `'none'` is\n * truthy, so the typo sailed through. Downstream, `NaN` loses every comparison it\n * takes part in, which is the worst possible failure for a limit: `--max-turns`\n * ran zero turns and reported `completed`, and `--max-budget-usd` read as\n * *configured* while permitting unbounded spend. Reject it at the boundary, and\n * test presence with `!== undefined` so an explicit `0` is a real zero rather than\n * a missing flag.\n */\nexport function parseNumericFlag(\n raw: unknown,\n flag: string,\n opts: { integer?: boolean; min?: number } = {},\n): number | undefined {\n if (raw === undefined || raw === null || raw === '') return undefined;\n const text = String(raw).trim();\n const value = opts.integer ? Number.parseInt(text, 10) : Number.parseFloat(text);\n // Number.parse* stops at the first bad character, so '12abc' would otherwise\n // silently become 12.\n if (!Number.isFinite(value) || !/^[+-]?(\\d+\\.?\\d*|\\.\\d+)$/.test(text)) {\n throw new Error(`${flag} expects a number, but received \"${text}\".`);\n }\n // `Number.parseInt('2.5', 10)` is 2, so testing the parsed value would never\n // catch a fractional input for an integer flag - it would silently truncate.\n if (opts.integer && text.includes('.')) {\n throw new Error(`${flag} expects a whole number, but received \"${text}\".`);\n }\n const min = opts.min ?? 0;\n if (value < min) {\n throw new Error(`${flag} must be at least ${min}, but received \"${text}\".`);\n }\n return value;\n}\n\n/**\n * Merge the root positional argument into `-p/--print [prompt]`.\n *\n * `--print` carries its prompt as its own optional value, so a prompt written\n * after a later flag (`book -p --model m \"fix it\"`) is a stray positional that\n * commander rejected with \"too many arguments\" (#226). Claude Code accepts the\n * prompt in either place, and so does Book now: the positional is the prompt\n * when the flag has no value of its own. Both at once is an error rather than a\n * silent choice, and a positional without `--print` is an error too, because the\n * TUI has nowhere to put it — and it is the shape a mistyped subcommand takes.\n *\n * Returns the resolved `--print` value, or `{ error }` for commander to report.\n */\nexport function resolvePrintPrompt(\n print: string | boolean | undefined,\n positional: string | undefined,\n): { print: string | boolean | undefined } | { error: string } {\n if (positional === undefined) return { print };\n if (print === undefined) {\n return {\n error: `unexpected argument '${positional}'. A prompt on the command line needs -p/--print (book -p \"${positional}\"); run book --help for the subcommands.`,\n };\n }\n if (typeof print === 'string') {\n return {\n error: `the prompt was given twice: --print '${print}' and the argument '${positional}'. Pass it once, either as the --print value or as the argument.`,\n };\n }\n return { print: positional };\n}\n","import {\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeSync,\n} from 'fs';\nimport { basename, dirname, join } from 'path';\nimport type { core } from 'zod';\nimport { deleteNestedValue, setNestedValue } from './cli/utils.js';\nimport { bookSettingsSchema } from './settings.js';\nimport { redactSettingValue } from './settings-redaction.js';\n\nexport type SettingsDocumentReadResult =\n | { status: 'absent'; path: string }\n | { status: 'valid'; path: string; document: Record<string, unknown> }\n | { status: 'malformed'; path: string; error: string }\n | { status: 'non-object'; path: string; error: string };\n\nexport interface SettingsDiagnostic {\n path: string;\n issuePath?: string;\n message: string;\n}\n\nexport type SettingsMutationResult =\n | {\n ok: true;\n path: string;\n document: Record<string, unknown>;\n values: Record<string, unknown>;\n changed: boolean;\n }\n | { ok: false; path: string; diagnostics: SettingsDiagnostic[] };\n\nexport interface SettingsRepositoryOptions {\n writeAtomic?: (path: string, contents: string) => void;\n}\n\nexport const SETTINGS_TOP_LEVEL_KEYS = Object.freeze(Object.keys(bookSettingsSchema.shape).sort());\n\nexport function formatSettingsKeyHelp(heading = 'Supported top-level settings:'): string {\n return `${heading}\\n${SETTINGS_TOP_LEVEL_KEYS.map((key) => ` ${key}`).join('\\n')}`;\n}\n\nfunction issueDiagnostic(path: string, issue: core.$ZodIssue): SettingsDiagnostic {\n return {\n path,\n issuePath: issue.path.join('.'),\n message: issue.message,\n };\n}\n\nfunction safeMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function readSettingsDocument(path: string): SettingsDocumentReadResult {\n if (!existsSync(path)) return { status: 'absent', path };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (error) {\n return { status: 'malformed', path, error: safeMessage(error) };\n }\n\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return { status: 'non-object', path, error: 'Settings must contain a JSON object.' };\n }\n\n return { status: 'valid', path, document: parsed as Record<string, unknown> };\n}\n\nexport function writeFileAtomic(path: string, contents: string): void {\n const directory = dirname(path);\n mkdirSync(directory, { recursive: true });\n const temporaryPath = join(\n directory,\n `.${basename(path)}.${process.pid}.${crypto.randomUUID()}.tmp`,\n );\n let descriptor: number | undefined;\n\n try {\n descriptor = openSync(temporaryPath, 'wx', 0o600);\n writeSync(descriptor, contents, undefined, 'utf-8');\n fsyncSync(descriptor);\n closeSync(descriptor);\n descriptor = undefined;\n renameSync(temporaryPath, path);\n } catch (error) {\n if (descriptor !== undefined) closeSync(descriptor);\n try {\n unlinkSync(temporaryPath);\n } catch {\n // The temporary file may not have been created.\n }\n throw error;\n }\n}\n\nfunction validateTopLevelKeys(\n path: string,\n document: Record<string, unknown>,\n): SettingsDiagnostic[] {\n const supported = new Set(SETTINGS_TOP_LEVEL_KEYS);\n return Object.keys(document)\n .filter((key) => !supported.has(key))\n .map((key) => ({\n path,\n issuePath: key,\n message: `Unknown top-level setting. Supported keys: ${SETTINGS_TOP_LEVEL_KEYS.join(', ')}`,\n }));\n}\n\nexport class SettingsRepository {\n private readonly writeAtomic: (path: string, contents: string) => void;\n\n constructor(\n readonly path: string,\n options: SettingsRepositoryOptions = {},\n ) {\n this.writeAtomic = options.writeAtomic ?? writeFileAtomic;\n }\n\n read(): SettingsDocumentReadResult {\n return readSettingsDocument(this.path);\n }\n\n set(values: Record<string, unknown>): SettingsMutationResult {\n return this.mutate((candidate) => {\n for (const [key, value] of Object.entries(values)) setNestedValue(candidate, key, value);\n }, values);\n }\n\n remove(paths: string[]): SettingsMutationResult {\n return this.mutate((candidate) => {\n for (const path of paths) deleteNestedValue(candidate, path.split('.'));\n }, {});\n }\n\n update(\n mutation: (candidate: Record<string, unknown>) => void,\n displayValues: Record<string, unknown> = {},\n ): SettingsMutationResult {\n return this.mutate(mutation, displayValues);\n }\n\n private mutate(\n mutation: (candidate: Record<string, unknown>) => void,\n values: Record<string, unknown>,\n ): SettingsMutationResult {\n let lock: number | undefined;\n try {\n lock = this.acquireLock();\n return this.mutateLocked(mutation, values);\n } catch (error) {\n return {\n ok: false,\n path: this.path,\n diagnostics: [{ path: this.path, message: safeMessage(error) }],\n };\n } finally {\n if (lock !== undefined) this.releaseLock(lock);\n }\n }\n\n private acquireLock(): number {\n mkdirSync(dirname(this.path), { recursive: true });\n const lockPath = `${this.path}.lock`;\n for (let attempt = 0; attempt < 50; attempt++) {\n try {\n return openSync(lockPath, 'wx', 0o600);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n try {\n if (Date.now() - statSync(lockPath).mtimeMs > 10_000) unlinkSync(lockPath);\n } catch {\n // Another process may have released or replaced the lock.\n }\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);\n }\n }\n throw new Error(`Timed out waiting for settings lock: ${lockPath}`);\n }\n\n private releaseLock(descriptor: number): void {\n closeSync(descriptor);\n try {\n unlinkSync(`${this.path}.lock`);\n } catch {\n // A stale-lock recovery may already have removed it.\n }\n }\n\n private mutateLocked(\n mutation: (candidate: Record<string, unknown>) => void,\n values: Record<string, unknown>,\n ): SettingsMutationResult {\n const source = this.read();\n if (source.status === 'malformed' || source.status === 'non-object') {\n return {\n ok: false,\n path: this.path,\n diagnostics: [{ path: this.path, message: source.error }],\n };\n }\n\n const candidate = structuredClone(source.status === 'valid' ? source.document : {});\n try {\n mutation(candidate);\n } catch (error) {\n return {\n ok: false,\n path: this.path,\n diagnostics: [{ path: this.path, message: safeMessage(error) }],\n };\n }\n\n const keyDiagnostics = validateTopLevelKeys(this.path, candidate);\n const validation = bookSettingsSchema.safeParse(candidate);\n const diagnostics = [\n ...keyDiagnostics,\n ...(validation.success\n ? []\n : validation.error.issues.map((issue) => issueDiagnostic(this.path, issue))),\n ];\n if (diagnostics.length > 0) return { ok: false, path: this.path, diagnostics };\n\n try {\n const changed =\n source.status !== 'valid' || JSON.stringify(source.document) !== JSON.stringify(candidate);\n if (changed) this.writeAtomic(this.path, JSON.stringify(candidate, null, 2) + '\\n');\n return {\n ok: true,\n path: this.path,\n document: candidate,\n changed,\n values: Object.fromEntries(\n Object.entries(values).map(([key, value]) => [key, redactSettingValue(key, value)]),\n ),\n };\n } catch (error) {\n return {\n ok: false,\n path: this.path,\n diagnostics: [{ path: this.path, message: safeMessage(error) }],\n };\n }\n }\n}\n\nexport function formatSettingsDiagnostics(diagnostics: SettingsDiagnostic[]): string {\n return diagnostics\n .map((diagnostic) => {\n const location = diagnostic.issuePath\n ? `${diagnostic.path} (${diagnostic.issuePath})`\n : diagnostic.path;\n return `${location}: ${diagnostic.message}`;\n })\n .join('\\n');\n}\n","const REDACTED_SECRET = '*** (stored)';\n\nfunction redactProviderRecord(value: unknown): unknown {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return value;\n const clone = structuredClone(value) as Record<string, unknown>;\n if ('apiKey' in clone) clone.apiKey = REDACTED_SECRET;\n return clone;\n}\n\nfunction redactProviderMap(value: unknown): unknown {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return value;\n const clone = structuredClone(value) as Record<string, unknown>;\n for (const [id, provider] of Object.entries(clone)) clone[id] = redactProviderRecord(provider);\n return clone;\n}\n\n/**\n * Removed blocks that may still carry a credential in a real settings file.\n *\n * Subscription authentication is gone, but `auth.profiles.<id>.clientSecret`\n * and the free-form `headers` that rode along with the bearer token are still\n * on disk wherever it was configured — and `book config list` prints the *raw*\n * document, not the validated one, so those keys survive into terminal\n * scrollback and pasted bug reports. Validation discarding a block is not the\n * same as a display path being safe, so the whole subtree is masked rather than\n * its individual leaves: nothing reads it any more, so there is nothing in it\n * worth showing.\n */\nconst REMOVED_SECRET_BEARING_BLOCKS = ['auth'];\n\nexport function redactSettingValue(path: string, value: unknown): unknown {\n const parts = path.split('.');\n if (parts[0] && REMOVED_SECRET_BEARING_BLOCKS.includes(parts[0])) return REDACTED_SECRET;\n if (parts[0] !== 'provider') return value;\n if (parts.length === 1) return redactProviderMap(value);\n if (parts.length === 2) return redactProviderRecord(value);\n return parts[parts.length - 1] === 'apiKey' ? REDACTED_SECRET : value;\n}\n\nexport function redactSettingsForDisplay<T>(value: T): T {\n if (!value || typeof value !== 'object') return value;\n const clone = structuredClone(value) as Record<string, unknown>;\n clone.provider = redactProviderMap(clone.provider);\n for (const key of REMOVED_SECRET_BEARING_BLOCKS) {\n if (clone[key] !== undefined) clone[key] = REDACTED_SECRET;\n }\n return clone as T;\n}\n"],"mappings":"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","names":[]}
|