apex-code 0.0.1-alpha.1 → 0.0.1-alpha.11

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 (798) hide show
  1. package/CHANGELOG.md +482 -0
  2. package/README.md +75 -680
  3. package/dist/cli/args.d.ts +21 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +119 -15
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/auth-command.d.ts.map +1 -1
  8. package/dist/cli/auth-command.js +3 -3
  9. package/dist/cli/auth-command.js.map +1 -1
  10. package/dist/cli/concurrent-session.d.ts +3 -0
  11. package/dist/cli/concurrent-session.d.ts.map +1 -0
  12. package/dist/cli/concurrent-session.js +13 -0
  13. package/dist/cli/concurrent-session.js.map +1 -0
  14. package/dist/cli/cost-command.d.ts +19 -0
  15. package/dist/cli/cost-command.d.ts.map +1 -0
  16. package/dist/cli/cost-command.js +107 -0
  17. package/dist/cli/cost-command.js.map +1 -0
  18. package/dist/cli/file-processor.d.ts.map +1 -1
  19. package/dist/cli/file-processor.js +2 -1
  20. package/dist/cli/file-processor.js.map +1 -1
  21. package/dist/cli/startup-ui.d.ts +1 -1
  22. package/dist/cli/startup-ui.d.ts.map +1 -1
  23. package/dist/cli/startup-ui.js +1 -2
  24. package/dist/cli/startup-ui.js.map +1 -1
  25. package/dist/cli.d.ts.map +1 -1
  26. package/dist/cli.js +99 -16
  27. package/dist/cli.js.map +1 -1
  28. package/dist/config.d.ts +5 -4
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +58 -24
  31. package/dist/config.js.map +1 -1
  32. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  33. package/dist/core/agent-session-runtime.js +2 -0
  34. package/dist/core/agent-session-runtime.js.map +1 -1
  35. package/dist/core/agent-session-services.d.ts +28 -0
  36. package/dist/core/agent-session-services.d.ts.map +1 -1
  37. package/dist/core/agent-session-services.js +140 -4
  38. package/dist/core/agent-session-services.js.map +1 -1
  39. package/dist/core/agent-session.d.ts +147 -9
  40. package/dist/core/agent-session.d.ts.map +1 -1
  41. package/dist/core/agent-session.js +440 -123
  42. package/dist/core/agent-session.js.map +1 -1
  43. package/dist/core/auth-storage.d.ts +4 -1
  44. package/dist/core/auth-storage.d.ts.map +1 -1
  45. package/dist/core/auth-storage.js +17 -14
  46. package/dist/core/auth-storage.js.map +1 -1
  47. package/dist/core/bash-executor.d.ts.map +1 -1
  48. package/dist/core/bash-executor.js +18 -10
  49. package/dist/core/bash-executor.js.map +1 -1
  50. package/dist/core/checkpoints/git-checkpoints.d.ts +33 -0
  51. package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
  52. package/dist/core/checkpoints/git-checkpoints.js +230 -0
  53. package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
  54. package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
  55. package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
  56. package/dist/core/checkpoints/session-checkpoints.js +29 -0
  57. package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
  58. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  59. package/dist/core/compaction/branch-summarization.js +3 -0
  60. package/dist/core/compaction/branch-summarization.js.map +1 -1
  61. package/dist/core/compaction/compaction.d.ts +4 -3
  62. package/dist/core/compaction/compaction.d.ts.map +1 -1
  63. package/dist/core/compaction/compaction.js +41 -32
  64. package/dist/core/compaction/compaction.js.map +1 -1
  65. package/dist/core/context/deferred-schemas.d.ts +92 -0
  66. package/dist/core/context/deferred-schemas.d.ts.map +1 -0
  67. package/dist/core/context/deferred-schemas.js +74 -0
  68. package/dist/core/context/deferred-schemas.js.map +1 -0
  69. package/dist/core/context/eviction.d.ts +47 -0
  70. package/dist/core/context/eviction.d.ts.map +1 -0
  71. package/dist/core/context/eviction.js +83 -0
  72. package/dist/core/context/eviction.js.map +1 -0
  73. package/dist/core/context/pipeline.d.ts +90 -0
  74. package/dist/core/context/pipeline.d.ts.map +1 -0
  75. package/dist/core/context/pipeline.js +109 -0
  76. package/dist/core/context/pipeline.js.map +1 -0
  77. package/dist/core/credential-failover.d.ts +30 -0
  78. package/dist/core/credential-failover.d.ts.map +1 -0
  79. package/dist/core/credential-failover.js +46 -0
  80. package/dist/core/credential-failover.js.map +1 -0
  81. package/dist/core/credential-pool.d.ts +60 -0
  82. package/dist/core/credential-pool.d.ts.map +1 -0
  83. package/dist/core/credential-pool.js +84 -0
  84. package/dist/core/credential-pool.js.map +1 -0
  85. package/dist/core/defaults.d.ts +1 -0
  86. package/dist/core/defaults.d.ts.map +1 -1
  87. package/dist/core/defaults.js +9 -0
  88. package/dist/core/defaults.js.map +1 -1
  89. package/dist/core/delegation/agents.d.ts +15 -0
  90. package/dist/core/delegation/agents.d.ts.map +1 -0
  91. package/dist/core/delegation/agents.js +55 -0
  92. package/dist/core/delegation/agents.js.map +1 -0
  93. package/dist/core/delegation/ceiling.d.ts +29 -0
  94. package/dist/core/delegation/ceiling.d.ts.map +1 -0
  95. package/dist/core/delegation/ceiling.js +34 -0
  96. package/dist/core/delegation/ceiling.js.map +1 -0
  97. package/dist/core/delegation/runtime.d.ts +94 -0
  98. package/dist/core/delegation/runtime.d.ts.map +1 -0
  99. package/dist/core/delegation/runtime.js +117 -0
  100. package/dist/core/delegation/runtime.js.map +1 -0
  101. package/dist/core/durable-state/daemon.d.ts +37 -0
  102. package/dist/core/durable-state/daemon.d.ts.map +1 -0
  103. package/dist/core/durable-state/daemon.js +62 -0
  104. package/dist/core/durable-state/daemon.js.map +1 -0
  105. package/dist/core/durable-state/provenance.d.ts +7 -0
  106. package/dist/core/durable-state/provenance.d.ts.map +1 -0
  107. package/dist/core/durable-state/provenance.js +24 -0
  108. package/dist/core/durable-state/provenance.js.map +1 -0
  109. package/dist/core/durable-state/sqlite.d.ts +84 -0
  110. package/dist/core/durable-state/sqlite.d.ts.map +1 -0
  111. package/dist/core/durable-state/sqlite.js +355 -0
  112. package/dist/core/durable-state/sqlite.js.map +1 -0
  113. package/dist/core/environment.d.ts +12 -0
  114. package/dist/core/environment.d.ts.map +1 -0
  115. package/dist/core/environment.js +69 -0
  116. package/dist/core/environment.js.map +1 -0
  117. package/dist/core/evidence-policy.d.ts +17 -0
  118. package/dist/core/evidence-policy.d.ts.map +1 -0
  119. package/dist/core/evidence-policy.js +25 -0
  120. package/dist/core/evidence-policy.js.map +1 -0
  121. package/dist/core/evidence.d.ts +16 -0
  122. package/dist/core/evidence.d.ts.map +1 -0
  123. package/dist/core/evidence.js +51 -0
  124. package/dist/core/evidence.js.map +1 -0
  125. package/dist/core/exec.d.ts.map +1 -1
  126. package/dist/core/exec.js +5 -2
  127. package/dist/core/exec.js.map +1 -1
  128. package/dist/core/experimental.d.ts +4 -0
  129. package/dist/core/experimental.d.ts.map +1 -1
  130. package/dist/core/experimental.js +6 -1
  131. package/dist/core/experimental.js.map +1 -1
  132. package/dist/core/extensions/index.d.ts +2 -2
  133. package/dist/core/extensions/index.d.ts.map +1 -1
  134. package/dist/core/extensions/index.js +1 -1
  135. package/dist/core/extensions/index.js.map +1 -1
  136. package/dist/core/extensions/loader.d.ts.map +1 -1
  137. package/dist/core/extensions/loader.js +122 -49
  138. package/dist/core/extensions/loader.js.map +1 -1
  139. package/dist/core/extensions/types.d.ts +44 -9
  140. package/dist/core/extensions/types.d.ts.map +1 -1
  141. package/dist/core/extensions/types.js +3 -0
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/footer-data-provider.d.ts +1 -1
  144. package/dist/core/footer-data-provider.d.ts.map +1 -1
  145. package/dist/core/footer-data-provider.js +1 -1
  146. package/dist/core/footer-data-provider.js.map +1 -1
  147. package/dist/core/http-dispatcher.d.ts +1 -2
  148. package/dist/core/http-dispatcher.d.ts.map +1 -1
  149. package/dist/core/http-dispatcher.js +2 -17
  150. package/dist/core/http-dispatcher.js.map +1 -1
  151. package/dist/core/http-idle-timeout.d.ts +12 -0
  152. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  153. package/dist/core/http-idle-timeout.js +27 -0
  154. package/dist/core/http-idle-timeout.js.map +1 -0
  155. package/dist/core/index.d.ts +1 -0
  156. package/dist/core/index.d.ts.map +1 -1
  157. package/dist/core/index.js +1 -0
  158. package/dist/core/index.js.map +1 -1
  159. package/dist/core/keybindings.d.ts +38 -13
  160. package/dist/core/keybindings.d.ts.map +1 -1
  161. package/dist/core/keybindings.js +26 -5
  162. package/dist/core/keybindings.js.map +1 -1
  163. package/dist/core/lsp/client.d.ts +78 -0
  164. package/dist/core/lsp/client.d.ts.map +1 -0
  165. package/dist/core/lsp/client.js +494 -0
  166. package/dist/core/lsp/client.js.map +1 -0
  167. package/dist/core/lsp/diagnostics.d.ts +47 -0
  168. package/dist/core/lsp/diagnostics.d.ts.map +1 -0
  169. package/dist/core/lsp/diagnostics.js +224 -0
  170. package/dist/core/lsp/diagnostics.js.map +1 -0
  171. package/dist/core/lsp/pool.d.ts +48 -0
  172. package/dist/core/lsp/pool.d.ts.map +1 -0
  173. package/dist/core/lsp/pool.js +150 -0
  174. package/dist/core/lsp/pool.js.map +1 -0
  175. package/dist/core/lsp/registry.d.ts +49 -0
  176. package/dist/core/lsp/registry.d.ts.map +1 -0
  177. package/dist/core/lsp/registry.js +215 -0
  178. package/dist/core/lsp/registry.js.map +1 -0
  179. package/dist/core/lsp/status.d.ts +23 -0
  180. package/dist/core/lsp/status.d.ts.map +1 -0
  181. package/dist/core/lsp/status.js +35 -0
  182. package/dist/core/lsp/status.js.map +1 -0
  183. package/dist/core/lsp/sync.d.ts +13 -0
  184. package/dist/core/lsp/sync.d.ts.map +1 -0
  185. package/dist/core/lsp/sync.js +71 -0
  186. package/dist/core/lsp/sync.js.map +1 -0
  187. package/dist/core/mcp/config.d.ts +16 -0
  188. package/dist/core/mcp/config.d.ts.map +1 -0
  189. package/dist/core/mcp/config.js +152 -0
  190. package/dist/core/mcp/config.js.map +1 -0
  191. package/dist/core/mcp/connector.d.ts +10 -0
  192. package/dist/core/mcp/connector.d.ts.map +1 -0
  193. package/dist/core/mcp/connector.js +70 -0
  194. package/dist/core/mcp/connector.js.map +1 -0
  195. package/dist/core/mcp/contract.d.ts +19 -0
  196. package/dist/core/mcp/contract.d.ts.map +1 -0
  197. package/dist/core/mcp/contract.js +89 -0
  198. package/dist/core/mcp/contract.js.map +1 -0
  199. package/dist/core/mcp/mcp-tool.d.ts +32 -0
  200. package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
  201. package/dist/core/mcp/mcp-tool.js +165 -0
  202. package/dist/core/mcp/mcp-tool.js.map +1 -0
  203. package/dist/core/mcp/metadata-cache.d.ts +29 -0
  204. package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
  205. package/dist/core/mcp/metadata-cache.js +99 -0
  206. package/dist/core/mcp/metadata-cache.js.map +1 -0
  207. package/dist/core/mcp/runtime.d.ts +18 -0
  208. package/dist/core/mcp/runtime.d.ts.map +1 -0
  209. package/dist/core/mcp/runtime.js +35 -0
  210. package/dist/core/mcp/runtime.js.map +1 -0
  211. package/dist/core/mcp/schema.d.ts +22 -0
  212. package/dist/core/mcp/schema.d.ts.map +1 -0
  213. package/dist/core/mcp/schema.js +20 -0
  214. package/dist/core/mcp/schema.js.map +1 -0
  215. package/dist/core/mcp/server-manager.d.ts +43 -0
  216. package/dist/core/mcp/server-manager.d.ts.map +1 -0
  217. package/dist/core/mcp/server-manager.js +142 -0
  218. package/dist/core/mcp/server-manager.js.map +1 -0
  219. package/dist/core/mcp/types.d.ts +98 -0
  220. package/dist/core/mcp/types.d.ts.map +1 -0
  221. package/dist/core/mcp/types.js +8 -0
  222. package/dist/core/mcp/types.js.map +1 -0
  223. package/dist/core/model-config.d.ts +18 -0
  224. package/dist/core/model-config.d.ts.map +1 -1
  225. package/dist/core/model-config.js +25 -6
  226. package/dist/core/model-config.js.map +1 -1
  227. package/dist/core/model-resolver.d.ts +21 -0
  228. package/dist/core/model-resolver.d.ts.map +1 -1
  229. package/dist/core/model-resolver.js +73 -8
  230. package/dist/core/model-resolver.js.map +1 -1
  231. package/dist/core/model-runtime.d.ts +73 -0
  232. package/dist/core/model-runtime.d.ts.map +1 -1
  233. package/dist/core/model-runtime.js +225 -8
  234. package/dist/core/model-runtime.js.map +1 -1
  235. package/dist/core/models-store.d.ts.map +1 -1
  236. package/dist/core/models-store.js +2 -1
  237. package/dist/core/models-store.js.map +1 -1
  238. package/dist/core/observability/aggregate.d.ts +21 -0
  239. package/dist/core/observability/aggregate.d.ts.map +1 -0
  240. package/dist/core/observability/aggregate.js +36 -0
  241. package/dist/core/observability/aggregate.js.map +1 -0
  242. package/dist/core/observability/otlp.d.ts +66 -0
  243. package/dist/core/observability/otlp.d.ts.map +1 -0
  244. package/dist/core/observability/otlp.js +95 -0
  245. package/dist/core/observability/otlp.js.map +1 -0
  246. package/dist/core/package-manager.d.ts.map +1 -1
  247. package/dist/core/package-manager.js +40 -16
  248. package/dist/core/package-manager.js.map +1 -1
  249. package/dist/core/permissions/gate.d.ts +42 -0
  250. package/dist/core/permissions/gate.d.ts.map +1 -0
  251. package/dist/core/permissions/gate.js +72 -0
  252. package/dist/core/permissions/gate.js.map +1 -0
  253. package/dist/core/permissions/modes.d.ts +18 -0
  254. package/dist/core/permissions/modes.d.ts.map +1 -0
  255. package/dist/core/permissions/modes.js +57 -0
  256. package/dist/core/permissions/modes.js.map +1 -0
  257. package/dist/core/permissions/responder.d.ts +30 -0
  258. package/dist/core/permissions/responder.d.ts.map +1 -0
  259. package/dist/core/permissions/responder.js +32 -0
  260. package/dist/core/permissions/responder.js.map +1 -0
  261. package/dist/core/permissions/rules.d.ts +34 -0
  262. package/dist/core/permissions/rules.d.ts.map +1 -0
  263. package/dist/core/permissions/rules.js +74 -0
  264. package/dist/core/permissions/rules.js.map +1 -0
  265. package/dist/core/permissions/startup.d.ts +45 -0
  266. package/dist/core/permissions/startup.d.ts.map +1 -0
  267. package/dist/core/permissions/startup.js +63 -0
  268. package/dist/core/permissions/startup.js.map +1 -0
  269. package/dist/core/permissions/store.d.ts +114 -0
  270. package/dist/core/permissions/store.d.ts.map +1 -0
  271. package/dist/core/permissions/store.js +229 -0
  272. package/dist/core/permissions/store.js.map +1 -0
  273. package/dist/core/pi-manifest.d.ts.map +1 -1
  274. package/dist/core/pi-manifest.js +2 -1
  275. package/dist/core/pi-manifest.js.map +1 -1
  276. package/dist/core/project-trust.d.ts.map +1 -1
  277. package/dist/core/project-trust.js +1 -1
  278. package/dist/core/project-trust.js.map +1 -1
  279. package/dist/core/provider-attribution.d.ts.map +1 -1
  280. package/dist/core/provider-attribution.js +6 -7
  281. package/dist/core/provider-attribution.js.map +1 -1
  282. package/dist/core/remote-catalog-provider.d.ts +2 -2
  283. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  284. package/dist/core/remote-catalog-provider.js +22 -17
  285. package/dist/core/remote-catalog-provider.js.map +1 -1
  286. package/dist/core/resource-loader.d.ts.map +1 -1
  287. package/dist/core/resource-loader.js +3 -2
  288. package/dist/core/resource-loader.js.map +1 -1
  289. package/dist/core/sandbox/bwrap-arguments.d.ts +52 -0
  290. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  291. package/dist/core/sandbox/bwrap-arguments.js +86 -0
  292. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  293. package/dist/core/sandbox/child-entry.d.ts +2 -0
  294. package/dist/core/sandbox/child-entry.d.ts.map +1 -0
  295. package/dist/core/sandbox/child-entry.js +22 -0
  296. package/dist/core/sandbox/child-entry.js.map +1 -0
  297. package/dist/core/sandbox/cli-launch.d.ts +88 -0
  298. package/dist/core/sandbox/cli-launch.d.ts.map +1 -0
  299. package/dist/core/sandbox/cli-launch.js +272 -0
  300. package/dist/core/sandbox/cli-launch.js.map +1 -0
  301. package/dist/core/sandbox/cli-supervisor.d.ts +30 -0
  302. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -0
  303. package/dist/core/sandbox/cli-supervisor.js +123 -0
  304. package/dist/core/sandbox/cli-supervisor.js.map +1 -0
  305. package/dist/core/sandbox/default-hosts.d.ts +28 -0
  306. package/dist/core/sandbox/default-hosts.d.ts.map +1 -0
  307. package/dist/core/sandbox/default-hosts.js +69 -0
  308. package/dist/core/sandbox/default-hosts.js.map +1 -0
  309. package/dist/core/sandbox/full-access.d.ts +28 -0
  310. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  311. package/dist/core/sandbox/full-access.js +63 -0
  312. package/dist/core/sandbox/full-access.js.map +1 -0
  313. package/dist/core/sandbox/git-identity.d.ts +57 -0
  314. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  315. package/dist/core/sandbox/git-identity.js +78 -0
  316. package/dist/core/sandbox/git-identity.js.map +1 -0
  317. package/dist/core/sandbox/host-approval.d.ts +42 -0
  318. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  319. package/dist/core/sandbox/host-approval.js +99 -0
  320. package/dist/core/sandbox/host-approval.js.map +1 -0
  321. package/dist/core/sandbox/linux-backend.d.ts +46 -0
  322. package/dist/core/sandbox/linux-backend.d.ts.map +1 -0
  323. package/dist/core/sandbox/linux-backend.js +304 -0
  324. package/dist/core/sandbox/linux-backend.js.map +1 -0
  325. package/dist/core/sandbox/macos-backend.d.ts +28 -0
  326. package/dist/core/sandbox/macos-backend.d.ts.map +1 -0
  327. package/dist/core/sandbox/macos-backend.js +313 -0
  328. package/dist/core/sandbox/macos-backend.js.map +1 -0
  329. package/dist/core/sandbox/network-proxy.d.ts +38 -0
  330. package/dist/core/sandbox/network-proxy.d.ts.map +1 -0
  331. package/dist/core/sandbox/network-proxy.js +153 -0
  332. package/dist/core/sandbox/network-proxy.js.map +1 -0
  333. package/dist/core/sandbox/network-refusal.d.ts +24 -0
  334. package/dist/core/sandbox/network-refusal.d.ts.map +1 -0
  335. package/dist/core/sandbox/network-refusal.js +72 -0
  336. package/dist/core/sandbox/network-refusal.js.map +1 -0
  337. package/dist/core/sandbox/policy.d.ts +40 -0
  338. package/dist/core/sandbox/policy.d.ts.map +1 -0
  339. package/dist/core/sandbox/policy.js +55 -0
  340. package/dist/core/sandbox/policy.js.map +1 -0
  341. package/dist/core/sandbox/profiles.d.ts +25 -0
  342. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  343. package/dist/core/sandbox/profiles.js +23 -0
  344. package/dist/core/sandbox/profiles.js.map +1 -0
  345. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  346. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  347. package/dist/core/sandbox/rpc/command-client.js +86 -0
  348. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  349. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  350. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  351. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  352. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  353. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  354. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  355. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  356. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  357. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  358. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  359. package/dist/core/sandbox/rpc/credential-proxy.js +287 -0
  360. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  361. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  362. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  363. package/dist/core/sandbox/rpc/framing.js +114 -0
  364. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  365. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +40 -0
  366. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  367. package/dist/core/sandbox/rpc/git-credential-helper.js +152 -0
  368. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  369. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +48 -0
  370. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  371. package/dist/core/sandbox/rpc/git-credential-proxy.js +142 -0
  372. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  373. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  374. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  375. package/dist/core/sandbox/supervisor-temp.js +21 -0
  376. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  377. package/dist/core/sandbox/supervisor.d.ts +51 -0
  378. package/dist/core/sandbox/supervisor.d.ts.map +1 -0
  379. package/dist/core/sandbox/supervisor.js +18 -0
  380. package/dist/core/sandbox/supervisor.js.map +1 -0
  381. package/dist/core/sandbox/terminal-handoff.d.ts +45 -0
  382. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  383. package/dist/core/sandbox/terminal-handoff.js +176 -0
  384. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  385. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  386. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  387. package/dist/core/sandbox/terminal-size.js +105 -0
  388. package/dist/core/sandbox/terminal-size.js.map +1 -0
  389. package/dist/core/sandbox/violations.d.ts +23 -0
  390. package/dist/core/sandbox/violations.d.ts.map +1 -0
  391. package/dist/core/sandbox/violations.js +30 -0
  392. package/dist/core/sandbox/violations.js.map +1 -0
  393. package/dist/core/sdk.d.ts +32 -41
  394. package/dist/core/sdk.d.ts.map +1 -1
  395. package/dist/core/sdk.js +174 -6
  396. package/dist/core/sdk.js.map +1 -1
  397. package/dist/core/session-export.d.ts +4 -0
  398. package/dist/core/session-export.d.ts.map +1 -0
  399. package/dist/core/session-export.js +32 -0
  400. package/dist/core/session-export.js.map +1 -0
  401. package/dist/core/session-lease.d.ts +31 -0
  402. package/dist/core/session-lease.d.ts.map +1 -0
  403. package/dist/core/session-lease.js +138 -0
  404. package/dist/core/session-lease.js.map +1 -0
  405. package/dist/core/session-manager.d.ts +58 -2
  406. package/dist/core/session-manager.d.ts.map +1 -1
  407. package/dist/core/session-manager.js +92 -7
  408. package/dist/core/session-manager.js.map +1 -1
  409. package/dist/core/session-share.d.ts +31 -0
  410. package/dist/core/session-share.d.ts.map +1 -0
  411. package/dist/core/session-share.js +45 -0
  412. package/dist/core/session-share.js.map +1 -0
  413. package/dist/core/settings-diagnostics.d.ts +9 -0
  414. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  415. package/dist/core/settings-diagnostics.js +21 -0
  416. package/dist/core/settings-diagnostics.js.map +1 -0
  417. package/dist/core/settings-manager.d.ts +99 -9
  418. package/dist/core/settings-manager.d.ts.map +1 -1
  419. package/dist/core/settings-manager.js +141 -36
  420. package/dist/core/settings-manager.js.map +1 -1
  421. package/dist/core/skills.d.ts +19 -7
  422. package/dist/core/skills.d.ts.map +1 -1
  423. package/dist/core/skills.js +128 -52
  424. package/dist/core/skills.js.map +1 -1
  425. package/dist/core/slash-commands.d.ts.map +1 -1
  426. package/dist/core/slash-commands.js +6 -2
  427. package/dist/core/slash-commands.js.map +1 -1
  428. package/dist/core/system-prompt.d.ts +2 -2
  429. package/dist/core/system-prompt.d.ts.map +1 -1
  430. package/dist/core/system-prompt.js +59 -68
  431. package/dist/core/system-prompt.js.map +1 -1
  432. package/dist/core/timings.d.ts +1 -1
  433. package/dist/core/timings.d.ts.map +1 -1
  434. package/dist/core/timings.js +3 -2
  435. package/dist/core/timings.js.map +1 -1
  436. package/dist/core/tools/ask-user.d.ts +25 -0
  437. package/dist/core/tools/ask-user.d.ts.map +1 -0
  438. package/dist/core/tools/ask-user.js +49 -0
  439. package/dist/core/tools/ask-user.js.map +1 -0
  440. package/dist/core/tools/bash-command-segments.d.ts +22 -0
  441. package/dist/core/tools/bash-command-segments.d.ts.map +1 -0
  442. package/dist/core/tools/bash-command-segments.js +128 -0
  443. package/dist/core/tools/bash-command-segments.js.map +1 -0
  444. package/dist/core/tools/bash.d.ts +40 -4
  445. package/dist/core/tools/bash.d.ts.map +1 -1
  446. package/dist/core/tools/bash.js +183 -32
  447. package/dist/core/tools/bash.js.map +1 -1
  448. package/dist/core/tools/contract-snapshot.d.ts +58 -0
  449. package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
  450. package/dist/core/tools/contract-snapshot.js +51 -0
  451. package/dist/core/tools/contract-snapshot.js.map +1 -0
  452. package/dist/core/tools/contract.d.ts +185 -0
  453. package/dist/core/tools/contract.d.ts.map +1 -0
  454. package/dist/core/tools/contract.js +50 -0
  455. package/dist/core/tools/contract.js.map +1 -0
  456. package/dist/core/tools/delegate.d.ts +38 -0
  457. package/dist/core/tools/delegate.d.ts.map +1 -0
  458. package/dist/core/tools/delegate.js +90 -0
  459. package/dist/core/tools/delegate.js.map +1 -0
  460. package/dist/core/tools/diagnostics.d.ts +39 -0
  461. package/dist/core/tools/diagnostics.d.ts.map +1 -0
  462. package/dist/core/tools/diagnostics.js +62 -0
  463. package/dist/core/tools/diagnostics.js.map +1 -0
  464. package/dist/core/tools/edit-diff.d.ts +0 -5
  465. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  466. package/dist/core/tools/edit-diff.js +2 -5
  467. package/dist/core/tools/edit-diff.js.map +1 -1
  468. package/dist/core/tools/edit.d.ts +12 -2
  469. package/dist/core/tools/edit.d.ts.map +1 -1
  470. package/dist/core/tools/edit.js +61 -10
  471. package/dist/core/tools/edit.js.map +1 -1
  472. package/dist/core/tools/find.d.ts +2 -2
  473. package/dist/core/tools/find.d.ts.map +1 -1
  474. package/dist/core/tools/find.js +13 -1
  475. package/dist/core/tools/find.js.map +1 -1
  476. package/dist/core/tools/grep.d.ts +4 -2
  477. package/dist/core/tools/grep.d.ts.map +1 -1
  478. package/dist/core/tools/grep.js +47 -10
  479. package/dist/core/tools/grep.js.map +1 -1
  480. package/dist/core/tools/index.d.ts +60 -6
  481. package/dist/core/tools/index.d.ts.map +1 -1
  482. package/dist/core/tools/index.js +148 -2
  483. package/dist/core/tools/index.js.map +1 -1
  484. package/dist/core/tools/ls.d.ts +4 -2
  485. package/dist/core/tools/ls.d.ts.map +1 -1
  486. package/dist/core/tools/ls.js +17 -1
  487. package/dist/core/tools/ls.js.map +1 -1
  488. package/dist/core/tools/lsp.d.ts +62 -0
  489. package/dist/core/tools/lsp.d.ts.map +1 -0
  490. package/dist/core/tools/lsp.js +216 -0
  491. package/dist/core/tools/lsp.js.map +1 -0
  492. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  493. package/dist/core/tools/output-accumulator.js +1 -1
  494. package/dist/core/tools/output-accumulator.js.map +1 -1
  495. package/dist/core/tools/path-permission.d.ts +18 -0
  496. package/dist/core/tools/path-permission.d.ts.map +1 -0
  497. package/dist/core/tools/path-permission.js +28 -0
  498. package/dist/core/tools/path-permission.js.map +1 -0
  499. package/dist/core/tools/plan-present.d.ts +27 -0
  500. package/dist/core/tools/plan-present.d.ts.map +1 -0
  501. package/dist/core/tools/plan-present.js +55 -0
  502. package/dist/core/tools/plan-present.js.map +1 -0
  503. package/dist/core/tools/powershell.d.ts +16 -0
  504. package/dist/core/tools/powershell.d.ts.map +1 -0
  505. package/dist/core/tools/powershell.js +39 -0
  506. package/dist/core/tools/powershell.js.map +1 -0
  507. package/dist/core/tools/read.d.ts +2 -2
  508. package/dist/core/tools/read.d.ts.map +1 -1
  509. package/dist/core/tools/read.js +14 -0
  510. package/dist/core/tools/read.js.map +1 -1
  511. package/dist/core/tools/skill-search.d.ts +32 -0
  512. package/dist/core/tools/skill-search.d.ts.map +1 -0
  513. package/dist/core/tools/skill-search.js +56 -0
  514. package/dist/core/tools/skill-search.js.map +1 -0
  515. package/dist/core/tools/test.d.ts +34 -0
  516. package/dist/core/tools/test.d.ts.map +1 -0
  517. package/dist/core/tools/test.js +75 -0
  518. package/dist/core/tools/test.js.map +1 -0
  519. package/dist/core/tools/todo-write.d.ts +31 -0
  520. package/dist/core/tools/todo-write.d.ts.map +1 -0
  521. package/dist/core/tools/todo-write.js +51 -0
  522. package/dist/core/tools/todo-write.js.map +1 -0
  523. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -2
  524. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  525. package/dist/core/tools/tool-definition-wrapper.js +11 -1
  526. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  527. package/dist/core/tools/tool-schema.d.ts +22 -0
  528. package/dist/core/tools/tool-schema.d.ts.map +1 -0
  529. package/dist/core/tools/tool-schema.js +45 -0
  530. package/dist/core/tools/tool-schema.js.map +1 -0
  531. package/dist/core/tools/web-fetch.d.ts +26 -0
  532. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  533. package/dist/core/tools/web-fetch.js +62 -0
  534. package/dist/core/tools/web-fetch.js.map +1 -0
  535. package/dist/core/tools/web-search-exa.d.ts +33 -0
  536. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  537. package/dist/core/tools/web-search-exa.js +128 -0
  538. package/dist/core/tools/web-search-exa.js.map +1 -0
  539. package/dist/core/tools/web-search.d.ts +26 -0
  540. package/dist/core/tools/web-search.d.ts.map +1 -0
  541. package/dist/core/tools/web-search.js +53 -0
  542. package/dist/core/tools/web-search.js.map +1 -0
  543. package/dist/core/tools/write.d.ts +16 -2
  544. package/dist/core/tools/write.d.ts.map +1 -1
  545. package/dist/core/tools/write.js +48 -2
  546. package/dist/core/tools/write.js.map +1 -1
  547. package/dist/core/trust-manager.d.ts.map +1 -1
  548. package/dist/core/trust-manager.js +2 -1
  549. package/dist/core/trust-manager.js.map +1 -1
  550. package/dist/core/usage-performance-store.d.ts +56 -0
  551. package/dist/core/usage-performance-store.d.ts.map +1 -0
  552. package/dist/core/usage-performance-store.js +85 -0
  553. package/dist/core/usage-performance-store.js.map +1 -0
  554. package/dist/core/web-search-provider.d.ts +64 -0
  555. package/dist/core/web-search-provider.d.ts.map +1 -0
  556. package/dist/core/web-search-provider.js +149 -0
  557. package/dist/core/web-search-provider.js.map +1 -0
  558. package/dist/extensions/llama/index.d.ts.map +1 -1
  559. package/dist/extensions/llama/index.js +2 -0
  560. package/dist/extensions/llama/index.js.map +1 -1
  561. package/dist/extensions/llama/provider.d.ts.map +1 -1
  562. package/dist/extensions/llama/provider.js +6 -2
  563. package/dist/extensions/llama/provider.js.map +1 -1
  564. package/dist/index.d.ts +9 -6
  565. package/dist/index.d.ts.map +1 -1
  566. package/dist/index.js +7 -4
  567. package/dist/index.js.map +1 -1
  568. package/dist/main.d.ts +5 -0
  569. package/dist/main.d.ts.map +1 -1
  570. package/dist/main.js +87 -22
  571. package/dist/main.js.map +1 -1
  572. package/dist/migrations.d.ts.map +1 -1
  573. package/dist/migrations.js +6 -5
  574. package/dist/migrations.js.map +1 -1
  575. package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
  576. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  577. package/dist/modes/interactive/components/assistant-message.js +182 -23
  578. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  579. package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
  580. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  581. package/dist/modes/interactive/components/bash-execution.js +20 -0
  582. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  583. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  584. package/dist/modes/interactive/components/config-selector.js +9 -6
  585. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  586. package/dist/modes/interactive/components/custom-editor.d.ts +72 -1
  587. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  588. package/dist/modes/interactive/components/custom-editor.js +338 -1
  589. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  590. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  591. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  592. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  593. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  594. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  595. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  596. package/dist/modes/interactive/components/extension-selector.js +24 -6
  597. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  598. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -4
  599. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  600. package/dist/modes/interactive/components/first-time-setup.js +17 -41
  601. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  602. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  603. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  604. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  605. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  606. package/dist/modes/interactive/components/footer.d.ts +31 -1
  607. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  608. package/dist/modes/interactive/components/footer.js +205 -24
  609. package/dist/modes/interactive/components/footer.js.map +1 -1
  610. package/dist/modes/interactive/components/index.d.ts +2 -0
  611. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  612. package/dist/modes/interactive/components/index.js +2 -0
  613. package/dist/modes/interactive/components/index.js.map +1 -1
  614. package/dist/modes/interactive/components/model-selector.d.ts +31 -9
  615. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  616. package/dist/modes/interactive/components/model-selector.js +236 -96
  617. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  618. package/dist/modes/interactive/components/settings-selector.d.ts +25 -5
  619. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  620. package/dist/modes/interactive/components/settings-selector.js +226 -58
  621. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  622. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  623. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  624. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  625. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  626. package/dist/modes/interactive/components/splash-header.d.ts +66 -0
  627. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
  628. package/dist/modes/interactive/components/splash-header.js +180 -0
  629. package/dist/modes/interactive/components/splash-header.js.map +1 -0
  630. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  631. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  632. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  633. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  634. package/dist/modes/interactive/components/tool-execution.d.ts +28 -1
  635. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  636. package/dist/modes/interactive/components/tool-execution.js +144 -35
  637. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  638. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  639. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  640. package/dist/modes/interactive/components/tool-panel.js +130 -0
  641. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  642. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  643. package/dist/modes/interactive/external-editor.js +60 -10
  644. package/dist/modes/interactive/external-editor.js.map +1 -1
  645. package/dist/modes/interactive/interactive-mode.d.ts +90 -5
  646. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  647. package/dist/modes/interactive/interactive-mode.js +729 -206
  648. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  649. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  650. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  651. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  652. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  653. package/dist/modes/interactive/theme/apex.json +93 -0
  654. package/dist/modes/interactive/theme/dark.json +2 -0
  655. package/dist/modes/interactive/theme/light.json +3 -1
  656. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  657. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  658. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  659. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  660. package/dist/modes/interactive/theme/theme-schema.json +11 -3
  661. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  662. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  663. package/dist/modes/interactive/theme/theme.js +65 -10
  664. package/dist/modes/interactive/theme/theme.js.map +1 -1
  665. package/dist/modes/json-event.d.ts +18 -12
  666. package/dist/modes/json-event.d.ts.map +1 -1
  667. package/dist/modes/json-event.js +22 -5
  668. package/dist/modes/json-event.js.map +1 -1
  669. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  670. package/dist/modes/rpc/rpc-mode.js +2 -1
  671. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  672. package/dist/package-manager-cli.d.ts +1 -0
  673. package/dist/package-manager-cli.d.ts.map +1 -1
  674. package/dist/package-manager-cli.js +210 -19
  675. package/dist/package-manager-cli.js.map +1 -1
  676. package/dist/rpc-entry.d.ts.map +1 -1
  677. package/dist/rpc-entry.js +2 -1
  678. package/dist/rpc-entry.js.map +1 -1
  679. package/dist/testing/replay/metrics.d.ts +24 -0
  680. package/dist/testing/replay/metrics.d.ts.map +1 -0
  681. package/dist/testing/replay/metrics.js +35 -0
  682. package/dist/testing/replay/metrics.js.map +1 -0
  683. package/dist/testing/replay/recorded-provider.d.ts +10 -0
  684. package/dist/testing/replay/recorded-provider.d.ts.map +1 -0
  685. package/dist/testing/replay/recorded-provider.js +108 -0
  686. package/dist/testing/replay/recorded-provider.js.map +1 -0
  687. package/dist/testing/replay/runner.d.ts +56 -0
  688. package/dist/testing/replay/runner.d.ts.map +1 -0
  689. package/dist/testing/replay/runner.js +406 -0
  690. package/dist/testing/replay/runner.js.map +1 -0
  691. package/dist/themes/apex-logo.d.ts +41 -0
  692. package/dist/themes/apex-logo.d.ts.map +1 -0
  693. package/dist/themes/apex-logo.js +35 -0
  694. package/dist/themes/apex-logo.js.map +1 -0
  695. package/dist/utils/apex-code-user-agent.d.ts +2 -0
  696. package/dist/utils/apex-code-user-agent.d.ts.map +1 -0
  697. package/dist/utils/apex-code-user-agent.js +5 -0
  698. package/dist/utils/apex-code-user-agent.js.map +1 -0
  699. package/dist/utils/changelog.d.ts +7 -2
  700. package/dist/utils/changelog.d.ts.map +1 -1
  701. package/dist/utils/changelog.js +82 -13
  702. package/dist/utils/changelog.js.map +1 -1
  703. package/dist/utils/clipboard-image.d.ts.map +1 -1
  704. package/dist/utils/clipboard-image.js +1 -1
  705. package/dist/utils/clipboard-image.js.map +1 -1
  706. package/dist/utils/frontmatter.d.ts.map +1 -1
  707. package/dist/utils/frontmatter.js +2 -1
  708. package/dist/utils/frontmatter.js.map +1 -1
  709. package/dist/utils/management-http.d.ts +5 -3
  710. package/dist/utils/management-http.d.ts.map +1 -1
  711. package/dist/utils/management-http.js +14 -10
  712. package/dist/utils/management-http.js.map +1 -1
  713. package/dist/utils/shell.d.ts +3 -0
  714. package/dist/utils/shell.d.ts.map +1 -1
  715. package/dist/utils/shell.js +17 -5
  716. package/dist/utils/shell.js.map +1 -1
  717. package/dist/utils/syntax-highlight.d.ts +1 -0
  718. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  719. package/dist/utils/syntax-highlight.js +60 -1
  720. package/dist/utils/syntax-highlight.js.map +1 -1
  721. package/dist/utils/text.d.ts +8 -0
  722. package/dist/utils/text.d.ts.map +1 -0
  723. package/dist/utils/text.js +9 -0
  724. package/dist/utils/text.js.map +1 -0
  725. package/dist/utils/tools-manager.d.ts +70 -2
  726. package/dist/utils/tools-manager.d.ts.map +1 -1
  727. package/dist/utils/tools-manager.js +280 -124
  728. package/dist/utils/tools-manager.js.map +1 -1
  729. package/dist/utils/version-check.d.ts +7 -5
  730. package/dist/utils/version-check.d.ts.map +1 -1
  731. package/dist/utils/version-check.js +27 -14
  732. package/dist/utils/version-check.js.map +1 -1
  733. package/dist/utils/windows-self-update.d.ts.map +1 -1
  734. package/dist/utils/windows-self-update.js +1 -1
  735. package/dist/utils/windows-self-update.js.map +1 -1
  736. package/docs/compaction.md +41 -24
  737. package/docs/containerization.md +24 -21
  738. package/docs/custom-provider.md +15 -12
  739. package/docs/development.md +11 -11
  740. package/docs/environment-variables.md +37 -77
  741. package/docs/extensions.md +68 -54
  742. package/docs/index.md +12 -24
  743. package/docs/json.md +18 -11
  744. package/docs/keybindings.md +18 -12
  745. package/docs/llama-cpp.md +9 -7
  746. package/docs/models.md +17 -11
  747. package/docs/packages.md +47 -43
  748. package/docs/prompt-templates.md +3 -3
  749. package/docs/providers.md +10 -10
  750. package/docs/quickstart.md +49 -32
  751. package/docs/rpc.md +35 -18
  752. package/docs/sdk.md +20 -6
  753. package/docs/security.md +18 -18
  754. package/docs/session-format.md +9 -9
  755. package/docs/sessions.md +13 -13
  756. package/docs/settings.md +83 -16
  757. package/docs/shell-aliases.md +1 -1
  758. package/docs/skills.md +66 -15
  759. package/docs/terminal-setup.md +44 -19
  760. package/docs/termux.md +4 -4
  761. package/docs/themes.md +32 -11
  762. package/docs/tmux.md +4 -4
  763. package/docs/tui.md +5 -5
  764. package/docs/usage.md +61 -53
  765. package/docs/windows.md +24 -2
  766. package/examples/extensions/border-status-editor.ts +1 -1
  767. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  768. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  769. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  770. package/examples/extensions/git-checkpoint.ts +24 -36
  771. package/examples/extensions/gondolin/package-lock.json +2 -2
  772. package/examples/extensions/gondolin/package.json +1 -1
  773. package/examples/extensions/notify.ts +3 -1
  774. package/examples/extensions/sandbox/package-lock.json +2 -2
  775. package/examples/extensions/sandbox/package.json +1 -1
  776. package/examples/extensions/subagent/README.md +3 -1
  777. package/examples/extensions/subagent/agents.ts +40 -9
  778. package/examples/extensions/subagent/index.ts +27 -4
  779. package/examples/extensions/titlebar-spinner.ts +1 -1
  780. package/examples/extensions/with-deps/package-lock.json +2 -2
  781. package/examples/extensions/with-deps/package.json +1 -1
  782. package/examples/rpc-extension-ui.ts +1 -1
  783. package/examples/sdk/06-extensions.ts +1 -1
  784. package/examples/sdk/README.md +1 -1
  785. package/npm-shrinkwrap.json +435 -452
  786. package/package.json +17 -18
  787. package/dist/core/telemetry.d.ts +0 -3
  788. package/dist/core/telemetry.d.ts.map +0 -1
  789. package/dist/core/telemetry.js +0 -9
  790. package/dist/core/telemetry.js.map +0 -1
  791. package/dist/server/create-harness.d.ts +0 -26
  792. package/dist/server/create-harness.d.ts.map +0 -1
  793. package/dist/server/create-harness.js +0 -104
  794. package/dist/server/create-harness.js.map +0 -1
  795. package/dist/utils/pi-user-agent.d.ts +0 -2
  796. package/dist/utils/pi-user-agent.d.ts.map +0 -1
  797. package/dist/utils/pi-user-agent.js +0 -5
  798. package/dist/utils/pi-user-agent.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ import type { AgentSessionRuntimeDiagnostic } from "./agent-session-services.ts";
