apex-code 0.0.1-alpha.0 → 0.0.1-alpha.10

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 (739) hide show
  1. package/CHANGELOG.md +471 -0
  2. package/README.md +74 -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 +35 -20
  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 +121 -9
  40. package/dist/core/agent-session.d.ts.map +1 -1
  41. package/dist/core/agent-session.js +364 -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 +11 -10
  49. package/dist/core/bash-executor.js.map +1 -1
  50. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  51. package/dist/core/compaction/branch-summarization.js +3 -0
  52. package/dist/core/compaction/branch-summarization.js.map +1 -1
  53. package/dist/core/compaction/compaction.d.ts +4 -3
  54. package/dist/core/compaction/compaction.d.ts.map +1 -1
  55. package/dist/core/compaction/compaction.js +41 -32
  56. package/dist/core/compaction/compaction.js.map +1 -1
  57. package/dist/core/context/deferred-schemas.d.ts +92 -0
  58. package/dist/core/context/deferred-schemas.d.ts.map +1 -0
  59. package/dist/core/context/deferred-schemas.js +74 -0
  60. package/dist/core/context/deferred-schemas.js.map +1 -0
  61. package/dist/core/context/eviction.d.ts +47 -0
  62. package/dist/core/context/eviction.d.ts.map +1 -0
  63. package/dist/core/context/eviction.js +83 -0
  64. package/dist/core/context/eviction.js.map +1 -0
  65. package/dist/core/context/pipeline.d.ts +90 -0
  66. package/dist/core/context/pipeline.d.ts.map +1 -0
  67. package/dist/core/context/pipeline.js +109 -0
  68. package/dist/core/context/pipeline.js.map +1 -0
  69. package/dist/core/credential-failover.d.ts +30 -0
  70. package/dist/core/credential-failover.d.ts.map +1 -0
  71. package/dist/core/credential-failover.js +46 -0
  72. package/dist/core/credential-failover.js.map +1 -0
  73. package/dist/core/credential-pool.d.ts +60 -0
  74. package/dist/core/credential-pool.d.ts.map +1 -0
  75. package/dist/core/credential-pool.js +84 -0
  76. package/dist/core/credential-pool.js.map +1 -0
  77. package/dist/core/defaults.d.ts +1 -0
  78. package/dist/core/defaults.d.ts.map +1 -1
  79. package/dist/core/defaults.js +9 -0
  80. package/dist/core/defaults.js.map +1 -1
  81. package/dist/core/delegation/agents.d.ts +15 -0
  82. package/dist/core/delegation/agents.d.ts.map +1 -0
  83. package/dist/core/delegation/agents.js +55 -0
  84. package/dist/core/delegation/agents.js.map +1 -0
  85. package/dist/core/delegation/ceiling.d.ts +29 -0
  86. package/dist/core/delegation/ceiling.d.ts.map +1 -0
  87. package/dist/core/delegation/ceiling.js +34 -0
  88. package/dist/core/delegation/ceiling.js.map +1 -0
  89. package/dist/core/delegation/runtime.d.ts +94 -0
  90. package/dist/core/delegation/runtime.d.ts.map +1 -0
  91. package/dist/core/delegation/runtime.js +117 -0
  92. package/dist/core/delegation/runtime.js.map +1 -0
  93. package/dist/core/durable-state/daemon.d.ts +37 -0
  94. package/dist/core/durable-state/daemon.d.ts.map +1 -0
  95. package/dist/core/durable-state/daemon.js +62 -0
  96. package/dist/core/durable-state/daemon.js.map +1 -0
  97. package/dist/core/durable-state/provenance.d.ts +7 -0
  98. package/dist/core/durable-state/provenance.d.ts.map +1 -0
  99. package/dist/core/durable-state/provenance.js +24 -0
  100. package/dist/core/durable-state/provenance.js.map +1 -0
  101. package/dist/core/durable-state/sqlite.d.ts +84 -0
  102. package/dist/core/durable-state/sqlite.d.ts.map +1 -0
  103. package/dist/core/durable-state/sqlite.js +355 -0
  104. package/dist/core/durable-state/sqlite.js.map +1 -0
  105. package/dist/core/environment.d.ts +12 -0
  106. package/dist/core/environment.d.ts.map +1 -0
  107. package/dist/core/environment.js +69 -0
  108. package/dist/core/environment.js.map +1 -0
  109. package/dist/core/evidence-policy.d.ts +17 -0
  110. package/dist/core/evidence-policy.d.ts.map +1 -0
  111. package/dist/core/evidence-policy.js +25 -0
  112. package/dist/core/evidence-policy.js.map +1 -0
  113. package/dist/core/evidence.d.ts +16 -0
  114. package/dist/core/evidence.d.ts.map +1 -0
  115. package/dist/core/evidence.js +51 -0
  116. package/dist/core/evidence.js.map +1 -0
  117. package/dist/core/experimental.d.ts +4 -0
  118. package/dist/core/experimental.d.ts.map +1 -1
  119. package/dist/core/experimental.js +6 -1
  120. package/dist/core/experimental.js.map +1 -1
  121. package/dist/core/extensions/index.d.ts +2 -2
  122. package/dist/core/extensions/index.d.ts.map +1 -1
  123. package/dist/core/extensions/index.js +1 -1
  124. package/dist/core/extensions/index.js.map +1 -1
  125. package/dist/core/extensions/loader.d.ts.map +1 -1
  126. package/dist/core/extensions/loader.js +115 -48
  127. package/dist/core/extensions/loader.js.map +1 -1
  128. package/dist/core/extensions/types.d.ts +44 -9
  129. package/dist/core/extensions/types.d.ts.map +1 -1
  130. package/dist/core/extensions/types.js +3 -0
  131. package/dist/core/extensions/types.js.map +1 -1
  132. package/dist/core/footer-data-provider.d.ts +1 -1
  133. package/dist/core/footer-data-provider.d.ts.map +1 -1
  134. package/dist/core/footer-data-provider.js +1 -1
  135. package/dist/core/footer-data-provider.js.map +1 -1
  136. package/dist/core/http-dispatcher.d.ts +1 -2
  137. package/dist/core/http-dispatcher.d.ts.map +1 -1
  138. package/dist/core/http-dispatcher.js +2 -17
  139. package/dist/core/http-dispatcher.js.map +1 -1
  140. package/dist/core/http-idle-timeout.d.ts +12 -0
  141. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  142. package/dist/core/http-idle-timeout.js +27 -0
  143. package/dist/core/http-idle-timeout.js.map +1 -0
  144. package/dist/core/index.d.ts +1 -0
  145. package/dist/core/index.d.ts.map +1 -1
  146. package/dist/core/index.js +1 -0
  147. package/dist/core/index.js.map +1 -1
  148. package/dist/core/keybindings.d.ts +38 -13
  149. package/dist/core/keybindings.d.ts.map +1 -1
  150. package/dist/core/keybindings.js +26 -5
  151. package/dist/core/keybindings.js.map +1 -1
  152. package/dist/core/lsp/client.d.ts +78 -0
  153. package/dist/core/lsp/client.d.ts.map +1 -0
  154. package/dist/core/lsp/client.js +494 -0
  155. package/dist/core/lsp/client.js.map +1 -0
  156. package/dist/core/lsp/diagnostics.d.ts +47 -0
  157. package/dist/core/lsp/diagnostics.d.ts.map +1 -0
  158. package/dist/core/lsp/diagnostics.js +224 -0
  159. package/dist/core/lsp/diagnostics.js.map +1 -0
  160. package/dist/core/lsp/pool.d.ts +48 -0
  161. package/dist/core/lsp/pool.d.ts.map +1 -0
  162. package/dist/core/lsp/pool.js +150 -0
  163. package/dist/core/lsp/pool.js.map +1 -0
  164. package/dist/core/lsp/registry.d.ts +49 -0
  165. package/dist/core/lsp/registry.d.ts.map +1 -0
  166. package/dist/core/lsp/registry.js +215 -0
  167. package/dist/core/lsp/registry.js.map +1 -0
  168. package/dist/core/lsp/status.d.ts +23 -0
  169. package/dist/core/lsp/status.d.ts.map +1 -0
  170. package/dist/core/lsp/status.js +35 -0
  171. package/dist/core/lsp/status.js.map +1 -0
  172. package/dist/core/lsp/sync.d.ts +13 -0
  173. package/dist/core/lsp/sync.d.ts.map +1 -0
  174. package/dist/core/lsp/sync.js +71 -0
  175. package/dist/core/lsp/sync.js.map +1 -0
  176. package/dist/core/model-config.d.ts +18 -0
  177. package/dist/core/model-config.d.ts.map +1 -1
  178. package/dist/core/model-config.js +25 -6
  179. package/dist/core/model-config.js.map +1 -1
  180. package/dist/core/model-resolver.d.ts +21 -0
  181. package/dist/core/model-resolver.d.ts.map +1 -1
  182. package/dist/core/model-resolver.js +73 -8
  183. package/dist/core/model-resolver.js.map +1 -1
  184. package/dist/core/model-runtime.d.ts +73 -0
  185. package/dist/core/model-runtime.d.ts.map +1 -1
  186. package/dist/core/model-runtime.js +225 -8
  187. package/dist/core/model-runtime.js.map +1 -1
  188. package/dist/core/models-store.d.ts.map +1 -1
  189. package/dist/core/models-store.js +2 -1
  190. package/dist/core/models-store.js.map +1 -1
  191. package/dist/core/observability/aggregate.d.ts +21 -0
  192. package/dist/core/observability/aggregate.d.ts.map +1 -0
  193. package/dist/core/observability/aggregate.js +36 -0
  194. package/dist/core/observability/aggregate.js.map +1 -0
  195. package/dist/core/observability/otlp.d.ts +66 -0
  196. package/dist/core/observability/otlp.d.ts.map +1 -0
  197. package/dist/core/observability/otlp.js +95 -0
  198. package/dist/core/observability/otlp.js.map +1 -0
  199. package/dist/core/package-manager.d.ts.map +1 -1
  200. package/dist/core/package-manager.js +40 -16
  201. package/dist/core/package-manager.js.map +1 -1
  202. package/dist/core/permissions/gate.d.ts +42 -0
  203. package/dist/core/permissions/gate.d.ts.map +1 -0
  204. package/dist/core/permissions/gate.js +72 -0
  205. package/dist/core/permissions/gate.js.map +1 -0
  206. package/dist/core/permissions/modes.d.ts +18 -0
  207. package/dist/core/permissions/modes.d.ts.map +1 -0
  208. package/dist/core/permissions/modes.js +57 -0
  209. package/dist/core/permissions/modes.js.map +1 -0
  210. package/dist/core/permissions/responder.d.ts +30 -0
  211. package/dist/core/permissions/responder.d.ts.map +1 -0
  212. package/dist/core/permissions/responder.js +32 -0
  213. package/dist/core/permissions/responder.js.map +1 -0
  214. package/dist/core/permissions/rules.d.ts +34 -0
  215. package/dist/core/permissions/rules.d.ts.map +1 -0
  216. package/dist/core/permissions/rules.js +74 -0
  217. package/dist/core/permissions/rules.js.map +1 -0
  218. package/dist/core/permissions/startup.d.ts +45 -0
  219. package/dist/core/permissions/startup.d.ts.map +1 -0
  220. package/dist/core/permissions/startup.js +63 -0
  221. package/dist/core/permissions/startup.js.map +1 -0
  222. package/dist/core/permissions/store.d.ts +114 -0
  223. package/dist/core/permissions/store.d.ts.map +1 -0
  224. package/dist/core/permissions/store.js +229 -0
  225. package/dist/core/permissions/store.js.map +1 -0
  226. package/dist/core/pi-manifest.d.ts.map +1 -1
  227. package/dist/core/pi-manifest.js +2 -1
  228. package/dist/core/pi-manifest.js.map +1 -1
  229. package/dist/core/project-trust.d.ts.map +1 -1
  230. package/dist/core/project-trust.js +1 -1
  231. package/dist/core/project-trust.js.map +1 -1
  232. package/dist/core/provider-attribution.d.ts.map +1 -1
  233. package/dist/core/provider-attribution.js +6 -7
  234. package/dist/core/provider-attribution.js.map +1 -1
  235. package/dist/core/remote-catalog-provider.d.ts +2 -2
  236. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  237. package/dist/core/remote-catalog-provider.js +22 -17
  238. package/dist/core/remote-catalog-provider.js.map +1 -1
  239. package/dist/core/resource-loader.d.ts.map +1 -1
  240. package/dist/core/resource-loader.js +3 -2
  241. package/dist/core/resource-loader.js.map +1 -1
  242. package/dist/core/sandbox/bwrap-arguments.d.ts +52 -0
  243. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  244. package/dist/core/sandbox/bwrap-arguments.js +86 -0
  245. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  246. package/dist/core/sandbox/child-entry.d.ts +2 -0
  247. package/dist/core/sandbox/child-entry.d.ts.map +1 -0
  248. package/dist/core/sandbox/child-entry.js +22 -0
  249. package/dist/core/sandbox/child-entry.js.map +1 -0
  250. package/dist/core/sandbox/cli-launch.d.ts +88 -0
  251. package/dist/core/sandbox/cli-launch.d.ts.map +1 -0
  252. package/dist/core/sandbox/cli-launch.js +272 -0
  253. package/dist/core/sandbox/cli-launch.js.map +1 -0
  254. package/dist/core/sandbox/cli-supervisor.d.ts +30 -0
  255. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -0
  256. package/dist/core/sandbox/cli-supervisor.js +123 -0
  257. package/dist/core/sandbox/cli-supervisor.js.map +1 -0
  258. package/dist/core/sandbox/default-hosts.d.ts +28 -0
  259. package/dist/core/sandbox/default-hosts.d.ts.map +1 -0
  260. package/dist/core/sandbox/default-hosts.js +69 -0
  261. package/dist/core/sandbox/default-hosts.js.map +1 -0
  262. package/dist/core/sandbox/full-access.d.ts +28 -0
  263. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  264. package/dist/core/sandbox/full-access.js +63 -0
  265. package/dist/core/sandbox/full-access.js.map +1 -0
  266. package/dist/core/sandbox/git-identity.d.ts +57 -0
  267. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  268. package/dist/core/sandbox/git-identity.js +78 -0
  269. package/dist/core/sandbox/git-identity.js.map +1 -0
  270. package/dist/core/sandbox/host-approval.d.ts +42 -0
  271. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  272. package/dist/core/sandbox/host-approval.js +99 -0
  273. package/dist/core/sandbox/host-approval.js.map +1 -0
  274. package/dist/core/sandbox/linux-backend.d.ts +46 -0
  275. package/dist/core/sandbox/linux-backend.d.ts.map +1 -0
  276. package/dist/core/sandbox/linux-backend.js +304 -0
  277. package/dist/core/sandbox/linux-backend.js.map +1 -0
  278. package/dist/core/sandbox/macos-backend.d.ts +28 -0
  279. package/dist/core/sandbox/macos-backend.d.ts.map +1 -0
  280. package/dist/core/sandbox/macos-backend.js +313 -0
  281. package/dist/core/sandbox/macos-backend.js.map +1 -0
  282. package/dist/core/sandbox/network-proxy.d.ts +38 -0
  283. package/dist/core/sandbox/network-proxy.d.ts.map +1 -0
  284. package/dist/core/sandbox/network-proxy.js +153 -0
  285. package/dist/core/sandbox/network-proxy.js.map +1 -0
  286. package/dist/core/sandbox/network-refusal.d.ts +24 -0
  287. package/dist/core/sandbox/network-refusal.d.ts.map +1 -0
  288. package/dist/core/sandbox/network-refusal.js +72 -0
  289. package/dist/core/sandbox/network-refusal.js.map +1 -0
  290. package/dist/core/sandbox/policy.d.ts +40 -0
  291. package/dist/core/sandbox/policy.d.ts.map +1 -0
  292. package/dist/core/sandbox/policy.js +55 -0
  293. package/dist/core/sandbox/policy.js.map +1 -0
  294. package/dist/core/sandbox/profiles.d.ts +25 -0
  295. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  296. package/dist/core/sandbox/profiles.js +23 -0
  297. package/dist/core/sandbox/profiles.js.map +1 -0
  298. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  299. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  300. package/dist/core/sandbox/rpc/command-client.js +86 -0
  301. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  302. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  303. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  304. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  305. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  306. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  307. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  308. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  309. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  310. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  311. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  312. package/dist/core/sandbox/rpc/credential-proxy.js +287 -0
  313. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  314. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  315. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  316. package/dist/core/sandbox/rpc/framing.js +114 -0
  317. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  318. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +40 -0
  319. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  320. package/dist/core/sandbox/rpc/git-credential-helper.js +152 -0
  321. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  322. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +48 -0
  323. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  324. package/dist/core/sandbox/rpc/git-credential-proxy.js +142 -0
  325. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  326. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  327. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  328. package/dist/core/sandbox/supervisor-temp.js +21 -0
  329. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  330. package/dist/core/sandbox/supervisor.d.ts +51 -0
  331. package/dist/core/sandbox/supervisor.d.ts.map +1 -0
  332. package/dist/core/sandbox/supervisor.js +18 -0
  333. package/dist/core/sandbox/supervisor.js.map +1 -0
  334. package/dist/core/sandbox/terminal-handoff.d.ts +45 -0
  335. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  336. package/dist/core/sandbox/terminal-handoff.js +176 -0
  337. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  338. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  339. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  340. package/dist/core/sandbox/terminal-size.js +105 -0
  341. package/dist/core/sandbox/terminal-size.js.map +1 -0
  342. package/dist/core/sandbox/violations.d.ts +23 -0
  343. package/dist/core/sandbox/violations.d.ts.map +1 -0
  344. package/dist/core/sandbox/violations.js +30 -0
  345. package/dist/core/sandbox/violations.js.map +1 -0
  346. package/dist/core/sdk.d.ts +32 -41
  347. package/dist/core/sdk.d.ts.map +1 -1
  348. package/dist/core/sdk.js +161 -6
  349. package/dist/core/sdk.js.map +1 -1
  350. package/dist/core/session-export.d.ts +4 -0
  351. package/dist/core/session-export.d.ts.map +1 -0
  352. package/dist/core/session-export.js +32 -0
  353. package/dist/core/session-export.js.map +1 -0
  354. package/dist/core/session-lease.d.ts +31 -0
  355. package/dist/core/session-lease.d.ts.map +1 -0
  356. package/dist/core/session-lease.js +138 -0
  357. package/dist/core/session-lease.js.map +1 -0
  358. package/dist/core/session-manager.d.ts +46 -2
  359. package/dist/core/session-manager.d.ts.map +1 -1
  360. package/dist/core/session-manager.js +62 -4
  361. package/dist/core/session-manager.js.map +1 -1
  362. package/dist/core/session-share.d.ts +31 -0
  363. package/dist/core/session-share.d.ts.map +1 -0
  364. package/dist/core/session-share.js +45 -0
  365. package/dist/core/session-share.js.map +1 -0
  366. package/dist/core/settings-diagnostics.d.ts +9 -0
  367. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  368. package/dist/core/settings-diagnostics.js +21 -0
  369. package/dist/core/settings-diagnostics.js.map +1 -0
  370. package/dist/core/settings-manager.d.ts +92 -9
  371. package/dist/core/settings-manager.d.ts.map +1 -1
  372. package/dist/core/settings-manager.js +138 -36
  373. package/dist/core/settings-manager.js.map +1 -1
  374. package/dist/core/skills.d.ts +19 -7
  375. package/dist/core/skills.d.ts.map +1 -1
  376. package/dist/core/skills.js +128 -52
  377. package/dist/core/skills.js.map +1 -1
  378. package/dist/core/slash-commands.d.ts.map +1 -1
  379. package/dist/core/slash-commands.js +5 -2
  380. package/dist/core/slash-commands.js.map +1 -1
  381. package/dist/core/system-prompt.d.ts +2 -2
  382. package/dist/core/system-prompt.d.ts.map +1 -1
  383. package/dist/core/system-prompt.js +59 -68
  384. package/dist/core/system-prompt.js.map +1 -1
  385. package/dist/core/timings.d.ts +1 -1
  386. package/dist/core/timings.d.ts.map +1 -1
  387. package/dist/core/timings.js +3 -2
  388. package/dist/core/timings.js.map +1 -1
  389. package/dist/core/tools/ask-user.d.ts +25 -0
  390. package/dist/core/tools/ask-user.d.ts.map +1 -0
  391. package/dist/core/tools/ask-user.js +49 -0
  392. package/dist/core/tools/ask-user.js.map +1 -0
  393. package/dist/core/tools/bash-command-segments.d.ts +22 -0
  394. package/dist/core/tools/bash-command-segments.d.ts.map +1 -0
  395. package/dist/core/tools/bash-command-segments.js +128 -0
  396. package/dist/core/tools/bash-command-segments.js.map +1 -0
  397. package/dist/core/tools/bash.d.ts +40 -4
  398. package/dist/core/tools/bash.d.ts.map +1 -1
  399. package/dist/core/tools/bash.js +183 -32
  400. package/dist/core/tools/bash.js.map +1 -1
  401. package/dist/core/tools/contract.d.ts +183 -0
  402. package/dist/core/tools/contract.d.ts.map +1 -0
  403. package/dist/core/tools/contract.js +48 -0
  404. package/dist/core/tools/contract.js.map +1 -0
  405. package/dist/core/tools/delegate.d.ts +38 -0
  406. package/dist/core/tools/delegate.d.ts.map +1 -0
  407. package/dist/core/tools/delegate.js +90 -0
  408. package/dist/core/tools/delegate.js.map +1 -0
  409. package/dist/core/tools/diagnostics.d.ts +39 -0
  410. package/dist/core/tools/diagnostics.d.ts.map +1 -0
  411. package/dist/core/tools/diagnostics.js +62 -0
  412. package/dist/core/tools/diagnostics.js.map +1 -0
  413. package/dist/core/tools/edit-diff.d.ts +0 -5
  414. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  415. package/dist/core/tools/edit-diff.js +2 -5
  416. package/dist/core/tools/edit-diff.js.map +1 -1
  417. package/dist/core/tools/edit.d.ts +12 -2
  418. package/dist/core/tools/edit.d.ts.map +1 -1
  419. package/dist/core/tools/edit.js +61 -10
  420. package/dist/core/tools/edit.js.map +1 -1
  421. package/dist/core/tools/find.d.ts +2 -2
  422. package/dist/core/tools/find.d.ts.map +1 -1
  423. package/dist/core/tools/find.js +13 -1
  424. package/dist/core/tools/find.js.map +1 -1
  425. package/dist/core/tools/grep.d.ts +4 -2
  426. package/dist/core/tools/grep.d.ts.map +1 -1
  427. package/dist/core/tools/grep.js +47 -10
  428. package/dist/core/tools/grep.js.map +1 -1
  429. package/dist/core/tools/index.d.ts +51 -6
  430. package/dist/core/tools/index.d.ts.map +1 -1
  431. package/dist/core/tools/index.js +145 -2
  432. package/dist/core/tools/index.js.map +1 -1
  433. package/dist/core/tools/ls.d.ts +4 -2
  434. package/dist/core/tools/ls.d.ts.map +1 -1
  435. package/dist/core/tools/ls.js +17 -1
  436. package/dist/core/tools/ls.js.map +1 -1
  437. package/dist/core/tools/lsp.d.ts +62 -0
  438. package/dist/core/tools/lsp.d.ts.map +1 -0
  439. package/dist/core/tools/lsp.js +216 -0
  440. package/dist/core/tools/lsp.js.map +1 -0
  441. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  442. package/dist/core/tools/output-accumulator.js +1 -1
  443. package/dist/core/tools/output-accumulator.js.map +1 -1
  444. package/dist/core/tools/path-permission.d.ts +18 -0
  445. package/dist/core/tools/path-permission.d.ts.map +1 -0
  446. package/dist/core/tools/path-permission.js +28 -0
  447. package/dist/core/tools/path-permission.js.map +1 -0
  448. package/dist/core/tools/plan-present.d.ts +27 -0
  449. package/dist/core/tools/plan-present.d.ts.map +1 -0
  450. package/dist/core/tools/plan-present.js +55 -0
  451. package/dist/core/tools/plan-present.js.map +1 -0
  452. package/dist/core/tools/powershell.d.ts +16 -0
  453. package/dist/core/tools/powershell.d.ts.map +1 -0
  454. package/dist/core/tools/powershell.js +39 -0
  455. package/dist/core/tools/powershell.js.map +1 -0
  456. package/dist/core/tools/read.d.ts +2 -2
  457. package/dist/core/tools/read.d.ts.map +1 -1
  458. package/dist/core/tools/read.js +14 -0
  459. package/dist/core/tools/read.js.map +1 -1
  460. package/dist/core/tools/skill-search.d.ts +32 -0
  461. package/dist/core/tools/skill-search.d.ts.map +1 -0
  462. package/dist/core/tools/skill-search.js +56 -0
  463. package/dist/core/tools/skill-search.js.map +1 -0
  464. package/dist/core/tools/test.d.ts +34 -0
  465. package/dist/core/tools/test.d.ts.map +1 -0
  466. package/dist/core/tools/test.js +75 -0
  467. package/dist/core/tools/test.js.map +1 -0
  468. package/dist/core/tools/todo-write.d.ts +31 -0
  469. package/dist/core/tools/todo-write.d.ts.map +1 -0
  470. package/dist/core/tools/todo-write.js +51 -0
  471. package/dist/core/tools/todo-write.js.map +1 -0
  472. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -2
  473. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  474. package/dist/core/tools/tool-definition-wrapper.js +11 -1
  475. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  476. package/dist/core/tools/tool-schema.d.ts +22 -0
  477. package/dist/core/tools/tool-schema.d.ts.map +1 -0
  478. package/dist/core/tools/tool-schema.js +45 -0
  479. package/dist/core/tools/tool-schema.js.map +1 -0
  480. package/dist/core/tools/web-fetch.d.ts +26 -0
  481. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  482. package/dist/core/tools/web-fetch.js +62 -0
  483. package/dist/core/tools/web-fetch.js.map +1 -0
  484. package/dist/core/tools/web-search-exa.d.ts +33 -0
  485. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  486. package/dist/core/tools/web-search-exa.js +128 -0
  487. package/dist/core/tools/web-search-exa.js.map +1 -0
  488. package/dist/core/tools/web-search.d.ts +26 -0
  489. package/dist/core/tools/web-search.d.ts.map +1 -0
  490. package/dist/core/tools/web-search.js +53 -0
  491. package/dist/core/tools/web-search.js.map +1 -0
  492. package/dist/core/tools/write.d.ts +16 -2
  493. package/dist/core/tools/write.d.ts.map +1 -1
  494. package/dist/core/tools/write.js +48 -2
  495. package/dist/core/tools/write.js.map +1 -1
  496. package/dist/core/trust-manager.d.ts.map +1 -1
  497. package/dist/core/trust-manager.js +2 -1
  498. package/dist/core/trust-manager.js.map +1 -1
  499. package/dist/core/usage-performance-store.d.ts +56 -0
  500. package/dist/core/usage-performance-store.d.ts.map +1 -0
  501. package/dist/core/usage-performance-store.js +85 -0
  502. package/dist/core/usage-performance-store.js.map +1 -0
  503. package/dist/core/web-search-provider.d.ts +64 -0
  504. package/dist/core/web-search-provider.d.ts.map +1 -0
  505. package/dist/core/web-search-provider.js +149 -0
  506. package/dist/core/web-search-provider.js.map +1 -0
  507. package/dist/extensions/llama/index.d.ts.map +1 -1
  508. package/dist/extensions/llama/index.js +2 -0
  509. package/dist/extensions/llama/index.js.map +1 -1
  510. package/dist/extensions/llama/provider.d.ts.map +1 -1
  511. package/dist/extensions/llama/provider.js +6 -2
  512. package/dist/extensions/llama/provider.js.map +1 -1
  513. package/dist/index.d.ts +7 -6
  514. package/dist/index.d.ts.map +1 -1
  515. package/dist/index.js +5 -4
  516. package/dist/index.js.map +1 -1
  517. package/dist/main.d.ts +5 -0
  518. package/dist/main.d.ts.map +1 -1
  519. package/dist/main.js +87 -22
  520. package/dist/main.js.map +1 -1
  521. package/dist/migrations.d.ts.map +1 -1
  522. package/dist/migrations.js +6 -5
  523. package/dist/migrations.js.map +1 -1
  524. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  525. package/dist/modes/interactive/components/config-selector.js +9 -6
  526. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  527. package/dist/modes/interactive/components/custom-editor.d.ts +72 -1
  528. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/custom-editor.js +338 -1
  530. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  531. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  532. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  534. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  535. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  536. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  537. package/dist/modes/interactive/components/extension-selector.js +24 -6
  538. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  539. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -4
  540. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/first-time-setup.js +17 -41
  542. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  543. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  544. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  545. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  546. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  547. package/dist/modes/interactive/components/footer.d.ts +23 -1
  548. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  549. package/dist/modes/interactive/components/footer.js +182 -21
  550. package/dist/modes/interactive/components/footer.js.map +1 -1
  551. package/dist/modes/interactive/components/index.d.ts +2 -0
  552. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  553. package/dist/modes/interactive/components/index.js +2 -0
  554. package/dist/modes/interactive/components/index.js.map +1 -1
  555. package/dist/modes/interactive/components/model-selector.d.ts +31 -9
  556. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  557. package/dist/modes/interactive/components/model-selector.js +236 -96
  558. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  559. package/dist/modes/interactive/components/settings-selector.d.ts +25 -5
  560. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  561. package/dist/modes/interactive/components/settings-selector.js +226 -58
  562. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  563. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  564. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  565. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  566. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  567. package/dist/modes/interactive/components/splash-header.d.ts +66 -0
  568. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
  569. package/dist/modes/interactive/components/splash-header.js +180 -0
  570. package/dist/modes/interactive/components/splash-header.js.map +1 -0
  571. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  572. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  573. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  574. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  575. package/dist/modes/interactive/components/tool-execution.d.ts +16 -1
  576. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  577. package/dist/modes/interactive/components/tool-execution.js +113 -35
  578. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  579. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  580. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  581. package/dist/modes/interactive/components/tool-panel.js +130 -0
  582. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  583. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  584. package/dist/modes/interactive/external-editor.js +60 -10
  585. package/dist/modes/interactive/external-editor.js.map +1 -1
  586. package/dist/modes/interactive/interactive-mode.d.ts +61 -5
  587. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  588. package/dist/modes/interactive/interactive-mode.js +642 -203
  589. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  590. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  591. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  592. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  593. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  594. package/dist/modes/interactive/theme/apex.json +93 -0
  595. package/dist/modes/interactive/theme/dark.json +2 -0
  596. package/dist/modes/interactive/theme/light.json +3 -1
  597. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  598. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  599. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  600. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  601. package/dist/modes/interactive/theme/theme-schema.json +11 -3
  602. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  603. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  604. package/dist/modes/interactive/theme/theme.js +65 -10
  605. package/dist/modes/interactive/theme/theme.js.map +1 -1
  606. package/dist/modes/json-event.d.ts +18 -12
  607. package/dist/modes/json-event.d.ts.map +1 -1
  608. package/dist/modes/json-event.js +22 -5
  609. package/dist/modes/json-event.js.map +1 -1
  610. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  611. package/dist/modes/rpc/rpc-mode.js +2 -1
  612. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  613. package/dist/package-manager-cli.d.ts +1 -0
  614. package/dist/package-manager-cli.d.ts.map +1 -1
  615. package/dist/package-manager-cli.js +211 -14
  616. package/dist/package-manager-cli.js.map +1 -1
  617. package/dist/rpc-entry.d.ts.map +1 -1
  618. package/dist/rpc-entry.js +2 -1
  619. package/dist/rpc-entry.js.map +1 -1
  620. package/dist/server/create-harness.d.ts +1 -1
  621. package/dist/server/create-harness.d.ts.map +1 -1
  622. package/dist/server/create-harness.js +8 -5
  623. package/dist/server/create-harness.js.map +1 -1
  624. package/dist/testing/replay/metrics.d.ts +24 -0
  625. package/dist/testing/replay/metrics.d.ts.map +1 -0
  626. package/dist/testing/replay/metrics.js +35 -0
  627. package/dist/testing/replay/metrics.js.map +1 -0
  628. package/dist/testing/replay/recorded-provider.d.ts +10 -0
  629. package/dist/testing/replay/recorded-provider.d.ts.map +1 -0
  630. package/dist/testing/replay/recorded-provider.js +108 -0
  631. package/dist/testing/replay/recorded-provider.js.map +1 -0
  632. package/dist/testing/replay/runner.d.ts +56 -0
  633. package/dist/testing/replay/runner.d.ts.map +1 -0
  634. package/dist/testing/replay/runner.js +406 -0
  635. package/dist/testing/replay/runner.js.map +1 -0
  636. package/dist/themes/apex-logo.d.ts +41 -0
  637. package/dist/themes/apex-logo.d.ts.map +1 -0
  638. package/dist/themes/apex-logo.js +35 -0
  639. package/dist/themes/apex-logo.js.map +1 -0
  640. package/dist/utils/apex-code-user-agent.d.ts +2 -0
  641. package/dist/utils/apex-code-user-agent.d.ts.map +1 -0
  642. package/dist/utils/apex-code-user-agent.js +5 -0
  643. package/dist/utils/apex-code-user-agent.js.map +1 -0
  644. package/dist/utils/changelog.d.ts +7 -2
  645. package/dist/utils/changelog.d.ts.map +1 -1
  646. package/dist/utils/changelog.js +82 -13
  647. package/dist/utils/changelog.js.map +1 -1
  648. package/dist/utils/clipboard-image.d.ts.map +1 -1
  649. package/dist/utils/clipboard-image.js +1 -1
  650. package/dist/utils/clipboard-image.js.map +1 -1
  651. package/dist/utils/frontmatter.d.ts.map +1 -1
  652. package/dist/utils/frontmatter.js +2 -1
  653. package/dist/utils/frontmatter.js.map +1 -1
  654. package/dist/utils/management-http.d.ts +5 -3
  655. package/dist/utils/management-http.d.ts.map +1 -1
  656. package/dist/utils/management-http.js +14 -10
  657. package/dist/utils/management-http.js.map +1 -1
  658. package/dist/utils/shell.d.ts +3 -0
  659. package/dist/utils/shell.d.ts.map +1 -1
  660. package/dist/utils/shell.js +17 -5
  661. package/dist/utils/shell.js.map +1 -1
  662. package/dist/utils/syntax-highlight.d.ts +1 -0
  663. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  664. package/dist/utils/syntax-highlight.js +60 -1
  665. package/dist/utils/syntax-highlight.js.map +1 -1
  666. package/dist/utils/text.d.ts +8 -0
  667. package/dist/utils/text.d.ts.map +1 -0
  668. package/dist/utils/text.js +9 -0
  669. package/dist/utils/text.js.map +1 -0
  670. package/dist/utils/tools-manager.d.ts +70 -2
  671. package/dist/utils/tools-manager.d.ts.map +1 -1
  672. package/dist/utils/tools-manager.js +280 -124
  673. package/dist/utils/tools-manager.js.map +1 -1
  674. package/dist/utils/version-check.d.ts +7 -5
  675. package/dist/utils/version-check.d.ts.map +1 -1
  676. package/dist/utils/version-check.js +25 -14
  677. package/dist/utils/version-check.js.map +1 -1
  678. package/dist/utils/windows-self-update.d.ts.map +1 -1
  679. package/dist/utils/windows-self-update.js +1 -1
  680. package/dist/utils/windows-self-update.js.map +1 -1
  681. package/docs/compaction.md +39 -24
  682. package/docs/containerization.md +24 -21
  683. package/docs/custom-provider.md +15 -12
  684. package/docs/development.md +11 -11
  685. package/docs/environment-variables.md +37 -77
  686. package/docs/extensions.md +68 -54
  687. package/docs/index.md +12 -24
  688. package/docs/json.md +18 -11
  689. package/docs/keybindings.md +18 -12
  690. package/docs/llama-cpp.md +9 -7
  691. package/docs/models.md +17 -11
  692. package/docs/packages.md +47 -43
  693. package/docs/prompt-templates.md +3 -3
  694. package/docs/providers.md +10 -10
  695. package/docs/quickstart.md +49 -32
  696. package/docs/rpc.md +35 -18
  697. package/docs/sdk.md +20 -6
  698. package/docs/security.md +18 -18
  699. package/docs/session-format.md +9 -9
  700. package/docs/sessions.md +13 -13
  701. package/docs/settings.md +83 -16
  702. package/docs/shell-aliases.md +1 -1
  703. package/docs/skills.md +66 -15
  704. package/docs/terminal-setup.md +44 -19
  705. package/docs/termux.md +4 -4
  706. package/docs/themes.md +32 -11
  707. package/docs/tmux.md +4 -4
  708. package/docs/tui.md +5 -5
  709. package/docs/usage.md +61 -53
  710. package/docs/windows.md +24 -2
  711. package/examples/extensions/border-status-editor.ts +1 -1
  712. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  713. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  714. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  715. package/examples/extensions/git-checkpoint.ts +2 -2
  716. package/examples/extensions/gondolin/package-lock.json +2 -2
  717. package/examples/extensions/gondolin/package.json +1 -1
  718. package/examples/extensions/notify.ts +3 -1
  719. package/examples/extensions/sandbox/package-lock.json +2 -2
  720. package/examples/extensions/sandbox/package.json +1 -1
  721. package/examples/extensions/subagent/README.md +3 -1
  722. package/examples/extensions/subagent/agents.ts +40 -9
  723. package/examples/extensions/subagent/index.ts +27 -4
  724. package/examples/extensions/titlebar-spinner.ts +1 -1
  725. package/examples/extensions/with-deps/package-lock.json +2 -2
  726. package/examples/extensions/with-deps/package.json +1 -1
  727. package/examples/rpc-extension-ui.ts +1 -1
  728. package/examples/sdk/06-extensions.ts +1 -1
  729. package/examples/sdk/README.md +1 -1
  730. package/npm-shrinkwrap.json +280 -445
  731. package/package.json +9 -12
  732. package/dist/core/telemetry.d.ts +0 -3
  733. package/dist/core/telemetry.d.ts.map +0 -1
  734. package/dist/core/telemetry.js +0 -9
  735. package/dist/core/telemetry.js.map +0 -1
  736. package/dist/utils/pi-user-agent.d.ts +0 -2
  737. package/dist/utils/pi-user-agent.d.ts.map +0 -1
  738. package/dist/utils/pi-user-agent.js +0 -5
  739. package/dist/utils/pi-user-agent.js.map +0 -1
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Context pipeline wiring — shared by `AgentSession` (production) and the offline
3
+ * replay harness (`src/testing/replay/runner.ts`), so there is exactly one
4
+ * implementation of "how deferred-schema resolution and eviction attach to an
5
+ * `Agent`" rather than two independently maintained copies.
6
+ *
7
+ * Implements the ordering settled in `docs/architecture/contracts.md` § 2:
8
+ * deferred-schema resolution → tool-result eviction → compaction. Compaction runs
9
+ * reactively from its own existing seam (`_checkCompaction` in `agent-session.ts`)
10
+ * and is untouched here; this module only adds the two stages that run *ahead of*
11
+ * every LLM request, so that reactive check is reached less often because the
12
+ * request it is reacting to is smaller.
13
+ *
14
+ * The two stages land in different seams because they operate on different halves
15
+ * of the outbound request. Eviction is a pure function of `AgentMessage[]`, which is
16
+ * exactly what `transformContext` sees, immediately before `convertToLlm` — so it is
17
+ * wired there. Deferred-schema resolution operates on the *tool list*, not messages;
18
+ * `transformContext`'s signature has no tools parameter, and `AgentContext.tools` is
19
+ * a snapshot taken once per prompt rather than rebuilt per request. The seam that
20
+ * actually sees the assembled outbound tool list on every request is
21
+ * `streamFunction` — it receives the full `Context`, tools included, immediately
22
+ * before the provider call — so the projection is applied there instead. Because the
23
+ * two stages act on disjoint fields of the request with no data dependency between
24
+ * them, this does not change the observable pipeline order.
25
+ */
26
+ import type { Agent, StreamFn } from "apex-code-agent-core";
27
+ import { type ContractLookup } from "./eviction.ts";
28
+ /**
29
+ * Eviction-budget formula shared by every caller of `installContextPipeline`.
30
+ * Compaction fires once total context tokens exceed `contextWindow - reserveTokens`
31
+ * (`shouldCompact` in `core/compaction/compaction.ts`). Budgeting eviction — counted
32
+ * purely against tool-result tokens, per `evictToolResults`'s own contract — at half
33
+ * of that headroom leaves the other half free for system prompt and conversational
34
+ * growth, so eviction (cheap, structure-preserving) gets a chance to shrink the
35
+ * transcript before the expensive compaction stage is ever reached, matching
36
+ * contracts.md § 2's "why this order" (eviction before compaction, so compaction is
37
+ * reached later and less often).
38
+ *
39
+ * `Math.max(0, ...)` mirrors `shouldCompact`'s own behavior when `contextWindow` is
40
+ * unknown (0): evict aggressively rather than not at all, rather than inventing a
41
+ * different, unproven fallback.
42
+ *
43
+ * Production (`AgentSession`) calls this with the real model's `contextWindow` and
44
+ * the user's configured `reserveTokens`. The offline replay harness deliberately
45
+ * does *not* call this with the fixture model's `contextWindow` — see
46
+ * `REPLAY_EVICTION_BUDGET` in `src/testing/replay/runner.ts` for why a dedicated
47
+ * constant is used there instead.
48
+ */
49
+ export declare function evictionBudget(contextWindow: number, reserveTokens: number): number;
50
+ /**
51
+ * Adapter between a caller's tool registry and `announceToolsByName`, which
52
+ * operates on a minimal `DeferrableTool` shape that has no notion of a tool
53
+ * registry. Only `parameters` is ever replaced; every other field of the outbound
54
+ * tool (name, description, and on `AgentTool` specifically, `execute`, `label`,
55
+ * etc.) passes through unchanged via the object spread.
56
+ *
57
+ * A tool with no entry in `contractLookup` (a foreign/unclassified tool) is treated
58
+ * as `deferSchema: false` here — the safe default on this axis is to keep
59
+ * describing it fully, the mirror image of eviction's "no contract => don't evict"
60
+ * default: when unsure, don't withhold information the model needs.
61
+ */
62
+ export declare function projectToolSchemas<T extends {
63
+ name: string;
64
+ description: string;
65
+ parameters: unknown;
66
+ }>(tools: readonly T[], contractLookup: ContractLookup, loadedSchemaNames?: ReadonlySet<string>): T[];
67
+ /** Returns true for the built-in streamSimple function, including its context-pipeline wrapper. */
68
+ export declare function isDefaultStreamFunction(streamFunction: StreamFn): boolean;
69
+ export interface ContextPipelineOptions {
70
+ /** Resolves a tool's contract; shared by both eviction and schema projection. */
71
+ contractLookup: ContractLookup;
72
+ /** Names whose real schemas have been loaded by the model in this session. */
73
+ loadedSchemaNames?: ReadonlySet<string>;
74
+ /**
75
+ * Eviction budget as a thunk, not a plain number: `AgentSession`'s budget
76
+ * depends on `this.model` and `this.settingsManager`, both of which can change
77
+ * over the session's lifetime (model switch, settings edit), and is never
78
+ * cached. Evaluating it fresh on every request is what keeps eviction correct
79
+ * after either changes mid-session.
80
+ */
81
+ evictionBudget: () => number;
82
+ }
83
+ /**
84
+ * Installs the settled context pipeline (deferred-schema resolution → eviction)
85
+ * onto `agent`, chaining onto whatever `transformContext` / `streamFunction` the
86
+ * caller already installed rather than replacing it — the same pattern
87
+ * `AgentSession._installAgentNextTurnRefresh` uses for `prepareNextTurnWithContext`.
88
+ */
89
+ export declare function installContextPipeline(agent: Agent, options: ContextPipelineOptions): void;
90
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/context/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAE,KAAK,cAAc,EAAoB,MAAM,eAAe,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,EACtG,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,cAAc,EAAE,cAAc,EAC9B,iBAAiB,GAAE,WAAW,CAAC,MAAM,CAAa,GAChD,CAAC,EAAE,CAcL;AAID,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,CAEzE;AAED,MAAM,WAAW,sBAAsB;IACtC,iFAAiF;IACjF,cAAc,EAAE,cAAc,CAAC;IAC/B,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,GAAG,IAAI,CA0B1F","sourcesContent":["/**\n * Context pipeline wiring — shared by `AgentSession` (production) and the offline\n * replay harness (`src/testing/replay/runner.ts`), so there is exactly one\n * implementation of \"how deferred-schema resolution and eviction attach to an\n * `Agent`\" rather than two independently maintained copies.\n *\n * Implements the ordering settled in `docs/architecture/contracts.md` § 2:\n * deferred-schema resolution → tool-result eviction → compaction. Compaction runs\n * reactively from its own existing seam (`_checkCompaction` in `agent-session.ts`)\n * and is untouched here; this module only adds the two stages that run *ahead of*\n * every LLM request, so that reactive check is reached less often because the\n * request it is reacting to is smaller.\n *\n * The two stages land in different seams because they operate on different halves\n * of the outbound request. Eviction is a pure function of `AgentMessage[]`, which is\n * exactly what `transformContext` sees, immediately before `convertToLlm` — so it is\n * wired there. Deferred-schema resolution operates on the *tool list*, not messages;\n * `transformContext`'s signature has no tools parameter, and `AgentContext.tools` is\n * a snapshot taken once per prompt rather than rebuilt per request. The seam that\n * actually sees the assembled outbound tool list on every request is\n * `streamFunction` — it receives the full `Context`, tools included, immediately\n * before the provider call — so the projection is applied there instead. Because the\n * two stages act on disjoint fields of the request with no data dependency between\n * them, this does not change the observable pipeline order.\n */\n\nimport { streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport type { Agent, StreamFn } from \"apex-code-agent-core\";\nimport { resolveToolContext } from \"../tools/contract.ts\";\nimport { announceToolsByName, type DeferrableTool } from \"./deferred-schemas.ts\";\nimport { type ContractLookup, evictToolResults } from \"./eviction.ts\";\n\n/**\n * Eviction-budget formula shared by every caller of `installContextPipeline`.\n * Compaction fires once total context tokens exceed `contextWindow - reserveTokens`\n * (`shouldCompact` in `core/compaction/compaction.ts`). Budgeting eviction — counted\n * purely against tool-result tokens, per `evictToolResults`'s own contract — at half\n * of that headroom leaves the other half free for system prompt and conversational\n * growth, so eviction (cheap, structure-preserving) gets a chance to shrink the\n * transcript before the expensive compaction stage is ever reached, matching\n * contracts.md § 2's \"why this order\" (eviction before compaction, so compaction is\n * reached later and less often).\n *\n * `Math.max(0, ...)` mirrors `shouldCompact`'s own behavior when `contextWindow` is\n * unknown (0): evict aggressively rather than not at all, rather than inventing a\n * different, unproven fallback.\n *\n * Production (`AgentSession`) calls this with the real model's `contextWindow` and\n * the user's configured `reserveTokens`. The offline replay harness deliberately\n * does *not* call this with the fixture model's `contextWindow` — see\n * `REPLAY_EVICTION_BUDGET` in `src/testing/replay/runner.ts` for why a dedicated\n * constant is used there instead.\n */\nexport function evictionBudget(contextWindow: number, reserveTokens: number): number {\n\treturn Math.max(0, Math.floor((contextWindow - reserveTokens) / 2));\n}\n\n/**\n * Adapter between a caller's tool registry and `announceToolsByName`, which\n * operates on a minimal `DeferrableTool` shape that has no notion of a tool\n * registry. Only `parameters` is ever replaced; every other field of the outbound\n * tool (name, description, and on `AgentTool` specifically, `execute`, `label`,\n * etc.) passes through unchanged via the object spread.\n *\n * A tool with no entry in `contractLookup` (a foreign/unclassified tool) is treated\n * as `deferSchema: false` here — the safe default on this axis is to keep\n * describing it fully, the mirror image of eviction's \"no contract => don't evict\"\n * default: when unsure, don't withhold information the model needs.\n */\nexport function projectToolSchemas<T extends { name: string; description: string; parameters: unknown }>(\n\ttools: readonly T[],\n\tcontractLookup: ContractLookup,\n\tloadedSchemaNames: ReadonlySet<string> = new Set(),\n): T[] {\n\tconst deferrable: DeferrableTool[] = tools.map((tool) => ({\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters,\n\t\tcontract: {\n\t\t\tcontext: {\n\t\t\t\tdeferSchema:\n\t\t\t\t\t!loadedSchemaNames.has(tool.name) && resolveToolContext(contractLookup, tool.name).context.deferSchema,\n\t\t\t},\n\t\t},\n\t}));\n\tconst announced = announceToolsByName(deferrable);\n\treturn tools.map((tool, index) => ({ ...tool, parameters: announced[index].parameters }));\n}\n\nconst defaultStreamFunctions = new WeakSet<StreamFn>();\n\n/** Returns true for the built-in streamSimple function, including its context-pipeline wrapper. */\nexport function isDefaultStreamFunction(streamFunction: StreamFn): boolean {\n\treturn streamFunction === streamSimple || defaultStreamFunctions.has(streamFunction);\n}\n\nexport interface ContextPipelineOptions {\n\t/** Resolves a tool's contract; shared by both eviction and schema projection. */\n\tcontractLookup: ContractLookup;\n\t/** Names whose real schemas have been loaded by the model in this session. */\n\tloadedSchemaNames?: ReadonlySet<string>;\n\t/**\n\t * Eviction budget as a thunk, not a plain number: `AgentSession`'s budget\n\t * depends on `this.model` and `this.settingsManager`, both of which can change\n\t * over the session's lifetime (model switch, settings edit), and is never\n\t * cached. Evaluating it fresh on every request is what keeps eviction correct\n\t * after either changes mid-session.\n\t */\n\tevictionBudget: () => number;\n}\n\n/**\n * Installs the settled context pipeline (deferred-schema resolution → eviction)\n * onto `agent`, chaining onto whatever `transformContext` / `streamFunction` the\n * caller already installed rather than replacing it — the same pattern\n * `AgentSession._installAgentNextTurnRefresh` uses for `prepareNextTurnWithContext`.\n */\nexport function installContextPipeline(agent: Agent, options: ContextPipelineOptions): void {\n\tconst { contractLookup, evictionBudget: getBudget, loadedSchemaNames = new Set<string>() } = options;\n\n\tconst previousTransformContext = agent.transformContext;\n\tagent.transformContext = async (messages, signal) => {\n\t\tconst afterPrevious = previousTransformContext ? await previousTransformContext(messages, signal) : messages;\n\t\treturn evictToolResults(afterPrevious, contractLookup, getBudget());\n\t};\n\n\tconst previousStreamFunction = agent.streamFunction;\n\tconst wrappedStreamFunction = (\n\t\tmodel: Parameters<typeof previousStreamFunction>[0],\n\t\tcontext: Parameters<typeof previousStreamFunction>[1],\n\t\tstreamOptions: Parameters<typeof previousStreamFunction>[2],\n\t) => {\n\t\tif (!context.tools || context.tools.length === 0) {\n\t\t\treturn previousStreamFunction(model, context, streamOptions);\n\t\t}\n\t\treturn previousStreamFunction(\n\t\t\tmodel,\n\t\t\t{ ...context, tools: projectToolSchemas(context.tools, contractLookup, loadedSchemaNames) },\n\t\t\tstreamOptions,\n\t\t);\n\t};\n\tif (isDefaultStreamFunction(previousStreamFunction)) defaultStreamFunctions.add(wrappedStreamFunction);\n\tagent.streamFunction = wrappedStreamFunction;\n}\n"]}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Context pipeline wiring — shared by `AgentSession` (production) and the offline
3
+ * replay harness (`src/testing/replay/runner.ts`), so there is exactly one
4
+ * implementation of "how deferred-schema resolution and eviction attach to an
5
+ * `Agent`" rather than two independently maintained copies.
6
+ *
7
+ * Implements the ordering settled in `docs/architecture/contracts.md` § 2:
8
+ * deferred-schema resolution → tool-result eviction → compaction. Compaction runs
9
+ * reactively from its own existing seam (`_checkCompaction` in `agent-session.ts`)
10
+ * and is untouched here; this module only adds the two stages that run *ahead of*
11
+ * every LLM request, so that reactive check is reached less often because the
12
+ * request it is reacting to is smaller.
13
+ *
14
+ * The two stages land in different seams because they operate on different halves
15
+ * of the outbound request. Eviction is a pure function of `AgentMessage[]`, which is
16
+ * exactly what `transformContext` sees, immediately before `convertToLlm` — so it is
17
+ * wired there. Deferred-schema resolution operates on the *tool list*, not messages;
18
+ * `transformContext`'s signature has no tools parameter, and `AgentContext.tools` is
19
+ * a snapshot taken once per prompt rather than rebuilt per request. The seam that
20
+ * actually sees the assembled outbound tool list on every request is
21
+ * `streamFunction` — it receives the full `Context`, tools included, immediately
22
+ * before the provider call — so the projection is applied there instead. Because the
23
+ * two stages act on disjoint fields of the request with no data dependency between
24
+ * them, this does not change the observable pipeline order.
25
+ */
26
+ import { streamSimple } from "@earendil-works/pi-ai/compat";
27
+ import { resolveToolContext } from "../tools/contract.js";
28
+ import { announceToolsByName } from "./deferred-schemas.js";
29
+ import { evictToolResults } from "./eviction.js";
30
+ /**
31
+ * Eviction-budget formula shared by every caller of `installContextPipeline`.
32
+ * Compaction fires once total context tokens exceed `contextWindow - reserveTokens`
33
+ * (`shouldCompact` in `core/compaction/compaction.ts`). Budgeting eviction — counted
34
+ * purely against tool-result tokens, per `evictToolResults`'s own contract — at half
35
+ * of that headroom leaves the other half free for system prompt and conversational
36
+ * growth, so eviction (cheap, structure-preserving) gets a chance to shrink the
37
+ * transcript before the expensive compaction stage is ever reached, matching
38
+ * contracts.md § 2's "why this order" (eviction before compaction, so compaction is
39
+ * reached later and less often).
40
+ *
41
+ * `Math.max(0, ...)` mirrors `shouldCompact`'s own behavior when `contextWindow` is
42
+ * unknown (0): evict aggressively rather than not at all, rather than inventing a
43
+ * different, unproven fallback.
44
+ *
45
+ * Production (`AgentSession`) calls this with the real model's `contextWindow` and
46
+ * the user's configured `reserveTokens`. The offline replay harness deliberately
47
+ * does *not* call this with the fixture model's `contextWindow` — see
48
+ * `REPLAY_EVICTION_BUDGET` in `src/testing/replay/runner.ts` for why a dedicated
49
+ * constant is used there instead.
50
+ */
51
+ export function evictionBudget(contextWindow, reserveTokens) {
52
+ return Math.max(0, Math.floor((contextWindow - reserveTokens) / 2));
53
+ }
54
+ /**
55
+ * Adapter between a caller's tool registry and `announceToolsByName`, which
56
+ * operates on a minimal `DeferrableTool` shape that has no notion of a tool
57
+ * registry. Only `parameters` is ever replaced; every other field of the outbound
58
+ * tool (name, description, and on `AgentTool` specifically, `execute`, `label`,
59
+ * etc.) passes through unchanged via the object spread.
60
+ *
61
+ * A tool with no entry in `contractLookup` (a foreign/unclassified tool) is treated
62
+ * as `deferSchema: false` here — the safe default on this axis is to keep
63
+ * describing it fully, the mirror image of eviction's "no contract => don't evict"
64
+ * default: when unsure, don't withhold information the model needs.
65
+ */
66
+ export function projectToolSchemas(tools, contractLookup, loadedSchemaNames = new Set()) {
67
+ const deferrable = tools.map((tool) => ({
68
+ name: tool.name,
69
+ description: tool.description,
70
+ parameters: tool.parameters,
71
+ contract: {
72
+ context: {
73
+ deferSchema: !loadedSchemaNames.has(tool.name) && resolveToolContext(contractLookup, tool.name).context.deferSchema,
74
+ },
75
+ },
76
+ }));
77
+ const announced = announceToolsByName(deferrable);
78
+ return tools.map((tool, index) => ({ ...tool, parameters: announced[index].parameters }));
79
+ }
80
+ const defaultStreamFunctions = new WeakSet();
81
+ /** Returns true for the built-in streamSimple function, including its context-pipeline wrapper. */
82
+ export function isDefaultStreamFunction(streamFunction) {
83
+ return streamFunction === streamSimple || defaultStreamFunctions.has(streamFunction);
84
+ }
85
+ /**
86
+ * Installs the settled context pipeline (deferred-schema resolution → eviction)
87
+ * onto `agent`, chaining onto whatever `transformContext` / `streamFunction` the
88
+ * caller already installed rather than replacing it — the same pattern
89
+ * `AgentSession._installAgentNextTurnRefresh` uses for `prepareNextTurnWithContext`.
90
+ */
91
+ export function installContextPipeline(agent, options) {
92
+ const { contractLookup, evictionBudget: getBudget, loadedSchemaNames = new Set() } = options;
93
+ const previousTransformContext = agent.transformContext;
94
+ agent.transformContext = async (messages, signal) => {
95
+ const afterPrevious = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
96
+ return evictToolResults(afterPrevious, contractLookup, getBudget());
97
+ };
98
+ const previousStreamFunction = agent.streamFunction;
99
+ const wrappedStreamFunction = (model, context, streamOptions) => {
100
+ if (!context.tools || context.tools.length === 0) {
101
+ return previousStreamFunction(model, context, streamOptions);
102
+ }
103
+ return previousStreamFunction(model, { ...context, tools: projectToolSchemas(context.tools, contractLookup, loadedSchemaNames) }, streamOptions);
104
+ };
105
+ if (isDefaultStreamFunction(previousStreamFunction))
106
+ defaultStreamFunctions.add(wrappedStreamFunction);
107
+ agent.streamFunction = wrappedStreamFunction;
108
+ }
109
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/core/context/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Context pipeline wiring — shared by `AgentSession` (production) and the offline\n * replay harness (`src/testing/replay/runner.ts`), so there is exactly one\n * implementation of \"how deferred-schema resolution and eviction attach to an\n * `Agent`\" rather than two independently maintained copies.\n *\n * Implements the ordering settled in `docs/architecture/contracts.md` § 2:\n * deferred-schema resolution → tool-result eviction → compaction. Compaction runs\n * reactively from its own existing seam (`_checkCompaction` in `agent-session.ts`)\n * and is untouched here; this module only adds the two stages that run *ahead of*\n * every LLM request, so that reactive check is reached less often because the\n * request it is reacting to is smaller.\n *\n * The two stages land in different seams because they operate on different halves\n * of the outbound request. Eviction is a pure function of `AgentMessage[]`, which is\n * exactly what `transformContext` sees, immediately before `convertToLlm` — so it is\n * wired there. Deferred-schema resolution operates on the *tool list*, not messages;\n * `transformContext`'s signature has no tools parameter, and `AgentContext.tools` is\n * a snapshot taken once per prompt rather than rebuilt per request. The seam that\n * actually sees the assembled outbound tool list on every request is\n * `streamFunction` — it receives the full `Context`, tools included, immediately\n * before the provider call — so the projection is applied there instead. Because the\n * two stages act on disjoint fields of the request with no data dependency between\n * them, this does not change the observable pipeline order.\n */\n\nimport { streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport type { Agent, StreamFn } from \"apex-code-agent-core\";\nimport { resolveToolContext } from \"../tools/contract.ts\";\nimport { announceToolsByName, type DeferrableTool } from \"./deferred-schemas.ts\";\nimport { type ContractLookup, evictToolResults } from \"./eviction.ts\";\n\n/**\n * Eviction-budget formula shared by every caller of `installContextPipeline`.\n * Compaction fires once total context tokens exceed `contextWindow - reserveTokens`\n * (`shouldCompact` in `core/compaction/compaction.ts`). Budgeting eviction — counted\n * purely against tool-result tokens, per `evictToolResults`'s own contract — at half\n * of that headroom leaves the other half free for system prompt and conversational\n * growth, so eviction (cheap, structure-preserving) gets a chance to shrink the\n * transcript before the expensive compaction stage is ever reached, matching\n * contracts.md § 2's \"why this order\" (eviction before compaction, so compaction is\n * reached later and less often).\n *\n * `Math.max(0, ...)` mirrors `shouldCompact`'s own behavior when `contextWindow` is\n * unknown (0): evict aggressively rather than not at all, rather than inventing a\n * different, unproven fallback.\n *\n * Production (`AgentSession`) calls this with the real model's `contextWindow` and\n * the user's configured `reserveTokens`. The offline replay harness deliberately\n * does *not* call this with the fixture model's `contextWindow` — see\n * `REPLAY_EVICTION_BUDGET` in `src/testing/replay/runner.ts` for why a dedicated\n * constant is used there instead.\n */\nexport function evictionBudget(contextWindow: number, reserveTokens: number): number {\n\treturn Math.max(0, Math.floor((contextWindow - reserveTokens) / 2));\n}\n\n/**\n * Adapter between a caller's tool registry and `announceToolsByName`, which\n * operates on a minimal `DeferrableTool` shape that has no notion of a tool\n * registry. Only `parameters` is ever replaced; every other field of the outbound\n * tool (name, description, and on `AgentTool` specifically, `execute`, `label`,\n * etc.) passes through unchanged via the object spread.\n *\n * A tool with no entry in `contractLookup` (a foreign/unclassified tool) is treated\n * as `deferSchema: false` here — the safe default on this axis is to keep\n * describing it fully, the mirror image of eviction's \"no contract => don't evict\"\n * default: when unsure, don't withhold information the model needs.\n */\nexport function projectToolSchemas<T extends { name: string; description: string; parameters: unknown }>(\n\ttools: readonly T[],\n\tcontractLookup: ContractLookup,\n\tloadedSchemaNames: ReadonlySet<string> = new Set(),\n): T[] {\n\tconst deferrable: DeferrableTool[] = tools.map((tool) => ({\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters,\n\t\tcontract: {\n\t\t\tcontext: {\n\t\t\t\tdeferSchema:\n\t\t\t\t\t!loadedSchemaNames.has(tool.name) && resolveToolContext(contractLookup, tool.name).context.deferSchema,\n\t\t\t},\n\t\t},\n\t}));\n\tconst announced = announceToolsByName(deferrable);\n\treturn tools.map((tool, index) => ({ ...tool, parameters: announced[index].parameters }));\n}\n\nconst defaultStreamFunctions = new WeakSet<StreamFn>();\n\n/** Returns true for the built-in streamSimple function, including its context-pipeline wrapper. */\nexport function isDefaultStreamFunction(streamFunction: StreamFn): boolean {\n\treturn streamFunction === streamSimple || defaultStreamFunctions.has(streamFunction);\n}\n\nexport interface ContextPipelineOptions {\n\t/** Resolves a tool's contract; shared by both eviction and schema projection. */\n\tcontractLookup: ContractLookup;\n\t/** Names whose real schemas have been loaded by the model in this session. */\n\tloadedSchemaNames?: ReadonlySet<string>;\n\t/**\n\t * Eviction budget as a thunk, not a plain number: `AgentSession`'s budget\n\t * depends on `this.model` and `this.settingsManager`, both of which can change\n\t * over the session's lifetime (model switch, settings edit), and is never\n\t * cached. Evaluating it fresh on every request is what keeps eviction correct\n\t * after either changes mid-session.\n\t */\n\tevictionBudget: () => number;\n}\n\n/**\n * Installs the settled context pipeline (deferred-schema resolution → eviction)\n * onto `agent`, chaining onto whatever `transformContext` / `streamFunction` the\n * caller already installed rather than replacing it — the same pattern\n * `AgentSession._installAgentNextTurnRefresh` uses for `prepareNextTurnWithContext`.\n */\nexport function installContextPipeline(agent: Agent, options: ContextPipelineOptions): void {\n\tconst { contractLookup, evictionBudget: getBudget, loadedSchemaNames = new Set<string>() } = options;\n\n\tconst previousTransformContext = agent.transformContext;\n\tagent.transformContext = async (messages, signal) => {\n\t\tconst afterPrevious = previousTransformContext ? await previousTransformContext(messages, signal) : messages;\n\t\treturn evictToolResults(afterPrevious, contractLookup, getBudget());\n\t};\n\n\tconst previousStreamFunction = agent.streamFunction;\n\tconst wrappedStreamFunction = (\n\t\tmodel: Parameters<typeof previousStreamFunction>[0],\n\t\tcontext: Parameters<typeof previousStreamFunction>[1],\n\t\tstreamOptions: Parameters<typeof previousStreamFunction>[2],\n\t) => {\n\t\tif (!context.tools || context.tools.length === 0) {\n\t\t\treturn previousStreamFunction(model, context, streamOptions);\n\t\t}\n\t\treturn previousStreamFunction(\n\t\t\tmodel,\n\t\t\t{ ...context, tools: projectToolSchemas(context.tools, contractLookup, loadedSchemaNames) },\n\t\t\tstreamOptions,\n\t\t);\n\t};\n\tif (isDefaultStreamFunction(previousStreamFunction)) defaultStreamFunctions.add(wrappedStreamFunction);\n\tagent.streamFunction = wrappedStreamFunction;\n}\n"]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pure helpers for bounded, pre-completion credential failover around
3
+ * ModelRuntime.streamSimple(). Classification and stream buffering/replay only;
4
+ * pool selection state lives in CredentialPool, request orchestration in ModelRuntime.
5
+ */
6
+ import type { AssistantMessage, AssistantMessageEvent } from "@earendil-works/pi-ai";
7
+ import type { CredentialFailureKind } from "./credential-pool.ts";
8
+ /**
9
+ * Classifies a failed AssistantMessage into a rotation-eligible CredentialFailureKind,
10
+ * or undefined when the failure should not trigger credential rotation (success,
11
+ * abort, or a non-retryable provider error such as quota exhaustion).
12
+ */
13
+ export declare function classifyCredentialFailure(message: AssistantMessage): CredentialFailureKind | undefined;
14
+ /** An AsyncIterable<AssistantMessageEvent> paired with its eventual AssistantMessage, matching the shape `lazyStream` forwards. */
15
+ export interface ResultStream extends AsyncIterable<AssistantMessageEvent> {
16
+ result(): Promise<AssistantMessage>;
17
+ }
18
+ export interface DrainedAttempt {
19
+ events: readonly AssistantMessageEvent[];
20
+ message: AssistantMessage;
21
+ }
22
+ /**
23
+ * Fully consumes one attempt's stream before any event reaches the caller. This is
24
+ * what makes a failed attempt invisible to the caller: nothing is forwarded until the
25
+ * attempt's outcome (and therefore its retry eligibility) is known.
26
+ */
27
+ export declare function drainAttempt(stream: ResultStream): Promise<DrainedAttempt>;
28
+ /** Replays a fully-drained attempt's events as a fresh stream terminating in its known message. */
29
+ export declare function replayAttempt({ events, message }: DrainedAttempt): ResultStream;
30
+ //# sourceMappingURL=credential-failover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-failover.d.ts","sourceRoot":"","sources":["../../src/core/credential-failover.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAErF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMlE;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,qBAAqB,GAAG,SAAS,CAOtG;AAED,mIAAmI;AACnI,MAAM,WAAW,YAAa,SAAQ,aAAa,CAAC,qBAAqB,CAAC;IACzE,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACzC,OAAO,EAAE,gBAAgB,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAIhF;AAED,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,cAAc,GAAG,YAAY,CAO/E","sourcesContent":["/**\n * Pure helpers for bounded, pre-completion credential failover around\n * ModelRuntime.streamSimple(). Classification and stream buffering/replay only;\n * pool selection state lives in CredentialPool, request orchestration in ModelRuntime.\n */\n\nimport type { AssistantMessage, AssistantMessageEvent } from \"@earendil-works/pi-ai\";\nimport { isRetryableAssistantError } from \"@earendil-works/pi-ai\";\nimport type { CredentialFailureKind } from \"./credential-pool.ts\";\n\nconst RATE_LIMIT_PATTERN = /\\b429\\b|rate.?limit|too many requests/i;\nconst BLOCKED_CREDENTIAL_PATTERN =\n\t/\\b401\\b|\\b403\\b|unauthorized|forbidden|invalid.?api.?key|permission denied|expired/i;\n\n/**\n * Classifies a failed AssistantMessage into a rotation-eligible CredentialFailureKind,\n * or undefined when the failure should not trigger credential rotation (success,\n * abort, or a non-retryable provider error such as quota exhaustion).\n */\nexport function classifyCredentialFailure(message: AssistantMessage): CredentialFailureKind | undefined {\n\tif (message.stopReason !== \"error\" || !message.errorMessage) return undefined;\n\tconst text = message.errorMessage;\n\tif (RATE_LIMIT_PATTERN.test(text)) return \"rate_limited\";\n\tif (BLOCKED_CREDENTIAL_PATTERN.test(text)) return \"blocked\";\n\tif (isRetryableAssistantError(message)) return \"temporary\";\n\treturn undefined;\n}\n\n/** An AsyncIterable<AssistantMessageEvent> paired with its eventual AssistantMessage, matching the shape `lazyStream` forwards. */\nexport interface ResultStream extends AsyncIterable<AssistantMessageEvent> {\n\tresult(): Promise<AssistantMessage>;\n}\n\nexport interface DrainedAttempt {\n\tevents: readonly AssistantMessageEvent[];\n\tmessage: AssistantMessage;\n}\n\n/**\n * Fully consumes one attempt's stream before any event reaches the caller. This is\n * what makes a failed attempt invisible to the caller: nothing is forwarded until the\n * attempt's outcome (and therefore its retry eligibility) is known.\n */\nexport async function drainAttempt(stream: ResultStream): Promise<DrainedAttempt> {\n\tconst events: AssistantMessageEvent[] = [];\n\tfor await (const event of stream) events.push(event);\n\treturn { events, message: await stream.result() };\n}\n\n/** Replays a fully-drained attempt's events as a fresh stream terminating in its known message. */\nexport function replayAttempt({ events, message }: DrainedAttempt): ResultStream {\n\treturn {\n\t\tasync *[Symbol.asyncIterator]() {\n\t\t\tyield* events;\n\t\t},\n\t\tresult: () => Promise.resolve(message),\n\t};\n}\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Pure helpers for bounded, pre-completion credential failover around
3
+ * ModelRuntime.streamSimple(). Classification and stream buffering/replay only;
4
+ * pool selection state lives in CredentialPool, request orchestration in ModelRuntime.
5
+ */
6
+ import { isRetryableAssistantError } from "@earendil-works/pi-ai";
7
+ const RATE_LIMIT_PATTERN = /\b429\b|rate.?limit|too many requests/i;
8
+ const BLOCKED_CREDENTIAL_PATTERN = /\b401\b|\b403\b|unauthorized|forbidden|invalid.?api.?key|permission denied|expired/i;
9
+ /**
10
+ * Classifies a failed AssistantMessage into a rotation-eligible CredentialFailureKind,
11
+ * or undefined when the failure should not trigger credential rotation (success,
12
+ * abort, or a non-retryable provider error such as quota exhaustion).
13
+ */
14
+ export function classifyCredentialFailure(message) {
15
+ if (message.stopReason !== "error" || !message.errorMessage)
16
+ return undefined;
17
+ const text = message.errorMessage;
18
+ if (RATE_LIMIT_PATTERN.test(text))
19
+ return "rate_limited";
20
+ if (BLOCKED_CREDENTIAL_PATTERN.test(text))
21
+ return "blocked";
22
+ if (isRetryableAssistantError(message))
23
+ return "temporary";
24
+ return undefined;
25
+ }
26
+ /**
27
+ * Fully consumes one attempt's stream before any event reaches the caller. This is
28
+ * what makes a failed attempt invisible to the caller: nothing is forwarded until the
29
+ * attempt's outcome (and therefore its retry eligibility) is known.
30
+ */
31
+ export async function drainAttempt(stream) {
32
+ const events = [];
33
+ for await (const event of stream)
34
+ events.push(event);
35
+ return { events, message: await stream.result() };
36
+ }
37
+ /** Replays a fully-drained attempt's events as a fresh stream terminating in its known message. */
38
+ export function replayAttempt({ events, message }) {
39
+ return {
40
+ async *[Symbol.asyncIterator]() {
41
+ yield* events;
42
+ },
43
+ result: () => Promise.resolve(message),
44
+ };
45
+ }
46
+ //# sourceMappingURL=credential-failover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-failover.js","sourceRoot":"","sources":["../../src/core/credential-failover.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,MAAM,kBAAkB,GAAG,wCAAwC,CAAC;AACpE,MAAM,0BAA0B,GAC/B,qFAAqF,CAAC;AAEvF;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAyB,EAAqC;IACvG,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IAClC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,cAAc,CAAC;IACzD,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,yBAAyB,CAAC,OAAO,CAAC;QAAE,OAAO,WAAW,CAAC;IAC3D,OAAO,SAAS,CAAC;AAAA,CACjB;AAYD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAoB,EAA2B;IACjF,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM;QAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;AAAA,CAClD;AAED,mGAAmG;AACnG,MAAM,UAAU,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,EAAkB,EAAgB;IAChF,OAAO;QACN,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG;YAC/B,KAAK,CAAC,CAAC,MAAM,CAAC;QAAA,CACd;QACD,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;KACtC,CAAC;AAAA,CACF","sourcesContent":["/**\n * Pure helpers for bounded, pre-completion credential failover around\n * ModelRuntime.streamSimple(). Classification and stream buffering/replay only;\n * pool selection state lives in CredentialPool, request orchestration in ModelRuntime.\n */\n\nimport type { AssistantMessage, AssistantMessageEvent } from \"@earendil-works/pi-ai\";\nimport { isRetryableAssistantError } from \"@earendil-works/pi-ai\";\nimport type { CredentialFailureKind } from \"./credential-pool.ts\";\n\nconst RATE_LIMIT_PATTERN = /\\b429\\b|rate.?limit|too many requests/i;\nconst BLOCKED_CREDENTIAL_PATTERN =\n\t/\\b401\\b|\\b403\\b|unauthorized|forbidden|invalid.?api.?key|permission denied|expired/i;\n\n/**\n * Classifies a failed AssistantMessage into a rotation-eligible CredentialFailureKind,\n * or undefined when the failure should not trigger credential rotation (success,\n * abort, or a non-retryable provider error such as quota exhaustion).\n */\nexport function classifyCredentialFailure(message: AssistantMessage): CredentialFailureKind | undefined {\n\tif (message.stopReason !== \"error\" || !message.errorMessage) return undefined;\n\tconst text = message.errorMessage;\n\tif (RATE_LIMIT_PATTERN.test(text)) return \"rate_limited\";\n\tif (BLOCKED_CREDENTIAL_PATTERN.test(text)) return \"blocked\";\n\tif (isRetryableAssistantError(message)) return \"temporary\";\n\treturn undefined;\n}\n\n/** An AsyncIterable<AssistantMessageEvent> paired with its eventual AssistantMessage, matching the shape `lazyStream` forwards. */\nexport interface ResultStream extends AsyncIterable<AssistantMessageEvent> {\n\tresult(): Promise<AssistantMessage>;\n}\n\nexport interface DrainedAttempt {\n\tevents: readonly AssistantMessageEvent[];\n\tmessage: AssistantMessage;\n}\n\n/**\n * Fully consumes one attempt's stream before any event reaches the caller. This is\n * what makes a failed attempt invisible to the caller: nothing is forwarded until the\n * attempt's outcome (and therefore its retry eligibility) is known.\n */\nexport async function drainAttempt(stream: ResultStream): Promise<DrainedAttempt> {\n\tconst events: AssistantMessageEvent[] = [];\n\tfor await (const event of stream) events.push(event);\n\treturn { events, message: await stream.result() };\n}\n\n/** Replays a fully-drained attempt's events as a fresh stream terminating in its known message. */\nexport function replayAttempt({ events, message }: DrainedAttempt): ResultStream {\n\treturn {\n\t\tasync *[Symbol.asyncIterator]() {\n\t\t\tyield* events;\n\t\t},\n\t\tresult: () => Promise.resolve(message),\n\t};\n}\n"]}
@@ -0,0 +1,60 @@
1
+ /** Non-secret credential selection state for a single process. */
2
+ export type CredentialIdentity = string & {
3
+ readonly __brand: "CredentialIdentity";
4
+ };
5
+ export declare function createCredentialIdentity(value: string): CredentialIdentity;
6
+ export interface CredentialPoolEntry {
7
+ identity: CredentialIdentity;
8
+ providerId: string;
9
+ }
10
+ export type CredentialFailureKind = "rate_limited" | "blocked" | "temporary";
11
+ export interface CredentialPoolOptions {
12
+ entries: readonly CredentialPoolEntry[];
13
+ now?: () => number;
14
+ cooldownMs?: number;
15
+ }
16
+ export interface CredentialPoolSelection {
17
+ identity: CredentialIdentity;
18
+ providerId: string;
19
+ }
20
+ export interface CredentialPoolSnapshotEntry {
21
+ identity: CredentialIdentity;
22
+ providerId: string;
23
+ blockedUntil: number | undefined;
24
+ }
25
+ export interface CredentialRefreshLease {
26
+ identity: CredentialIdentity;
27
+ owner: string;
28
+ expiresAt: number;
29
+ }
30
+ export declare class CredentialPool {
31
+ private readonly entries;
32
+ private readonly now;
33
+ private readonly cooldownMs;
34
+ private readonly blockedUntilByIdentity;
35
+ private readonly refreshLeaseByIdentity;
36
+ private nextIndex;
37
+ constructor({ entries, now, cooldownMs }: CredentialPoolOptions);
38
+ select({ providerId, attempted }: {
39
+ providerId: string;
40
+ attempted: ReadonlySet<CredentialIdentity>;
41
+ }): CredentialPoolSelection | undefined;
42
+ recordFailure({ identity, kind }: {
43
+ identity: CredentialIdentity;
44
+ kind: CredentialFailureKind;
45
+ }): void;
46
+ snapshot(): CredentialPoolSnapshotEntry[];
47
+ private activeLease;
48
+ /** Grant a refresh lease for an identity, unless another owner already holds an unexpired one. */
49
+ acquireRefreshLease({ identity, owner, durationMs }: {
50
+ identity: CredentialIdentity;
51
+ owner: string;
52
+ durationMs: number;
53
+ }): CredentialRefreshLease | undefined;
54
+ /** Release a held refresh lease. Returns false if the caller is not the current owner. */
55
+ releaseRefreshLease({ identity, owner }: {
56
+ identity: CredentialIdentity;
57
+ owner: string;
58
+ }): boolean;
59
+ }
60
+ //# sourceMappingURL=credential-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-pool.d.ts","sourceRoot":"","sources":["../../src/core/credential-pool.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAErF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAG1E;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyC;IAChF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyD;IAChG,OAAO,CAAC,SAAS,CAAK;IAEtB,YAAY,EAAE,OAAO,EAAE,GAAc,EAAE,UAAmB,EAAE,EAAE,qBAAqB,EAWlF;IAED,MAAM,CAAC,EACN,UAAU,EACV,SAAS,EACT,EAAE;QACF,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC;KAC3C,GAAG,uBAAuB,GAAG,SAAS,CAkBtC;IAED,aAAa,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAAE,QAAQ,EAAE,kBAAkB,CAAC;QAAC,IAAI,EAAE,qBAAqB,CAAA;KAAE,GAAG,IAAI,CAIrG;IAED,QAAQ,IAAI,2BAA2B,EAAE,CAMxC;IAED,OAAO,CAAC,WAAW;IAUnB,kGAAkG;IAClG,mBAAmB,CAAC,EACnB,QAAQ,EACR,KAAK,EACL,UAAU,EACV,EAAE;QACF,QAAQ,EAAE,kBAAkB,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACnB,GAAG,sBAAsB,GAAG,SAAS,CAMrC;IAED,0FAA0F;IAC1F,mBAAmB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QAAE,QAAQ,EAAE,kBAAkB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAKjG;CACD","sourcesContent":["/** Non-secret credential selection state for a single process. */\n\nexport type CredentialIdentity = string & { readonly __brand: \"CredentialIdentity\" };\n\nexport function createCredentialIdentity(value: string): CredentialIdentity {\n\tif (!value.trim()) throw new Error(\"Credential identity must not be empty\");\n\treturn value as CredentialIdentity;\n}\n\nexport interface CredentialPoolEntry {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n}\n\nexport type CredentialFailureKind = \"rate_limited\" | \"blocked\" | \"temporary\";\n\nexport interface CredentialPoolOptions {\n\tentries: readonly CredentialPoolEntry[];\n\tnow?: () => number;\n\tcooldownMs?: number;\n}\n\nexport interface CredentialPoolSelection {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n}\n\nexport interface CredentialPoolSnapshotEntry {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n\tblockedUntil: number | undefined;\n}\n\nexport interface CredentialRefreshLease {\n\tidentity: CredentialIdentity;\n\towner: string;\n\texpiresAt: number;\n}\n\nexport class CredentialPool {\n\tprivate readonly entries: readonly CredentialPoolEntry[];\n\tprivate readonly now: () => number;\n\tprivate readonly cooldownMs: number;\n\tprivate readonly blockedUntilByIdentity = new Map<CredentialIdentity, number>();\n\tprivate readonly refreshLeaseByIdentity = new Map<CredentialIdentity, CredentialRefreshLease>();\n\tprivate nextIndex = 0;\n\n\tconstructor({ entries, now = Date.now, cooldownMs = 60_000 }: CredentialPoolOptions) {\n\t\tconst seen = new Set<CredentialIdentity>();\n\t\tfor (const entry of entries) {\n\t\t\tif (seen.has(entry.identity)) {\n\t\t\t\tthrow new Error(`Duplicate credential identity \"${entry.identity}\"`);\n\t\t\t}\n\t\t\tseen.add(entry.identity);\n\t\t}\n\t\tthis.entries = entries;\n\t\tthis.now = now;\n\t\tthis.cooldownMs = cooldownMs;\n\t}\n\n\tselect({\n\t\tproviderId,\n\t\tattempted,\n\t}: {\n\t\tproviderId: string;\n\t\tattempted: ReadonlySet<CredentialIdentity>;\n\t}): CredentialPoolSelection | undefined {\n\t\tif (this.entries.length === 0) return undefined;\n\t\tconst now = this.now();\n\t\tfor (let offset = 0; offset < this.entries.length; offset++) {\n\t\t\tconst index = (this.nextIndex + offset) % this.entries.length;\n\t\t\tconst entry = this.entries[index];\n\t\t\tconst blockedUntil = this.blockedUntilByIdentity.get(entry.identity);\n\t\t\tif (\n\t\t\t\tentry.providerId !== providerId ||\n\t\t\t\tattempted.has(entry.identity) ||\n\t\t\t\t(blockedUntil !== undefined && blockedUntil > now)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.nextIndex = (index + 1) % this.entries.length;\n\t\t\treturn entry;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\trecordFailure({ identity, kind }: { identity: CredentialIdentity; kind: CredentialFailureKind }): void {\n\t\tif (kind === \"rate_limited\" || kind === \"blocked\") {\n\t\t\tthis.blockedUntilByIdentity.set(identity, this.now() + this.cooldownMs);\n\t\t}\n\t}\n\n\tsnapshot(): CredentialPoolSnapshotEntry[] {\n\t\treturn this.entries.map((entry) => ({\n\t\t\tidentity: entry.identity,\n\t\t\tproviderId: entry.providerId,\n\t\t\tblockedUntil: this.blockedUntilByIdentity.get(entry.identity),\n\t\t}));\n\t}\n\n\tprivate activeLease(identity: CredentialIdentity): CredentialRefreshLease | undefined {\n\t\tconst lease = this.refreshLeaseByIdentity.get(identity);\n\t\tif (!lease) return undefined;\n\t\tif (lease.expiresAt <= this.now()) {\n\t\t\tthis.refreshLeaseByIdentity.delete(identity);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn lease;\n\t}\n\n\t/** Grant a refresh lease for an identity, unless another owner already holds an unexpired one. */\n\tacquireRefreshLease({\n\t\tidentity,\n\t\towner,\n\t\tdurationMs,\n\t}: {\n\t\tidentity: CredentialIdentity;\n\t\towner: string;\n\t\tdurationMs: number;\n\t}): CredentialRefreshLease | undefined {\n\t\tconst existing = this.activeLease(identity);\n\t\tif (existing && existing.owner !== owner) return undefined;\n\t\tconst lease: CredentialRefreshLease = { identity, owner, expiresAt: this.now() + durationMs };\n\t\tthis.refreshLeaseByIdentity.set(identity, lease);\n\t\treturn lease;\n\t}\n\n\t/** Release a held refresh lease. Returns false if the caller is not the current owner. */\n\treleaseRefreshLease({ identity, owner }: { identity: CredentialIdentity; owner: string }): boolean {\n\t\tconst existing = this.activeLease(identity);\n\t\tif (!existing || existing.owner !== owner) return false;\n\t\tthis.refreshLeaseByIdentity.delete(identity);\n\t\treturn true;\n\t}\n}\n"]}
@@ -0,0 +1,84 @@
1
+ /** Non-secret credential selection state for a single process. */
2
+ export function createCredentialIdentity(value) {
3
+ if (!value.trim())
4
+ throw new Error("Credential identity must not be empty");
5
+ return value;
6
+ }
7
+ export class CredentialPool {
8
+ entries;
9
+ now;
10
+ cooldownMs;
11
+ blockedUntilByIdentity = new Map();
12
+ refreshLeaseByIdentity = new Map();
13
+ nextIndex = 0;
14
+ constructor({ entries, now = Date.now, cooldownMs = 60_000 }) {
15
+ const seen = new Set();
16
+ for (const entry of entries) {
17
+ if (seen.has(entry.identity)) {
18
+ throw new Error(`Duplicate credential identity "${entry.identity}"`);
19
+ }
20
+ seen.add(entry.identity);
21
+ }
22
+ this.entries = entries;
23
+ this.now = now;
24
+ this.cooldownMs = cooldownMs;
25
+ }
26
+ select({ providerId, attempted, }) {
27
+ if (this.entries.length === 0)
28
+ return undefined;
29
+ const now = this.now();
30
+ for (let offset = 0; offset < this.entries.length; offset++) {
31
+ const index = (this.nextIndex + offset) % this.entries.length;
32
+ const entry = this.entries[index];
33
+ const blockedUntil = this.blockedUntilByIdentity.get(entry.identity);
34
+ if (entry.providerId !== providerId ||
35
+ attempted.has(entry.identity) ||
36
+ (blockedUntil !== undefined && blockedUntil > now)) {
37
+ continue;
38
+ }
39
+ this.nextIndex = (index + 1) % this.entries.length;
40
+ return entry;
41
+ }
42
+ return undefined;
43
+ }
44
+ recordFailure({ identity, kind }) {
45
+ if (kind === "rate_limited" || kind === "blocked") {
46
+ this.blockedUntilByIdentity.set(identity, this.now() + this.cooldownMs);
47
+ }
48
+ }
49
+ snapshot() {
50
+ return this.entries.map((entry) => ({
51
+ identity: entry.identity,
52
+ providerId: entry.providerId,
53
+ blockedUntil: this.blockedUntilByIdentity.get(entry.identity),
54
+ }));
55
+ }
56
+ activeLease(identity) {
57
+ const lease = this.refreshLeaseByIdentity.get(identity);
58
+ if (!lease)
59
+ return undefined;
60
+ if (lease.expiresAt <= this.now()) {
61
+ this.refreshLeaseByIdentity.delete(identity);
62
+ return undefined;
63
+ }
64
+ return lease;
65
+ }
66
+ /** Grant a refresh lease for an identity, unless another owner already holds an unexpired one. */
67
+ acquireRefreshLease({ identity, owner, durationMs, }) {
68
+ const existing = this.activeLease(identity);
69
+ if (existing && existing.owner !== owner)
70
+ return undefined;
71
+ const lease = { identity, owner, expiresAt: this.now() + durationMs };
72
+ this.refreshLeaseByIdentity.set(identity, lease);
73
+ return lease;
74
+ }
75
+ /** Release a held refresh lease. Returns false if the caller is not the current owner. */
76
+ releaseRefreshLease({ identity, owner }) {
77
+ const existing = this.activeLease(identity);
78
+ if (!existing || existing.owner !== owner)
79
+ return false;
80
+ this.refreshLeaseByIdentity.delete(identity);
81
+ return true;
82
+ }
83
+ }
84
+ //# sourceMappingURL=credential-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-pool.js","sourceRoot":"","sources":["../../src/core/credential-pool.ts"],"names":[],"mappings":"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","sourcesContent":["/** Non-secret credential selection state for a single process. */\n\nexport type CredentialIdentity = string & { readonly __brand: \"CredentialIdentity\" };\n\nexport function createCredentialIdentity(value: string): CredentialIdentity {\n\tif (!value.trim()) throw new Error(\"Credential identity must not be empty\");\n\treturn value as CredentialIdentity;\n}\n\nexport interface CredentialPoolEntry {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n}\n\nexport type CredentialFailureKind = \"rate_limited\" | \"blocked\" | \"temporary\";\n\nexport interface CredentialPoolOptions {\n\tentries: readonly CredentialPoolEntry[];\n\tnow?: () => number;\n\tcooldownMs?: number;\n}\n\nexport interface CredentialPoolSelection {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n}\n\nexport interface CredentialPoolSnapshotEntry {\n\tidentity: CredentialIdentity;\n\tproviderId: string;\n\tblockedUntil: number | undefined;\n}\n\nexport interface CredentialRefreshLease {\n\tidentity: CredentialIdentity;\n\towner: string;\n\texpiresAt: number;\n}\n\nexport class CredentialPool {\n\tprivate readonly entries: readonly CredentialPoolEntry[];\n\tprivate readonly now: () => number;\n\tprivate readonly cooldownMs: number;\n\tprivate readonly blockedUntilByIdentity = new Map<CredentialIdentity, number>();\n\tprivate readonly refreshLeaseByIdentity = new Map<CredentialIdentity, CredentialRefreshLease>();\n\tprivate nextIndex = 0;\n\n\tconstructor({ entries, now = Date.now, cooldownMs = 60_000 }: CredentialPoolOptions) {\n\t\tconst seen = new Set<CredentialIdentity>();\n\t\tfor (const entry of entries) {\n\t\t\tif (seen.has(entry.identity)) {\n\t\t\t\tthrow new Error(`Duplicate credential identity \"${entry.identity}\"`);\n\t\t\t}\n\t\t\tseen.add(entry.identity);\n\t\t}\n\t\tthis.entries = entries;\n\t\tthis.now = now;\n\t\tthis.cooldownMs = cooldownMs;\n\t}\n\n\tselect({\n\t\tproviderId,\n\t\tattempted,\n\t}: {\n\t\tproviderId: string;\n\t\tattempted: ReadonlySet<CredentialIdentity>;\n\t}): CredentialPoolSelection | undefined {\n\t\tif (this.entries.length === 0) return undefined;\n\t\tconst now = this.now();\n\t\tfor (let offset = 0; offset < this.entries.length; offset++) {\n\t\t\tconst index = (this.nextIndex + offset) % this.entries.length;\n\t\t\tconst entry = this.entries[index];\n\t\t\tconst blockedUntil = this.blockedUntilByIdentity.get(entry.identity);\n\t\t\tif (\n\t\t\t\tentry.providerId !== providerId ||\n\t\t\t\tattempted.has(entry.identity) ||\n\t\t\t\t(blockedUntil !== undefined && blockedUntil > now)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.nextIndex = (index + 1) % this.entries.length;\n\t\t\treturn entry;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\trecordFailure({ identity, kind }: { identity: CredentialIdentity; kind: CredentialFailureKind }): void {\n\t\tif (kind === \"rate_limited\" || kind === \"blocked\") {\n\t\t\tthis.blockedUntilByIdentity.set(identity, this.now() + this.cooldownMs);\n\t\t}\n\t}\n\n\tsnapshot(): CredentialPoolSnapshotEntry[] {\n\t\treturn this.entries.map((entry) => ({\n\t\t\tidentity: entry.identity,\n\t\t\tproviderId: entry.providerId,\n\t\t\tblockedUntil: this.blockedUntilByIdentity.get(entry.identity),\n\t\t}));\n\t}\n\n\tprivate activeLease(identity: CredentialIdentity): CredentialRefreshLease | undefined {\n\t\tconst lease = this.refreshLeaseByIdentity.get(identity);\n\t\tif (!lease) return undefined;\n\t\tif (lease.expiresAt <= this.now()) {\n\t\t\tthis.refreshLeaseByIdentity.delete(identity);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn lease;\n\t}\n\n\t/** Grant a refresh lease for an identity, unless another owner already holds an unexpired one. */\n\tacquireRefreshLease({\n\t\tidentity,\n\t\towner,\n\t\tdurationMs,\n\t}: {\n\t\tidentity: CredentialIdentity;\n\t\towner: string;\n\t\tdurationMs: number;\n\t}): CredentialRefreshLease | undefined {\n\t\tconst existing = this.activeLease(identity);\n\t\tif (existing && existing.owner !== owner) return undefined;\n\t\tconst lease: CredentialRefreshLease = { identity, owner, expiresAt: this.now() + durationMs };\n\t\tthis.refreshLeaseByIdentity.set(identity, lease);\n\t\treturn lease;\n\t}\n\n\t/** Release a held refresh lease. Returns false if the caller is not the current owner. */\n\treleaseRefreshLease({ identity, owner }: { identity: CredentialIdentity; owner: string }): boolean {\n\t\tconst existing = this.activeLease(identity);\n\t\tif (!existing || existing.owner !== owner) return false;\n\t\tthis.refreshLeaseByIdentity.delete(identity);\n\t\treturn true;\n\t}\n}\n"]}
@@ -1,3 +1,4 @@
1
1
  import type { ThinkingLevel } from "apex-code-agent-core";
2
2
  export declare const DEFAULT_THINKING_LEVEL: ThinkingLevel;
3
+ export declare const THINKING_LEVEL_OPTIONS: readonly ThinkingLevel[];
3
4
  //# sourceMappingURL=defaults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/core/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC","sourcesContent":["import type { ThinkingLevel } from \"apex-code-agent-core\";\n\nexport const DEFAULT_THINKING_LEVEL: ThinkingLevel = \"medium\";\n"]}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/core/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAC9D,eAAO,MAAM,sBAAsB,EAAE,SAAS,aAAa,EAQ1D,CAAC","sourcesContent":["import type { ThinkingLevel } from \"apex-code-agent-core\";\n\nexport const DEFAULT_THINKING_LEVEL: ThinkingLevel = \"medium\";\nexport const THINKING_LEVEL_OPTIONS: readonly ThinkingLevel[] = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n];\n"]}
@@ -1,2 +1,11 @@
1
1
  export const DEFAULT_THINKING_LEVEL = "medium";
2
+ export const THINKING_LEVEL_OPTIONS = [
3
+ "off",
4
+ "minimal",
5
+ "low",
6
+ "medium",
7
+ "high",
8
+ "xhigh",
9
+ "max",
10
+ ];
2
11
  //# sourceMappingURL=defaults.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/core/defaults.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAkB,QAAQ,CAAC","sourcesContent":["import type { ThinkingLevel } from \"apex-code-agent-core\";\n\nexport const DEFAULT_THINKING_LEVEL: ThinkingLevel = \"medium\";\n"]}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/core/defaults.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAkB,QAAQ,CAAC;AAC9D,MAAM,CAAC,MAAM,sBAAsB,GAA6B;IAC/D,KAAK;IACL,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,KAAK;CACL,CAAC","sourcesContent":["import type { ThinkingLevel } from \"apex-code-agent-core\";\n\nexport const DEFAULT_THINKING_LEVEL: ThinkingLevel = \"medium\";\nexport const THINKING_LEVEL_OPTIONS: readonly ThinkingLevel[] = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n];\n"]}