2
+ import type { SettingsManager } from "./settings-manager.ts";
3
+ export declare function collectSettingsDiagnostics(settingsManager: SettingsManager): AgentSessionRuntimeDiagnostic[];
4
+ /**
5
+ * Remove duplicate type/message diagnostics while preserving their first occurrence.
6
+ * Startup and runtime settings managers can report the same file error.
7
+ */
8
+ export declare function deduplicateDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): AgentSessionRuntimeDiagnostic[];
9
+ //# sourceMappingURL=settings-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/settings-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,wBAAgB,0BAA0B,CAAC,eAAe,EAAE,eAAe,GAAG,6BAA6B,EAAE,CAK5G;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,WAAW,EAAE,SAAS,6BAA6B,EAAE,GACnD,6BAA6B,EAAE,CAQjC","sourcesContent":["import type { AgentSessionRuntimeDiagnostic } from \"./agent-session-services.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\nexport function collectSettingsDiagnostics(settingsManager: SettingsManager): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, path, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: path ? `Invalid settings file ${path}: ${error.message}` : `Invalid ${scope} settings: ${error.message}`,\n\t}));\n}\n\n/**\n * Remove duplicate type/message diagnostics while preserving their first occurrence.\n * Startup and runtime settings managers can report the same file error.\n */\nexport function deduplicateDiagnostics(\n\tdiagnostics: readonly AgentSessionRuntimeDiagnostic[],\n): AgentSessionRuntimeDiagnostic[] {\n\tconst seen = new Set<string>();\n\treturn diagnostics.filter((diagnostic) => {\n\t\tconst key = `${diagnostic.type}\\0${diagnostic.message}`;\n\t\tif (seen.has(key)) return false;\n\t\tseen.add(key);\n\t\treturn true;\n\t});\n}\n"]}
@@ -0,0 +1,21 @@
1
+ export function collectSettingsDiagnostics(settingsManager) {
2
+ return settingsManager.drainErrors().map(({ scope, path, error }) => ({
3
+ type: "warning",
4
+ message: path ? `Invalid settings file ${path}: ${error.message}` : `Invalid ${scope} settings: ${error.message}`,
5
+ }));
6
+ }
7
+ /**
8
+ * Remove duplicate type/message diagnostics while preserving their first occurrence.
9
+ * Startup and runtime settings managers can report the same file error.
10
+ */
11
+ export function deduplicateDiagnostics(diagnostics) {
12
+ const seen = new Set();
13
+ return diagnostics.filter((diagnostic) => {
14
+ const key = `${diagnostic.type}\0${diagnostic.message}`;
15
+ if (seen.has(key))
16
+ return false;
17
+ seen.add(key);
18
+ return true;
19
+ });
20
+ }
21
+ //# sourceMappingURL=settings-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-diagnostics.js","sourceRoot":"","sources":["../../src/core/settings-diagnostics.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,0BAA0B,CAAC,eAAgC,EAAmC;IAC7G,OAAO,eAAe,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,yBAAyB,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,cAAc,KAAK,CAAC,OAAO,EAAE;KACjH,CAAC,CAAC,CAAC;AAAA,CACJ;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACrC,WAAqD,EACnB;IAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QACxD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IAAA,CACZ,CAAC,CAAC;AAAA,CACH","sourcesContent":["import type { AgentSessionRuntimeDiagnostic } from \"./agent-session-services.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\nexport function collectSettingsDiagnostics(settingsManager: SettingsManager): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, path, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: path ? `Invalid settings file ${path}: ${error.message}` : `Invalid ${scope} settings: ${error.message}`,\n\t}));\n}\n\n/**\n * Remove duplicate type/message diagnostics while preserving their first occurrence.\n * Startup and runtime settings managers can report the same file error.\n */\nexport function deduplicateDiagnostics(\n\tdiagnostics: readonly AgentSessionRuntimeDiagnostic[],\n): AgentSessionRuntimeDiagnostic[] {\n\tconst seen = new Set<string>();\n\treturn diagnostics.filter((diagnostic) => {\n\t\tconst key = `${diagnostic.type}\\0${diagnostic.message}`;\n\t\tif (seen.has(key)) return false;\n\t\tseen.add(key);\n\t\treturn true;\n\t});\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import type { Transport } from "@earendil-works/pi-ai";
2
2
  import type { TuiMode as RendererTuiMode, ScrollViewScrollbar } from "@earendil-works/pi-tui";