@@ -0,0 +1,15 @@
1
+ /** Markdown agent-definition discovery (roadmap Phase 5, task 5.5).
2
+ * User definitions are always eligible. Project definitions are eligible only
3
+ * through the existing project-trust decision; discovery never prompts or creates
4
+ * a second trust mechanism. Files are parsed on lookup so edits take effect on the
5
+ * next delegation and malformed definitions simply remain unavailable.
6
+ */
7
+ import type { AgentDefinitionResolver } from "./runtime.ts";
8
+ export interface CreateAgentDefinitionResolverOptions {
9
+ cwd: string;
10
+ agentDir: string;
11
+ /** Delegated to SettingsManager.isProjectTrusted() in production. */
12
+ isProjectTrusted: () => boolean;
13
+ }
14
+ export declare function createAgentDefinitionResolver(options: CreateAgentDefinitionResolverOptions): AgentDefinitionResolver;
15
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/agents.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAmB,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAS7E,MAAM,WAAW,oCAAoC;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,OAAO,CAAC;CAChC;AAyCD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,oCAAoC,GAAG,uBAAuB,CAKpH","sourcesContent":["/** Markdown agent-definition discovery (roadmap Phase 5, task 5.5).\n * User definitions are always eligible. Project definitions are eligible only\n * through the existing project-trust decision; discovery never prompts or creates\n * a second trust mechanism. Files are parsed on lookup so edits take effect on the\n * next delegation and malformed definitions simply remain unavailable.\n */\n\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseFrontmatter } from \"../../utils/frontmatter.ts\";\nimport type { AgentDefinition, AgentDefinitionResolver } from \"./runtime.ts\";\n\ninterface AgentFrontmatter extends Record<string, unknown> {\n\tname?: unknown;\n\tdescription?: unknown;\n\ttools?: unknown;\n\tmodel?: unknown;\n}\n\nexport interface CreateAgentDefinitionResolverOptions {\n\tcwd: string;\n\tagentDir: string;\n\t/** Delegated to SettingsManager.isProjectTrusted() in production. */\n\tisProjectTrusted: () => boolean;\n}\n\nfunction parseDefinition(content: string): AgentDefinition | undefined {\n\ttry {\n\t\tconst { frontmatter, body } = parseFrontmatter<AgentFrontmatter>(content);\n\t\tif (\n\t\t\ttypeof frontmatter.name !== \"string\" ||\n\t\t\t!frontmatter.name ||\n\t\t\ttypeof frontmatter.description !== \"string\" ||\n\t\t\t!frontmatter.description ||\n\t\t\t!Array.isArray(frontmatter.tools) ||\n\t\t\t!frontmatter.tools.every((tool): tool is string => typeof tool === \"string\" && tool.length > 0) ||\n\t\t\t(frontmatter.model !== undefined && (typeof frontmatter.model !== \"string\" || !frontmatter.model))\n\t\t)\n\t\t\treturn undefined;\n\t\treturn {\n\t\t\tname: frontmatter.name,\n\t\t\tdescription: frontmatter.description,\n\t\t\ttools: [...frontmatter.tools],\n\t\t\tmodel: frontmatter.model,\n\t\t\tsystemPrompt: body,\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction discover(dir: string, agentType: string): AgentDefinition | undefined {\n\tif (!existsSync(dir)) return undefined;\n\ttry {\n\t\tfor (const filename of readdirSync(dir).sort()) {\n\t\t\tif (!filename.endsWith(\".md\")) continue;\n\t\t\tconst definition = parseDefinition(readFileSync(join(dir, filename), \"utf8\"));\n\t\t\tif (definition?.name === agentType) return definition;\n\t\t}\n\t} catch {\n\t\t// A directory that cannot be read behaves as having no usable definitions.\n\t}\n\treturn undefined;\n}\n\nexport function createAgentDefinitionResolver(options: CreateAgentDefinitionResolverOptions): AgentDefinitionResolver {\n\tconst userDir = join(options.agentDir, \"agents\");\n\tconst projectDir = join(options.cwd, \".apex-code\", \"agents\");\n\treturn (agentType) =>\n\t\tdiscover(userDir, agentType) ?? (options.isProjectTrusted() ? discover(projectDir, agentType) : undefined);\n}\n"]}