3
3
  import type { ThinkingLevel } from "apex-code-agent-core";
4
+ import type { CheckpointSettings } from "./checkpoints/git-checkpoints.ts";
5
+ import type { LspSettings } from "./lsp/registry.ts";
4
6
  export interface CompactionSettings {
5
7
  enabled?: boolean;
6
8
  reserveTokens?: number;
@@ -22,11 +24,15 @@ export interface RetrySettings {
22
24
  provider?: ProviderRetrySettings;
23
25
  }
24
26
  export type TuiMode = RendererTuiMode;
27
+ export type FullscreenExitOutput = "transcript" | "resume-hint";
25
28
  export interface TerminalSettings {
26
29
  showImages?: boolean;
27
30
  imageWidthCells?: number;
28
31
  clearOnShrink?: boolean;
29
32
  showTerminalProgress?: boolean;
33
+ symbolPreset?: "unicode" | "ascii";
34
+ colorBlindMode?: boolean;
35
+ tokenUsageDisplay?: "off" | "compact" | "full";
30
36
  }
31
37
  export interface ImageSettings {
32
38
  autoResize?: boolean;
@@ -62,11 +68,36 @@ export type PackageSource = string | {
62
68
  prompts?: string[];
63
69
  themes?: string[];
64
70
  };
71
+ export interface NetworkSettings {
72
+ allowedHosts?: string[];
73
+ /**
74
+ * Permit the built-in model-provider hosts and the update check inside the sandbox.
75
+ * Defaults to true; set false to return to denying everything `allowedHosts` omits.
76
+ */
77
+ allowDefaultHosts?: boolean;
78
+ }
79
+ /**
80
+ * Backend for the `web_search` tool. Unset leaves the tool registered but
81
+ * unconfigured, which is what it has been since Phase 4 shipped it.
82
+ *
83
+ * `apiKey` is a config-value reference (`"$EXA_API_KEY"`, or `"!op read ..."`),
84
+ * resolved by `resolveConfigValue` exactly like a model provider's key. A literal
85
+ * key must never be written here: settings are a file this loader writes back.
86
+ */
87
+ export interface WebSearchSettings {
88
+ provider?: "exa";
89
+ apiKey?: string;
90
+ numResults?: number;
91
+ snippetMaxCharacters?: number;
92
+ endpoint?: string;
93
+ }
65
94
  export interface Settings {
66
95
  lastChangelogVersion?: string;
96
+ firstUseHints?: string[];
67
97
  defaultProvider?: string;
68
98
  defaultModel?: string;
69
99
  defaultThinkingLevel?: ThinkingLevel;
100
+ modelThinkingLevels?: Record<string, ThinkingLevel>;
70
101
  transport?: TransportSetting;
71
102
  steeringMode?: "all" | "one-at-a-time";
72
103
  followUpMode?: "all" | "one-at-a-time";
@@ -83,9 +114,7 @@ export interface Settings {
83
114
  shellCommandPrefix?: string;
84
115
  npmCommand?: string[];
85
116
  collapseChangelog?: boolean;
86
- enableInstallTelemetry?: boolean;
87
- enableAnalytics?: boolean;
88
- trackingId?: string;
117
+ sendProviderAttribution?: boolean;
89
118
  packages?: PackageSource[];
90
119
  extensions?: string[];
91
120
  skills?: string[];
@@ -95,6 +124,7 @@ export interface Settings {
95
124
  terminal?: TerminalSettings;
96
125
  images?: ImageSettings;
97
126
  enabledModels?: string[];
127
+ defaultTools?: string[];
98
128
  doubleEscapeAction?: "fork" | "tree" | "none";
99
129
  treeFilterMode?: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
100
130
  thinkingBudgets?: ThinkingBudgetsSettings;
@@ -109,8 +139,48 @@ export interface Settings {
109
139
  httpIdleTimeoutMs?: number;
110
140
  websocketConnectTimeoutMs?: number;
111
141
  tuiMode?: TuiMode;
142
+ fullscreenExitOutput?: FullscreenExitOutput;
112
143
  fullscreenScrollbar?: ScrollViewScrollbar;
144
+ network?: NetworkSettings;
145
+ /**
146
+ * Named OS-boundary profiles, keyed by the name `--permission-profile` selects.
147
+ *
148
+ * Read only from global scope by `core/sandbox/profiles.ts`; a project-scope copy is
149
+ * ignored, per ADR 0016.
150
+ */
151
+ sandboxProfiles?: Record<string, {
152
+ allowedHosts?: string[];
153
+ additionalWritableRoots?: string[];
154
+ }>;
155
+ delegationMaxDepth?: number;
156
+ observability?: ObservabilitySettings;
157
+ lsp?: LspSettings;
158
+ webSearch?: WebSearchSettings;
159
+ /**
160
+ * Git-backed worktree checkpoints. Absent by default; an absent key constructs no
161
+ * engine, so an unconfigured session runs no `git` subprocess and writes no ref.
162
+ */
163
+ checkpoints?: CheckpointSettings;
113
164
  }
165
+ /**
166
+ * User-directed OTLP trace export (roadmap Phase 8, ADR 0012) -- data goes to the
167
+ * user's own collector, never to this project. Unset `otlpEndpoint` means export
168
+ * never activates; there is no separate on/off switch to forget to flip.
169
+ */
170
+ export interface ObservabilitySettings {
171
+ otlpEndpoint?: string;
172
+ otlpHeaders?: Record<string, string>;
173
+ retentionDays?: number;
174
+ }
175
+ /**
176
+ * Hard ceiling on `delegationMaxDepth`, independent of what a user configures. A
177
+ * placeholder pending real measurement (the open question `docs/plans/2026-08-14-
178
+ * delegation-and-multi-agent.md` carries into this task): each level multiplies
179
+ * both token cost and the distance between the human and the work, and this
180
+ * repository has not yet measured that cost per level. 5 is conservative headroom
181
+ * above the default of 2, not a derived number.
182
+ */
183
+ export declare const DELEGATION_MAX_DEPTH_HARD_CAP = 5;
114
184
  export type SettingsScope = "global" | "project";
115
185
  export interface SettingsManagerCreateOptions {
116
186
  projectTrusted?: boolean;
@@ -120,6 +190,7 @@ export interface SettingsStorage {
120
190
  }
121
191
  export interface SettingsError {
122
192
  scope: SettingsScope;
193
+ path?: string;
123
194
  error: Error;
124
195
  }
125
196
  export declare class FileSettingsStorage implements SettingsStorage {
@@ -148,11 +219,14 @@ export declare class SettingsManager {
148
219
  private projectSettingsLoadError;
149
220
  private writeQueue;
150
221
  private errors;
222
+ private settingsPaths;
151
223
  private constructor();
152
224
  /** Create a SettingsManager that loads from files */
153
225
  static create(cwd: string, agentDir?: string, options?: SettingsManagerCreateOptions): SettingsManager;
154
226
  /** Create a SettingsManager from an arbitrary storage backend */
155
227
  static fromStorage(storage: SettingsStorage, options?: SettingsManagerCreateOptions): SettingsManager;
228
+ /** Create a manager while retaining optional file paths for reported storage errors. */
229
+ private static fromStorageWithPaths;
156
230
  /** Create an in-memory SettingsManager (no file I/O) */
157
231
  static inMemory(settings?: Partial<Settings>, options?: SettingsManagerCreateOptions): SettingsManager;
158
232
  private static loadFromStorage;
@@ -183,6 +257,8 @@ export declare class SettingsManager {
183
257
  drainErrors(): SettingsError[];
184
258
  getLastChangelogVersion(): string | undefined;
185
259
  setLastChangelogVersion(version: string): void;
260
+ getFirstUseHints(): string[];
261
+ setFirstUseHints(hints: readonly string[]): void;
186
262
  getSessionDir(): string | undefined;
187
263
  getDefaultProvider(): string | undefined;
188
264
  getDefaultModel(): string | undefined;
@@ -198,6 +274,10 @@ export declare class SettingsManager {
198
274
  setTheme(theme: string): void;
199
275
  getDefaultThinkingLevel(): ThinkingLevel | undefined;
200
276
  setDefaultThinkingLevel(level: ThinkingLevel): void;
277
+ getModelThinkingLevel(provider: string, modelId: string): ThinkingLevel | undefined;
278
+ getAllModelThinkingLevels(): Record<string, ThinkingLevel>;
279
+ setModelThinkingLevel(provider: string, modelId: string, level: ThinkingLevel): void;
280
+ removeModelThinkingLevel(provider: string, modelId: string): void;
201
281
  getTransport(): TransportSetting;
202
282
  setTransport(transport: TransportSetting): void;
203
283
  getCompactionEnabled(): boolean;
@@ -213,6 +293,11 @@ export declare class SettingsManager {
213
293
  reserveTokens: number;
214
294
  skipPrompt: boolean;
215
295
  };
296
+ getNetworkSettings(): NetworkSettings | undefined;
297
+ getSandboxProfiles(): Settings["sandboxProfiles"];
298
+ getLspSettings(): LspSettings | undefined;
299
+ getWebSearchSettings(): WebSearchSettings | undefined;
300
+ getCheckpointSettings(): CheckpointSettings | undefined;
216
301
  getBranchSummarySkipPrompt(): boolean;
217
302
  getRetryEnabled(): boolean;
218
303
  setRetryEnabled(enabled: boolean): void;
@@ -221,6 +306,7 @@ export declare class SettingsManager {
221
306
  maxRetries: number;
222
307
  baseDelayMs: number;
223
308
  };
309
+ getObservabilitySettings(): ObservabilitySettings;
224
310
  getHttpIdleTimeoutMs(): number;
225
311
  setHttpIdleTimeoutMs(timeoutMs: number): void;
226
312
  getProviderRetrySettings(): {
@@ -229,6 +315,8 @@ export declare class SettingsManager {
229
315
  maxRetryDelayMs: number;
230
316
  };
231
317
  getWebSocketConnectTimeoutMs(): number | undefined;
318
+ /** Max delegation recursion depth (roadmap Phase 5, task 5.3). A non-positive or missing configured value falls back to the default rather than being rejected outright -- this bound is a safety ceiling, not a value where a malformed setting should block startup. Always clamped to DELEGATION_MAX_DEPTH_HARD_CAP, regardless of configuration. */
319
+ getDelegationMaxDepth(): number;
232
320
  getHideThinkingBlock(): boolean;
233
321
  getShowCacheMissNotices(): boolean;
234
322
  getExternalEditorCommand(): string;
@@ -246,12 +334,8 @@ export declare class SettingsManager {
246
334
  setNpmCommand(command: string[] | undefined): void;
247
335
  getCollapseChangelog(): boolean;
248
336
  setCollapseChangelog(collapse: boolean): void;
249
- getEnableInstallTelemetry(): boolean;
250
- setEnableInstallTelemetry(enabled: boolean): void;
251
- getEnableAnalytics(): boolean;
252
- getTrackingId(): string | undefined;
253
- /** Set the analytics opt-in preference; generates a tracking identifier on first opt-in */
254
- setEnableAnalytics(enabled: boolean): void;
337
+ getSendProviderAttribution(): boolean;
338
+ setSendProviderAttribution(enabled: boolean): void;
255
339
  getPackages(): PackageSource[];
256
340
  setPackages(packages: PackageSource[]): void;
257
341
  setProjectPackages(packages: PackageSource[]): void;
@@ -274,12 +358,17 @@ export declare class SettingsManager {
274
358
  setShowImages(show: boolean): void;
275
359
  getImageWidthCells(): number;
276
360
  setImageWidthCells(width: number): void;
361
+ getSymbolPreset(): "unicode" | "ascii";
362
+ getColorBlindMode(): boolean;
363
+ getTokenUsageDisplay(): "off" | "compact" | "full";
277
364
  getClearOnShrink(): boolean;
278
365
  setClearOnShrink(enabled: boolean): void;
279
366
  getShowTerminalProgress(): boolean;
280
367
  setShowTerminalProgress(enabled: boolean): void;
281
368
  getTuiMode(): TuiMode;
282
369
  setTuiMode(mode: TuiMode): void;
370
+ getFullscreenExitOutput(): FullscreenExitOutput;
371
+ setFullscreenExitOutput(output: FullscreenExitOutput): void;
283
372
  getFullscreenScrollbar(): ScrollViewScrollbar;
284
373
  setFullscreenScrollbar(mode: ScrollViewScrollbar): void;
285
374
  getImageAutoResize(): boolean;
@@ -287,6 +376,7 @@ export declare class SettingsManager {
287
376
  getBlockImages(): boolean;
288
377
  setBlockImages(blocked: boolean): void;
289
378
  getEnabledModels(): string[] | undefined;
379
+ getDefaultTools(): string[] | undefined;
290
380
  setEnabledModels(patterns: string[] | undefined): void;
291
381
  getDoubleEscapeAction(): "fork" | "tree" | "none";
292
382
  setDoubleEscapeAction(action: "fork" | "tree" | "none"): void;
@@ -1 +1 @@
1
- {"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Transport } from \"@earendil-works/pi-ai\";\nimport type { TuiMode as RendererTuiMode, ScrollViewScrollbar } from \"@earendil-works/pi-tui\";\nimport type { ThinkingLevel } from \"apex-code-agent-core\";\nimport { randomUUID } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { normalizePath, resolvePath } from \"../utils/paths.ts\";\nimport { DEFAULT_HTTP_IDLE_TIMEOUT_MS, parseHttpIdleTimeoutMs } from \"./http-dispatcher.ts\";\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tkeepRecentTokens?: number; // default: 20000\n}\n\nexport interface BranchSummarySettings {\n\treserveTokens?: number; // default: 16384 (tokens reserved for prompt + LLM response)\n\tskipPrompt?: boolean; // default: false - when true, skips \"Summarize branch?\" prompt and defaults to no summary\n}\n\nexport interface ProviderRetrySettings {\n\ttimeoutMs?: number; // SDK/provider request timeout in milliseconds\n\tmaxRetries?: number; // SDK/provider retry attempts\n\tmaxRetryDelayMs?: number; // default: 60000 (max server-requested delay before failing)\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n\tprovider?: ProviderRetrySettings;\n}\n\nexport type TuiMode = RendererTuiMode;\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n\timageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)\n\tclearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)\n\tshowTerminalProgress?: boolean; // default: false (OSC 9;4 terminal progress indicators)\n}\n\nexport interface ImageSettings {\n\tautoResize?: boolean; // default: true (resize images to 2000x2000 max for better model compatibility)\n\tblockImages?: boolean; // default: false - when true, prevents all images from being sent to LLM providers\n}\n\nexport interface ThinkingBudgetsSettings {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\nexport type MermaidRenderingMode = \"off\" | \"final\" | \"streaming\";\n\nexport interface MarkdownSettings {\n\tcodeBlockIndent?: string; // default: \" \"\n\tmermaid?: MermaidRenderingMode; // default: \"streaming\"\n}\n\nexport interface WarningSettings {\n\tanthropicExtraUsage?: boolean; // default: true\n}\n\nexport type DefaultProjectTrust = \"ask\" | \"always\" | \"never\";\n\nexport type TransportSetting = Transport;\n\n/**\n * Package source for npm/git packages.\n * - String form: load all resources from the package\n * - Object form: filter which resources to load\n * - autoload=false: start empty and only apply explicit resource patterns\n */\nexport type PackageSource =\n\t| string\n\t| {\n\t\t\tsource: string;\n\t\t\tautoload?: boolean;\n\t\t\textensions?: string[];\n\t\t\tskills?: string[];\n\t\t\tprompts?: string[];\n\t\t\tthemes?: string[];\n\t };\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\tdefaultThinkingLevel?: ThinkingLevel;\n\ttransport?: TransportSetting; // default: \"auto\"\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tcompaction?: CompactionSettings;\n\tbranchSummary?: BranchSummarySettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\tshowCacheMissNotices?: boolean; // default: false - show transcript notices for significant prompt-cache misses\n\texternalEditor?: string; // Command for Ctrl+G external editor; takes precedence over VISUAL/EDITOR\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows); supports leading ~ expansion\n\tquietStartup?: boolean;\n\tdefaultProjectTrust?: DefaultProjectTrust; // default: \"ask\"; global setting only\n\tshellCommandPrefix?: string; // Prefix prepended to every bash command (e.g., \"shopt -s expand_aliases\" for alias support)\n\tnpmCommand?: string[]; // Command used for npm package lookup/install operations, argv-style (e.g., [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"])\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\tenableInstallTelemetry?: boolean; // default: true - anonymous version/update ping after changelog-detected updates\n\tenableAnalytics?: boolean; // default: false - opt-in analytics data sharing\n\ttrackingId?: string; // analytics tracking identifier, generated when analytics is enabled\n\tpackages?: PackageSource[]; // Array of npm/git package sources (string or object with filtering)\n\textensions?: string[]; // Array of local extension file paths or directories\n\tskills?: string[]; // Array of local skill file paths or directories\n\tprompts?: string[]; // Array of local prompt template paths or directories\n\tthemes?: string[]; // Array of local theme file paths or directories\n\tenableSkillCommands?: boolean; // default: true - register skills as /skill:name commands\n\tterminal?: TerminalSettings;\n\timages?: ImageSettings;\n\tenabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)\n\tdoubleEscapeAction?: \"fork\" | \"tree\" | \"none\"; // Action for double-escape with empty editor (default: \"tree\")\n\ttreeFilterMode?: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"; // Default filter when opening /tree\n\tthinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels\n\teditorPaddingX?: number; // Horizontal padding for input editor (default: 0)\n\toutputPad?: 0 | 1; // Horizontal padding for chat message output (default: 1)\n\tautocompleteMaxVisible?: number; // Max visible items in autocomplete dropdown (default: 5)\n\tshowHardwareCursor?: boolean; // Show terminal cursor while still positioning it for IME\n\tmarkdown?: MarkdownSettings;\n\twarnings?: WarningSettings;\n\tsessionDir?: string; // Custom session storage directory (same format as --session-dir CLI flag)\n\thttpProxy?: string; // Proxy URL applied as HTTP_PROXY and HTTPS_PROXY for Pi-managed HTTP clients\n\thttpIdleTimeoutMs?: number; // HTTP header/body idle timeout in milliseconds; 0 disables it\n\twebsocketConnectTimeoutMs?: number; // WebSocket connect/open handshake timeout in milliseconds; 0 disables it\n\ttuiMode?: TuiMode; // default: \"regular\"\n\tfullscreenScrollbar?: ScrollViewScrollbar; // default: \"auto\"; no effect in regular TUI mode\n}\n\nfunction isMergeableObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction deepMergeObjects(base: Record<string, unknown>, overrides: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...base };\n\n\tfor (const key of Object.keys(overrides)) {\n\t\tconst overrideValue = overrides[key];\n\t\tif (overrideValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst baseValue = base[key];\n\t\tresult[key] =\n\t\t\tisMergeableObject(baseValue) && isMergeableObject(overrideValue)\n\t\t\t\t? deepMergeObjects(baseValue, overrideValue)\n\t\t\t\t: overrideValue;\n\t}\n\n\treturn result;\n}\n\n/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */\nfunction deepMergeSettings(base: Settings, overrides: Settings): Settings {\n\treturn deepMergeObjects(base as Record<string, unknown>, overrides as Record<string, unknown>) as Settings;\n}\n\nfunction parseTimeoutSetting(value: unknown, settingName: string): number | undefined {\n\tconst timeoutMs = parseHttpIdleTimeoutMs(value);\n\tif (timeoutMs !== undefined) {\n\t\treturn timeoutMs;\n\t}\n\tif (value !== undefined) {\n\t\tthrow new Error(`Invalid ${settingName} setting: ${String(value)}`);\n\t}\n\treturn undefined;\n}\n\nexport type SettingsScope = \"global\" | \"project\";\n\nexport interface SettingsManagerCreateOptions {\n\tprojectTrusted?: boolean;\n}\n\nexport interface SettingsStorage {\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void;\n}\n\nexport interface SettingsError {\n\tscope: SettingsScope;\n\terror: Error;\n}\n\nexport class FileSettingsStorage implements SettingsStorage {\n\tprivate globalSettingsPath: string;\n\tprivate projectSettingsPath: string;\n\n\tconstructor(cwd: string, agentDir: string) {\n\t\tconst resolvedCwd = resolvePath(cwd);\n\t\tconst resolvedAgentDir = resolvePath(agentDir);\n\t\tthis.globalSettingsPath = join(resolvedAgentDir, \"settings.json\");\n\t\tthis.projectSettingsPath = join(resolvedCwd, CONFIG_DIR_NAME, \"settings.json\");\n\t}\n\n\tprivate acquireLockSyncWithRetry(path: string): () => void {\n\t\tconst maxAttempts = 10;\n\t\tconst delayMs = 20;\n\t\tlet lastError: unknown;\n\n\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn lockfile.lockSync(path, { realpath: false });\n\t\t\t} catch (error) {\n\t\t\t\tconst code =\n\t\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t\t: undefined;\n\t\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tlastError = error;\n\t\t\t\tconst start = Date.now();\n\t\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t\t// Sleep synchronously to avoid changing callers to async.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow (lastError as Error) ?? new Error(\"Failed to acquire settings lock\");\n\t}\n\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void {\n\t\tconst path = scope === \"global\" ? this.globalSettingsPath : this.projectSettingsPath;\n\t\tconst dir = dirname(path);\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\t// Only create directory and lock if file exists or we need to write\n\t\t\tconst fileExists = existsSync(path);\n\t\t\tif (fileExists) {\n\t\t\t\trelease = this.acquireLockSyncWithRetry(path);\n\t\t\t}\n\t\t\tconst current = fileExists ? readFileSync(path, \"utf-8\") : undefined;\n\t\t\tconst next = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\t// Only create directory when we actually need to write\n\t\t\t\tif (!existsSync(dir)) {\n\t\t\t\t\tmkdirSync(dir, { recursive: true });\n\t\t\t\t}\n\t\t\t\tif (!release) {\n\t\t\t\t\trelease = this.acquireLockSyncWithRetry(path);\n\t\t\t\t}\n\t\t\t\twriteFileSync(path, next, \"utf-8\");\n\t\t\t}\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemorySettingsStorage implements SettingsStorage {\n\tprivate global: string | undefined;\n\tprivate project: string | undefined;\n\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void {\n\t\tconst current = scope === \"global\" ? this.global : this.project;\n\t\tconst next = fn(current);\n\t\tif (next !== undefined) {\n\t\t\tif (scope === \"global\") {\n\t\t\t\tthis.global = next;\n\t\t\t} else {\n\t\t\t\tthis.project = next;\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class SettingsManager {\n\tprivate storage: SettingsStorage;\n\tprivate globalSettings: Settings;\n\tprivate projectSettings: Settings;\n\tprivate settings: Settings;\n\tprivate projectTrusted: boolean;\n\tprivate modifiedFields = new Set<keyof Settings>(); // Track global fields modified during session\n\tprivate modifiedNestedFields = new Map<keyof Settings, Set<string>>(); // Track global nested field modifications\n\tprivate modifiedProjectFields = new Set<keyof Settings>(); // Track project fields modified during session\n\tprivate modifiedProjectNestedFields = new Map<keyof Settings, Set<string>>(); // Track project nested field modifications\n\tprivate globalSettingsLoadError: Error | null = null; // Track if global settings file had parse errors\n\tprivate projectSettingsLoadError: Error | null = null; // Track if project settings file had parse errors\n\tprivate writeQueue: Promise<void> = Promise.resolve();\n\tprivate errors: SettingsError[];\n\n\tprivate constructor(\n\t\tstorage: SettingsStorage,\n\t\tinitialGlobal: Settings,\n\t\tinitialProject: Settings,\n\t\tglobalLoadError: Error | null = null,\n\t\tprojectLoadError: Error | null = null,\n\t\tinitialErrors: SettingsError[] = [],\n\t\tprojectTrusted = true,\n\t) {\n\t\tthis.storage = storage;\n\t\tthis.globalSettings = initialGlobal;\n\t\tthis.projectSettings = initialProject;\n\t\tthis.projectTrusted = projectTrusted;\n\t\tthis.globalSettingsLoadError = globalLoadError;\n\t\tthis.projectSettingsLoadError = projectLoadError;\n\t\tthis.errors = [...initialErrors];\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\t/** Create a SettingsManager that loads from files */\n\tstatic create(\n\t\tcwd: string,\n\t\tagentDir: string = getAgentDir(),\n\t\toptions: SettingsManagerCreateOptions = {},\n\t): SettingsManager {\n\t\tconst storage = new FileSettingsStorage(cwd, agentDir);\n\t\treturn SettingsManager.fromStorage(storage, options);\n\t}\n\n\t/** Create a SettingsManager from an arbitrary storage backend */\n\tstatic fromStorage(storage: SettingsStorage, options: SettingsManagerCreateOptions = {}): SettingsManager {\n\t\tconst projectTrusted = options.projectTrusted ?? true;\n\t\tconst globalLoad = SettingsManager.tryLoadFromStorage(storage, \"global\");\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(storage, \"project\", projectTrusted);\n\t\tconst initialErrors: SettingsError[] = [];\n\t\tif (globalLoad.error) {\n\t\t\tinitialErrors.push({ scope: \"global\", error: globalLoad.error });\n\t\t}\n\t\tif (projectLoad.error) {\n\t\t\tinitialErrors.push({ scope: \"project\", error: projectLoad.error });\n\t\t}\n\n\t\treturn new SettingsManager(\n\t\t\tstorage,\n\t\t\tglobalLoad.settings,\n\t\t\tprojectLoad.settings,\n\t\t\tglobalLoad.error,\n\t\t\tprojectLoad.error,\n\t\t\tinitialErrors,\n\t\t\tprojectTrusted,\n\t\t);\n\t}\n\n\t/** Create an in-memory SettingsManager (no file I/O) */\n\tstatic inMemory(settings: Partial<Settings> = {}, options: SettingsManagerCreateOptions = {}): SettingsManager {\n\t\tconst storage = new InMemorySettingsStorage();\n\t\tconst initialSettings = SettingsManager.migrateSettings(structuredClone(settings) as Record<string, unknown>);\n\t\tstorage.withLock(\"global\", () => JSON.stringify(initialSettings, null, 2));\n\t\treturn SettingsManager.fromStorage(storage, options);\n\t}\n\n\tprivate static loadFromStorage(storage: SettingsStorage, scope: SettingsScope, projectTrusted = true): Settings {\n\t\tif (scope === \"project\" && !projectTrusted) {\n\t\t\treturn {};\n\t\t}\n\n\t\tlet content: string | undefined;\n\t\tstorage.withLock(scope, (current) => {\n\t\t\tcontent = current;\n\t\t\treturn undefined;\n\t\t});\n\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\tconst settings = JSON.parse(content);\n\t\treturn SettingsManager.migrateSettings(settings);\n\t}\n\n\tprivate static tryLoadFromStorage(\n\t\tstorage: SettingsStorage,\n\t\tscope: SettingsScope,\n\t\tprojectTrusted = true,\n\t): { settings: Settings; error: Error | null } {\n\t\ttry {\n\t\t\treturn { settings: SettingsManager.loadFromStorage(storage, scope, projectTrusted), error: null };\n\t\t} catch (error) {\n\t\t\treturn { settings: {}, error: error as Error };\n\t\t}\n\t}\n\n\t/** Migrate old settings format to new format */\n\tprivate static migrateSettings(settings: Record<string, unknown>): Settings {\n\t\t// Migrate queueMode -> steeringMode\n\t\tif (\"queueMode\" in settings && !(\"steeringMode\" in settings)) {\n\t\t\tsettings.steeringMode = settings.queueMode;\n\t\t\tdelete settings.queueMode;\n\t\t}\n\n\t\t// Migrate legacy websockets boolean -> transport enum\n\t\tif (!(\"transport\" in settings) && typeof settings.websockets === \"boolean\") {\n\t\t\tsettings.transport = settings.websockets ? \"websocket\" : \"sse\";\n\t\t\tdelete settings.websockets;\n\t\t}\n\n\t\t// Migrate old skills object format to new array format\n\t\tif (\n\t\t\t\"skills\" in settings &&\n\t\t\ttypeof settings.skills === \"object\" &&\n\t\t\tsettings.skills !== null &&\n\t\t\t!Array.isArray(settings.skills)\n\t\t) {\n\t\t\tconst skillsSettings = settings.skills as {\n\t\t\t\tenableSkillCommands?: boolean;\n\t\t\t\tcustomDirectories?: unknown;\n\t\t\t};\n\t\t\tif (skillsSettings.enableSkillCommands !== undefined && settings.enableSkillCommands === undefined) {\n\t\t\t\tsettings.enableSkillCommands = skillsSettings.enableSkillCommands;\n\t\t\t}\n\t\t\tif (Array.isArray(skillsSettings.customDirectories) && skillsSettings.customDirectories.length > 0) {\n\t\t\t\tsettings.skills = skillsSettings.customDirectories;\n\t\t\t} else {\n\t\t\t\tdelete settings.skills;\n\t\t\t}\n\t\t}\n\n\t\t// Migrate retry.maxDelayMs -> retry.provider.maxRetryDelayMs\n\t\tif (\n\t\t\t\"retry\" in settings &&\n\t\t\ttypeof settings.retry === \"object\" &&\n\t\t\tsettings.retry !== null &&\n\t\t\t!Array.isArray(settings.retry)\n\t\t) {\n\t\t\tconst retrySettings = settings.retry as Record<string, unknown>;\n\t\t\tconst providerSettings =\n\t\t\t\ttypeof retrySettings.provider === \"object\" && retrySettings.provider !== null\n\t\t\t\t\t? (retrySettings.provider as Record<string, unknown>)\n\t\t\t\t\t: undefined;\n\t\t\tif (\n\t\t\t\ttypeof retrySettings.maxDelayMs === \"number\" &&\n\t\t\t\t(providerSettings?.maxRetryDelayMs === undefined || providerSettings?.maxRetryDelayMs === null)\n\t\t\t) {\n\t\t\t\tretrySettings.provider = {\n\t\t\t\t\t...(providerSettings ?? {}),\n\t\t\t\t\tmaxRetryDelayMs: retrySettings.maxDelayMs,\n\t\t\t\t};\n\t\t\t}\n\t\t\tdelete retrySettings.maxDelayMs;\n\t\t}\n\n\t\treturn settings as Settings;\n\t}\n\n\tgetGlobalSettings(): Settings {\n\t\treturn structuredClone(this.globalSettings);\n\t}\n\n\tgetProjectSettings(): Settings {\n\t\treturn structuredClone(this.projectSettings);\n\t}\n\n\tisProjectTrusted(): boolean {\n\t\treturn this.projectTrusted;\n\t}\n\n\tsetProjectTrusted(trusted: boolean): void {\n\t\tif (this.projectTrusted === trusted) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.projectTrusted = trusted;\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\n\t\tif (!trusted) {\n\t\t\tthis.projectSettings = {};\n\t\t\tthis.projectSettingsLoadError = null;\n\t\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t\t\treturn;\n\t\t}\n\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(this.storage, \"project\", trusted);\n\t\tthis.projectSettings = projectLoad.settings;\n\t\tthis.projectSettingsLoadError = projectLoad.error;\n\t\tif (projectLoad.error) {\n\t\t\tthis.recordError(\"project\", projectLoad.error);\n\t\t}\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tawait this.writeQueue;\n\t\tconst globalLoad = SettingsManager.tryLoadFromStorage(this.storage, \"global\");\n\t\tif (!globalLoad.error) {\n\t\t\tthis.globalSettings = globalLoad.settings;\n\t\t\tthis.globalSettingsLoadError = null;\n\t\t} else {\n\t\t\tthis.globalSettingsLoadError = globalLoad.error;\n\t\t\tthis.recordError(\"global\", globalLoad.error);\n\t\t}\n\n\t\tthis.modifiedFields.clear();\n\t\tthis.modifiedNestedFields.clear();\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(this.storage, \"project\", this.projectTrusted);\n\t\tif (!projectLoad.error) {\n\t\t\tthis.projectSettings = projectLoad.settings;\n\t\t\tthis.projectSettingsLoadError = null;\n\t\t} else {\n\t\t\tthis.projectSettingsLoadError = projectLoad.error;\n\t\t\tthis.recordError(\"project\", projectLoad.error);\n\t\t}\n\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\t/** Apply additional overrides on top of current settings */\n\tapplyOverrides(overrides: Partial<Settings>): void {\n\t\tthis.settings = deepMergeSettings(this.settings, overrides);\n\t}\n\n\t/** Mark a global field as modified during this session */\n\tprivate markModified(field: keyof Settings, nestedKey?: string): void {\n\t\tthis.modifiedFields.add(field);\n\t\tif (nestedKey) {\n\t\t\tif (!this.modifiedNestedFields.has(field)) {\n\t\t\t\tthis.modifiedNestedFields.set(field, new Set());\n\t\t\t}\n\t\t\tthis.modifiedNestedFields.get(field)!.add(nestedKey);\n\t\t}\n\t}\n\n\t/** Mark a project field as modified during this session */\n\tprivate markProjectModified(field: keyof Settings, nestedKey?: string): void {\n\t\tthis.modifiedProjectFields.add(field);\n\t\tif (nestedKey) {\n\t\t\tif (!this.modifiedProjectNestedFields.has(field)) {\n\t\t\t\tthis.modifiedProjectNestedFields.set(field, new Set());\n\t\t\t}\n\t\t\tthis.modifiedProjectNestedFields.get(field)!.add(nestedKey);\n\t\t}\n\t}\n\n\tprivate assertProjectTrustedForWrite(): void {\n\t\tif (!this.projectTrusted) {\n\t\t\tthrow new Error(\"Project is not trusted; refusing to write project settings\");\n\t\t}\n\t}\n\n\tprivate recordError(scope: SettingsScope, error: unknown): void {\n\t\tconst normalizedError = error instanceof Error ? error : new Error(String(error));\n\t\tthis.errors.push({ scope, error: normalizedError });\n\t}\n\n\tprivate clearModifiedScope(scope: SettingsScope): void {\n\t\tif (scope === \"global\") {\n\t\t\tthis.modifiedFields.clear();\n\t\t\tthis.modifiedNestedFields.clear();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\t}\n\n\tprivate enqueueWrite(scope: SettingsScope, task: () => void): void {\n\t\tthis.writeQueue = this.writeQueue\n\t\t\t.then(() => {\n\t\t\t\tif (scope === \"project\") {\n\t\t\t\t\tthis.assertProjectTrustedForWrite();\n\t\t\t\t}\n\t\t\t\ttask();\n\t\t\t\tthis.clearModifiedScope(scope);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.recordError(scope, error);\n\t\t\t});\n\t}\n\n\tprivate cloneModifiedNestedFields(source: Map<keyof Settings, Set<string>>): Map<keyof Settings, Set<string>> {\n\t\tconst snapshot = new Map<keyof Settings, Set<string>>();\n\t\tfor (const [key, value] of source.entries()) {\n\t\t\tsnapshot.set(key, new Set(value));\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\tprivate persistScopedSettings(\n\t\tscope: SettingsScope,\n\t\tsnapshotSettings: Settings,\n\t\tmodifiedFields: Set<keyof Settings>,\n\t\tmodifiedNestedFields: Map<keyof Settings, Set<string>>,\n\t): void {\n\t\tthis.storage.withLock(scope, (current) => {\n\t\t\tconst currentFileSettings = current\n\t\t\t\t? SettingsManager.migrateSettings(JSON.parse(current) as Record<string, unknown>)\n\t\t\t\t: {};\n\t\t\tconst mergedSettings: Settings = { ...currentFileSettings };\n\t\t\tfor (const field of modifiedFields) {\n\t\t\t\tconst value = snapshotSettings[field];\n\t\t\t\tif (modifiedNestedFields.has(field) && typeof value === \"object\" && value !== null) {\n\t\t\t\t\tconst nestedModified = modifiedNestedFields.get(field)!;\n\t\t\t\t\tconst baseNested = (currentFileSettings[field] as Record<string, unknown>) ?? {};\n\t\t\t\t\tconst inMemoryNested = value as Record<string, unknown>;\n\t\t\t\t\tconst mergedNested = { ...baseNested };\n\t\t\t\t\tfor (const nestedKey of nestedModified) {\n\t\t\t\t\t\tmergedNested[nestedKey] = inMemoryNested[nestedKey];\n\t\t\t\t\t}\n\t\t\t\t\t(mergedSettings as Record<string, unknown>)[field] = mergedNested;\n\t\t\t\t} else {\n\t\t\t\t\t(mergedSettings as Record<string, unknown>)[field] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn JSON.stringify(mergedSettings, null, 2);\n\t\t});\n\t}\n\n\tprivate save(): void {\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\n\t\tif (this.globalSettingsLoadError) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst snapshotGlobalSettings = structuredClone(this.globalSettings);\n\t\tconst modifiedFields = new Set(this.modifiedFields);\n\t\tconst modifiedNestedFields = this.cloneModifiedNestedFields(this.modifiedNestedFields);\n\n\t\tthis.enqueueWrite(\"global\", () => {\n\t\t\tthis.persistScopedSettings(\"global\", snapshotGlobalSettings, modifiedFields, modifiedNestedFields);\n\t\t});\n\t}\n\n\tprivate saveProjectSettings(settings: Settings): void {\n\t\tthis.assertProjectTrustedForWrite();\n\t\tthis.projectSettings = structuredClone(settings);\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\n\t\tif (this.projectSettingsLoadError) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst snapshotProjectSettings = structuredClone(this.projectSettings);\n\t\tconst modifiedFields = new Set(this.modifiedProjectFields);\n\t\tconst modifiedNestedFields = this.cloneModifiedNestedFields(this.modifiedProjectNestedFields);\n\t\tthis.enqueueWrite(\"project\", () => {\n\t\t\tthis.persistScopedSettings(\"project\", snapshotProjectSettings, modifiedFields, modifiedNestedFields);\n\t\t});\n\t}\n\n\tprivate updateProjectSettings(field: keyof Settings, update: (settings: Settings) => void): void {\n\t\tthis.assertProjectTrustedForWrite();\n\t\tconst projectSettings = structuredClone(this.projectSettings);\n\t\tupdate(projectSettings);\n\t\tthis.markProjectModified(field);\n\t\tthis.saveProjectSettings(projectSettings);\n\t}\n\n\tasync flush(): Promise<void> {\n\t\tawait this.writeQueue;\n\t}\n\n\tdrainErrors(): SettingsError[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\tgetLastChangelogVersion(): string | undefined {\n\t\treturn this.settings.lastChangelogVersion;\n\t}\n\n\tsetLastChangelogVersion(version: string): void {\n\t\tthis.globalSettings.lastChangelogVersion = version;\n\t\tthis.markModified(\"lastChangelogVersion\");\n\t\tthis.save();\n\t}\n\n\tgetSessionDir(): string | undefined {\n\t\tconst sessionDir = this.settings.sessionDir;\n\t\treturn sessionDir ? normalizePath(sessionDir) : sessionDir;\n\t}\n\n\tgetDefaultProvider(): string | undefined {\n\t\treturn this.settings.defaultProvider;\n\t}\n\n\tgetDefaultModel(): string | undefined {\n\t\treturn this.settings.defaultModel;\n\t}\n\n\tsetDefaultProvider(provider: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.markModified(\"defaultProvider\");\n\t\tthis.save();\n\t}\n\n\tsetDefaultModel(modelId: string): void {\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.markModified(\"defaultModel\");\n\t\tthis.save();\n\t}\n\n\tsetDefaultModelAndProvider(provider: string, modelId: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.markModified(\"defaultProvider\");\n\t\tthis.markModified(\"defaultModel\");\n\t\tthis.save();\n\t}\n\n\tgetSteeringMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.steeringMode || \"one-at-a-time\";\n\t}\n\n\tsetSteeringMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.steeringMode = mode;\n\t\tthis.markModified(\"steeringMode\");\n\t\tthis.save();\n\t}\n\n\tgetFollowUpMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.followUpMode || \"one-at-a-time\";\n\t}\n\n\tsetFollowUpMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.followUpMode = mode;\n\t\tthis.markModified(\"followUpMode\");\n\t\tthis.save();\n\t}\n\n\tgetThemeSetting(): string | undefined {\n\t\tconst value = this.settings.theme;\n\t\tif (typeof value === \"string\") return value;\n\t\treturn undefined;\n\t}\n\n\tgetTheme(): string | undefined {\n\t\tconst theme = this.getThemeSetting();\n\t\treturn theme?.includes(\"/\") ? undefined : theme;\n\t}\n\n\tsetTheme(theme: string): void {\n\t\tthis.globalSettings.theme = theme;\n\t\tthis.markModified(\"theme\");\n\t\tthis.save();\n\t}\n\n\tgetDefaultThinkingLevel(): ThinkingLevel | undefined {\n\t\treturn this.settings.defaultThinkingLevel;\n\t}\n\n\tsetDefaultThinkingLevel(level: ThinkingLevel): void {\n\t\tthis.globalSettings.defaultThinkingLevel = level;\n\t\tthis.markModified(\"defaultThinkingLevel\");\n\t\tthis.save();\n\t}\n\n\tgetTransport(): TransportSetting {\n\t\treturn this.settings.transport ?? \"auto\";\n\t}\n\n\tsetTransport(transport: TransportSetting): void {\n\t\tthis.globalSettings.transport = transport;\n\t\tthis.markModified(\"transport\");\n\t\tthis.save();\n\t}\n\n\tgetCompactionEnabled(): boolean {\n\t\treturn this.settings.compaction?.enabled ?? true;\n\t}\n\n\tsetCompactionEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.compaction) {\n\t\t\tthis.globalSettings.compaction = {};\n\t\t}\n\t\tthis.globalSettings.compaction.enabled = enabled;\n\t\tthis.markModified(\"compaction\", \"enabled\");\n\t\tthis.save();\n\t}\n\n\tgetCompactionReserveTokens(): number {\n\t\treturn this.settings.compaction?.reserveTokens ?? 16384;\n\t}\n\n\tgetCompactionKeepRecentTokens(): number {\n\t\treturn this.settings.compaction?.keepRecentTokens ?? 20000;\n\t}\n\n\tgetCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number } {\n\t\treturn {\n\t\t\tenabled: this.getCompactionEnabled(),\n\t\t\treserveTokens: this.getCompactionReserveTokens(),\n\t\t\tkeepRecentTokens: this.getCompactionKeepRecentTokens(),\n\t\t};\n\t}\n\n\tgetBranchSummarySettings(): { reserveTokens: number; skipPrompt: boolean } {\n\t\treturn {\n\t\t\treserveTokens: this.settings.branchSummary?.reserveTokens ?? 16384,\n\t\t\tskipPrompt: this.settings.branchSummary?.skipPrompt ?? false,\n\t\t};\n\t}\n\n\tgetBranchSummarySkipPrompt(): boolean {\n\t\treturn this.settings.branchSummary?.skipPrompt ?? false;\n\t}\n\n\tgetRetryEnabled(): boolean {\n\t\treturn this.settings.retry?.enabled ?? true;\n\t}\n\n\tsetRetryEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.retry) {\n\t\t\tthis.globalSettings.retry = {};\n\t\t}\n\t\tthis.globalSettings.retry.enabled = enabled;\n\t\tthis.markModified(\"retry\", \"enabled\");\n\t\tthis.save();\n\t}\n\n\tgetRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number } {\n\t\treturn {\n\t\t\tenabled: this.getRetryEnabled(),\n\t\t\tmaxRetries: this.settings.retry?.maxRetries ?? 3,\n\t\t\tbaseDelayMs: this.settings.retry?.baseDelayMs ?? 2000,\n\t\t};\n\t}\n\n\tgetHttpIdleTimeoutMs(): number {\n\t\treturn parseTimeoutSetting(this.settings.httpIdleTimeoutMs, \"httpIdleTimeoutMs\") ?? DEFAULT_HTTP_IDLE_TIMEOUT_MS;\n\t}\n\n\tsetHttpIdleTimeoutMs(timeoutMs: number): void {\n\t\tif (!Number.isFinite(timeoutMs) || timeoutMs < 0) {\n\t\t\tthrow new Error(`Invalid httpIdleTimeoutMs setting: ${String(timeoutMs)}`);\n\t\t}\n\t\tthis.globalSettings.httpIdleTimeoutMs = Math.floor(timeoutMs);\n\t\tthis.markModified(\"httpIdleTimeoutMs\");\n\t\tthis.save();\n\t}\n\n\tgetProviderRetrySettings(): { timeoutMs?: number; maxRetries?: number; maxRetryDelayMs: number } {\n\t\treturn {\n\t\t\ttimeoutMs: this.settings.retry?.provider?.timeoutMs,\n\t\t\tmaxRetries: this.settings.retry?.provider?.maxRetries,\n\t\t\tmaxRetryDelayMs: this.settings.retry?.provider?.maxRetryDelayMs ?? 60000,\n\t\t};\n\t}\n\n\tgetWebSocketConnectTimeoutMs(): number | undefined {\n\t\treturn parseTimeoutSetting(this.settings.websocketConnectTimeoutMs, \"websocketConnectTimeoutMs\");\n\t}\n\n\tgetHideThinkingBlock(): boolean {\n\t\treturn this.settings.hideThinkingBlock ?? false;\n\t}\n\n\tgetShowCacheMissNotices(): boolean {\n\t\treturn this.settings.showCacheMissNotices ?? false;\n\t}\n\n\tgetExternalEditorCommand(): string {\n\t\tconst configuredEditor = this.settings.externalEditor;\n\t\tif (typeof configuredEditor === \"string\" && configuredEditor.trim() !== \"\") {\n\t\t\treturn configuredEditor;\n\t\t}\n\t\tconst environmentEditor = process.env.VISUAL || process.env.EDITOR;\n\t\tif (environmentEditor) {\n\t\t\treturn environmentEditor;\n\t\t}\n\t\treturn process.platform === \"win32\" ? \"notepad\" : \"nano\";\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.globalSettings.hideThinkingBlock = hide;\n\t\tthis.markModified(\"hideThinkingBlock\");\n\t\tthis.save();\n\t}\n\n\tsetShowCacheMissNotices(show: boolean): void {\n\t\tthis.globalSettings.showCacheMissNotices = show;\n\t\tthis.markModified(\"showCacheMissNotices\");\n\t\tthis.save();\n\t}\n\n\tgetShellPath(): string | undefined {\n\t\tconst shellPath = this.settings.shellPath;\n\t\treturn shellPath ? normalizePath(shellPath) : shellPath;\n\t}\n\n\tsetShellPath(path: string | undefined): void {\n\t\tthis.globalSettings.shellPath = path;\n\t\tthis.markModified(\"shellPath\");\n\t\tthis.save();\n\t}\n\n\tgetQuietStartup(): boolean {\n\t\treturn this.settings.quietStartup ?? false;\n\t}\n\n\tsetQuietStartup(quiet: boolean): void {\n\t\tthis.globalSettings.quietStartup = quiet;\n\t\tthis.markModified(\"quietStartup\");\n\t\tthis.save();\n\t}\n\n\tgetDefaultProjectTrust(): DefaultProjectTrust {\n\t\tconst value = this.globalSettings.defaultProjectTrust;\n\t\treturn value === \"always\" || value === \"never\" ? value : \"ask\";\n\t}\n\n\tsetDefaultProjectTrust(defaultProjectTrust: DefaultProjectTrust): void {\n\t\tthis.globalSettings.defaultProjectTrust = defaultProjectTrust;\n\t\tthis.markModified(\"defaultProjectTrust\");\n\t\tthis.save();\n\t}\n\n\tgetShellCommandPrefix(): string | undefined {\n\t\treturn this.settings.shellCommandPrefix;\n\t}\n\n\tsetShellCommandPrefix(prefix: string | undefined): void {\n\t\tthis.globalSettings.shellCommandPrefix = prefix;\n\t\tthis.markModified(\"shellCommandPrefix\");\n\t\tthis.save();\n\t}\n\n\tgetNpmCommand(): string[] | undefined {\n\t\treturn this.settings.npmCommand ? [...this.settings.npmCommand] : undefined;\n\t}\n\n\tsetNpmCommand(command: string[] | undefined): void {\n\t\tthis.globalSettings.npmCommand = command ? [...command] : undefined;\n\t\tthis.markModified(\"npmCommand\");\n\t\tthis.save();\n\t}\n\n\tgetCollapseChangelog(): boolean {\n\t\treturn this.settings.collapseChangelog ?? false;\n\t}\n\n\tsetCollapseChangelog(collapse: boolean): void {\n\t\tthis.globalSettings.collapseChangelog = collapse;\n\t\tthis.markModified(\"collapseChangelog\");\n\t\tthis.save();\n\t}\n\n\tgetEnableInstallTelemetry(): boolean {\n\t\treturn this.settings.enableInstallTelemetry ?? true;\n\t}\n\n\tsetEnableInstallTelemetry(enabled: boolean): void {\n\t\tthis.globalSettings.enableInstallTelemetry = enabled;\n\t\tthis.markModified(\"enableInstallTelemetry\");\n\t\tthis.save();\n\t}\n\n\tgetEnableAnalytics(): boolean {\n\t\treturn this.settings.enableAnalytics ?? false;\n\t}\n\n\tgetTrackingId(): string | undefined {\n\t\treturn this.settings.trackingId;\n\t}\n\n\t/** Set the analytics opt-in preference; generates a tracking identifier on first opt-in */\n\tsetEnableAnalytics(enabled: boolean): void {\n\t\tthis.globalSettings.enableAnalytics = enabled;\n\t\tthis.markModified(\"enableAnalytics\");\n\t\tif (enabled && !this.globalSettings.trackingId) {\n\t\t\tthis.globalSettings.trackingId = randomUUID();\n\t\t\tthis.markModified(\"trackingId\");\n\t\t}\n\t\tthis.save();\n\t}\n\n\tgetPackages(): PackageSource[] {\n\t\treturn [...(this.settings.packages ?? [])];\n\t}\n\n\tsetPackages(packages: PackageSource[]): void {\n\t\tthis.globalSettings.packages = packages;\n\t\tthis.markModified(\"packages\");\n\t\tthis.save();\n\t}\n\n\tsetProjectPackages(packages: PackageSource[]): void {\n\t\tthis.updateProjectSettings(\"packages\", (settings) => {\n\t\t\tsettings.packages = packages;\n\t\t});\n\t}\n\n\tgetExtensionPaths(): string[] {\n\t\treturn [...(this.settings.extensions ?? [])];\n\t}\n\n\tsetExtensionPaths(paths: string[]): void {\n\t\tthis.globalSettings.extensions = paths;\n\t\tthis.markModified(\"extensions\");\n\t\tthis.save();\n\t}\n\n\tsetProjectExtensionPaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"extensions\", (settings) => {\n\t\t\tsettings.extensions = paths;\n\t\t});\n\t}\n\n\tgetSkillPaths(): string[] {\n\t\treturn [...(this.settings.skills ?? [])];\n\t}\n\n\tsetSkillPaths(paths: string[]): void {\n\t\tthis.globalSettings.skills = paths;\n\t\tthis.markModified(\"skills\");\n\t\tthis.save();\n\t}\n\n\tsetProjectSkillPaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"skills\", (settings) => {\n\t\t\tsettings.skills = paths;\n\t\t});\n\t}\n\n\tgetPromptTemplatePaths(): string[] {\n\t\treturn [...(this.settings.prompts ?? [])];\n\t}\n\n\tsetPromptTemplatePaths(paths: string[]): void {\n\t\tthis.globalSettings.prompts = paths;\n\t\tthis.markModified(\"prompts\");\n\t\tthis.save();\n\t}\n\n\tsetProjectPromptTemplatePaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"prompts\", (settings) => {\n\t\t\tsettings.prompts = paths;\n\t\t});\n\t}\n\n\tgetThemePaths(): string[] {\n\t\treturn [...(this.settings.themes ?? [])];\n\t}\n\n\tsetThemePaths(paths: string[]): void {\n\t\tthis.globalSettings.themes = paths;\n\t\tthis.markModified(\"themes\");\n\t\tthis.save();\n\t}\n\n\tsetProjectThemePaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"themes\", (settings) => {\n\t\t\tsettings.themes = paths;\n\t\t});\n\t}\n\n\tgetEnableSkillCommands(): boolean {\n\t\treturn this.settings.enableSkillCommands ?? true;\n\t}\n\n\tsetEnableSkillCommands(enabled: boolean): void {\n\t\tthis.globalSettings.enableSkillCommands = enabled;\n\t\tthis.markModified(\"enableSkillCommands\");\n\t\tthis.save();\n\t}\n\n\tgetThinkingBudgets(): ThinkingBudgetsSettings | undefined {\n\t\treturn this.settings.thinkingBudgets;\n\t}\n\n\tgetShowImages(): boolean {\n\t\treturn this.settings.terminal?.showImages ?? true;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showImages = show;\n\t\tthis.markModified(\"terminal\", \"showImages\");\n\t\tthis.save();\n\t}\n\n\tgetImageWidthCells(): number {\n\t\tconst width = this.settings.terminal?.imageWidthCells;\n\t\tif (typeof width !== \"number\" || !Number.isFinite(width)) {\n\t\t\treturn 60;\n\t\t}\n\t\treturn Math.max(1, Math.floor(width));\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.markModified(\"terminal\", \"imageWidthCells\");\n\t\tthis.save();\n\t}\n\n\tgetClearOnShrink(): boolean {\n\t\t// Settings takes precedence, then env var, then default false\n\t\tif (this.settings.terminal?.clearOnShrink !== undefined) {\n\t\t\treturn this.settings.terminal.clearOnShrink;\n\t\t}\n\t\treturn process.env.PI_CLEAR_ON_SHRINK === \"1\";\n\t}\n\n\tsetClearOnShrink(enabled: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.clearOnShrink = enabled;\n\t\tthis.markModified(\"terminal\", \"clearOnShrink\");\n\t\tthis.save();\n\t}\n\n\tgetShowTerminalProgress(): boolean {\n\t\treturn this.settings.terminal?.showTerminalProgress ?? false;\n\t}\n\n\tsetShowTerminalProgress(enabled: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showTerminalProgress = enabled;\n\t\tthis.markModified(\"terminal\", \"showTerminalProgress\");\n\t\tthis.save();\n\t}\n\n\tgetTuiMode(): TuiMode {\n\t\treturn this.settings.tuiMode === \"fullscreen\" ? \"fullscreen\" : \"regular\";\n\t}\n\n\tsetTuiMode(mode: TuiMode): void {\n\t\tthis.globalSettings.tuiMode = mode;\n\t\tthis.markModified(\"tuiMode\");\n\t\tthis.save();\n\t}\n\n\tgetFullscreenScrollbar(): ScrollViewScrollbar {\n\t\tconst mode = this.settings.fullscreenScrollbar;\n\t\treturn mode === \"always\" || mode === \"hidden\" ? mode : \"auto\";\n\t}\n\n\tsetFullscreenScrollbar(mode: ScrollViewScrollbar): void {\n\t\tthis.globalSettings.fullscreenScrollbar = mode;\n\t\tthis.markModified(\"fullscreenScrollbar\");\n\t\tthis.save();\n\t}\n\n\tgetImageAutoResize(): boolean {\n\t\treturn this.settings.images?.autoResize ?? true;\n\t}\n\n\tsetImageAutoResize(enabled: boolean): void {\n\t\tif (!this.globalSettings.images) {\n\t\t\tthis.globalSettings.images = {};\n\t\t}\n\t\tthis.globalSettings.images.autoResize = enabled;\n\t\tthis.markModified(\"images\", \"autoResize\");\n\t\tthis.save();\n\t}\n\n\tgetBlockImages(): boolean {\n\t\treturn this.settings.images?.blockImages ?? false;\n\t}\n\n\tsetBlockImages(blocked: boolean): void {\n\t\tif (!this.globalSettings.images) {\n\t\t\tthis.globalSettings.images = {};\n\t\t}\n\t\tthis.globalSettings.images.blockImages = blocked;\n\t\tthis.markModified(\"images\", \"blockImages\");\n\t\tthis.save();\n\t}\n\n\tgetEnabledModels(): string[] | undefined {\n\t\treturn this.settings.enabledModels;\n\t}\n\n\tsetEnabledModels(patterns: string[] | undefined): void {\n\t\tthis.globalSettings.enabledModels = patterns;\n\t\tthis.markModified(\"enabledModels\");\n\t\tthis.save();\n\t}\n\n\tgetDoubleEscapeAction(): \"fork\" | \"tree\" | \"none\" {\n\t\treturn this.settings.doubleEscapeAction ?? \"tree\";\n\t}\n\n\tsetDoubleEscapeAction(action: \"fork\" | \"tree\" | \"none\"): void {\n\t\tthis.globalSettings.doubleEscapeAction = action;\n\t\tthis.markModified(\"doubleEscapeAction\");\n\t\tthis.save();\n\t}\n\n\tgetTreeFilterMode(): \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\" {\n\t\tconst mode = this.settings.treeFilterMode;\n\t\tconst valid = [\"default\", \"no-tools\", \"user-only\", \"labeled-only\", \"all\"];\n\t\treturn mode && valid.includes(mode) ? mode : \"default\";\n\t}\n\n\tsetTreeFilterMode(mode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"): void {\n\t\tthis.globalSettings.treeFilterMode = mode;\n\t\tthis.markModified(\"treeFilterMode\");\n\t\tthis.save();\n\t}\n\n\tgetShowHardwareCursor(): boolean {\n\t\treturn this.settings.showHardwareCursor ?? process.env.PI_HARDWARE_CURSOR === \"1\";\n\t}\n\n\tsetShowHardwareCursor(enabled: boolean): void {\n\t\tthis.globalSettings.showHardwareCursor = enabled;\n\t\tthis.markModified(\"showHardwareCursor\");\n\t\tthis.save();\n\t}\n\n\tgetEditorPaddingX(): number {\n\t\treturn this.settings.editorPaddingX ?? 0;\n\t}\n\n\tsetEditorPaddingX(padding: number): void {\n\t\tthis.globalSettings.editorPaddingX = Math.max(0, Math.min(3, Math.floor(padding)));\n\t\tthis.markModified(\"editorPaddingX\");\n\t\tthis.save();\n\t}\n\n\tgetOutputPad(): 0 | 1 {\n\t\treturn this.settings.outputPad === 0 ? 0 : 1;\n\t}\n\n\tsetOutputPad(padding: 0 | 1): void {\n\t\tthis.globalSettings.outputPad = padding;\n\t\tthis.markModified(\"outputPad\");\n\t\tthis.save();\n\t}\n\n\tgetAutocompleteMaxVisible(): number {\n\t\treturn this.settings.autocompleteMaxVisible ?? 5;\n\t}\n\n\tsetAutocompleteMaxVisible(maxVisible: number): void {\n\t\tthis.globalSettings.autocompleteMaxVisible = Math.max(3, Math.min(20, Math.floor(maxVisible)));\n\t\tthis.markModified(\"autocompleteMaxVisible\");\n\t\tthis.save();\n\t}\n\n\tgetCodeBlockIndent(): string {\n\t\treturn this.settings.markdown?.codeBlockIndent ?? \" \";\n\t}\n\n\tgetMermaidRenderingMode(): MermaidRenderingMode {\n\t\tconst mode = this.settings.markdown?.mermaid;\n\t\treturn mode === \"off\" || mode === \"final\" ? mode : \"streaming\";\n\t}\n\n\tsetMermaidRenderingMode(mode: MermaidRenderingMode): void {\n\t\tthis.globalSettings.markdown ??= {};\n\t\tthis.globalSettings.markdown.mermaid = mode;\n\t\tthis.markModified(\"markdown\", \"mermaid\");\n\t\tthis.save();\n\t}\n\n\tgetWarnings(): WarningSettings {\n\t\treturn { ...(this.settings.warnings ?? {}) };\n\t}\n\n\tsetWarnings(warnings: WarningSettings): void {\n\t\tthis.globalSettings.warnings = { ...warnings };\n\t\tthis.markModified(\"warnings\");\n\t\tthis.save();\n\t}\n}\n"]}
1
+ {"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport type { Transport } from \"@earendil-works/pi-ai\";\nimport type { TuiMode as RendererTuiMode, ScrollViewScrollbar } from \"@earendil-works/pi-tui\";\nimport type { ThinkingLevel } from \"apex-code-agent-core\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { normalizePath, resolvePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\nimport type { CheckpointSettings } from \"./checkpoints/git-checkpoints.ts\";\nimport { getApexEnvironment } from \"./environment.ts\";\nimport { DEFAULT_HTTP_IDLE_TIMEOUT_MS, parseHttpIdleTimeoutMs } from \"./http-dispatcher.ts\";\nimport type { LspSettings } from \"./lsp/registry.ts\";\n\n/**\n * `proper-lockfile` is required lazily, not imported: the supervisor loads this module\n * on every launch just to read settings, and a static import puts the lock library\n * (measured: the single largest share of the settings-manager import cost) on the\n * pre-child critical path where it is never used -- the supervisor only reads. The\n * sync `require` keeps `withLock`'s synchronous interface; the write path pays the\n * load once, on first write.\n */\nconst requireFromHere = createRequire(import.meta.url);\ntype ProperLockfile = typeof import(\"proper-lockfile\");\nlet lockfileModule: ProperLockfile | undefined;\nfunction lockfile(): ProperLockfile {\n\tif (!lockfileModule) {\n\t\tlockfileModule = requireFromHere(\"proper-lockfile\") as ProperLockfile;\n\t}\n\treturn lockfileModule;\n}\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tkeepRecentTokens?: number; // default: 20000\n}\n\nexport interface BranchSummarySettings {\n\treserveTokens?: number; // default: 16384 (tokens reserved for prompt + LLM response)\n\tskipPrompt?: boolean; // default: false - when true, skips \"Summarize branch?\" prompt and defaults to no summary\n}\n\nexport interface ProviderRetrySettings {\n\ttimeoutMs?: number; // SDK/provider request timeout in milliseconds\n\tmaxRetries?: number; // SDK/provider retry attempts\n\tmaxRetryDelayMs?: number; // default: 60000 (max server-requested delay before failing)\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n\tprovider?: ProviderRetrySettings;\n}\n\nexport type TuiMode = RendererTuiMode;\nexport type FullscreenExitOutput = \"transcript\" | \"resume-hint\";\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n\timageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)\n\tclearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)\n\tshowTerminalProgress?: boolean; // default: false (OSC 9;4 terminal progress indicators)\n\tsymbolPreset?: \"unicode\" | \"ascii\"; // default: \"unicode\" (roadmap Phase 8: footer glyph fallback)\n\tcolorBlindMode?: boolean; // default: false (roadmap Phase 8: adjusts footer palette; the underlying signal is never color-only regardless of this setting)\n\ttokenUsageDisplay?: \"off\" | \"compact\" | \"full\"; // default: \"compact\" (roadmap Phase 8: footer token/cost stats verbosity)\n}\n\nexport interface ImageSettings {\n\tautoResize?: boolean; // default: true (resize images to 2000x2000 max for better model compatibility)\n\tblockImages?: boolean; // default: false - when true, prevents all images from being sent to LLM providers\n}\n\nexport interface ThinkingBudgetsSettings {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\nexport type MermaidRenderingMode = \"off\" | \"final\" | \"streaming\";\n\nexport interface MarkdownSettings {\n\tcodeBlockIndent?: string; // default: \" \"\n\tmermaid?: MermaidRenderingMode; // default: \"streaming\"\n}\n\nexport interface WarningSettings {\n\tanthropicExtraUsage?: boolean; // default: true\n}\n\nexport type DefaultProjectTrust = \"ask\" | \"always\" | \"never\";\n\nexport type TransportSetting = Transport;\n\n/**\n * Package source for npm/git packages.\n * - String form: load all resources from the package\n * - Object form: filter which resources to load\n * - autoload=false: start empty and only apply explicit resource patterns\n */\nexport type PackageSource =\n\t| string\n\t| {\n\t\t\tsource: string;\n\t\t\tautoload?: boolean;\n\t\t\textensions?: string[];\n\t\t\tskills?: string[];\n\t\t\tprompts?: string[];\n\t\t\tthemes?: string[];\n\t };\n\nexport interface NetworkSettings {\n\tallowedHosts?: string[];\n\t/**\n\t * Permit the built-in model-provider hosts and the update check inside the sandbox.\n\t * Defaults to true; set false to return to denying everything `allowedHosts` omits.\n\t */\n\tallowDefaultHosts?: boolean;\n}\n\n/**\n * Backend for the `web_search` tool. Unset leaves the tool registered but\n * unconfigured, which is what it has been since Phase 4 shipped it.\n *\n * `apiKey` is a config-value reference (`\"$EXA_API_KEY\"`, or `\"!op read ...\"`),\n * resolved by `resolveConfigValue` exactly like a model provider's key. A literal\n * key must never be written here: settings are a file this loader writes back.\n */\nexport interface WebSearchSettings {\n\tprovider?: \"exa\";\n\tapiKey?: string; // default: the provider's own env var, e.g. \"$EXA_API_KEY\"\n\tnumResults?: number;\n\tsnippetMaxCharacters?: number;\n\tendpoint?: string; // override for an API-compatible endpoint\n}\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tfirstUseHints?: string[];\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\tdefaultThinkingLevel?: ThinkingLevel;\n\tmodelThinkingLevels?: Record<string, ThinkingLevel>; // per-model default thinking level overrides keyed by \"provider/modelId\"\n\ttransport?: TransportSetting; // default: \"auto\"\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tcompaction?: CompactionSettings;\n\tbranchSummary?: BranchSummarySettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\tshowCacheMissNotices?: boolean; // default: false - show prompt-cache miss and compaction cost notices\n\texternalEditor?: string; // Command for Ctrl+G external editor; takes precedence over VISUAL/EDITOR\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows); supports leading ~ expansion\n\tquietStartup?: boolean;\n\tdefaultProjectTrust?: DefaultProjectTrust; // default: \"ask\"; global setting only\n\tshellCommandPrefix?: string; // Prefix prepended to every bash command (e.g., \"shopt -s expand_aliases\" for alias support)\n\tnpmCommand?: string[]; // Command used for npm package lookup/install operations, argv-style (e.g., [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"])\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\t// default: true - HTTP attribution headers (e.g. OpenRouter/NVIDIA billing-origin\n\t// tags) sent to the LLM provider you configured, for that provider's own\n\t// attribution purposes. Never sent to a third party (roadmap Phase 9).\n\tsendProviderAttribution?: boolean;\n\tpackages?: PackageSource[]; // Array of npm/git package sources (string or object with filtering)\n\textensions?: string[]; // Array of local extension file paths or directories\n\tskills?: string[]; // Array of local skill file paths or directories\n\tprompts?: string[]; // Array of local prompt template paths or directories\n\tthemes?: string[]; // Array of local theme file paths or directories\n\tenableSkillCommands?: boolean; // default: true - register skills as /skill:name commands\n\tterminal?: TerminalSettings;\n\timages?: ImageSettings;\n\tenabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)\n\tdefaultTools?: string[]; // Initial built-in tool selection\n\tdoubleEscapeAction?: \"fork\" | \"tree\" | \"none\"; // Action for double-escape with empty editor (default: \"tree\")\n\ttreeFilterMode?: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"; // Default filter when opening /tree\n\tthinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels\n\teditorPaddingX?: number; // Horizontal padding for input editor (default: 0)\n\toutputPad?: 0 | 1; // Horizontal padding for chat message output (default: 1)\n\tautocompleteMaxVisible?: number; // Max visible items in autocomplete dropdown (default: 5)\n\tshowHardwareCursor?: boolean; // Show terminal cursor while still positioning it for IME\n\tmarkdown?: MarkdownSettings;\n\twarnings?: WarningSettings;\n\tsessionDir?: string; // Custom session storage directory (same format as --session-dir CLI flag)\n\thttpProxy?: string; // Proxy URL applied as HTTP_PROXY and HTTPS_PROXY for Pi-managed HTTP clients\n\thttpIdleTimeoutMs?: number; // HTTP header/body idle timeout in milliseconds; 0 disables it\n\twebsocketConnectTimeoutMs?: number; // WebSocket connect/open handshake timeout in milliseconds; 0 disables it\n\ttuiMode?: TuiMode; // default: \"regular\"\n\tfullscreenExitOutput?: FullscreenExitOutput; // default: \"transcript\"; no effect in regular TUI mode\n\tfullscreenScrollbar?: ScrollViewScrollbar; // default: \"auto\"; no effect in regular TUI mode\n\tnetwork?: NetworkSettings;\n\t/**\n\t * Named OS-boundary profiles, keyed by the name `--permission-profile` selects.\n\t *\n\t * Read only from global scope by `core/sandbox/profiles.ts`; a project-scope copy is\n\t * ignored, per ADR 0016.\n\t */\n\tsandboxProfiles?: Record<string, { allowedHosts?: string[]; additionalWritableRoots?: string[] }>;\n\tdelegationMaxDepth?: number; // Max delegation recursion depth (roadmap Phase 5, task 5.3). default: 2, hard-capped at DELEGATION_MAX_DEPTH_HARD_CAP\n\tobservability?: ObservabilitySettings;\n\tlsp?: LspSettings;\n\twebSearch?: WebSearchSettings;\n\t/**\n\t * Git-backed worktree checkpoints. Absent by default; an absent key constructs no\n\t * engine, so an unconfigured session runs no `git` subprocess and writes no ref.\n\t */\n\tcheckpoints?: CheckpointSettings;\n}\n\n/**\n * User-directed OTLP trace export (roadmap Phase 8, ADR 0012) -- data goes to the\n * user's own collector, never to this project. Unset `otlpEndpoint` means export\n * never activates; there is no separate on/off switch to forget to flip.\n */\nexport interface ObservabilitySettings {\n\totlpEndpoint?: string; // e.g. \"http://localhost:4318\"; POSTed to as \"<endpoint>/v1/traces\"\n\totlpHeaders?: Record<string, string>; // extra headers for the OTLP export request, e.g. collector auth\n\tretentionDays?: number; // default: 90; usage-performance ledger rows older than this are pruned on store open\n}\n\n/**\n * Hard ceiling on `delegationMaxDepth`, independent of what a user configures. A\n * placeholder pending real measurement (the open question `docs/plans/2026-08-14-\n * delegation-and-multi-agent.md` carries into this task): each level multiplies\n * both token cost and the distance between the human and the work, and this\n * repository has not yet measured that cost per level. 5 is conservative headroom\n * above the default of 2, not a derived number.\n */\nexport const DELEGATION_MAX_DEPTH_HARD_CAP = 5;\n\nfunction isMergeableObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction deepMergeObjects(base: Record<string, unknown>, overrides: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...base };\n\n\tfor (const key of Object.keys(overrides)) {\n\t\tconst overrideValue = overrides[key];\n\t\tif (overrideValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst baseValue = base[key];\n\t\tresult[key] =\n\t\t\tisMergeableObject(baseValue) && isMergeableObject(overrideValue)\n\t\t\t\t? deepMergeObjects(baseValue, overrideValue)\n\t\t\t\t: overrideValue;\n\t}\n\n\treturn result;\n}\n\n/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */\nfunction deepMergeSettings(base: Settings, overrides: Settings): Settings {\n\treturn deepMergeObjects(base as Record<string, unknown>, overrides as Record<string, unknown>) as Settings;\n}\n\nfunction parseTimeoutSetting(value: unknown, settingName: string): number | undefined {\n\tconst timeoutMs = parseHttpIdleTimeoutMs(value);\n\tif (timeoutMs !== undefined) {\n\t\treturn timeoutMs;\n\t}\n\tif (value !== undefined) {\n\t\tthrow new Error(`Invalid ${settingName} setting: ${String(value)}`);\n\t}\n\treturn undefined;\n}\n\nexport type SettingsScope = \"global\" | \"project\";\n\nexport interface SettingsManagerCreateOptions {\n\tprojectTrusted?: boolean;\n}\n\nexport interface SettingsStorage {\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void;\n}\n\nexport interface SettingsError {\n\tscope: SettingsScope;\n\tpath?: string;\n\terror: Error;\n}\n\ntype SettingsPaths = Partial<Record<SettingsScope, string>>;\n\nfunction toSettingsError(scope: SettingsScope, error: unknown, path?: string): SettingsError {\n\treturn {\n\t\tscope,\n\t\t...(path ? { path } : {}),\n\t\terror: error instanceof Error ? error : new Error(String(error)),\n\t};\n}\n\nexport class FileSettingsStorage implements SettingsStorage {\n\tprivate globalSettingsPath: string;\n\tprivate projectSettingsPath: string;\n\n\tconstructor(cwd: string, agentDir: string) {\n\t\tconst resolvedCwd = resolvePath(cwd);\n\t\tconst resolvedAgentDir = resolvePath(agentDir);\n\t\tthis.globalSettingsPath = join(resolvedAgentDir, \"settings.json\");\n\t\tthis.projectSettingsPath = join(resolvedCwd, CONFIG_DIR_NAME, \"settings.json\");\n\t}\n\n\tprivate acquireLockSyncWithRetry(path: string): () => void {\n\t\tconst maxAttempts = 10;\n\t\tconst delayMs = 20;\n\t\tlet lastError: unknown;\n\n\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn lockfile().lockSync(path, { realpath: false });\n\t\t\t} catch (error) {\n\t\t\t\tconst code =\n\t\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t\t: undefined;\n\t\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tlastError = error;\n\t\t\t\tconst start = Date.now();\n\t\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t\t// Sleep synchronously to avoid changing callers to async.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow (lastError as Error) ?? new Error(\"Failed to acquire settings lock\");\n\t}\n\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void {\n\t\tconst path = scope === \"global\" ? this.globalSettingsPath : this.projectSettingsPath;\n\t\tconst dir = dirname(path);\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\t// Only create directory and lock if file exists or we need to write\n\t\t\tconst fileExists = existsSync(path);\n\t\t\tif (fileExists) {\n\t\t\t\trelease = this.acquireLockSyncWithRetry(path);\n\t\t\t}\n\t\t\tconst current = fileExists ? readFileSync(path, \"utf-8\") : undefined;\n\t\t\tconst next = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\t// Only create directory when we actually need to write\n\t\t\t\tif (!existsSync(dir)) {\n\t\t\t\t\tmkdirSync(dir, { recursive: true });\n\t\t\t\t}\n\t\t\t\tif (!release) {\n\t\t\t\t\trelease = this.acquireLockSyncWithRetry(path);\n\t\t\t\t}\n\t\t\t\twriteFileSync(path, next, \"utf-8\");\n\t\t\t}\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemorySettingsStorage implements SettingsStorage {\n\tprivate global: string | undefined;\n\tprivate project: string | undefined;\n\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void {\n\t\tconst current = scope === \"global\" ? this.global : this.project;\n\t\tconst next = fn(current);\n\t\tif (next !== undefined) {\n\t\t\tif (scope === \"global\") {\n\t\t\t\tthis.global = next;\n\t\t\t} else {\n\t\t\t\tthis.project = next;\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class SettingsManager {\n\tprivate storage: SettingsStorage;\n\tprivate globalSettings: Settings;\n\tprivate projectSettings: Settings;\n\tprivate settings: Settings;\n\tprivate projectTrusted: boolean;\n\tprivate modifiedFields = new Set<keyof Settings>(); // Track global fields modified during session\n\tprivate modifiedNestedFields = new Map<keyof Settings, Set<string>>(); // Track global nested field modifications\n\tprivate modifiedProjectFields = new Set<keyof Settings>(); // Track project fields modified during session\n\tprivate modifiedProjectNestedFields = new Map<keyof Settings, Set<string>>(); // Track project nested field modifications\n\tprivate globalSettingsLoadError: Error | null = null; // Track if global settings file had parse errors\n\tprivate projectSettingsLoadError: Error | null = null; // Track if project settings file had parse errors\n\tprivate writeQueue: Promise<void> = Promise.resolve();\n\tprivate errors: SettingsError[];\n\tprivate settingsPaths: SettingsPaths;\n\n\tprivate constructor(\n\t\tstorage: SettingsStorage,\n\t\tinitialGlobal: Settings,\n\t\tinitialProject: Settings,\n\t\tglobalLoadError: Error | null = null,\n\t\tprojectLoadError: Error | null = null,\n\t\tinitialErrors: SettingsError[] = [],\n\t\tprojectTrusted = true,\n\t\tsettingsPaths: SettingsPaths = {},\n\t) {\n\t\tthis.storage = storage;\n\t\tthis.globalSettings = initialGlobal;\n\t\tthis.projectSettings = initialProject;\n\t\tthis.projectTrusted = projectTrusted;\n\t\tthis.globalSettingsLoadError = globalLoadError;\n\t\tthis.projectSettingsLoadError = projectLoadError;\n\t\tthis.errors = [...initialErrors];\n\t\tthis.settingsPaths = settingsPaths;\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\t/** Create a SettingsManager that loads from files */\n\tstatic create(\n\t\tcwd: string,\n\t\tagentDir: string = getAgentDir(),\n\t\toptions: SettingsManagerCreateOptions = {},\n\t): SettingsManager {\n\t\tconst resolvedCwd = resolvePath(cwd);\n\t\tconst resolvedAgentDir = resolvePath(agentDir);\n\t\tconst storage = new FileSettingsStorage(resolvedCwd, resolvedAgentDir);\n\t\treturn SettingsManager.fromStorageWithPaths(storage, options, {\n\t\t\tglobal: join(resolvedAgentDir, \"settings.json\"),\n\t\t\tproject: join(resolvedCwd, CONFIG_DIR_NAME, \"settings.json\"),\n\t\t});\n\t}\n\n\t/** Create a SettingsManager from an arbitrary storage backend */\n\tstatic fromStorage(storage: SettingsStorage, options: SettingsManagerCreateOptions = {}): SettingsManager {\n\t\treturn SettingsManager.fromStorageWithPaths(storage, options);\n\t}\n\n\t/** Create a manager while retaining optional file paths for reported storage errors. */\n\tprivate static fromStorageWithPaths(\n\t\tstorage: SettingsStorage,\n\t\toptions: SettingsManagerCreateOptions,\n\t\tsettingsPaths: SettingsPaths = {},\n\t): SettingsManager {\n\t\tconst projectTrusted = options.projectTrusted ?? true;\n\t\tconst globalLoad = SettingsManager.tryLoadFromStorage(storage, \"global\");\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(storage, \"project\", projectTrusted);\n\t\tconst initialErrors: SettingsError[] = [];\n\t\tif (globalLoad.error) {\n\t\t\tinitialErrors.push(toSettingsError(\"global\", globalLoad.error, settingsPaths.global));\n\t\t}\n\t\tif (projectLoad.error) {\n\t\t\tinitialErrors.push(toSettingsError(\"project\", projectLoad.error, settingsPaths.project));\n\t\t}\n\n\t\treturn new SettingsManager(\n\t\t\tstorage,\n\t\t\tglobalLoad.settings,\n\t\t\tprojectLoad.settings,\n\t\t\tglobalLoad.error,\n\t\t\tprojectLoad.error,\n\t\t\tinitialErrors,\n\t\t\tprojectTrusted,\n\t\t\tsettingsPaths,\n\t\t);\n\t}\n\n\t/** Create an in-memory SettingsManager (no file I/O) */\n\tstatic inMemory(settings: Partial<Settings> = {}, options: SettingsManagerCreateOptions = {}): SettingsManager {\n\t\tconst storage = new InMemorySettingsStorage();\n\t\tconst initialSettings = SettingsManager.migrateSettings(structuredClone(settings) as Record<string, unknown>);\n\t\tstorage.withLock(\"global\", () => JSON.stringify(initialSettings, null, 2));\n\t\treturn SettingsManager.fromStorage(storage, options);\n\t}\n\n\tprivate static loadFromStorage(storage: SettingsStorage, scope: SettingsScope, projectTrusted = true): Settings {\n\t\tif (scope === \"project\" && !projectTrusted) {\n\t\t\treturn {};\n\t\t}\n\n\t\tlet content: string | undefined;\n\t\tstorage.withLock(scope, (current) => {\n\t\t\tcontent = current;\n\t\t\treturn undefined;\n\t\t});\n\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\tconst settings = JSON.parse(stripBom(content));\n\t\treturn SettingsManager.migrateSettings(settings);\n\t}\n\n\tprivate static tryLoadFromStorage(\n\t\tstorage: SettingsStorage,\n\t\tscope: SettingsScope,\n\t\tprojectTrusted = true,\n\t): { settings: Settings; error: Error | null } {\n\t\ttry {\n\t\t\treturn { settings: SettingsManager.loadFromStorage(storage, scope, projectTrusted), error: null };\n\t\t} catch (error) {\n\t\t\treturn { settings: {}, error: error as Error };\n\t\t}\n\t}\n\n\t/** Migrate old settings format to new format */\n\tprivate static migrateSettings(settings: Record<string, unknown>): Settings {\n\t\t// Migrate queueMode -> steeringMode\n\t\tif (\"queueMode\" in settings && !(\"steeringMode\" in settings)) {\n\t\t\tsettings.steeringMode = settings.queueMode;\n\t\t\tdelete settings.queueMode;\n\t\t}\n\n\t\t// Migrate legacy websockets boolean -> transport enum\n\t\tif (!(\"transport\" in settings) && typeof settings.websockets === \"boolean\") {\n\t\t\tsettings.transport = settings.websockets ? \"websocket\" : \"sse\";\n\t\t\tdelete settings.websockets;\n\t\t}\n\n\t\t// Migrate old skills object format to new array format\n\t\tif (\n\t\t\t\"skills\" in settings &&\n\t\t\ttypeof settings.skills === \"object\" &&\n\t\t\tsettings.skills !== null &&\n\t\t\t!Array.isArray(settings.skills)\n\t\t) {\n\t\t\tconst skillsSettings = settings.skills as {\n\t\t\t\tenableSkillCommands?: boolean;\n\t\t\t\tcustomDirectories?: unknown;\n\t\t\t};\n\t\t\tif (skillsSettings.enableSkillCommands !== undefined && settings.enableSkillCommands === undefined) {\n\t\t\t\tsettings.enableSkillCommands = skillsSettings.enableSkillCommands;\n\t\t\t}\n\t\t\tif (Array.isArray(skillsSettings.customDirectories) && skillsSettings.customDirectories.length > 0) {\n\t\t\t\tsettings.skills = skillsSettings.customDirectories;\n\t\t\t} else {\n\t\t\t\tdelete settings.skills;\n\t\t\t}\n\t\t}\n\n\t\t// Migrate retry.maxDelayMs -> retry.provider.maxRetryDelayMs\n\t\tif (\n\t\t\t\"retry\" in settings &&\n\t\t\ttypeof settings.retry === \"object\" &&\n\t\t\tsettings.retry !== null &&\n\t\t\t!Array.isArray(settings.retry)\n\t\t) {\n\t\t\tconst retrySettings = settings.retry as Record<string, unknown>;\n\t\t\tconst providerSettings =\n\t\t\t\ttypeof retrySettings.provider === \"object\" && retrySettings.provider !== null\n\t\t\t\t\t? (retrySettings.provider as Record<string, unknown>)\n\t\t\t\t\t: undefined;\n\t\t\tif (\n\t\t\t\ttypeof retrySettings.maxDelayMs === \"number\" &&\n\t\t\t\t(providerSettings?.maxRetryDelayMs === undefined || providerSettings?.maxRetryDelayMs === null)\n\t\t\t) {\n\t\t\t\tretrySettings.provider = {\n\t\t\t\t\t...(providerSettings ?? {}),\n\t\t\t\t\tmaxRetryDelayMs: retrySettings.maxDelayMs,\n\t\t\t\t};\n\t\t\t}\n\t\t\tdelete retrySettings.maxDelayMs;\n\t\t}\n\n\t\treturn settings as Settings;\n\t}\n\n\tgetGlobalSettings(): Settings {\n\t\treturn structuredClone(this.globalSettings);\n\t}\n\n\tgetProjectSettings(): Settings {\n\t\treturn structuredClone(this.projectSettings);\n\t}\n\n\tisProjectTrusted(): boolean {\n\t\treturn this.projectTrusted;\n\t}\n\n\tsetProjectTrusted(trusted: boolean): void {\n\t\tif (this.projectTrusted === trusted) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.projectTrusted = trusted;\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\n\t\tif (!trusted) {\n\t\t\tthis.projectSettings = {};\n\t\t\tthis.projectSettingsLoadError = null;\n\t\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t\t\treturn;\n\t\t}\n\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(this.storage, \"project\", trusted);\n\t\tthis.projectSettings = projectLoad.settings;\n\t\tthis.projectSettingsLoadError = projectLoad.error;\n\t\tif (projectLoad.error) {\n\t\t\tthis.recordError(\"project\", projectLoad.error);\n\t\t}\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tawait this.writeQueue;\n\t\tconst globalLoad = SettingsManager.tryLoadFromStorage(this.storage, \"global\");\n\t\tif (!globalLoad.error) {\n\t\t\tthis.globalSettings = globalLoad.settings;\n\t\t\tthis.globalSettingsLoadError = null;\n\t\t} else {\n\t\t\tthis.globalSettingsLoadError = globalLoad.error;\n\t\t\tthis.recordError(\"global\", globalLoad.error);\n\t\t}\n\n\t\tthis.modifiedFields.clear();\n\t\tthis.modifiedNestedFields.clear();\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\n\t\tconst projectLoad = SettingsManager.tryLoadFromStorage(this.storage, \"project\", this.projectTrusted);\n\t\tif (!projectLoad.error) {\n\t\t\tthis.projectSettings = projectLoad.settings;\n\t\t\tthis.projectSettingsLoadError = null;\n\t\t} else {\n\t\t\tthis.projectSettingsLoadError = projectLoad.error;\n\t\t\tthis.recordError(\"project\", projectLoad.error);\n\t\t}\n\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\t}\n\n\t/** Apply additional overrides on top of current settings */\n\tapplyOverrides(overrides: Partial<Settings>): void {\n\t\tthis.settings = deepMergeSettings(this.settings, overrides);\n\t}\n\n\t/** Mark a global field as modified during this session */\n\tprivate markModified(field: keyof Settings, nestedKey?: string): void {\n\t\tthis.modifiedFields.add(field);\n\t\tif (nestedKey) {\n\t\t\tif (!this.modifiedNestedFields.has(field)) {\n\t\t\t\tthis.modifiedNestedFields.set(field, new Set());\n\t\t\t}\n\t\t\tthis.modifiedNestedFields.get(field)!.add(nestedKey);\n\t\t}\n\t}\n\n\t/** Mark a project field as modified during this session */\n\tprivate markProjectModified(field: keyof Settings, nestedKey?: string): void {\n\t\tthis.modifiedProjectFields.add(field);\n\t\tif (nestedKey) {\n\t\t\tif (!this.modifiedProjectNestedFields.has(field)) {\n\t\t\t\tthis.modifiedProjectNestedFields.set(field, new Set());\n\t\t\t}\n\t\t\tthis.modifiedProjectNestedFields.get(field)!.add(nestedKey);\n\t\t}\n\t}\n\n\tprivate assertProjectTrustedForWrite(): void {\n\t\tif (!this.projectTrusted) {\n\t\t\tthrow new Error(\"Project is not trusted; refusing to write project settings\");\n\t\t}\n\t}\n\n\tprivate recordError(scope: SettingsScope, error: unknown): void {\n\t\tthis.errors.push(toSettingsError(scope, error, this.settingsPaths[scope]));\n\t}\n\n\tprivate clearModifiedScope(scope: SettingsScope): void {\n\t\tif (scope === \"global\") {\n\t\t\tthis.modifiedFields.clear();\n\t\t\tthis.modifiedNestedFields.clear();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.modifiedProjectFields.clear();\n\t\tthis.modifiedProjectNestedFields.clear();\n\t}\n\n\tprivate enqueueWrite(scope: SettingsScope, task: () => void): void {\n\t\tthis.writeQueue = this.writeQueue\n\t\t\t.then(() => {\n\t\t\t\tif (scope === \"project\") {\n\t\t\t\t\tthis.assertProjectTrustedForWrite();\n\t\t\t\t}\n\t\t\t\ttask();\n\t\t\t\tthis.clearModifiedScope(scope);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.recordError(scope, error);\n\t\t\t});\n\t}\n\n\tprivate cloneModifiedNestedFields(source: Map<keyof Settings, Set<string>>): Map<keyof Settings, Set<string>> {\n\t\tconst snapshot = new Map<keyof Settings, Set<string>>();\n\t\tfor (const [key, value] of source.entries()) {\n\t\t\tsnapshot.set(key, new Set(value));\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\tprivate persistScopedSettings(\n\t\tscope: SettingsScope,\n\t\tsnapshotSettings: Settings,\n\t\tmodifiedFields: Set<keyof Settings>,\n\t\tmodifiedNestedFields: Map<keyof Settings, Set<string>>,\n\t): void {\n\t\tthis.storage.withLock(scope, (current) => {\n\t\t\tconst currentFileSettings = current\n\t\t\t\t? SettingsManager.migrateSettings(JSON.parse(stripBom(current)) as Record<string, unknown>)\n\t\t\t\t: {};\n\t\t\tconst mergedSettings: Settings = { ...currentFileSettings };\n\t\t\tfor (const field of modifiedFields) {\n\t\t\t\tconst value = snapshotSettings[field];\n\t\t\t\tif (modifiedNestedFields.has(field) && typeof value === \"object\" && value !== null) {\n\t\t\t\t\tconst nestedModified = modifiedNestedFields.get(field)!;\n\t\t\t\t\tconst baseNested = (currentFileSettings[field] as Record<string, unknown>) ?? {};\n\t\t\t\t\tconst inMemoryNested = value as Record<string, unknown>;\n\t\t\t\t\tconst mergedNested = { ...baseNested };\n\t\t\t\t\tfor (const nestedKey of nestedModified) {\n\t\t\t\t\t\tmergedNested[nestedKey] = inMemoryNested[nestedKey];\n\t\t\t\t\t}\n\t\t\t\t\t(mergedSettings as Record<string, unknown>)[field] = mergedNested;\n\t\t\t\t} else {\n\t\t\t\t\t(mergedSettings as Record<string, unknown>)[field] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn JSON.stringify(mergedSettings, null, 2);\n\t\t});\n\t}\n\n\tprivate save(): void {\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\n\t\tif (this.globalSettingsLoadError) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst snapshotGlobalSettings = structuredClone(this.globalSettings);\n\t\tconst modifiedFields = new Set(this.modifiedFields);\n\t\tconst modifiedNestedFields = this.cloneModifiedNestedFields(this.modifiedNestedFields);\n\n\t\tthis.enqueueWrite(\"global\", () => {\n\t\t\tthis.persistScopedSettings(\"global\", snapshotGlobalSettings, modifiedFields, modifiedNestedFields);\n\t\t});\n\t}\n\n\tprivate saveProjectSettings(settings: Settings): void {\n\t\tthis.assertProjectTrustedForWrite();\n\t\tthis.projectSettings = structuredClone(settings);\n\t\tthis.settings = deepMergeSettings(this.globalSettings, this.projectSettings);\n\n\t\tif (this.projectSettingsLoadError) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst snapshotProjectSettings = structuredClone(this.projectSettings);\n\t\tconst modifiedFields = new Set(this.modifiedProjectFields);\n\t\tconst modifiedNestedFields = this.cloneModifiedNestedFields(this.modifiedProjectNestedFields);\n\t\tthis.enqueueWrite(\"project\", () => {\n\t\t\tthis.persistScopedSettings(\"project\", snapshotProjectSettings, modifiedFields, modifiedNestedFields);\n\t\t});\n\t}\n\n\tprivate updateProjectSettings(field: keyof Settings, update: (settings: Settings) => void): void {\n\t\tthis.assertProjectTrustedForWrite();\n\t\tconst projectSettings = structuredClone(this.projectSettings);\n\t\tupdate(projectSettings);\n\t\tthis.markProjectModified(field);\n\t\tthis.saveProjectSettings(projectSettings);\n\t}\n\n\tasync flush(): Promise<void> {\n\t\tawait this.writeQueue;\n\t}\n\n\tdrainErrors(): SettingsError[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\tgetLastChangelogVersion(): string | undefined {\n\t\treturn this.settings.lastChangelogVersion;\n\t}\n\n\tsetLastChangelogVersion(version: string): void {\n\t\tthis.globalSettings.lastChangelogVersion = version;\n\t\tthis.markModified(\"lastChangelogVersion\");\n\t\tthis.save();\n\t}\n\n\tgetFirstUseHints(): string[] {\n\t\treturn [...(this.settings.firstUseHints ?? [])];\n\t}\n\n\tsetFirstUseHints(hints: readonly string[]): void {\n\t\tthis.globalSettings.firstUseHints = [...new Set(hints)];\n\t\tthis.markModified(\"firstUseHints\");\n\t\tthis.save();\n\t}\n\n\tgetSessionDir(): string | undefined {\n\t\tconst sessionDir = this.settings.sessionDir;\n\t\treturn sessionDir ? normalizePath(sessionDir) : sessionDir;\n\t}\n\n\tgetDefaultProvider(): string | undefined {\n\t\treturn this.settings.defaultProvider;\n\t}\n\n\tgetDefaultModel(): string | undefined {\n\t\treturn this.settings.defaultModel;\n\t}\n\n\tsetDefaultProvider(provider: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.markModified(\"defaultProvider\");\n\t\tthis.save();\n\t}\n\n\tsetDefaultModel(modelId: string): void {\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.markModified(\"defaultModel\");\n\t\tthis.save();\n\t}\n\n\tsetDefaultModelAndProvider(provider: string, modelId: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.markModified(\"defaultProvider\");\n\t\tthis.markModified(\"defaultModel\");\n\t\tthis.save();\n\t}\n\n\tgetSteeringMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.steeringMode || \"one-at-a-time\";\n\t}\n\n\tsetSteeringMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.steeringMode = mode;\n\t\tthis.markModified(\"steeringMode\");\n\t\tthis.save();\n\t}\n\n\tgetFollowUpMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.followUpMode || \"one-at-a-time\";\n\t}\n\n\tsetFollowUpMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.followUpMode = mode;\n\t\tthis.markModified(\"followUpMode\");\n\t\tthis.save();\n\t}\n\n\tgetThemeSetting(): string | undefined {\n\t\tconst value = this.settings.theme;\n\t\tif (typeof value === \"string\") return value;\n\t\treturn undefined;\n\t}\n\n\tgetTheme(): string | undefined {\n\t\tconst theme = this.getThemeSetting();\n\t\treturn theme?.includes(\"/\") ? undefined : theme;\n\t}\n\n\tsetTheme(theme: string): void {\n\t\tthis.globalSettings.theme = theme;\n\t\tthis.markModified(\"theme\");\n\t\tthis.save();\n\t}\n\n\tgetDefaultThinkingLevel(): ThinkingLevel | undefined {\n\t\treturn this.settings.defaultThinkingLevel;\n\t}\n\n\tsetDefaultThinkingLevel(level: ThinkingLevel): void {\n\t\tthis.globalSettings.defaultThinkingLevel = level;\n\t\tthis.markModified(\"defaultThinkingLevel\");\n\t\tthis.save();\n\t}\n\n\tgetModelThinkingLevel(provider: string, modelId: string): ThinkingLevel | undefined {\n\t\treturn this.settings.modelThinkingLevels?.[`${provider}/${modelId}`];\n\t}\n\n\tgetAllModelThinkingLevels(): Record<string, ThinkingLevel> {\n\t\treturn { ...(this.settings.modelThinkingLevels ?? {}) };\n\t}\n\n\tsetModelThinkingLevel(provider: string, modelId: string, level: ThinkingLevel): void {\n\t\tif (!this.globalSettings.modelThinkingLevels) {\n\t\t\tthis.globalSettings.modelThinkingLevels = {};\n\t\t}\n\t\tthis.globalSettings.modelThinkingLevels[`${provider}/${modelId}`] = level;\n\t\tthis.markModified(\"modelThinkingLevels\");\n\t\tthis.save();\n\t}\n\n\tremoveModelThinkingLevel(provider: string, modelId: string): void {\n\t\tif (!this.globalSettings.modelThinkingLevels) return;\n\t\tdelete this.globalSettings.modelThinkingLevels[`${provider}/${modelId}`];\n\t\tif (Object.keys(this.globalSettings.modelThinkingLevels).length === 0) {\n\t\t\tdelete this.globalSettings.modelThinkingLevels;\n\t\t}\n\t\tthis.markModified(\"modelThinkingLevels\");\n\t\tthis.save();\n\t}\n\n\tgetTransport(): TransportSetting {\n\t\treturn this.settings.transport ?? \"auto\";\n\t}\n\n\tsetTransport(transport: TransportSetting): void {\n\t\tthis.globalSettings.transport = transport;\n\t\tthis.markModified(\"transport\");\n\t\tthis.save();\n\t}\n\n\tgetCompactionEnabled(): boolean {\n\t\treturn this.settings.compaction?.enabled ?? true;\n\t}\n\n\tsetCompactionEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.compaction) {\n\t\t\tthis.globalSettings.compaction = {};\n\t\t}\n\t\tthis.globalSettings.compaction.enabled = enabled;\n\t\tthis.markModified(\"compaction\", \"enabled\");\n\t\tthis.save();\n\t}\n\n\tgetCompactionReserveTokens(): number {\n\t\treturn this.settings.compaction?.reserveTokens ?? 16384;\n\t}\n\n\tgetCompactionKeepRecentTokens(): number {\n\t\treturn this.settings.compaction?.keepRecentTokens ?? 20000;\n\t}\n\n\tgetCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number } {\n\t\treturn {\n\t\t\tenabled: this.getCompactionEnabled(),\n\t\t\treserveTokens: this.getCompactionReserveTokens(),\n\t\t\tkeepRecentTokens: this.getCompactionKeepRecentTokens(),\n\t\t};\n\t}\n\n\tgetBranchSummarySettings(): { reserveTokens: number; skipPrompt: boolean } {\n\t\treturn {\n\t\t\treserveTokens: this.settings.branchSummary?.reserveTokens ?? 16384,\n\t\t\tskipPrompt: this.settings.branchSummary?.skipPrompt ?? false,\n\t\t};\n\t}\n\n\tgetNetworkSettings(): NetworkSettings | undefined {\n\t\treturn this.settings.network;\n\t}\n\n\tgetSandboxProfiles(): Settings[\"sandboxProfiles\"] {\n\t\treturn this.settings.sandboxProfiles === undefined ? undefined : structuredClone(this.settings.sandboxProfiles);\n\t}\n\n\tgetLspSettings(): LspSettings | undefined {\n\t\treturn this.settings.lsp === undefined ? undefined : structuredClone(this.settings.lsp);\n\t}\n\n\tgetWebSearchSettings(): WebSearchSettings | undefined {\n\t\treturn this.settings.webSearch === undefined ? undefined : structuredClone(this.settings.webSearch);\n\t}\n\n\tgetCheckpointSettings(): CheckpointSettings | undefined {\n\t\treturn this.settings.checkpoints === undefined ? undefined : structuredClone(this.settings.checkpoints);\n\t}\n\n\tgetBranchSummarySkipPrompt(): boolean {\n\t\treturn this.settings.branchSummary?.skipPrompt ?? false;\n\t}\n\n\tgetRetryEnabled(): boolean {\n\t\treturn this.settings.retry?.enabled ?? true;\n\t}\n\n\tsetRetryEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.retry) {\n\t\t\tthis.globalSettings.retry = {};\n\t\t}\n\t\tthis.globalSettings.retry.enabled = enabled;\n\t\tthis.markModified(\"retry\", \"enabled\");\n\t\tthis.save();\n\t}\n\n\tgetRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number } {\n\t\treturn {\n\t\t\tenabled: this.getRetryEnabled(),\n\t\t\tmaxRetries: this.settings.retry?.maxRetries ?? 3,\n\t\t\tbaseDelayMs: this.settings.retry?.baseDelayMs ?? 2000,\n\t\t};\n\t}\n\n\tgetObservabilitySettings(): ObservabilitySettings {\n\t\treturn this.settings.observability ?? {};\n\t}\n\n\tgetHttpIdleTimeoutMs(): number {\n\t\treturn parseTimeoutSetting(this.settings.httpIdleTimeoutMs, \"httpIdleTimeoutMs\") ?? DEFAULT_HTTP_IDLE_TIMEOUT_MS;\n\t}\n\n\tsetHttpIdleTimeoutMs(timeoutMs: number): void {\n\t\tif (!Number.isFinite(timeoutMs) || timeoutMs < 0) {\n\t\t\tthrow new Error(`Invalid httpIdleTimeoutMs setting: ${String(timeoutMs)}`);\n\t\t}\n\t\tthis.globalSettings.httpIdleTimeoutMs = Math.floor(timeoutMs);\n\t\tthis.markModified(\"httpIdleTimeoutMs\");\n\t\tthis.save();\n\t}\n\n\tgetProviderRetrySettings(): { timeoutMs?: number; maxRetries?: number; maxRetryDelayMs: number } {\n\t\treturn {\n\t\t\ttimeoutMs: this.settings.retry?.provider?.timeoutMs,\n\t\t\tmaxRetries: this.settings.retry?.provider?.maxRetries,\n\t\t\tmaxRetryDelayMs: this.settings.retry?.provider?.maxRetryDelayMs ?? 60000,\n\t\t};\n\t}\n\n\tgetWebSocketConnectTimeoutMs(): number | undefined {\n\t\treturn parseTimeoutSetting(this.settings.websocketConnectTimeoutMs, \"websocketConnectTimeoutMs\");\n\t}\n\n\t/** Max delegation recursion depth (roadmap Phase 5, task 5.3). A non-positive or missing configured value falls back to the default rather than being rejected outright -- this bound is a safety ceiling, not a value where a malformed setting should block startup. Always clamped to DELEGATION_MAX_DEPTH_HARD_CAP, regardless of configuration. */\n\tgetDelegationMaxDepth(): number {\n\t\tconst DEFAULT = 2;\n\t\tconst configured = this.settings.delegationMaxDepth;\n\t\tconst value = Number.isFinite(configured) && (configured as number) > 0 ? (configured as number) : DEFAULT;\n\t\treturn Math.min(Math.floor(value), DELEGATION_MAX_DEPTH_HARD_CAP);\n\t}\n\n\tgetHideThinkingBlock(): boolean {\n\t\treturn this.settings.hideThinkingBlock ?? false;\n\t}\n\n\tgetShowCacheMissNotices(): boolean {\n\t\treturn this.settings.showCacheMissNotices ?? false;\n\t}\n\n\tgetExternalEditorCommand(): string {\n\t\tconst configuredEditor = this.settings.externalEditor;\n\t\tif (typeof configuredEditor === \"string\" && configuredEditor.trim() !== \"\") {\n\t\t\treturn configuredEditor;\n\t\t}\n\t\tconst environmentEditor = process.env.VISUAL || process.env.EDITOR;\n\t\tif (environmentEditor) {\n\t\t\treturn environmentEditor;\n\t\t}\n\t\treturn process.platform === \"win32\" ? \"notepad\" : \"nano\";\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.globalSettings.hideThinkingBlock = hide;\n\t\tthis.markModified(\"hideThinkingBlock\");\n\t\tthis.save();\n\t}\n\n\tsetShowCacheMissNotices(show: boolean): void {\n\t\tthis.globalSettings.showCacheMissNotices = show;\n\t\tthis.markModified(\"showCacheMissNotices\");\n\t\tthis.save();\n\t}\n\n\tgetShellPath(): string | undefined {\n\t\tconst shellPath = this.settings.shellPath;\n\t\treturn shellPath ? normalizePath(shellPath) : shellPath;\n\t}\n\n\tsetShellPath(path: string | undefined): void {\n\t\tthis.globalSettings.shellPath = path;\n\t\tthis.markModified(\"shellPath\");\n\t\tthis.save();\n\t}\n\n\tgetQuietStartup(): boolean {\n\t\treturn this.settings.quietStartup ?? false;\n\t}\n\n\tsetQuietStartup(quiet: boolean): void {\n\t\tthis.globalSettings.quietStartup = quiet;\n\t\tthis.markModified(\"quietStartup\");\n\t\tthis.save();\n\t}\n\n\tgetDefaultProjectTrust(): DefaultProjectTrust {\n\t\tconst value = this.globalSettings.defaultProjectTrust;\n\t\treturn value === \"always\" || value === \"never\" ? value : \"ask\";\n\t}\n\n\tsetDefaultProjectTrust(defaultProjectTrust: DefaultProjectTrust): void {\n\t\tthis.globalSettings.defaultProjectTrust = defaultProjectTrust;\n\t\tthis.markModified(\"defaultProjectTrust\");\n\t\tthis.save();\n\t}\n\n\tgetShellCommandPrefix(): string | undefined {\n\t\treturn this.settings.shellCommandPrefix;\n\t}\n\n\tsetShellCommandPrefix(prefix: string | undefined): void {\n\t\tthis.globalSettings.shellCommandPrefix = prefix;\n\t\tthis.markModified(\"shellCommandPrefix\");\n\t\tthis.save();\n\t}\n\n\tgetNpmCommand(): string[] | undefined {\n\t\treturn this.settings.npmCommand ? [...this.settings.npmCommand] : undefined;\n\t}\n\n\tsetNpmCommand(command: string[] | undefined): void {\n\t\tthis.globalSettings.npmCommand = command ? [...command] : undefined;\n\t\tthis.markModified(\"npmCommand\");\n\t\tthis.save();\n\t}\n\n\tgetCollapseChangelog(): boolean {\n\t\treturn this.settings.collapseChangelog ?? false;\n\t}\n\n\tsetCollapseChangelog(collapse: boolean): void {\n\t\tthis.globalSettings.collapseChangelog = collapse;\n\t\tthis.markModified(\"collapseChangelog\");\n\t\tthis.save();\n\t}\n\n\tgetSendProviderAttribution(): boolean {\n\t\treturn this.settings.sendProviderAttribution ?? true;\n\t}\n\n\tsetSendProviderAttribution(enabled: boolean): void {\n\t\tthis.globalSettings.sendProviderAttribution = enabled;\n\t\tthis.markModified(\"sendProviderAttribution\");\n\t\tthis.save();\n\t}\n\n\tgetPackages(): PackageSource[] {\n\t\treturn [...(this.settings.packages ?? [])];\n\t}\n\n\tsetPackages(packages: PackageSource[]): void {\n\t\tthis.globalSettings.packages = packages;\n\t\tthis.markModified(\"packages\");\n\t\tthis.save();\n\t}\n\n\tsetProjectPackages(packages: PackageSource[]): void {\n\t\tthis.updateProjectSettings(\"packages\", (settings) => {\n\t\t\tsettings.packages = packages;\n\t\t});\n\t}\n\n\tgetExtensionPaths(): string[] {\n\t\treturn [...(this.settings.extensions ?? [])];\n\t}\n\n\tsetExtensionPaths(paths: string[]): void {\n\t\tthis.globalSettings.extensions = paths;\n\t\tthis.markModified(\"extensions\");\n\t\tthis.save();\n\t}\n\n\tsetProjectExtensionPaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"extensions\", (settings) => {\n\t\t\tsettings.extensions = paths;\n\t\t});\n\t}\n\n\tgetSkillPaths(): string[] {\n\t\treturn [...(this.settings.skills ?? [])];\n\t}\n\n\tsetSkillPaths(paths: string[]): void {\n\t\tthis.globalSettings.skills = paths;\n\t\tthis.markModified(\"skills\");\n\t\tthis.save();\n\t}\n\n\tsetProjectSkillPaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"skills\", (settings) => {\n\t\t\tsettings.skills = paths;\n\t\t});\n\t}\n\n\tgetPromptTemplatePaths(): string[] {\n\t\treturn [...(this.settings.prompts ?? [])];\n\t}\n\n\tsetPromptTemplatePaths(paths: string[]): void {\n\t\tthis.globalSettings.prompts = paths;\n\t\tthis.markModified(\"prompts\");\n\t\tthis.save();\n\t}\n\n\tsetProjectPromptTemplatePaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"prompts\", (settings) => {\n\t\t\tsettings.prompts = paths;\n\t\t});\n\t}\n\n\tgetThemePaths(): string[] {\n\t\treturn [...(this.settings.themes ?? [])];\n\t}\n\n\tsetThemePaths(paths: string[]): void {\n\t\tthis.globalSettings.themes = paths;\n\t\tthis.markModified(\"themes\");\n\t\tthis.save();\n\t}\n\n\tsetProjectThemePaths(paths: string[]): void {\n\t\tthis.updateProjectSettings(\"themes\", (settings) => {\n\t\t\tsettings.themes = paths;\n\t\t});\n\t}\n\n\tgetEnableSkillCommands(): boolean {\n\t\treturn this.settings.enableSkillCommands ?? true;\n\t}\n\n\tsetEnableSkillCommands(enabled: boolean): void {\n\t\tthis.globalSettings.enableSkillCommands = enabled;\n\t\tthis.markModified(\"enableSkillCommands\");\n\t\tthis.save();\n\t}\n\n\tgetThinkingBudgets(): ThinkingBudgetsSettings | undefined {\n\t\treturn this.settings.thinkingBudgets;\n\t}\n\n\tgetShowImages(): boolean {\n\t\treturn this.settings.terminal?.showImages ?? true;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showImages = show;\n\t\tthis.markModified(\"terminal\", \"showImages\");\n\t\tthis.save();\n\t}\n\n\tgetImageWidthCells(): number {\n\t\tconst width = this.settings.terminal?.imageWidthCells;\n\t\tif (typeof width !== \"number\" || !Number.isFinite(width)) {\n\t\t\treturn 60;\n\t\t}\n\t\treturn Math.max(1, Math.floor(width));\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.markModified(\"terminal\", \"imageWidthCells\");\n\t\tthis.save();\n\t}\n\n\tgetSymbolPreset(): \"unicode\" | \"ascii\" {\n\t\treturn this.settings.terminal?.symbolPreset ?? \"unicode\";\n\t}\n\n\tgetColorBlindMode(): boolean {\n\t\treturn this.settings.terminal?.colorBlindMode ?? false;\n\t}\n\n\tgetTokenUsageDisplay(): \"off\" | \"compact\" | \"full\" {\n\t\treturn this.settings.terminal?.tokenUsageDisplay ?? \"compact\";\n\t}\n\n\tgetClearOnShrink(): boolean {\n\t\t// Settings takes precedence, then env var, then default false\n\t\tif (this.settings.terminal?.clearOnShrink !== undefined) {\n\t\t\treturn this.settings.terminal.clearOnShrink;\n\t\t}\n\t\treturn getApexEnvironment(\"APEX_CODE_CLEAR_ON_SHRINK\") === \"1\";\n\t}\n\n\tsetClearOnShrink(enabled: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.clearOnShrink = enabled;\n\t\tthis.markModified(\"terminal\", \"clearOnShrink\");\n\t\tthis.save();\n\t}\n\n\tgetShowTerminalProgress(): boolean {\n\t\treturn this.settings.terminal?.showTerminalProgress ?? false;\n\t}\n\n\tsetShowTerminalProgress(enabled: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showTerminalProgress = enabled;\n\t\tthis.markModified(\"terminal\", \"showTerminalProgress\");\n\t\tthis.save();\n\t}\n\n\tgetTuiMode(): TuiMode {\n\t\treturn this.settings.tuiMode === \"fullscreen\" ? \"fullscreen\" : \"regular\";\n\t}\n\n\tsetTuiMode(mode: TuiMode): void {\n\t\tthis.globalSettings.tuiMode = mode;\n\t\tthis.markModified(\"tuiMode\");\n\t\tthis.save();\n\t}\n\n\tgetFullscreenExitOutput(): FullscreenExitOutput {\n\t\treturn this.settings.fullscreenExitOutput === \"resume-hint\" ? \"resume-hint\" : \"transcript\";\n\t}\n\n\tsetFullscreenExitOutput(output: FullscreenExitOutput): void {\n\t\tthis.globalSettings.fullscreenExitOutput = output;\n\t\tthis.markModified(\"fullscreenExitOutput\");\n\t\tthis.save();\n\t}\n\n\tgetFullscreenScrollbar(): ScrollViewScrollbar {\n\t\tconst mode = this.settings.fullscreenScrollbar;\n\t\treturn mode === \"always\" || mode === \"hidden\" ? mode : \"auto\";\n\t}\n\n\tsetFullscreenScrollbar(mode: ScrollViewScrollbar): void {\n\t\tthis.globalSettings.fullscreenScrollbar = mode;\n\t\tthis.markModified(\"fullscreenScrollbar\");\n\t\tthis.save();\n\t}\n\n\tgetImageAutoResize(): boolean {\n\t\treturn this.settings.images?.autoResize ?? true;\n\t}\n\n\tsetImageAutoResize(enabled: boolean): void {\n\t\tif (!this.globalSettings.images) {\n\t\t\tthis.globalSettings.images = {};\n\t\t}\n\t\tthis.globalSettings.images.autoResize = enabled;\n\t\tthis.markModified(\"images\", \"autoResize\");\n\t\tthis.save();\n\t}\n\n\tgetBlockImages(): boolean {\n\t\treturn this.settings.images?.blockImages ?? false;\n\t}\n\n\tsetBlockImages(blocked: boolean): void {\n\t\tif (!this.globalSettings.images) {\n\t\t\tthis.globalSettings.images = {};\n\t\t}\n\t\tthis.globalSettings.images.blockImages = blocked;\n\t\tthis.markModified(\"images\", \"blockImages\");\n\t\tthis.save();\n\t}\n\n\tgetEnabledModels(): string[] | undefined {\n\t\treturn this.settings.enabledModels;\n\t}\n\n\tgetDefaultTools(): string[] | undefined {\n\t\tconst tools = this.settings.defaultTools;\n\t\treturn tools ? [...tools] : undefined;\n\t}\n\n\tsetEnabledModels(patterns: string[] | undefined): void {\n\t\tthis.globalSettings.enabledModels = patterns;\n\t\tthis.markModified(\"enabledModels\");\n\t\tthis.save();\n\t}\n\n\tgetDoubleEscapeAction(): \"fork\" | \"tree\" | \"none\" {\n\t\treturn this.settings.doubleEscapeAction ?? \"tree\";\n\t}\n\n\tsetDoubleEscapeAction(action: \"fork\" | \"tree\" | \"none\"): void {\n\t\tthis.globalSettings.doubleEscapeAction = action;\n\t\tthis.markModified(\"doubleEscapeAction\");\n\t\tthis.save();\n\t}\n\n\tgetTreeFilterMode(): \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\" {\n\t\tconst mode = this.settings.treeFilterMode;\n\t\tconst valid = [\"default\", \"no-tools\", \"user-only\", \"labeled-only\", \"all\"];\n\t\treturn mode && valid.includes(mode) ? mode : \"default\";\n\t}\n\n\tsetTreeFilterMode(mode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"): void {\n\t\tthis.globalSettings.treeFilterMode = mode;\n\t\tthis.markModified(\"treeFilterMode\");\n\t\tthis.save();\n\t}\n\n\tgetShowHardwareCursor(): boolean {\n\t\treturn this.settings.showHardwareCursor ?? getApexEnvironment(\"APEX_CODE_HARDWARE_CURSOR\") === \"1\";\n\t}\n\n\tsetShowHardwareCursor(enabled: boolean): void {\n\t\tthis.globalSettings.showHardwareCursor = enabled;\n\t\tthis.markModified(\"showHardwareCursor\");\n\t\tthis.save();\n\t}\n\n\tgetEditorPaddingX(): number {\n\t\treturn this.settings.editorPaddingX ?? 0;\n\t}\n\n\tsetEditorPaddingX(padding: number): void {\n\t\tthis.globalSettings.editorPaddingX = Math.max(0, Math.min(3, Math.floor(padding)));\n\t\tthis.markModified(\"editorPaddingX\");\n\t\tthis.save();\n\t}\n\n\tgetOutputPad(): 0 | 1 {\n\t\treturn this.settings.outputPad === 0 ? 0 : 1;\n\t}\n\n\tsetOutputPad(padding: 0 | 1): void {\n\t\tthis.globalSettings.outputPad = padding;\n\t\tthis.markModified(\"outputPad\");\n\t\tthis.save();\n\t}\n\n\tgetAutocompleteMaxVisible(): number {\n\t\treturn this.settings.autocompleteMaxVisible ?? 5;\n\t}\n\n\tsetAutocompleteMaxVisible(maxVisible: number): void {\n\t\tthis.globalSettings.autocompleteMaxVisible = Math.max(3, Math.min(20, Math.floor(maxVisible)));\n\t\tthis.markModified(\"autocompleteMaxVisible\");\n\t\tthis.save();\n\t}\n\n\tgetCodeBlockIndent(): string {\n\t\treturn this.settings.markdown?.codeBlockIndent ?? \" \";\n\t}\n\n\tgetMermaidRenderingMode(): MermaidRenderingMode {\n\t\tconst mode = this.settings.markdown?.mermaid;\n\t\treturn mode === \"off\" || mode === \"final\" ? mode : \"streaming\";\n\t}\n\n\tsetMermaidRenderingMode(mode: MermaidRenderingMode): void {\n\t\tthis.globalSettings.markdown ??= {};\n\t\tthis.globalSettings.markdown.mermaid = mode;\n\t\tthis.markModified(\"markdown\", \"mermaid\");\n\t\tthis.save();\n\t}\n\n\tgetWarnings(): WarningSettings {\n\t\treturn { ...(this.settings.warnings ?? {}) };\n\t}\n\n\tsetWarnings(warnings: WarningSettings): void {\n\t\tthis.globalSettings.warnings = { ...warnings };\n\t\tthis.markModified(\"warnings\");\n\t\tthis.save();\n\t}\n}\n"]}