@caupulican/pi-adaptative 0.85.4 → 0.86.1

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 (480) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/bun/cli.d.ts +1 -1
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js +1 -0
  5. package/dist/bun/cli.js.map +1 -1
  6. package/dist/core/agent-paths.d.ts +3 -3
  7. package/dist/core/agent-paths.d.ts.map +1 -1
  8. package/dist/core/agent-paths.js +3 -3
  9. package/dist/core/agent-paths.js.map +1 -1
  10. package/dist/core/agent-session-runtime.d.ts +1 -1
  11. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  12. package/dist/core/agent-session-runtime.js +1 -1
  13. package/dist/core/agent-session-runtime.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +11 -5
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +14 -3
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/auth-storage.d.ts +2 -2
  19. package/dist/core/auth-storage.d.ts.map +1 -1
  20. package/dist/core/auth-storage.js +2 -2
  21. package/dist/core/auth-storage.js.map +1 -1
  22. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  23. package/dist/core/autonomy/bounded-completion.js +19 -8
  24. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  25. package/dist/core/autonomy/lane-tool-surface.d.ts +11 -5
  26. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  27. package/dist/core/autonomy/lane-tool-surface.js +34 -8
  28. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  29. package/dist/core/autonomy/subagent-prompt.d.ts +3 -3
  30. package/dist/core/autonomy/subagent-prompt.js +9 -9
  31. package/dist/core/autonomy/subagent-prompt.js.map +1 -1
  32. package/dist/core/background-lane-controller.d.ts +10 -8
  33. package/dist/core/background-lane-controller.d.ts.map +1 -1
  34. package/dist/core/background-lane-controller.js +23 -13
  35. package/dist/core/background-lane-controller.js.map +1 -1
  36. package/dist/core/bash-execution-controller.d.ts +4 -0
  37. package/dist/core/bash-execution-controller.d.ts.map +1 -1
  38. package/dist/core/bash-execution-controller.js +11 -4
  39. package/dist/core/bash-execution-controller.js.map +1 -1
  40. package/dist/core/bash-executor.d.ts +2 -0
  41. package/dist/core/bash-executor.d.ts.map +1 -1
  42. package/dist/core/bash-executor.js +4 -3
  43. package/dist/core/bash-executor.js.map +1 -1
  44. package/dist/core/billing-failover-controller.d.ts +2 -2
  45. package/dist/core/billing-failover-controller.d.ts.map +1 -1
  46. package/dist/core/billing-failover-controller.js +1 -1
  47. package/dist/core/billing-failover-controller.js.map +1 -1
  48. package/dist/core/capability-contract.d.ts +1 -1
  49. package/dist/core/capability-contract.d.ts.map +1 -1
  50. package/dist/core/capability-contract.js +0 -1
  51. package/dist/core/capability-contract.js.map +1 -1
  52. package/dist/core/compaction-controller.d.ts +8 -2
  53. package/dist/core/compaction-controller.d.ts.map +1 -1
  54. package/dist/core/compaction-controller.js +73 -3
  55. package/dist/core/compaction-controller.js.map +1 -1
  56. package/dist/core/compaction-support.d.ts +2 -2
  57. package/dist/core/compaction-support.d.ts.map +1 -1
  58. package/dist/core/compaction-support.js +9 -1
  59. package/dist/core/compaction-support.js.map +1 -1
  60. package/dist/core/context/artifact-retrieval.d.ts +1 -1
  61. package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
  62. package/dist/core/context/artifact-retrieval.js +1 -1
  63. package/dist/core/context/artifact-retrieval.js.map +1 -1
  64. package/dist/core/context/context-artifacts.d.ts +6 -6
  65. package/dist/core/context/context-artifacts.d.ts.map +1 -1
  66. package/dist/core/context/context-artifacts.js +151 -63
  67. package/dist/core/context/context-artifacts.js.map +1 -1
  68. package/dist/core/context/context-composition.js +1 -1
  69. package/dist/core/context/context-composition.js.map +1 -1
  70. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  71. package/dist/core/context/context-store-retention.js +5 -2
  72. package/dist/core/context/context-store-retention.js.map +1 -1
  73. package/dist/core/context/file-store-memory-provider.js +1 -1
  74. package/dist/core/context/file-store-memory-provider.js.map +1 -1
  75. package/dist/core/context/tool-output-packer.d.ts +1 -1
  76. package/dist/core/context/tool-output-packer.d.ts.map +1 -1
  77. package/dist/core/context/tool-output-packer.js +1 -1
  78. package/dist/core/context/tool-output-packer.js.map +1 -1
  79. package/dist/core/context-gc.d.ts.map +1 -1
  80. package/dist/core/context-gc.js +7 -5
  81. package/dist/core/context-gc.js.map +1 -1
  82. package/dist/core/context-pipeline.d.ts +2 -2
  83. package/dist/core/context-pipeline.d.ts.map +1 -1
  84. package/dist/core/context-pipeline.js +8 -4
  85. package/dist/core/context-pipeline.js.map +1 -1
  86. package/dist/core/cost/cost-summary.d.ts +1 -1
  87. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  88. package/dist/core/cost/cost-summary.js +1 -1
  89. package/dist/core/cost/cost-summary.js.map +1 -1
  90. package/dist/core/cost/daily-usage.d.ts +1 -1
  91. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  92. package/dist/core/cost/daily-usage.js +2 -2
  93. package/dist/core/cost/daily-usage.js.map +1 -1
  94. package/dist/core/cost/session-usage.d.ts +1 -1
  95. package/dist/core/cost/session-usage.d.ts.map +1 -1
  96. package/dist/core/cost/session-usage.js +1 -1
  97. package/dist/core/cost/session-usage.js.map +1 -1
  98. package/dist/core/default-tool-surface.d.ts +1 -0
  99. package/dist/core/default-tool-surface.d.ts.map +1 -1
  100. package/dist/core/default-tool-surface.js +3 -2
  101. package/dist/core/default-tool-surface.js.map +1 -1
  102. package/dist/core/delegation/worker-actions.js +1 -1
  103. package/dist/core/delegation/worker-actions.js.map +1 -1
  104. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +27 -8
  105. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  106. package/dist/core/delegation/worker-agent-control-coordinator.js +191 -33
  107. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  108. package/dist/core/delegation/worker-agent-control.d.ts +45 -6
  109. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  110. package/dist/core/delegation/worker-agent-control.js +110 -13
  111. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  112. package/dist/core/delegation/worker-attempt-executor.d.ts +1 -1
  113. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  114. package/dist/core/delegation/worker-attempt-executor.js +180 -160
  115. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  116. package/dist/core/delegation/worker-authority-resolver.d.ts +23 -0
  117. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -0
  118. package/dist/core/delegation/worker-authority-resolver.js +128 -0
  119. package/dist/core/delegation/worker-authority-resolver.js.map +1 -0
  120. package/dist/core/delegation/worker-conversation-store.d.ts +2 -1
  121. package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
  122. package/dist/core/delegation/worker-conversation-store.js +4 -3
  123. package/dist/core/delegation/worker-conversation-store.js.map +1 -1
  124. package/dist/core/delegation/worker-delegation-controller.d.ts +7 -1
  125. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  126. package/dist/core/delegation/worker-delegation-controller.js +260 -87
  127. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  128. package/dist/core/delegation/worker-delegation-request.d.ts +25 -4
  129. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  130. package/dist/core/delegation/worker-delegation-request.js +90 -1
  131. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  132. package/dist/core/delegation/worker-execution-policy.d.ts +2 -0
  133. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  134. package/dist/core/delegation/worker-execution-policy.js +22 -12
  135. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  136. package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
  137. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  138. package/dist/core/delegation/worker-lifecycle.js +4 -2
  139. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  140. package/dist/core/delegation/worker-profile-resolver.d.ts +0 -2
  141. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  142. package/dist/core/delegation/worker-profile-resolver.js +8 -35
  143. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  144. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
  145. package/dist/core/delegation/worker-recovery-coordinator.js +1 -0
  146. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
  147. package/dist/core/delegation/worker-runner.d.ts +6 -1
  148. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  149. package/dist/core/delegation/worker-runner.js +20 -6
  150. package/dist/core/delegation/worker-runner.js.map +1 -1
  151. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +47 -0
  152. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -0
  153. package/dist/core/delegation/worker-tree-budget-coordinator.js +210 -0
  154. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -0
  155. package/dist/core/extensions/builtin.d.ts +2 -2
  156. package/dist/core/extensions/builtin.d.ts.map +1 -1
  157. package/dist/core/extensions/builtin.js +2 -2
  158. package/dist/core/extensions/builtin.js.map +1 -1
  159. package/dist/core/extensions/bundled-virtual-modules.d.ts +2 -0
  160. package/dist/core/extensions/bundled-virtual-modules.d.ts.map +1 -0
  161. package/dist/core/extensions/bundled-virtual-modules.js +129 -0
  162. package/dist/core/extensions/bundled-virtual-modules.js.map +1 -0
  163. package/dist/core/extensions/factory-runtime.d.ts +22 -0
  164. package/dist/core/extensions/factory-runtime.d.ts.map +1 -0
  165. package/dist/core/extensions/factory-runtime.js +334 -0
  166. package/dist/core/extensions/factory-runtime.js.map +1 -0
  167. package/dist/core/extensions/index.d.ts +1 -1
  168. package/dist/core/extensions/index.d.ts.map +1 -1
  169. package/dist/core/extensions/index.js +1 -1
  170. package/dist/core/extensions/index.js.map +1 -1
  171. package/dist/core/extensions/lifecycle.d.ts +13 -0
  172. package/dist/core/extensions/lifecycle.d.ts.map +1 -0
  173. package/dist/core/extensions/lifecycle.js +52 -0
  174. package/dist/core/extensions/lifecycle.js.map +1 -0
  175. package/dist/core/extensions/loader.d.ts +3 -24
  176. package/dist/core/extensions/loader.d.ts.map +1 -1
  177. package/dist/core/extensions/loader.js +21 -531
  178. package/dist/core/extensions/loader.js.map +1 -1
  179. package/dist/core/extensions/virtual-modules.d.ts +51 -0
  180. package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
  181. package/dist/core/extensions/virtual-modules.js +59 -0
  182. package/dist/core/extensions/virtual-modules.js.map +1 -0
  183. package/dist/core/foreground-recovery-controller.d.ts +2 -1
  184. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  185. package/dist/core/foreground-recovery-controller.js +3 -3
  186. package/dist/core/foreground-recovery-controller.js.map +1 -1
  187. package/dist/core/goal-loop-controller.js +1 -1
  188. package/dist/core/goal-loop-controller.js.map +1 -1
  189. package/dist/core/goals/compact-goal-context.d.ts +1 -1
  190. package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
  191. package/dist/core/goals/compact-goal-context.js +1 -1
  192. package/dist/core/goals/compact-goal-context.js.map +1 -1
  193. package/dist/core/goals/goal-auto-continue-controller.js +1 -1
  194. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
  195. package/dist/core/goals/goal-session-controller.d.ts +1 -1
  196. package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
  197. package/dist/core/goals/goal-session-controller.js +1 -1
  198. package/dist/core/goals/goal-session-controller.js.map +1 -1
  199. package/dist/core/http-dispatcher.d.ts +1 -1
  200. package/dist/core/http-dispatcher.d.ts.map +1 -1
  201. package/dist/core/http-dispatcher.js +1 -1
  202. package/dist/core/http-dispatcher.js.map +1 -1
  203. package/dist/core/index.d.ts +3 -2
  204. package/dist/core/index.d.ts.map +1 -1
  205. package/dist/core/index.js +2 -1
  206. package/dist/core/index.js.map +1 -1
  207. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  208. package/dist/core/memory/providers/file-store.js +1 -1
  209. package/dist/core/memory/providers/file-store.js.map +1 -1
  210. package/dist/core/memory/providers/user-memory-archive.js +1 -1
  211. package/dist/core/memory/providers/user-memory-archive.js.map +1 -1
  212. package/dist/core/model-registry.d.ts +2 -1
  213. package/dist/core/model-registry.d.ts.map +1 -1
  214. package/dist/core/model-registry.js +4 -1
  215. package/dist/core/model-registry.js.map +1 -1
  216. package/dist/core/model-resolver.d.ts +1 -1
  217. package/dist/core/model-resolver.d.ts.map +1 -1
  218. package/dist/core/model-resolver.js +1 -1
  219. package/dist/core/model-resolver.js.map +1 -1
  220. package/dist/core/model-router-controller.js +1 -1
  221. package/dist/core/model-router-controller.js.map +1 -1
  222. package/dist/core/model-selection-controller.js +1 -1
  223. package/dist/core/model-selection-controller.js.map +1 -1
  224. package/dist/core/model-tool-protocol.d.ts +1 -1
  225. package/dist/core/model-tool-protocol.d.ts.map +1 -1
  226. package/dist/core/model-tool-protocol.js +1 -1
  227. package/dist/core/model-tool-protocol.js.map +1 -1
  228. package/dist/core/models/llamacpp-runtime.d.ts +7 -0
  229. package/dist/core/models/llamacpp-runtime.d.ts.map +1 -1
  230. package/dist/core/models/llamacpp-runtime.js +8 -3
  231. package/dist/core/models/llamacpp-runtime.js.map +1 -1
  232. package/dist/core/models/local-runtime.js +1 -1
  233. package/dist/core/models/local-runtime.js.map +1 -1
  234. package/dist/core/models/runtime-process.d.ts.map +1 -1
  235. package/dist/core/models/runtime-process.js +5 -18
  236. package/dist/core/models/runtime-process.js.map +1 -1
  237. package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
  238. package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
  239. package/dist/core/orchestration/bounded-string-array.js +17 -0
  240. package/dist/core/orchestration/bounded-string-array.js.map +1 -0
  241. package/dist/core/orchestration/capability-gateway.d.ts +16 -0
  242. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  243. package/dist/core/orchestration/capability-gateway.js +38 -0
  244. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  245. package/dist/core/orchestration/contracts.d.ts +11 -3
  246. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  247. package/dist/core/orchestration/contracts.js +0 -1
  248. package/dist/core/orchestration/contracts.js.map +1 -1
  249. package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
  250. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  251. package/dist/core/orchestration/delegation-ledger.js +3 -0
  252. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  253. package/dist/core/orchestration/event-store.d.ts +12 -10
  254. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  255. package/dist/core/orchestration/event-store.js +94 -104
  256. package/dist/core/orchestration/event-store.js.map +1 -1
  257. package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
  258. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
  259. package/dist/core/orchestration/lane-tool-manifests.js +4 -1
  260. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
  261. package/dist/core/orchestration/model-binding.d.ts +1 -1
  262. package/dist/core/orchestration/model-binding.d.ts.map +1 -1
  263. package/dist/core/orchestration/model-binding.js +1 -1
  264. package/dist/core/orchestration/model-binding.js.map +1 -1
  265. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
  266. package/dist/core/orchestration/policy-compiler.js +8 -9
  267. package/dist/core/orchestration/policy-compiler.js.map +1 -1
  268. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  269. package/dist/core/orchestration/profile-registry.js +4 -10
  270. package/dist/core/orchestration/profile-registry.js.map +1 -1
  271. package/dist/core/orchestration/task-profile-writer.js +1 -1
  272. package/dist/core/orchestration/task-profile-writer.js.map +1 -1
  273. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  274. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  275. package/dist/core/orchestration/task-runtime.js +58 -3
  276. package/dist/core/orchestration/task-runtime.js.map +1 -1
  277. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  278. package/dist/core/orchestration/worker-execution-contract.js +10 -17
  279. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  280. package/dist/core/process-matrix/runtime.d.ts +15 -1
  281. package/dist/core/process-matrix/runtime.d.ts.map +1 -1
  282. package/dist/core/process-matrix/runtime.js +55 -34
  283. package/dist/core/process-matrix/runtime.js.map +1 -1
  284. package/dist/core/reflection-controller.d.ts +4 -3
  285. package/dist/core/reflection-controller.d.ts.map +1 -1
  286. package/dist/core/reflection-controller.js +2 -2
  287. package/dist/core/reflection-controller.js.map +1 -1
  288. package/dist/core/research/model-fitness-controller.js +1 -1
  289. package/dist/core/research/model-fitness-controller.js.map +1 -1
  290. package/dist/core/research/research-lane-controller.d.ts +2 -2
  291. package/dist/core/research/research-lane-controller.d.ts.map +1 -1
  292. package/dist/core/research/research-lane-controller.js +1 -1
  293. package/dist/core/research/research-lane-controller.js.map +1 -1
  294. package/dist/core/resource-loader.d.ts +10 -19
  295. package/dist/core/resource-loader.d.ts.map +1 -1
  296. package/dist/core/resource-loader.js +8 -70
  297. package/dist/core/resource-loader.js.map +1 -1
  298. package/dist/core/risk-classifier.js +3 -3
  299. package/dist/core/risk-classifier.js.map +1 -1
  300. package/dist/core/runtime-builder.d.ts +4 -1
  301. package/dist/core/runtime-builder.d.ts.map +1 -1
  302. package/dist/core/runtime-builder.js +47 -18
  303. package/dist/core/runtime-builder.js.map +1 -1
  304. package/dist/core/scout-controller.d.ts +1 -1
  305. package/dist/core/scout-controller.d.ts.map +1 -1
  306. package/dist/core/scout-controller.js +1 -1
  307. package/dist/core/scout-controller.js.map +1 -1
  308. package/dist/core/sdk.d.ts +2 -2
  309. package/dist/core/sdk.d.ts.map +1 -1
  310. package/dist/core/sdk.js +3 -3
  311. package/dist/core/sdk.js.map +1 -1
  312. package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
  313. package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
  314. package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
  315. package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
  316. package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
  317. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  318. package/dist/core/secrets/credential-exposure-guard.js +31 -29
  319. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  320. package/dist/core/secrets/credential-manager.d.ts +109 -0
  321. package/dist/core/secrets/credential-manager.d.ts.map +1 -0
  322. package/dist/core/secrets/credential-manager.js +384 -0
  323. package/dist/core/secrets/credential-manager.js.map +1 -0
  324. package/dist/core/secrets/credential-project.d.ts +4 -0
  325. package/dist/core/secrets/credential-project.d.ts.map +1 -0
  326. package/dist/core/secrets/credential-project.js +145 -0
  327. package/dist/core/secrets/credential-project.js.map +1 -0
  328. package/dist/core/secrets/secret-dotenv.d.ts +1 -1
  329. package/dist/core/secrets/secret-dotenv.js +1 -1
  330. package/dist/core/secrets/secret-dotenv.js.map +1 -1
  331. package/dist/core/security/context-threat-scanner.d.ts +14 -0
  332. package/dist/core/security/context-threat-scanner.d.ts.map +1 -0
  333. package/dist/core/security/context-threat-scanner.js +71 -0
  334. package/dist/core/security/context-threat-scanner.js.map +1 -0
  335. package/dist/core/session-supervision-runtime.d.ts +4 -1
  336. package/dist/core/session-supervision-runtime.d.ts.map +1 -1
  337. package/dist/core/session-supervision-runtime.js +49 -11
  338. package/dist/core/session-supervision-runtime.js.map +1 -1
  339. package/dist/core/settings-manager.d.ts +4 -2
  340. package/dist/core/settings-manager.d.ts.map +1 -1
  341. package/dist/core/settings-manager.js +10 -6
  342. package/dist/core/settings-manager.js.map +1 -1
  343. package/dist/core/slash-commands.d.ts.map +1 -1
  344. package/dist/core/slash-commands.js +1 -0
  345. package/dist/core/slash-commands.js.map +1 -1
  346. package/dist/core/system-prompt.js +1 -1
  347. package/dist/core/system-prompt.js.map +1 -1
  348. package/dist/core/tool-capability-policy.js +2 -2
  349. package/dist/core/tool-capability-policy.js.map +1 -1
  350. package/dist/core/tool-recovery-logger.js +1 -1
  351. package/dist/core/tool-recovery-logger.js.map +1 -1
  352. package/dist/core/tools/artifact-retrieve.js +1 -1
  353. package/dist/core/tools/artifact-retrieve.js.map +1 -1
  354. package/dist/core/tools/bash.d.ts +2 -2
  355. package/dist/core/tools/bash.d.ts.map +1 -1
  356. package/dist/core/tools/bash.js +16 -4
  357. package/dist/core/tools/bash.js.map +1 -1
  358. package/dist/core/tools/delegate.d.ts +29 -1
  359. package/dist/core/tools/delegate.d.ts.map +1 -1
  360. package/dist/core/tools/delegate.js +179 -28
  361. package/dist/core/tools/delegate.js.map +1 -1
  362. package/dist/core/tools/extensionify-runtime.d.ts +44 -0
  363. package/dist/core/tools/extensionify-runtime.d.ts.map +1 -0
  364. package/dist/core/tools/extensionify-runtime.js +115 -0
  365. package/dist/core/tools/extensionify-runtime.js.map +1 -0
  366. package/dist/core/tools/extensionify.d.ts +9 -30
  367. package/dist/core/tools/extensionify.d.ts.map +1 -1
  368. package/dist/core/tools/extensionify.js +10 -140
  369. package/dist/core/tools/extensionify.js.map +1 -1
  370. package/dist/core/tools/find.d.ts +1 -1
  371. package/dist/core/tools/find.d.ts.map +1 -1
  372. package/dist/core/tools/find.js +1 -1
  373. package/dist/core/tools/find.js.map +1 -1
  374. package/dist/core/tools/git-filter.d.ts +1 -0
  375. package/dist/core/tools/git-filter.d.ts.map +1 -1
  376. package/dist/core/tools/git-filter.js +1 -1
  377. package/dist/core/tools/git-filter.js.map +1 -1
  378. package/dist/core/tools/index.d.ts +2 -4
  379. package/dist/core/tools/index.d.ts.map +1 -1
  380. package/dist/core/tools/index.js +7 -43
  381. package/dist/core/tools/index.js.map +1 -1
  382. package/dist/core/tools/ls.d.ts +1 -1
  383. package/dist/core/tools/ls.d.ts.map +1 -1
  384. package/dist/core/tools/ls.js +1 -1
  385. package/dist/core/tools/ls.js.map +1 -1
  386. package/dist/core/tools/output-accumulator.d.ts +1 -1
  387. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  388. package/dist/core/tools/output-accumulator.js +1 -1
  389. package/dist/core/tools/output-accumulator.js.map +1 -1
  390. package/dist/core/tools/profile-writer.js +3 -3
  391. package/dist/core/tools/profile-writer.js.map +1 -1
  392. package/dist/core/tools/python.d.ts +2 -0
  393. package/dist/core/tools/python.d.ts.map +1 -1
  394. package/dist/core/tools/python.js +17 -12
  395. package/dist/core/tools/python.js.map +1 -1
  396. package/dist/core/tools/render-utils.js +1 -1
  397. package/dist/core/tools/render-utils.js.map +1 -1
  398. package/dist/core/tools/run-process.d.ts +2 -0
  399. package/dist/core/tools/run-process.d.ts.map +1 -1
  400. package/dist/core/tools/run-process.js +7 -3
  401. package/dist/core/tools/run-process.js.map +1 -1
  402. package/dist/core/tools/search-command-guard.d.ts +8 -0
  403. package/dist/core/tools/search-command-guard.d.ts.map +1 -1
  404. package/dist/core/tools/search-command-guard.js +54 -0
  405. package/dist/core/tools/search-command-guard.js.map +1 -1
  406. package/dist/core/tools/secret-store.d.ts +8 -18
  407. package/dist/core/tools/secret-store.d.ts.map +1 -1
  408. package/dist/core/tools/secret-store.js +83 -348
  409. package/dist/core/tools/secret-store.js.map +1 -1
  410. package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
  411. package/dist/core/tools/shell-contract-router.js +9 -4
  412. package/dist/core/tools/shell-contract-router.js.map +1 -1
  413. package/dist/core/tools/shell-session.d.ts.map +1 -1
  414. package/dist/core/tools/shell-session.js +6 -4
  415. package/dist/core/tools/shell-session.js.map +1 -1
  416. package/dist/core/tools/tool-definition-factory.d.ts +32 -0
  417. package/dist/core/tools/tool-definition-factory.d.ts.map +1 -0
  418. package/dist/core/tools/tool-definition-factory.js +55 -0
  419. package/dist/core/tools/tool-definition-factory.js.map +1 -0
  420. package/dist/core/util/atomic-file.d.ts.map +1 -1
  421. package/dist/core/util/atomic-file.js +79 -32
  422. package/dist/core/util/atomic-file.js.map +1 -1
  423. package/dist/index.d.ts +5 -2
  424. package/dist/index.d.ts.map +1 -1
  425. package/dist/index.js +5 -2
  426. package/dist/index.js.map +1 -1
  427. package/dist/main.d.ts +2 -0
  428. package/dist/main.d.ts.map +1 -1
  429. package/dist/main.js +24 -18
  430. package/dist/main.js.map +1 -1
  431. package/dist/modes/interactive/auto-learn-controller.js +1 -1
  432. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  433. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/settings-selector.js +35 -14
  435. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  436. package/dist/modes/interactive/components/tool-execution.js +1 -1
  437. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  438. package/dist/modes/interactive/interactive-event-controller.js +1 -1
  439. package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
  440. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  441. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  442. package/dist/modes/interactive/interactive-mode.js +27 -4
  443. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  444. package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
  445. package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
  446. package/dist/modes/interactive/secret-menu-controller.js +276 -0
  447. package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
  448. package/dist/utils/child-process.js +1 -1
  449. package/dist/utils/child-process.js.map +1 -1
  450. package/dist/utils/tools-manager.d.ts +2 -1
  451. package/dist/utils/tools-manager.d.ts.map +1 -1
  452. package/dist/utils/tools-manager.js +43 -48
  453. package/dist/utils/tools-manager.js.map +1 -1
  454. package/dist/utils/zip-extractor.d.ts +8 -0
  455. package/dist/utils/zip-extractor.d.ts.map +1 -0
  456. package/dist/utils/zip-extractor.js +275 -0
  457. package/dist/utils/zip-extractor.js.map +1 -0
  458. package/docs/harness-architecture.md +34 -22
  459. package/docs/index.md +1 -1
  460. package/docs/resources.md +1 -1
  461. package/docs/settings.md +39 -103
  462. package/docs/usage.md +7 -5
  463. package/docs/worker-profiles.md +9 -7
  464. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  465. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  466. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  467. package/examples/extensions/sandbox/package-lock.json +2 -2
  468. package/examples/extensions/sandbox/package.json +1 -1
  469. package/examples/extensions/with-deps/package-lock.json +2 -2
  470. package/examples/extensions/with-deps/package.json +1 -1
  471. package/npm-shrinkwrap.json +12 -12
  472. package/package.json +7 -5
  473. package/dist/core/secrets/secret-vault-format.d.ts +0 -112
  474. package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
  475. package/dist/core/secrets/secret-vault-format.js +0 -396
  476. package/dist/core/secrets/secret-vault-format.js.map +0 -1
  477. package/dist/core/secrets/secret-vault.d.ts +0 -72
  478. package/dist/core/secrets/secret-vault.d.ts.map +0 -1
  479. package/dist/core/secrets/secret-vault.js +0 -663
  480. package/dist/core/secrets/secret-vault.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"context-artifacts.js","sourceRoot":"","sources":["../../../src/core/context/context-artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Artifact store abstraction (Phase 2): stable refs for raw large payloads, kept out of\n * band from prompt context. This module defines the `ArtifactStore` interface plus two\n * implementations: an in-memory one for tests, and `createFileArtifactStore` (session-\n * scoped, filesystem-backed). A SQLite-backed implementation waits until the Phase M0\n * storage-authority/location/concurrency decisions are accepted (see\n * docs/context-management-rework/memory-architecture.md).\n *\n * `createFileArtifactStore` is wired into live grep/find tool construction in\n * agent-session.ts (session-scoped under `<agentDir>/work/context/sessions/<sessionId>/artifacts/`).\n * References are registered at pack time and released when context-gc evicts the\n * corresponding grep/find tool result (opportunistic, conservative cleanup), with a\n * best-effort dispose-time sweep for zero-reference artifacts. Payloads are retrievable\n * out of band via the artifact_retrieve tool (context/artifact-retrieval.ts).\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { type ContextArtifactRef, estimateByteLength, estimateLineCount } from \"./context-item.ts\";\n\nexport interface ArtifactWriteRequest {\n\tkind: ContextArtifactRef[\"kind\"];\n\tcontent: string;\n\ttoolName?: string;\n\tcommand?: string;\n\tpath?: string;\n\tsessionEntryId?: string;\n\tcreatedAtTurn: number;\n\treproducible: boolean;\n}\n\nexport interface ArtifactRecord {\n\tref: ContextArtifactRef;\n\tcontent: string;\n}\n\nexport type MissingArtifactReason = \"not_found\" | \"cleaned_up\";\n\nexport interface MissingArtifactMarker {\n\tid: string;\n\tmissing: true;\n\treason: MissingArtifactReason;\n}\n\nexport function isMissingArtifactMarker(value: ArtifactRecord | MissingArtifactMarker): value is MissingArtifactMarker {\n\treturn (value as MissingArtifactMarker).missing === true;\n}\n\n/**\n * Artifact id for a capture event, not merely a payload: it hashes every ref-defining\n * field (kind, tool/command/path, content, sessionEntryId, createdAtTurn, reproducible).\n * A repeat write with identical content but a different turn or session entry is a\n * distinct capture and must get a distinct id -- otherwise the later capture's metadata\n * would be silently discarded in favor of the first write. Only a truly identical\n * request (same capture, re-submitted) is idempotent under this id.\n */\nexport function generateArtifactId(\n\trequest: Pick<\n\t\tArtifactWriteRequest,\n\t\t\"kind\" | \"content\" | \"toolName\" | \"command\" | \"path\" | \"sessionEntryId\" | \"createdAtTurn\" | \"reproducible\"\n\t>,\n): string {\n\tconst hash = createHash(\"sha256\");\n\tfor (const field of [\n\t\trequest.kind,\n\t\trequest.toolName ?? \"\",\n\t\trequest.command ?? \"\",\n\t\trequest.path ?? \"\",\n\t\trequest.sessionEntryId ?? \"\",\n\t\tString(request.createdAtTurn),\n\t\tString(request.reproducible),\n\t]) {\n\t\thash.update(field).update(\"\\0\");\n\t}\n\thash.update(request.content);\n\treturn hash.digest(\"hex\").slice(0, 24);\n}\n\nfunction createArtifactRef(id: string, request: ArtifactWriteRequest): ContextArtifactRef {\n\treturn {\n\t\tid,\n\t\tkind: request.kind,\n\t\tsessionEntryId: request.sessionEntryId,\n\t\ttoolName: request.toolName,\n\t\tcommand: request.command,\n\t\tpath: request.path,\n\t\tbyteLength: estimateByteLength(request.content),\n\t\tlineCount: estimateLineCount(request.content),\n\t\tcreatedAtTurn: request.createdAtTurn,\n\t\treproducible: request.reproducible,\n\t};\n}\n\nexport interface ArtifactStore {\n\twrite(request: ArtifactWriteRequest): ArtifactRecord;\n\tread(id: string): ArtifactRecord | MissingArtifactMarker;\n\t/**\n\t * Metadata-only lookup: the ref if `id` resolves to a live artifact, `undefined`\n\t * otherwise. Never loads the payload -- for the file store this must not touch the\n\t * payload file at all beyond an existence check, so a caller that only needs to know\n\t * \"does this still exist, and what are its ref fields\" (e.g. a per-turn audit pass)\n\t * never pays the cost of reading potentially large content off disk.\n\t */\n\treadRef(id: string): ContextArtifactRef | undefined;\n\thas(id: string): boolean;\n\t/**\n\t * Register that `holderId` (a context item id, session entry id, etc.) depends on this\n\t * artifact. Returns false if `id` does not exist (never written, or already cleaned\n\t * up) so a caller cannot believe it protected an artifact that was never registered.\n\t * Callers must fail closed (treat the artifact as unprotected) on a false return.\n\t */\n\taddReference(id: string, holderId: string): boolean;\n\t/** Release a previously registered dependency. Returns true only if a reference was actually removed. */\n\tremoveReference(id: string, holderId: string): boolean;\n\treferenceCount(id: string): number;\n\t/** Delete only artifacts with zero active references. Returns the ids actually deleted. */\n\tcleanup(): string[];\n}\n\ninterface StoredArtifact {\n\tref: ContextArtifactRef;\n\tcontent: string;\n\treferences: Set<string>;\n}\n\nexport function createInMemoryArtifactStore(): ArtifactStore {\n\tconst artifacts = new Map<string, StoredArtifact>();\n\tconst cleanedUp = new Set<string>();\n\n\treturn {\n\t\twrite(request: ArtifactWriteRequest): ArtifactRecord {\n\t\t\tconst id = generateArtifactId(request);\n\t\t\tconst existing = artifacts.get(id);\n\t\t\tif (existing) {\n\t\t\t\tcleanedUp.delete(id);\n\t\t\t\treturn { ref: existing.ref, content: existing.content };\n\t\t\t}\n\n\t\t\tconst ref = createArtifactRef(id, request);\n\t\t\tartifacts.set(id, { ref, content: request.content, references: new Set() });\n\t\t\tcleanedUp.delete(id);\n\t\t\treturn { ref, content: request.content };\n\t\t},\n\n\t\tread(id: string): ArtifactRecord | MissingArtifactMarker {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) {\n\t\t\t\treturn { id, missing: true, reason: cleanedUp.has(id) ? \"cleaned_up\" : \"not_found\" };\n\t\t\t}\n\t\t\treturn { ref: stored.ref, content: stored.content };\n\t\t},\n\n\t\treadRef(id: string): ContextArtifactRef | undefined {\n\t\t\treturn artifacts.get(id)?.ref;\n\t\t},\n\n\t\thas(id: string): boolean {\n\t\t\treturn artifacts.has(id);\n\t\t},\n\n\t\taddReference(id: string, holderId: string): boolean {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) return false;\n\t\t\tstored.references.add(holderId);\n\t\t\treturn true;\n\t\t},\n\n\t\tremoveReference(id: string, holderId: string): boolean {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) return false;\n\t\t\treturn stored.references.delete(holderId);\n\t\t},\n\n\t\treferenceCount(id: string): number {\n\t\t\treturn artifacts.get(id)?.references.size ?? 0;\n\t\t},\n\n\t\tcleanup(): string[] {\n\t\t\tconst deleted: string[] = [];\n\t\t\tfor (const [id, stored] of artifacts) {\n\t\t\t\tif (stored.references.size === 0) {\n\t\t\t\t\tartifacts.delete(id);\n\t\t\t\t\tcleanedUp.add(id);\n\t\t\t\t\tdeleted.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn deleted;\n\t\t},\n\t};\n}\n\nexport interface FileArtifactStoreOptions {\n\t/** Leased session work directory where payloads and metadata live. Created on first use. */\n\tbaseDir: string;\n\t/** Migrate an existing store before probing it; must remain zero-write when no legacy data exists. */\n\tprepareBaseDir?: () => void;\n\t/** Acquire the owning lease immediately before the first real store access. */\n\tacquireBaseDir?: () => string;\n}\n\ninterface PersistedArtifactMeta {\n\tref: ContextArtifactRef;\n\treferences: string[];\n}\n\nconst META_SUFFIX = \".meta.json\";\nconst PAYLOAD_SUFFIX = \".payload\";\n\n/**\n * Artifact ids are generated by `generateArtifactId` as a lowercase hex digest. Reject\n * anything else so a caller-supplied id (including one echoed back from model output)\n * can never be used as a path-traversal vector into `baseDir`.\n */\nfunction isSafeArtifactId(id: string): boolean {\n\treturn /^[0-9a-f]{1,64}$/.test(id);\n}\n\nfunction payloadPath(baseDir: string, id: string): string {\n\treturn join(baseDir, `${id}${PAYLOAD_SUFFIX}`);\n}\n\nfunction metaPath(baseDir: string, id: string): string {\n\treturn join(baseDir, `${id}${META_SUFFIX}`);\n}\n\nconst VALID_ARTIFACT_KINDS: ReadonlySet<ContextArtifactRef[\"kind\"]> = new Set([\n\t\"tool_output\",\n\t\"file_snapshot\",\n\t\"test_output\",\n\t\"diff\",\n\t\"transcript_slice\",\n]);\n\nfunction isValidArtifactRefShape(value: unknown): value is ContextArtifactRef {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst ref = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof ref.id === \"string\" &&\n\t\ttypeof ref.kind === \"string\" &&\n\t\tVALID_ARTIFACT_KINDS.has(ref.kind as ContextArtifactRef[\"kind\"]) &&\n\t\ttypeof ref.byteLength === \"number\" &&\n\t\ttypeof ref.createdAtTurn === \"number\" &&\n\t\ttypeof ref.reproducible === \"boolean\"\n\t);\n}\n\n/**\n * A parsed JSON value can be syntactically valid but semantically garbage (truncated\n * write, hand-edited file, future/incompatible format). Validate shape, not just parse\n * success, so a malformed sidecar can never produce an invalid ref or crash `cleanup()` --\n * it is treated as unusable/missing, the same as a sidecar that doesn't exist.\n */\nfunction isValidPersistedArtifactMeta(value: unknown): value is PersistedArtifactMeta {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst meta = value as Record<string, unknown>;\n\treturn (\n\t\tisValidArtifactRefShape(meta.ref) &&\n\t\tArray.isArray(meta.references) &&\n\t\tmeta.references.every((entry) => typeof entry === \"string\")\n\t);\n}\n\nfunction readMeta(baseDir: string, id: string): PersistedArtifactMeta | undefined {\n\tconst path = metaPath(baseDir, id);\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n\t\treturn isValidPersistedArtifactMeta(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction writeMeta(baseDir: string, id: string, meta: PersistedArtifactMeta): void {\n\twriteFileSync(metaPath(baseDir, id), JSON.stringify(meta), \"utf8\");\n}\n\n/**\n * Filesystem-backed `ArtifactStore`: payload and metadata (including reference holder ids)\n * are written to `baseDir` so content, ref fields, and cleanup-protecting references all\n * survive recreating the store (e.g. across a process restart against the same\n * directory) -- unlike the in-memory store, which loses everything when the instance is\n * dropped. No SQLite or other index is used; each artifact's metadata is a small sidecar\n * JSON file next to its payload file, per the \"keep SQLite out of scope unless a minimal\n * metadata shape is unavoidable\" constraint for this slice.\n *\n * The one thing that does NOT survive recreation: the missing-artifact reason\n * distinction. A fresh instance has no in-memory record of which ids it personally\n * cleaned up, so a previously-cleaned-up id reads back as \"not_found\" rather than\n * \"cleaned_up\" after a restart. This still always returns an explicit missing marker,\n * never fabricated or empty content -- it only affects which of the two reason codes is\n * reported.\n */\nexport function createFileArtifactStore(options: FileArtifactStoreOptions): ArtifactStore {\n\tconst baseDir = options.baseDir;\n\tconst cleanedUpThisInstance = new Set<string>();\n\tlet acquiredBaseDir: string | undefined;\n\tlet preparedBaseDir = false;\n\tconst ensureBaseDir = (): string => {\n\t\tpreparedBaseDir = true;\n\t\tacquiredBaseDir ??= options.acquireBaseDir?.() ?? baseDir;\n\t\tmkdirSync(acquiredBaseDir, { recursive: true });\n\t\treturn acquiredBaseDir;\n\t};\n\tconst ensureExistingBaseDir = (): boolean => {\n\t\tif (!preparedBaseDir) {\n\t\t\toptions.prepareBaseDir?.();\n\t\t\tpreparedBaseDir = true;\n\t\t}\n\t\tif (!existsSync(baseDir)) return false;\n\t\tensureBaseDir();\n\t\treturn true;\n\t};\n\n\treturn {\n\t\twrite(request: ArtifactWriteRequest): ArtifactRecord {\n\t\t\tensureBaseDir();\n\t\t\tconst id = generateArtifactId(request);\n\t\t\tconst existingMeta = readMeta(baseDir, id);\n\t\t\tconst existingPayloadPath = payloadPath(baseDir, id);\n\t\t\tif (existingMeta && existsSync(existingPayloadPath)) {\n\t\t\t\tcleanedUpThisInstance.delete(id);\n\t\t\t\treturn { ref: existingMeta.ref, content: readFileSync(existingPayloadPath, \"utf8\") };\n\t\t\t}\n\n\t\t\tconst ref = createArtifactRef(id, request);\n\t\t\twriteFileSync(payloadPath(baseDir, id), request.content, \"utf8\");\n\t\t\twriteMeta(baseDir, id, { ref, references: [] });\n\t\t\tcleanedUpThisInstance.delete(id);\n\t\t\treturn { ref, content: request.content };\n\t\t},\n\n\t\tread(id: string): ArtifactRecord | MissingArtifactMarker {\n\t\t\tif (!isSafeArtifactId(id)) return { id, missing: true, reason: \"not_found\" };\n\t\t\tif (!ensureExistingBaseDir()) return { id, missing: true, reason: \"not_found\" };\n\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\tconst pPath = payloadPath(baseDir, id);\n\t\t\tif (!meta || !existsSync(pPath)) {\n\t\t\t\treturn { id, missing: true, reason: cleanedUpThisInstance.has(id) ? \"cleaned_up\" : \"not_found\" };\n\t\t\t}\n\t\t\treturn { ref: meta.ref, content: readFileSync(pPath, \"utf8\") };\n\t\t},\n\n\t\treadRef(id: string): ContextArtifactRef | undefined {\n\t\t\tif (!isSafeArtifactId(id)) return undefined;\n\t\t\tif (!ensureExistingBaseDir()) return undefined;\n\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\tif (!meta || !existsSync(payloadPath(baseDir, id))) return undefined;\n\t\t\treturn meta.ref;\n\t\t},\n\n\t\thas(id: string): boolean {\n\t\t\tif (!isSafeArtifactId(id)) return false;\n\t\t\tif (!ensureExistingBaseDir()) return false;\n\t\t\treturn readMeta(baseDir, id) !== undefined && existsSync(payloadPath(baseDir, id));\n\t\t},\n\n\t\taddReference(id: string, holderId: string): boolean {\n\t\t\tif (!isSafeArtifactId(id)) return false;\n\t\t\tif (!ensureExistingBaseDir()) return false;\n\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\tif (!meta || !existsSync(payloadPath(baseDir, id))) return false;\n\t\t\tif (!meta.references.includes(holderId)) {\n\t\t\t\tmeta.references.push(holderId);\n\t\t\t\twriteMeta(baseDir, id, meta);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\tremoveReference(id: string, holderId: string): boolean {\n\t\t\tif (!isSafeArtifactId(id)) return false;\n\t\t\tif (!ensureExistingBaseDir()) return false;\n\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\tif (!meta) return false;\n\t\t\tconst index = meta.references.indexOf(holderId);\n\t\t\tif (index === -1) return false;\n\t\t\tmeta.references.splice(index, 1);\n\t\t\twriteMeta(baseDir, id, meta);\n\t\t\treturn true;\n\t\t},\n\n\t\treferenceCount(id: string): number {\n\t\t\tif (!isSafeArtifactId(id)) return 0;\n\t\t\tif (!ensureExistingBaseDir()) return 0;\n\t\t\treturn readMeta(baseDir, id)?.references.length ?? 0;\n\t\t},\n\n\t\tcleanup(): string[] {\n\t\t\tconst deleted: string[] = [];\n\t\t\tif (!ensureExistingBaseDir()) return deleted;\n\t\t\tfor (const entry of readdirSync(baseDir)) {\n\t\t\t\tif (!entry.endsWith(META_SUFFIX)) continue;\n\t\t\t\tconst id = entry.slice(0, -META_SUFFIX.length);\n\t\t\t\tif (!isSafeArtifactId(id)) continue;\n\t\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\t\tif (!meta || meta.references.length > 0) continue;\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(metaPath(baseDir, id));\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(payloadPath(baseDir, id));\n\t\t\t\t} catch {\n\t\t\t\t\t// Payload already gone; metadata removal above is what matters for reachability.\n\t\t\t\t}\n\t\t\t\tcleanedUpThisInstance.add(id);\n\t\t\t\tdeleted.push(id);\n\t\t\t}\n\t\t\treturn deleted;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"context-artifacts.js","sourceRoot":"","sources":["../../../src/core/context/context-artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Artifact store abstraction (Phase 2): stable refs for raw large payloads, kept out of\n * band from prompt context. This module defines the `ArtifactStore` interface plus two\n * implementations: an in-memory one for tests, and `createFileArtifactStore` (session-\n * scoped, filesystem-backed). A SQLite-backed implementation waits until the Phase M0\n * storage-authority/location/concurrency decisions are accepted (see\n * docs/context-management-rework/memory-architecture.md).\n *\n * `createFileArtifactStore` is wired into live grep/find tool construction in\n * agent-session.ts (session-scoped under `<agentDir>/work/context/sessions/<sessionId>/artifacts/`).\n * References are registered at pack time and released when context-gc evicts the\n * corresponding grep/find tool result (opportunistic, conservative cleanup), with a\n * best-effort dispose-time sweep for zero-reference artifacts. Payloads are retrievable\n * out of band via the artifact_retrieve tool (context/artifact-retrieval.ts).\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmdirSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\nimport { type ContextArtifactRef, estimateByteLength, estimateLineCount } from \"./context-item.ts\";\n\nexport interface ArtifactWriteRequest {\n\tkind: ContextArtifactRef[\"kind\"];\n\tcontent: string;\n\ttoolName?: string;\n\tcommand?: string;\n\tpath?: string;\n\tsessionEntryId?: string;\n\tcreatedAtTurn: number;\n\treproducible: boolean;\n}\n\nexport interface ArtifactRecord {\n\tref: ContextArtifactRef;\n\tcontent: string;\n}\n\nexport type MissingArtifactReason = \"not_found\" | \"cleaned_up\";\n\nexport interface MissingArtifactMarker {\n\tid: string;\n\tmissing: true;\n\treason: MissingArtifactReason;\n}\n\nexport function isMissingArtifactMarker(value: ArtifactRecord | MissingArtifactMarker): value is MissingArtifactMarker {\n\treturn (value as MissingArtifactMarker).missing === true;\n}\n\n/**\n * Artifact id for a capture event, not merely a payload: it hashes every ref-defining\n * field (kind, tool/command/path, content, sessionEntryId, createdAtTurn, reproducible).\n * A repeat write with identical content but a different turn or session entry is a\n * distinct capture and must get a distinct id -- otherwise the later capture's metadata\n * would be silently discarded in favor of the first write. Only a truly identical\n * request (same capture, re-submitted) is idempotent under this id.\n */\nexport function generateArtifactId(\n\trequest: Pick<\n\t\tArtifactWriteRequest,\n\t\t\"kind\" | \"content\" | \"toolName\" | \"command\" | \"path\" | \"sessionEntryId\" | \"createdAtTurn\" | \"reproducible\"\n\t>,\n): string {\n\tconst hash = createHash(\"sha256\");\n\tfor (const field of [\n\t\trequest.kind,\n\t\trequest.toolName ?? \"\",\n\t\trequest.command ?? \"\",\n\t\trequest.path ?? \"\",\n\t\trequest.sessionEntryId ?? \"\",\n\t\tString(request.createdAtTurn),\n\t\tString(request.reproducible),\n\t]) {\n\t\thash.update(field).update(\"\\0\");\n\t}\n\thash.update(request.content);\n\treturn hash.digest(\"hex\").slice(0, 24);\n}\n\nfunction createArtifactRef(id: string, request: ArtifactWriteRequest): ContextArtifactRef {\n\treturn {\n\t\tid,\n\t\tkind: request.kind,\n\t\tsessionEntryId: request.sessionEntryId,\n\t\ttoolName: request.toolName,\n\t\tcommand: request.command,\n\t\tpath: request.path,\n\t\tbyteLength: estimateByteLength(request.content),\n\t\tlineCount: estimateLineCount(request.content),\n\t\tcreatedAtTurn: request.createdAtTurn,\n\t\treproducible: request.reproducible,\n\t};\n}\n\nexport interface ArtifactStore {\n\twrite(request: ArtifactWriteRequest): ArtifactRecord;\n\tread(id: string): ArtifactRecord | MissingArtifactMarker;\n\t/**\n\t * Metadata-only lookup: the ref if `id` resolves to a live artifact, `undefined`\n\t * otherwise. Never loads the payload -- for the file store this must not touch the\n\t * payload file at all beyond an existence check, so a caller that only needs to know\n\t * \"does this still exist, and what are its ref fields\" (e.g. a per-turn audit pass)\n\t * never pays the cost of reading potentially large content off disk.\n\t */\n\treadRef(id: string): ContextArtifactRef | undefined;\n\thas(id: string): boolean;\n\t/**\n\t * Register that `holderId` (a context item id, session entry id, etc.) depends on this\n\t * artifact. Returns false if `id` does not exist (never written, or already cleaned\n\t * up) so a caller cannot believe it protected an artifact that was never registered.\n\t * Callers must fail closed (treat the artifact as unprotected) on a false return.\n\t */\n\taddReference(id: string, holderId: string): boolean;\n\t/** Release a previously registered dependency. Returns true only if a reference was actually removed. */\n\tremoveReference(id: string, holderId: string): boolean;\n\treferenceCount(id: string): number;\n\t/** Delete only artifacts with zero active references. Returns the ids actually deleted. */\n\tcleanup(): string[];\n}\n\ninterface StoredArtifact {\n\tref: ContextArtifactRef;\n\tcontent: string;\n\treferences: Set<string>;\n}\n\nexport function createInMemoryArtifactStore(): ArtifactStore {\n\tconst artifacts = new Map<string, StoredArtifact>();\n\tconst cleanedUp = new Set<string>();\n\n\treturn {\n\t\twrite(request: ArtifactWriteRequest): ArtifactRecord {\n\t\t\tconst id = generateArtifactId(request);\n\t\t\tconst existing = artifacts.get(id);\n\t\t\tif (existing) {\n\t\t\t\tcleanedUp.delete(id);\n\t\t\t\treturn { ref: existing.ref, content: existing.content };\n\t\t\t}\n\n\t\t\tconst ref = createArtifactRef(id, request);\n\t\t\tartifacts.set(id, { ref, content: request.content, references: new Set() });\n\t\t\tcleanedUp.delete(id);\n\t\t\treturn { ref, content: request.content };\n\t\t},\n\n\t\tread(id: string): ArtifactRecord | MissingArtifactMarker {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) {\n\t\t\t\treturn { id, missing: true, reason: cleanedUp.has(id) ? \"cleaned_up\" : \"not_found\" };\n\t\t\t}\n\t\t\treturn { ref: stored.ref, content: stored.content };\n\t\t},\n\n\t\treadRef(id: string): ContextArtifactRef | undefined {\n\t\t\treturn artifacts.get(id)?.ref;\n\t\t},\n\n\t\thas(id: string): boolean {\n\t\t\treturn artifacts.has(id);\n\t\t},\n\n\t\taddReference(id: string, holderId: string): boolean {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) return false;\n\t\t\tstored.references.add(holderId);\n\t\t\treturn true;\n\t\t},\n\n\t\tremoveReference(id: string, holderId: string): boolean {\n\t\t\tconst stored = artifacts.get(id);\n\t\t\tif (!stored) return false;\n\t\t\treturn stored.references.delete(holderId);\n\t\t},\n\n\t\treferenceCount(id: string): number {\n\t\t\treturn artifacts.get(id)?.references.size ?? 0;\n\t\t},\n\n\t\tcleanup(): string[] {\n\t\t\tconst deleted: string[] = [];\n\t\t\tfor (const [id, stored] of artifacts) {\n\t\t\t\tif (stored.references.size === 0) {\n\t\t\t\t\tartifacts.delete(id);\n\t\t\t\t\tcleanedUp.add(id);\n\t\t\t\t\tdeleted.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn deleted;\n\t\t},\n\t};\n}\n\nexport interface FileArtifactStoreOptions {\n\t/** Leased session work directory where payloads and metadata live. Created on first use. */\n\tbaseDir: string;\n\t/** Migrate an existing store before probing it; must remain zero-write when no legacy data exists. */\n\tprepareBaseDir?: () => void;\n\t/** Acquire the owning lease immediately before the first real store access. */\n\tacquireBaseDir?: () => string;\n}\n\ninterface PersistedArtifactMeta {\n\tref: ContextArtifactRef;\n\treferences: string[];\n}\n\nconst META_SUFFIX = \".meta.json\";\nconst PAYLOAD_SUFFIX = \".payload\";\nconst REFERENCES_SUFFIX = \".refs\";\n\n/**\n * Artifact ids are generated by `generateArtifactId` as a lowercase hex digest. Reject\n * anything else so a caller-supplied id (including one echoed back from model output)\n * can never be used as a path-traversal vector into `baseDir`.\n */\nfunction isSafeArtifactId(id: string): boolean {\n\treturn /^[0-9a-f]{1,64}$/.test(id);\n}\n\nfunction payloadPath(baseDir: string, id: string): string {\n\treturn join(baseDir, `${id}${PAYLOAD_SUFFIX}`);\n}\n\nfunction metaPath(baseDir: string, id: string): string {\n\treturn join(baseDir, `${id}${META_SUFFIX}`);\n}\n\nfunction referencesDir(baseDir: string, id: string): string {\n\treturn join(baseDir, `${id}${REFERENCES_SUFFIX}`);\n}\n\nfunction referencePath(baseDir: string, id: string, holderId: string): string {\n\treturn join(referencesDir(baseDir, id), createHash(\"sha256\").update(holderId).digest(\"hex\"));\n}\n\nconst VALID_ARTIFACT_KINDS: ReadonlySet<ContextArtifactRef[\"kind\"]> = new Set([\n\t\"tool_output\",\n\t\"file_snapshot\",\n\t\"test_output\",\n\t\"diff\",\n\t\"transcript_slice\",\n]);\n\nfunction isValidArtifactRefShape(value: unknown): value is ContextArtifactRef {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst ref = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof ref.id === \"string\" &&\n\t\ttypeof ref.kind === \"string\" &&\n\t\tVALID_ARTIFACT_KINDS.has(ref.kind as ContextArtifactRef[\"kind\"]) &&\n\t\ttypeof ref.byteLength === \"number\" &&\n\t\ttypeof ref.createdAtTurn === \"number\" &&\n\t\ttypeof ref.reproducible === \"boolean\"\n\t);\n}\n\n/**\n * A parsed JSON value can be syntactically valid but semantically garbage (truncated\n * write, hand-edited file, future/incompatible format). Validate shape, not just parse\n * success, so a malformed sidecar can never produce an invalid ref or crash `cleanup()` --\n * it is treated as unusable/missing, the same as a sidecar that doesn't exist.\n */\nfunction isValidPersistedArtifactMeta(value: unknown): value is PersistedArtifactMeta {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst meta = value as Record<string, unknown>;\n\treturn (\n\t\tisValidArtifactRefShape(meta.ref) &&\n\t\tArray.isArray(meta.references) &&\n\t\tmeta.references.every((entry) => typeof entry === \"string\")\n\t);\n}\n\nfunction readMeta(baseDir: string, id: string): PersistedArtifactMeta | undefined {\n\tconst path = metaPath(baseDir, id);\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n\t\treturn isValidPersistedArtifactMeta(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction writeMeta(baseDir: string, id: string, meta: PersistedArtifactMeta): void {\n\twriteFileAtomicSync(metaPath(baseDir, id), JSON.stringify(meta));\n}\n\n/**\n * Holder markers are immutable and every reader/writer holds the artifact lock. A direct exclusive\n * create is therefore already complete before it becomes observable; a temp-file rename would add\n * two Windows filesystem operations per holder without improving the visibility contract.\n */\nfunction writeReferenceMarker(baseDir: string, id: string, holderId: string): void {\n\tconst path = referencePath(baseDir, id, holderId);\n\tmkdirSync(referencesDir(baseDir, id), { recursive: true });\n\twriteFileSync(path, holderId, { encoding: \"utf8\", flag: \"wx\" });\n}\n\n/** Move the legacy shared reference array to O(1)-update holder markers exactly once. */\nfunction migratePersistedReferences(baseDir: string, id: string, meta: PersistedArtifactMeta): void {\n\tif (meta.references.length === 0) return;\n\tfor (const holderId of meta.references) {\n\t\tconst path = referencePath(baseDir, id, holderId);\n\t\tif (!existsSync(path)) writeReferenceMarker(baseDir, id, holderId);\n\t}\n\tmeta.references = [];\n\twriteMeta(baseDir, id, meta);\n}\n\n/** Undefined means the marker directory could not be inspected, so cleanup must fail closed. */\nfunction referenceMarkerCount(baseDir: string, id: string): number | undefined {\n\tconst dir = referencesDir(baseDir, id);\n\tif (!existsSync(dir)) return 0;\n\ttry {\n\t\treturn readdirSync(dir, { withFileTypes: true }).length;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Filesystem-backed `ArtifactStore`: payload and metadata (including reference holder ids)\n * are written to `baseDir` so content, ref fields, and cleanup-protecting references all survive\n * recreating the store (e.g. across a process restart against the same directory) -- unlike the\n * in-memory store, which loses everything when the instance is dropped. Each artifact has a small\n * metadata sidecar plus one hashed holder marker per active reference. Marker updates are O(1) and\n * every lifecycle mutation shares the artifact lock, so foreground/background processes cannot\n * lose ownership through a shared-array read-modify-write race.\n *\n * The one thing that does NOT survive recreation: the missing-artifact reason\n * distinction. A fresh instance has no in-memory record of which ids it personally\n * cleaned up, so a previously-cleaned-up id reads back as \"not_found\" rather than\n * \"cleaned_up\" after a restart. This still always returns an explicit missing marker,\n * never fabricated or empty content -- it only affects which of the two reason codes is\n * reported.\n */\nexport function createFileArtifactStore(options: FileArtifactStoreOptions): ArtifactStore {\n\tconst baseDir = options.baseDir;\n\tconst cleanedUpThisInstance = new Set<string>();\n\tlet acquiredBaseDir: string | undefined;\n\tlet preparedBaseDir = false;\n\tconst ensureBaseDir = (): string => {\n\t\tpreparedBaseDir = true;\n\t\tacquiredBaseDir ??= options.acquireBaseDir?.() ?? baseDir;\n\t\tmkdirSync(acquiredBaseDir, { recursive: true });\n\t\treturn acquiredBaseDir;\n\t};\n\tconst ensureExistingBaseDir = (): boolean => {\n\t\tif (!preparedBaseDir) {\n\t\t\toptions.prepareBaseDir?.();\n\t\t\tpreparedBaseDir = true;\n\t\t}\n\t\tif (!existsSync(baseDir)) return false;\n\t\tensureBaseDir();\n\t\treturn true;\n\t};\n\tconst mutateReference = (id: string, holderId: string, mutate: (path: string) => boolean): boolean => {\n\t\tif (!isSafeArtifactId(id) || !ensureExistingBaseDir()) return false;\n\t\ttry {\n\t\t\treturn withFileLockSync(metaPath(baseDir, id), () => {\n\t\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\t\tif (!meta) return false;\n\t\t\t\tmigratePersistedReferences(baseDir, id, meta);\n\t\t\t\treturn mutate(referencePath(baseDir, id, holderId));\n\t\t\t});\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\treturn {\n\t\twrite(request: ArtifactWriteRequest): ArtifactRecord {\n\t\t\tensureBaseDir();\n\t\t\tconst id = generateArtifactId(request);\n\t\t\treturn withFileLockSync(metaPath(baseDir, id), () => {\n\t\t\t\tconst existingMeta = readMeta(baseDir, id);\n\t\t\t\tconst existingPayloadPath = payloadPath(baseDir, id);\n\t\t\t\tif (existingMeta && existsSync(existingPayloadPath)) {\n\t\t\t\t\tcleanedUpThisInstance.delete(id);\n\t\t\t\t\treturn { ref: existingMeta.ref, content: readFileSync(existingPayloadPath, \"utf8\") };\n\t\t\t\t}\n\n\t\t\t\tconst ref = createArtifactRef(id, request);\n\t\t\t\twriteFileAtomicSync(payloadPath(baseDir, id), request.content);\n\t\t\t\twriteMeta(baseDir, id, { ref, references: [] });\n\t\t\t\tcleanedUpThisInstance.delete(id);\n\t\t\t\treturn { ref, content: request.content };\n\t\t\t});\n\t\t},\n\n\t\tread(id: string): ArtifactRecord | MissingArtifactMarker {\n\t\t\tif (!isSafeArtifactId(id)) return { id, missing: true, reason: \"not_found\" };\n\t\t\tif (!ensureExistingBaseDir()) return { id, missing: true, reason: \"not_found\" };\n\t\t\ttry {\n\t\t\t\treturn withFileLockSync(metaPath(baseDir, id), () => {\n\t\t\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\t\t\tconst pPath = payloadPath(baseDir, id);\n\t\t\t\t\tif (!meta || !existsSync(pPath)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tmissing: true,\n\t\t\t\t\t\t\treason: cleanedUpThisInstance.has(id) ? \"cleaned_up\" : \"not_found\",\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn { ref: meta.ref, content: readFileSync(pPath, \"utf8\") };\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\treturn { id, missing: true, reason: cleanedUpThisInstance.has(id) ? \"cleaned_up\" : \"not_found\" };\n\t\t\t}\n\t\t},\n\n\t\treadRef(id: string): ContextArtifactRef | undefined {\n\t\t\tif (!isSafeArtifactId(id)) return undefined;\n\t\t\tif (!ensureExistingBaseDir()) return undefined;\n\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\tif (!meta || !existsSync(payloadPath(baseDir, id))) return undefined;\n\t\t\treturn meta.ref;\n\t\t},\n\n\t\thas(id: string): boolean {\n\t\t\tif (!isSafeArtifactId(id)) return false;\n\t\t\tif (!ensureExistingBaseDir()) return false;\n\t\t\treturn readMeta(baseDir, id) !== undefined && existsSync(payloadPath(baseDir, id));\n\t\t},\n\n\t\taddReference(id: string, holderId: string): boolean {\n\t\t\treturn mutateReference(id, holderId, (path) => {\n\t\t\t\tif (!existsSync(payloadPath(baseDir, id))) return false;\n\t\t\t\tif (existsSync(path)) return readFileSync(path, \"utf8\") === holderId;\n\t\t\t\twriteReferenceMarker(baseDir, id, holderId);\n\t\t\t\treturn true;\n\t\t\t});\n\t\t},\n\n\t\tremoveReference(id: string, holderId: string): boolean {\n\t\t\treturn mutateReference(id, holderId, (path) => {\n\t\t\t\tif (!existsSync(path) || readFileSync(path, \"utf8\") !== holderId) return false;\n\t\t\t\tunlinkSync(path);\n\t\t\t\ttry {\n\t\t\t\t\trmdirSync(referencesDir(baseDir, id));\n\t\t\t\t} catch {}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t},\n\n\t\treferenceCount(id: string): number {\n\t\t\tif (!isSafeArtifactId(id)) return 0;\n\t\t\tif (!ensureExistingBaseDir()) return 0;\n\t\t\ttry {\n\t\t\t\treturn withFileLockSync(metaPath(baseDir, id), () => {\n\t\t\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\t\t\tif (!meta) return 0;\n\t\t\t\t\tmigratePersistedReferences(baseDir, id, meta);\n\t\t\t\t\treturn referenceMarkerCount(baseDir, id) ?? 0;\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t},\n\n\t\tcleanup(): string[] {\n\t\t\tconst deleted: string[] = [];\n\t\t\tif (!ensureExistingBaseDir()) return deleted;\n\t\t\tfor (const entry of readdirSync(baseDir)) {\n\t\t\t\tif (!entry.endsWith(META_SUFFIX)) continue;\n\t\t\t\tconst id = entry.slice(0, -META_SUFFIX.length);\n\t\t\t\tif (!isSafeArtifactId(id)) continue;\n\t\t\t\ttry {\n\t\t\t\t\twithFileLockSync(metaPath(baseDir, id), () => {\n\t\t\t\t\t\tconst meta = readMeta(baseDir, id);\n\t\t\t\t\t\tif (!meta) return;\n\t\t\t\t\t\tmigratePersistedReferences(baseDir, id, meta);\n\t\t\t\t\t\tconst references = referenceMarkerCount(baseDir, id);\n\t\t\t\t\t\tif (references === undefined || references > 0) return;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tunlinkSync(metaPath(baseDir, id));\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tunlinkSync(payloadPath(baseDir, id));\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Payload already gone; metadata removal above is what matters for reachability.\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trmdirSync(referencesDir(baseDir, id));\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t\tcleanedUpThisInstance.add(id);\n\t\t\t\t\t\tdeleted.push(id);\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t\treturn deleted;\n\t\t},\n\t};\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { estimateTokens } from "@caupulican/pi-agent-core/node";
1
+ import { estimateTokens } from "@caupulican/pi-agent-core/compaction/compaction";
2
2
  function estimateTextTokens(text) {
3
3
  return Math.ceil(text.length / 4);
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"context-composition.js","sourceRoot":"","sources":["../../../src/core/context/context-composition.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport { estimateTokens } from \"@caupulican/pi-agent-core/node\";\nimport type { CurationTelemetrySnapshot } from \"./brain-curator.ts\";\n\n/**\n * Context composition dashboard (user-facing): decomposes EVERYTHING that rides along on every\n * request — system prompt, active tool schemas, extension contributions, injected blocks\n * (memory recall pages, evidence blocks), and the session messages themselves (raw vs. GC-packed\n * vs. policy-stubbed) — so a user integrating their own tools/extensions can see exactly what\n * each addition costs per request and where cleaning is (or is not) working.\n *\n * Honesty contract: everything here is an ESTIMATE (chars/4) EXCEPT `providerReportedTokens`,\n * which is what the provider actually billed. The dashboard always shows both and the delta —\n * the delta is the measure of how much the estimates can be trusted, never hidden.\n *\n * Known exclusions (named, not hidden): extension `context` handlers may rewrite messages at\n * send time in ways this view cannot see. The memory evidence block and enforcement stubbing\n * are ALSO send-time-only, but those are modeled explicitly via `adjustments`.\n */\n\nexport interface ToolCompositionRow {\n\tname: string;\n\t/** Estimated tokens for the tool's name+description+schema as sent to the provider. */\n\tschemaTokens: number;\n\tsource: \"built-in\" | \"extension\";\n}\n\nexport interface ExtensionCompositionRow {\n\tname: string;\n\tpath: string;\n\ttoolCount: number;\n\tcommandCount: number;\n\t/** Estimated schema tokens of this extension's ACTIVE tools (its per-request cost). */\n\tactiveToolSchemaTokens: number;\n}\n\nexport interface MessageClassRow {\n\tlabel: string;\n\tcount: number;\n\ttokens: number;\n}\n\nexport interface ContextCompositionReport {\n\t/** Estimated tokens of the system prompt sent on every request. */\n\tsystemPromptTokens: number;\n\tsystemPromptChars: number;\n\t/** Estimated tokens of ALL active tool schemas sent on every request. */\n\ttoolSchemaTokens: number;\n\ttools: ToolCompositionRow[];\n\textensions: ExtensionCompositionRow[];\n\t/** Session message classes (raw/user/assistant/stubs/recall pages), heaviest first. */\n\tmessageClasses: MessageClassRow[];\n\tmessageTokens: number;\n\tmessageCount: number;\n\t/** Estimated total sent per request: system prompt + tool schemas + messages. */\n\testimatedRequestTokens: number;\n\t/** What the provider actually reported for the current context, when known. */\n\tproviderReportedTokens: number | null;\n\tcontextWindow: number | null;\n\tgc: { packedCount: number; savedTokens: number } | null;\n\tenforcement: { enforcedCount: number; advisoryEvictions: number } | null;\n\tcuration: { enabled: boolean; telemetry: CurationTelemetrySnapshot; lastSkipReason?: string } | null;\n\t/** Background/side-channel spend that does NOT ride in this context but bills the account. */\n\tspawned: { cost: number; reports: number } | null;\n\t/** Send-time-only deltas folded into estimatedRequestTokens: +evidence block, -policy stubs. */\n\tadjustments: { memoryEvidenceTokens: number; enforcementSavedTokens: number };\n\t/** Actionable, bounded observations derived from the numbers above. */\n\tobservations: string[];\n}\n\nexport interface BuildContextCompositionInput {\n\tsystemPrompt: string;\n\ttools: Array<{ name: string; description?: string; parameters?: unknown; source?: \"built-in\" | \"extension\" }>;\n\textensions: Array<{\n\t\tname: string;\n\t\tpath: string;\n\t\ttoolNames: string[];\n\t\tcommandCount: number;\n\t}>;\n\tmessages: AgentMessage[];\n\tproviderReportedTokens: number | null;\n\tcontextWindow: number | null;\n\tgc?: { packedCount: number; savedTokens: number };\n\tenforcement?: { enforcedCount: number; advisoryEvictions: number };\n\tcuration?: { enabled: boolean; telemetry: CurationTelemetrySnapshot; lastSkipReason?: string };\n\tspawned?: { cost: number; reports: number };\n\tadjustments?: { memoryEvidenceTokens: number; enforcementSavedTokens: number };\n\t/** Pre-formed warnings from other subsystems (e.g. profile-withheld context files). */\n\textraObservations?: string[];\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction messageText(message: AgentMessage): string {\n\tconst content = (message as { content?: unknown }).content;\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => (part as { type?: string }).type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n}\n\nfunction classifyMessage(message: AgentMessage): string {\n\tconst details = (\n\t\tmessage as { details?: { contextGc?: { packed?: unknown }; promptPolicy?: { enforced?: unknown } } }\n\t).details;\n\tif (details?.contextGc?.packed === true) return \"gc-packed stub\";\n\tif (details?.promptPolicy?.enforced === true) return \"policy stub\";\n\tif (message.role === \"custom\") {\n\t\tconst customType = (message as { customType?: string }).customType ?? \"\";\n\t\tif (customType === \"memory_context\" || messageText(message).includes(\"<memory_context\")) {\n\t\t\treturn \"memory recall page\";\n\t\t}\n\t\treturn `custom (${customType || \"unknown\"})`;\n\t}\n\tif (message.role === \"toolResult\") return `toolResult (${(message as { toolName?: string }).toolName ?? \"?\"})`;\n\treturn message.role;\n}\n\nexport function buildContextCompositionReport(input: BuildContextCompositionInput): ContextCompositionReport {\n\tconst systemPromptTokens = estimateTextTokens(input.systemPrompt);\n\n\tconst tools: ToolCompositionRow[] = input.tools\n\t\t.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tschemaTokens: estimateTextTokens(\n\t\t\t\tJSON.stringify({ name: tool.name, description: tool.description ?? \"\", parameters: tool.parameters ?? {} }),\n\t\t\t),\n\t\t\tsource: tool.source ?? (\"built-in\" as const),\n\t\t}))\n\t\t.sort((a, b) => b.schemaTokens - a.schemaTokens);\n\tconst toolSchemaTokens = tools.reduce((sum, tool) => sum + tool.schemaTokens, 0);\n\tconst toolTokensByName = new Map(tools.map((tool) => [tool.name, tool.schemaTokens]));\n\n\tconst extensions: ExtensionCompositionRow[] = input.extensions\n\t\t.map((extension) => ({\n\t\t\tname: extension.name,\n\t\t\tpath: extension.path,\n\t\t\ttoolCount: extension.toolNames.length,\n\t\t\tcommandCount: extension.commandCount,\n\t\t\tactiveToolSchemaTokens: extension.toolNames.reduce(\n\t\t\t\t(sum, toolName) => sum + (toolTokensByName.get(toolName) ?? 0),\n\t\t\t\t0,\n\t\t\t),\n\t\t}))\n\t\t.sort((a, b) => b.activeToolSchemaTokens - a.activeToolSchemaTokens);\n\n\tconst classes = new Map<string, MessageClassRow>();\n\tlet messageTokens = 0;\n\tfor (const message of input.messages) {\n\t\tconst label = classifyMessage(message);\n\t\tconst tokens = estimateTokens(message);\n\t\tmessageTokens += tokens;\n\t\tconst row = classes.get(label) ?? { label, count: 0, tokens: 0 };\n\t\trow.count++;\n\t\trow.tokens += tokens;\n\t\tclasses.set(label, row);\n\t}\n\tconst messageClasses = [...classes.values()].sort((a, b) => b.tokens - a.tokens);\n\n\tconst adjustments = input.adjustments ?? { memoryEvidenceTokens: 0, enforcementSavedTokens: 0 };\n\tconst estimatedRequestTokens = Math.max(\n\t\t0,\n\t\tsystemPromptTokens +\n\t\t\ttoolSchemaTokens +\n\t\t\tmessageTokens +\n\t\t\tadjustments.memoryEvidenceTokens -\n\t\t\tadjustments.enforcementSavedTokens,\n\t);\n\n\tconst observations: string[] = [...(input.extraObservations ?? [])];\n\tconst heaviestTool = tools[0];\n\tif (heaviestTool && toolSchemaTokens > 0 && heaviestTool.schemaTokens > Math.max(500, toolSchemaTokens * 0.3)) {\n\t\tobservations.push(\n\t\t\t`tool \"${heaviestTool.name}\" alone is ~${heaviestTool.schemaTokens} tokens of schema on EVERY request — trim its description/schema if you own it`,\n\t\t);\n\t}\n\tconst recall = messageClasses.find((row) => row.label === \"memory recall page\");\n\tif (recall && recall.tokens > 1500) {\n\t\tobservations.push(\n\t\t\t`${recall.count} memory recall page(s) hold ~${recall.tokens} tokens — verify context GC is packing stale ones (gc packed: ${input.gc?.packedCount ?? 0})`,\n\t\t);\n\t}\n\tif (input.contextWindow && systemPromptTokens + toolSchemaTokens > input.contextWindow * 0.35) {\n\t\tobservations.push(\n\t\t\t`fixed per-request overhead (system+tools) is ~${Math.round(((systemPromptTokens + toolSchemaTokens) / input.contextWindow) * 100)}% of the context window before any conversation`,\n\t\t);\n\t}\n\tif (input.providerReportedTokens !== null) {\n\t\tconst delta = input.providerReportedTokens - estimatedRequestTokens;\n\t\tif (Math.abs(delta) > Math.max(2000, estimatedRequestTokens * 0.25)) {\n\t\t\tobservations.push(\n\t\t\t\t`provider-reported context (${input.providerReportedTokens}) differs from the estimate by ${delta > 0 ? \"+\" : \"\"}${delta} tokens — treat estimates as directional`,\n\t\t\t);\n\t\t}\n\t}\n\tif (input.curation?.enabled && input.curation.lastSkipReason) {\n\t\tobservations.push(`curation is enabled but idle: ${input.curation.lastSkipReason}`);\n\t}\n\n\treturn {\n\t\tsystemPromptTokens,\n\t\tsystemPromptChars: input.systemPrompt.length,\n\t\ttoolSchemaTokens,\n\t\ttools,\n\t\textensions,\n\t\tmessageClasses,\n\t\tmessageTokens,\n\t\tmessageCount: input.messages.length,\n\t\testimatedRequestTokens,\n\t\tproviderReportedTokens: input.providerReportedTokens,\n\t\tcontextWindow: input.contextWindow,\n\t\tgc: input.gc ?? null,\n\t\tenforcement: input.enforcement ?? null,\n\t\tcuration: input.curation ?? null,\n\t\tspawned: input.spawned ?? null,\n\t\tadjustments,\n\t\tobservations,\n\t};\n}\n\n/** Bounded plain-text dashboard (interactive `/context` command and tests). */\nexport function formatContextCompositionDashboard(report: ContextCompositionReport, maxToolRows = 10): string {\n\tconst pct = (tokens: number) =>\n\t\treport.contextWindow ? ` (${((tokens / report.contextWindow) * 100).toFixed(1)}% of window)` : \"\";\n\tconst lines: string[] = [\n\t\t\"Context composition — what rides on EVERY request\",\n\t\t`estimated request total: ~${report.estimatedRequestTokens} tokens${pct(report.estimatedRequestTokens)}${\n\t\t\treport.providerReportedTokens !== null ? ` · provider-reported: ${report.providerReportedTokens}` : \"\"\n\t\t}`,\n\t\t\"\",\n\t\t`system prompt: ~${report.systemPromptTokens} tokens (${report.systemPromptChars} chars)`,\n\t\t`tool schemas: ~${report.toolSchemaTokens} tokens across ${report.tools.length} active tool(s)`,\n\t];\n\tfor (const tool of report.tools.slice(0, maxToolRows)) {\n\t\tlines.push(` - ${tool.name}: ~${tool.schemaTokens} tok [${tool.source}]`);\n\t}\n\tif (report.tools.length > maxToolRows) {\n\t\tconst rest = report.tools.slice(maxToolRows).reduce((sum, tool) => sum + tool.schemaTokens, 0);\n\t\tlines.push(` - (+${report.tools.length - maxToolRows} more: ~${rest} tok)`);\n\t}\n\tif (report.extensions.length > 0) {\n\t\tlines.push(\"\", \"extensions:\");\n\t\tfor (const extension of report.extensions.slice(0, 8)) {\n\t\t\tlines.push(\n\t\t\t\t` - ${extension.name}: ${extension.toolCount} tool(s), ${extension.commandCount} command(s), ~${extension.activeToolSchemaTokens} tok of active schemas`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\"\", `session messages: ${report.messageCount} row(s), ~${report.messageTokens} tokens`);\n\tif (report.adjustments.memoryEvidenceTokens > 0 || report.adjustments.enforcementSavedTokens > 0) {\n\t\tlines.push(\n\t\t\t`send-time adjustments: +${report.adjustments.memoryEvidenceTokens} memory evidence, -${report.adjustments.enforcementSavedTokens} policy stubs (applied when the request is built)`,\n\t\t);\n\t}\n\tfor (const row of report.messageClasses.slice(0, 10)) {\n\t\tlines.push(` - ${row.label}: ${row.count} row(s), ~${row.tokens} tok`);\n\t}\n\tif (report.gc) {\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t`context GC: ${report.gc.packedCount} row(s) packed, ~${report.gc.savedTokens} tokens saved this pass`,\n\t\t);\n\t}\n\tif (report.enforcement) {\n\t\tlines.push(\n\t\t\t`prompt policy: ${report.enforcement.enforcedCount} stub(s) this turn (${report.enforcement.advisoryEvictions} via brain advisory)`,\n\t\t);\n\t}\n\tif (report.curation) {\n\t\tconst t = report.curation.telemetry;\n\t\tlines.push(\n\t\t\t`brain curation: ${report.curation.enabled ? \"enabled\" : \"disabled\"} — ${t.jobsRun} job(s) run, ${t.parseFailures} parse failure(s), ${t.digestsServed} digest(s) served into stubs, ${t.queued} queued, ~${Math.ceil(t.localChars / 4)} tokens processed locally${\n\t\t\t\treport.curation.lastSkipReason ? ` · last skip: ${report.curation.lastSkipReason}` : \"\"\n\t\t\t}`,\n\t\t);\n\t}\n\tif (report.spawned && report.spawned.reports > 0) {\n\t\tlines.push(\n\t\t\t`spawned/background spend (NOT in this context): ${report.spawned.reports} report(s), $${report.spawned.cost.toFixed(4)}`,\n\t\t);\n\t}\n\tif (report.observations.length > 0) {\n\t\tlines.push(\"\", \"observations:\");\n\t\tfor (const observation of report.observations.slice(0, 5)) {\n\t\t\tlines.push(` ! ${observation}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"context-composition.js","sourceRoot":"","sources":["../../../src/core/context/context-composition.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport { estimateTokens } from \"@caupulican/pi-agent-core/compaction/compaction\";\nimport type { CurationTelemetrySnapshot } from \"./brain-curator.ts\";\n\n/**\n * Context composition dashboard (user-facing): decomposes EVERYTHING that rides along on every\n * request — system prompt, active tool schemas, extension contributions, injected blocks\n * (memory recall pages, evidence blocks), and the session messages themselves (raw vs. GC-packed\n * vs. policy-stubbed) — so a user integrating their own tools/extensions can see exactly what\n * each addition costs per request and where cleaning is (or is not) working.\n *\n * Honesty contract: everything here is an ESTIMATE (chars/4) EXCEPT `providerReportedTokens`,\n * which is what the provider actually billed. The dashboard always shows both and the delta —\n * the delta is the measure of how much the estimates can be trusted, never hidden.\n *\n * Known exclusions (named, not hidden): extension `context` handlers may rewrite messages at\n * send time in ways this view cannot see. The memory evidence block and enforcement stubbing\n * are ALSO send-time-only, but those are modeled explicitly via `adjustments`.\n */\n\nexport interface ToolCompositionRow {\n\tname: string;\n\t/** Estimated tokens for the tool's name+description+schema as sent to the provider. */\n\tschemaTokens: number;\n\tsource: \"built-in\" | \"extension\";\n}\n\nexport interface ExtensionCompositionRow {\n\tname: string;\n\tpath: string;\n\ttoolCount: number;\n\tcommandCount: number;\n\t/** Estimated schema tokens of this extension's ACTIVE tools (its per-request cost). */\n\tactiveToolSchemaTokens: number;\n}\n\nexport interface MessageClassRow {\n\tlabel: string;\n\tcount: number;\n\ttokens: number;\n}\n\nexport interface ContextCompositionReport {\n\t/** Estimated tokens of the system prompt sent on every request. */\n\tsystemPromptTokens: number;\n\tsystemPromptChars: number;\n\t/** Estimated tokens of ALL active tool schemas sent on every request. */\n\ttoolSchemaTokens: number;\n\ttools: ToolCompositionRow[];\n\textensions: ExtensionCompositionRow[];\n\t/** Session message classes (raw/user/assistant/stubs/recall pages), heaviest first. */\n\tmessageClasses: MessageClassRow[];\n\tmessageTokens: number;\n\tmessageCount: number;\n\t/** Estimated total sent per request: system prompt + tool schemas + messages. */\n\testimatedRequestTokens: number;\n\t/** What the provider actually reported for the current context, when known. */\n\tproviderReportedTokens: number | null;\n\tcontextWindow: number | null;\n\tgc: { packedCount: number; savedTokens: number } | null;\n\tenforcement: { enforcedCount: number; advisoryEvictions: number } | null;\n\tcuration: { enabled: boolean; telemetry: CurationTelemetrySnapshot; lastSkipReason?: string } | null;\n\t/** Background/side-channel spend that does NOT ride in this context but bills the account. */\n\tspawned: { cost: number; reports: number } | null;\n\t/** Send-time-only deltas folded into estimatedRequestTokens: +evidence block, -policy stubs. */\n\tadjustments: { memoryEvidenceTokens: number; enforcementSavedTokens: number };\n\t/** Actionable, bounded observations derived from the numbers above. */\n\tobservations: string[];\n}\n\nexport interface BuildContextCompositionInput {\n\tsystemPrompt: string;\n\ttools: Array<{ name: string; description?: string; parameters?: unknown; source?: \"built-in\" | \"extension\" }>;\n\textensions: Array<{\n\t\tname: string;\n\t\tpath: string;\n\t\ttoolNames: string[];\n\t\tcommandCount: number;\n\t}>;\n\tmessages: AgentMessage[];\n\tproviderReportedTokens: number | null;\n\tcontextWindow: number | null;\n\tgc?: { packedCount: number; savedTokens: number };\n\tenforcement?: { enforcedCount: number; advisoryEvictions: number };\n\tcuration?: { enabled: boolean; telemetry: CurationTelemetrySnapshot; lastSkipReason?: string };\n\tspawned?: { cost: number; reports: number };\n\tadjustments?: { memoryEvidenceTokens: number; enforcementSavedTokens: number };\n\t/** Pre-formed warnings from other subsystems (e.g. profile-withheld context files). */\n\textraObservations?: string[];\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction messageText(message: AgentMessage): string {\n\tconst content = (message as { content?: unknown }).content;\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => (part as { type?: string }).type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n}\n\nfunction classifyMessage(message: AgentMessage): string {\n\tconst details = (\n\t\tmessage as { details?: { contextGc?: { packed?: unknown }; promptPolicy?: { enforced?: unknown } } }\n\t).details;\n\tif (details?.contextGc?.packed === true) return \"gc-packed stub\";\n\tif (details?.promptPolicy?.enforced === true) return \"policy stub\";\n\tif (message.role === \"custom\") {\n\t\tconst customType = (message as { customType?: string }).customType ?? \"\";\n\t\tif (customType === \"memory_context\" || messageText(message).includes(\"<memory_context\")) {\n\t\t\treturn \"memory recall page\";\n\t\t}\n\t\treturn `custom (${customType || \"unknown\"})`;\n\t}\n\tif (message.role === \"toolResult\") return `toolResult (${(message as { toolName?: string }).toolName ?? \"?\"})`;\n\treturn message.role;\n}\n\nexport function buildContextCompositionReport(input: BuildContextCompositionInput): ContextCompositionReport {\n\tconst systemPromptTokens = estimateTextTokens(input.systemPrompt);\n\n\tconst tools: ToolCompositionRow[] = input.tools\n\t\t.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tschemaTokens: estimateTextTokens(\n\t\t\t\tJSON.stringify({ name: tool.name, description: tool.description ?? \"\", parameters: tool.parameters ?? {} }),\n\t\t\t),\n\t\t\tsource: tool.source ?? (\"built-in\" as const),\n\t\t}))\n\t\t.sort((a, b) => b.schemaTokens - a.schemaTokens);\n\tconst toolSchemaTokens = tools.reduce((sum, tool) => sum + tool.schemaTokens, 0);\n\tconst toolTokensByName = new Map(tools.map((tool) => [tool.name, tool.schemaTokens]));\n\n\tconst extensions: ExtensionCompositionRow[] = input.extensions\n\t\t.map((extension) => ({\n\t\t\tname: extension.name,\n\t\t\tpath: extension.path,\n\t\t\ttoolCount: extension.toolNames.length,\n\t\t\tcommandCount: extension.commandCount,\n\t\t\tactiveToolSchemaTokens: extension.toolNames.reduce(\n\t\t\t\t(sum, toolName) => sum + (toolTokensByName.get(toolName) ?? 0),\n\t\t\t\t0,\n\t\t\t),\n\t\t}))\n\t\t.sort((a, b) => b.activeToolSchemaTokens - a.activeToolSchemaTokens);\n\n\tconst classes = new Map<string, MessageClassRow>();\n\tlet messageTokens = 0;\n\tfor (const message of input.messages) {\n\t\tconst label = classifyMessage(message);\n\t\tconst tokens = estimateTokens(message);\n\t\tmessageTokens += tokens;\n\t\tconst row = classes.get(label) ?? { label, count: 0, tokens: 0 };\n\t\trow.count++;\n\t\trow.tokens += tokens;\n\t\tclasses.set(label, row);\n\t}\n\tconst messageClasses = [...classes.values()].sort((a, b) => b.tokens - a.tokens);\n\n\tconst adjustments = input.adjustments ?? { memoryEvidenceTokens: 0, enforcementSavedTokens: 0 };\n\tconst estimatedRequestTokens = Math.max(\n\t\t0,\n\t\tsystemPromptTokens +\n\t\t\ttoolSchemaTokens +\n\t\t\tmessageTokens +\n\t\t\tadjustments.memoryEvidenceTokens -\n\t\t\tadjustments.enforcementSavedTokens,\n\t);\n\n\tconst observations: string[] = [...(input.extraObservations ?? [])];\n\tconst heaviestTool = tools[0];\n\tif (heaviestTool && toolSchemaTokens > 0 && heaviestTool.schemaTokens > Math.max(500, toolSchemaTokens * 0.3)) {\n\t\tobservations.push(\n\t\t\t`tool \"${heaviestTool.name}\" alone is ~${heaviestTool.schemaTokens} tokens of schema on EVERY request — trim its description/schema if you own it`,\n\t\t);\n\t}\n\tconst recall = messageClasses.find((row) => row.label === \"memory recall page\");\n\tif (recall && recall.tokens > 1500) {\n\t\tobservations.push(\n\t\t\t`${recall.count} memory recall page(s) hold ~${recall.tokens} tokens — verify context GC is packing stale ones (gc packed: ${input.gc?.packedCount ?? 0})`,\n\t\t);\n\t}\n\tif (input.contextWindow && systemPromptTokens + toolSchemaTokens > input.contextWindow * 0.35) {\n\t\tobservations.push(\n\t\t\t`fixed per-request overhead (system+tools) is ~${Math.round(((systemPromptTokens + toolSchemaTokens) / input.contextWindow) * 100)}% of the context window before any conversation`,\n\t\t);\n\t}\n\tif (input.providerReportedTokens !== null) {\n\t\tconst delta = input.providerReportedTokens - estimatedRequestTokens;\n\t\tif (Math.abs(delta) > Math.max(2000, estimatedRequestTokens * 0.25)) {\n\t\t\tobservations.push(\n\t\t\t\t`provider-reported context (${input.providerReportedTokens}) differs from the estimate by ${delta > 0 ? \"+\" : \"\"}${delta} tokens — treat estimates as directional`,\n\t\t\t);\n\t\t}\n\t}\n\tif (input.curation?.enabled && input.curation.lastSkipReason) {\n\t\tobservations.push(`curation is enabled but idle: ${input.curation.lastSkipReason}`);\n\t}\n\n\treturn {\n\t\tsystemPromptTokens,\n\t\tsystemPromptChars: input.systemPrompt.length,\n\t\ttoolSchemaTokens,\n\t\ttools,\n\t\textensions,\n\t\tmessageClasses,\n\t\tmessageTokens,\n\t\tmessageCount: input.messages.length,\n\t\testimatedRequestTokens,\n\t\tproviderReportedTokens: input.providerReportedTokens,\n\t\tcontextWindow: input.contextWindow,\n\t\tgc: input.gc ?? null,\n\t\tenforcement: input.enforcement ?? null,\n\t\tcuration: input.curation ?? null,\n\t\tspawned: input.spawned ?? null,\n\t\tadjustments,\n\t\tobservations,\n\t};\n}\n\n/** Bounded plain-text dashboard (interactive `/context` command and tests). */\nexport function formatContextCompositionDashboard(report: ContextCompositionReport, maxToolRows = 10): string {\n\tconst pct = (tokens: number) =>\n\t\treport.contextWindow ? ` (${((tokens / report.contextWindow) * 100).toFixed(1)}% of window)` : \"\";\n\tconst lines: string[] = [\n\t\t\"Context composition — what rides on EVERY request\",\n\t\t`estimated request total: ~${report.estimatedRequestTokens} tokens${pct(report.estimatedRequestTokens)}${\n\t\t\treport.providerReportedTokens !== null ? ` · provider-reported: ${report.providerReportedTokens}` : \"\"\n\t\t}`,\n\t\t\"\",\n\t\t`system prompt: ~${report.systemPromptTokens} tokens (${report.systemPromptChars} chars)`,\n\t\t`tool schemas: ~${report.toolSchemaTokens} tokens across ${report.tools.length} active tool(s)`,\n\t];\n\tfor (const tool of report.tools.slice(0, maxToolRows)) {\n\t\tlines.push(` - ${tool.name}: ~${tool.schemaTokens} tok [${tool.source}]`);\n\t}\n\tif (report.tools.length > maxToolRows) {\n\t\tconst rest = report.tools.slice(maxToolRows).reduce((sum, tool) => sum + tool.schemaTokens, 0);\n\t\tlines.push(` - (+${report.tools.length - maxToolRows} more: ~${rest} tok)`);\n\t}\n\tif (report.extensions.length > 0) {\n\t\tlines.push(\"\", \"extensions:\");\n\t\tfor (const extension of report.extensions.slice(0, 8)) {\n\t\t\tlines.push(\n\t\t\t\t` - ${extension.name}: ${extension.toolCount} tool(s), ${extension.commandCount} command(s), ~${extension.activeToolSchemaTokens} tok of active schemas`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\"\", `session messages: ${report.messageCount} row(s), ~${report.messageTokens} tokens`);\n\tif (report.adjustments.memoryEvidenceTokens > 0 || report.adjustments.enforcementSavedTokens > 0) {\n\t\tlines.push(\n\t\t\t`send-time adjustments: +${report.adjustments.memoryEvidenceTokens} memory evidence, -${report.adjustments.enforcementSavedTokens} policy stubs (applied when the request is built)`,\n\t\t);\n\t}\n\tfor (const row of report.messageClasses.slice(0, 10)) {\n\t\tlines.push(` - ${row.label}: ${row.count} row(s), ~${row.tokens} tok`);\n\t}\n\tif (report.gc) {\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t`context GC: ${report.gc.packedCount} row(s) packed, ~${report.gc.savedTokens} tokens saved this pass`,\n\t\t);\n\t}\n\tif (report.enforcement) {\n\t\tlines.push(\n\t\t\t`prompt policy: ${report.enforcement.enforcedCount} stub(s) this turn (${report.enforcement.advisoryEvictions} via brain advisory)`,\n\t\t);\n\t}\n\tif (report.curation) {\n\t\tconst t = report.curation.telemetry;\n\t\tlines.push(\n\t\t\t`brain curation: ${report.curation.enabled ? \"enabled\" : \"disabled\"} — ${t.jobsRun} job(s) run, ${t.parseFailures} parse failure(s), ${t.digestsServed} digest(s) served into stubs, ${t.queued} queued, ~${Math.ceil(t.localChars / 4)} tokens processed locally${\n\t\t\t\treport.curation.lastSkipReason ? ` · last skip: ${report.curation.lastSkipReason}` : \"\"\n\t\t\t}`,\n\t\t);\n\t}\n\tif (report.spawned && report.spawned.reports > 0) {\n\t\tlines.push(\n\t\t\t`spawned/background spend (NOT in this context): ${report.spawned.reports} report(s), $${report.spawned.cost.toFixed(4)}`,\n\t\t);\n\t}\n\tif (report.observations.length > 0) {\n\t\tlines.push(\"\", \"observations:\");\n\t\tfor (const observation of report.observations.slice(0, 5)) {\n\t\t\tlines.push(` ! ${observation}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"context-store-retention.d.ts","sourceRoot":"","sources":["../../../src/core/context/context-store-retention.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,WAAW,CAAC;AAElD,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC;CAChB;AA0GD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAyBzF;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,4BAAiC,GAAG,MAAM,EAAE,CAEzG;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtG;AAED,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,4BAAiC,GACxC,0BAA0B,CAmB5B"}
1
+ {"version":3,"file":"context-store-retention.d.ts","sourceRoot":"","sources":["../../../src/core/context/context-store-retention.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,WAAW,CAAC;AAElD,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC;CAChB;AAgHD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAyBzF;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,4BAAiC,GAAG,MAAM,EAAE,CAEzG;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtG;AAED,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,4BAAiC,GACxC,0BAA0B,CAmB5B"}
@@ -27,7 +27,7 @@ function legacyContextStores(agentDir) {
27
27
  function isRecognizedPayload(kind, name) {
28
28
  if (kind === "gc")
29
29
  return /^[0-9a-f]{1,64}\.txt$/.test(name);
30
- return /^[0-9a-f]{1,64}(?:\.payload|\.meta\.json)$/.test(name);
30
+ return /^[0-9a-f]{1,64}(?:\.payload|\.meta\.json|\.refs)$/.test(name);
31
31
  }
32
32
  function isRealDirectory(path) {
33
33
  try {
@@ -44,7 +44,10 @@ function recognizedPayloads(sourceDir, kind) {
44
44
  if (entries.length > MAX_LEGACY_FILES_PER_SESSION)
45
45
  return undefined;
46
46
  return entries
47
- .filter((entry) => entry.isFile() && !entry.isSymbolicLink() && isRecognizedPayload(kind, entry.name))
47
+ .filter((entry) => (entry.isFile() ||
48
+ (kind === "artifacts" && entry.isDirectory() && /^[0-9a-f]{1,64}\.refs$/.test(entry.name))) &&
49
+ !entry.isSymbolicLink() &&
50
+ isRecognizedPayload(kind, entry.name))
48
51
  .map((entry) => entry.name);
49
52
  }
50
53
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"context-store-retention.js","sourceRoot":"","sources":["../../../src/core/context/context-store-retention.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmdirSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n\ttype WorkRetentionOptions,\n} from \"../../utils/work-directory.ts\";\n\nconst DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\nconst DEFAULT_MAX_SESSION_DIRS = 64;\nconst DEFAULT_MAX_TOTAL_BYTES = 512 * 1024 * 1024;\nconst MAX_LEGACY_SESSION_DIRS = 10_000;\nconst MAX_LEGACY_FILES_PER_SESSION = 100_000;\nconst CONTEXT_WORK_TENANT = \"sessions\";\nconst WORK_RUN_MANIFEST_FILE = \".pi-work-run.json\";\n\nexport type ContextStoreKind = \"gc\" | \"artifacts\";\n\nexport interface ContextStoreRetentionOptions {\n\tmaxAgeMs?: number;\n\tmaxSessionDirs?: number;\n\tmaxTotalBytes?: number;\n\tnow?: number;\n}\n\nexport interface ContextStoreRetentionLease {\n\treadonly gcDir: string;\n\treadonly artifactsDir: string;\n\trelease(): void;\n}\n\ninterface LegacyContextStore {\n\troot: string;\n\tkind: ContextStoreKind;\n\tmanagedRun: boolean;\n}\n\nfunction toWorkRetention(options: ContextStoreRetentionOptions): WorkRetentionOptions {\n\treturn {\n\t\tmaxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n\t\tmaxRuns: options.maxSessionDirs ?? DEFAULT_MAX_SESSION_DIRS,\n\t\tmaxTotalBytes: options.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES,\n\t\tnow: options.now,\n\t};\n}\n\nfunction legacyContextStores(agentDir: string): LegacyContextStore[] {\n\treturn [\n\t\t{ root: join(agentDir, \"context-gc\"), kind: \"gc\", managedRun: false },\n\t\t{ root: join(agentDir, \"context-artifacts\"), kind: \"artifacts\", managedRun: false },\n\t\t{ root: getWorkTenantDir(agentDir, \"context\", \"gc\"), kind: \"gc\", managedRun: true },\n\t\t{ root: getWorkTenantDir(agentDir, \"context\", \"artifacts\"), kind: \"artifacts\", managedRun: true },\n\t];\n}\n\nfunction isRecognizedPayload(kind: ContextStoreKind, name: string): boolean {\n\tif (kind === \"gc\") return /^[0-9a-f]{1,64}\\.txt$/.test(name);\n\treturn /^[0-9a-f]{1,64}(?:\\.payload|\\.meta\\.json)$/.test(name);\n}\n\nfunction isRealDirectory(path: string): boolean {\n\ttry {\n\t\tconst stats = lstatSync(path);\n\t\treturn stats.isDirectory() && !stats.isSymbolicLink();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction recognizedPayloads(sourceDir: string, kind: ContextStoreKind): string[] | undefined {\n\ttry {\n\t\tconst entries = readdirSync(sourceDir, { withFileTypes: true });\n\t\tif (entries.length > MAX_LEGACY_FILES_PER_SESSION) return undefined;\n\t\treturn entries\n\t\t\t.filter((entry) => entry.isFile() && !entry.isSymbolicLink() && isRecognizedPayload(kind, entry.name))\n\t\t\t.map((entry) => entry.name);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction removeLegacyRunIfEmpty(sourceDir: string, managedRun: boolean): void {\n\ttry {\n\t\trmdirSync(join(sourceDir, \".leases\"));\n\t} catch {}\n\tif (managedRun) {\n\t\ttry {\n\t\t\tconst entries = readdirSync(sourceDir);\n\t\t\tif (entries.length === 1 && entries[0] === WORK_RUN_MANIFEST_FILE) {\n\t\t\t\tunlinkSync(join(sourceDir, WORK_RUN_MANIFEST_FILE));\n\t\t\t}\n\t\t} catch {}\n\t}\n\ttry {\n\t\trmdirSync(sourceDir);\n\t} catch {}\n}\n\nfunction migrateLegacySessionStore(agentDir: string, sessionId: string, store: LegacyContextStore): void {\n\tconst sourceDir = join(store.root, sessionId);\n\tif (!isRealDirectory(sourceDir)) return;\n\tif (store.managedRun && hasActiveWorkRunLease(sourceDir)) return;\n\tconst payloads = recognizedPayloads(sourceDir, store.kind);\n\tif (!payloads) return;\n\n\tif (payloads.length > 0) {\n\t\tlet lease: ReturnType<typeof acquireWorkRun> | undefined;\n\t\ttry {\n\t\t\tlease = acquireWorkRun({\n\t\t\t\tagentDir,\n\t\t\t\tcategory: \"context\",\n\t\t\t\ttenant: CONTEXT_WORK_TENANT,\n\t\t\t\trunId: sessionId,\n\t\t\t\tretention: false,\n\t\t\t});\n\t\t\tconst targetDir = join(lease.path, store.kind);\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t\tfor (const name of payloads) {\n\t\t\t\tconst sourcePath = join(sourceDir, name);\n\t\t\t\tconst targetPath = join(targetDir, name);\n\t\t\t\tif (existsSync(targetPath)) continue;\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(sourcePath, targetPath);\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t} catch {\n\t\t\treturn;\n\t\t} finally {\n\t\t\tlease?.release();\n\t\t}\n\t}\n\n\tremoveLegacyRunIfEmpty(sourceDir, store.managedRun);\n}\n\n/**\n * Move recognized context payloads from both historical layouts into the single leased session\n * namespace. Unknown files, symlinks, active runs, and conflicting destinations are left untouched.\n */\nexport function migrateLegacyContextStores(agentDir: string, onlySessionId?: string): void {\n\tfor (const store of legacyContextStores(agentDir)) {\n\t\tlet sessionIds: string[];\n\t\tif (onlySessionId) {\n\t\t\tsessionIds = [onlySessionId];\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tsessionIds = readdirSync(store.root, { withFileTypes: true })\n\t\t\t\t\t.slice(0, MAX_LEGACY_SESSION_DIRS)\n\t\t\t\t\t.filter((entry) => entry.isDirectory() && !entry.isSymbolicLink())\n\t\t\t\t\t.map((entry) => entry.name);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tmigrateLegacySessionStore(agentDir, sessionId, store);\n\t\t}\n\t\ttry {\n\t\t\trmdirSync(store.root);\n\t\t} catch {}\n\t}\n\ttry {\n\t\trmdirSync(join(agentDir, \"work\", \"context\"));\n\t} catch {}\n}\n\nexport function pruneContextStores(agentDir: string, options: ContextStoreRetentionOptions = {}): string[] {\n\treturn pruneWorkTenant(agentDir, \"context\", CONTEXT_WORK_TENANT, toWorkRetention(options));\n}\n\nexport function getContextStoreDir(agentDir: string, kind: ContextStoreKind, sessionId: string): string {\n\treturn join(getWorkRunDir(agentDir, \"context\", CONTEXT_WORK_TENANT, sessionId), kind);\n}\n\nexport function acquireContextStoreRetention(\n\tagentDir: string,\n\tsessionId: string,\n\toptions: ContextStoreRetentionOptions = {},\n): ContextStoreRetentionLease {\n\tmigrateLegacyContextStores(agentDir, sessionId);\n\tconst lease = acquireWorkRun({\n\t\tagentDir,\n\t\tcategory: \"context\",\n\t\ttenant: CONTEXT_WORK_TENANT,\n\t\trunId: sessionId,\n\t\tretention: toWorkRetention(options),\n\t});\n\tlet released = false;\n\treturn {\n\t\tgcDir: join(lease.path, \"gc\"),\n\t\tartifactsDir: join(lease.path, \"artifacts\"),\n\t\trelease(): void {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tlease.release();\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"context-store-retention.js","sourceRoot":"","sources":["../../../src/core/context/context-store-retention.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmdirSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n\ttype WorkRetentionOptions,\n} from \"../../utils/work-directory.ts\";\n\nconst DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\nconst DEFAULT_MAX_SESSION_DIRS = 64;\nconst DEFAULT_MAX_TOTAL_BYTES = 512 * 1024 * 1024;\nconst MAX_LEGACY_SESSION_DIRS = 10_000;\nconst MAX_LEGACY_FILES_PER_SESSION = 100_000;\nconst CONTEXT_WORK_TENANT = \"sessions\";\nconst WORK_RUN_MANIFEST_FILE = \".pi-work-run.json\";\n\nexport type ContextStoreKind = \"gc\" | \"artifacts\";\n\nexport interface ContextStoreRetentionOptions {\n\tmaxAgeMs?: number;\n\tmaxSessionDirs?: number;\n\tmaxTotalBytes?: number;\n\tnow?: number;\n}\n\nexport interface ContextStoreRetentionLease {\n\treadonly gcDir: string;\n\treadonly artifactsDir: string;\n\trelease(): void;\n}\n\ninterface LegacyContextStore {\n\troot: string;\n\tkind: ContextStoreKind;\n\tmanagedRun: boolean;\n}\n\nfunction toWorkRetention(options: ContextStoreRetentionOptions): WorkRetentionOptions {\n\treturn {\n\t\tmaxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n\t\tmaxRuns: options.maxSessionDirs ?? DEFAULT_MAX_SESSION_DIRS,\n\t\tmaxTotalBytes: options.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES,\n\t\tnow: options.now,\n\t};\n}\n\nfunction legacyContextStores(agentDir: string): LegacyContextStore[] {\n\treturn [\n\t\t{ root: join(agentDir, \"context-gc\"), kind: \"gc\", managedRun: false },\n\t\t{ root: join(agentDir, \"context-artifacts\"), kind: \"artifacts\", managedRun: false },\n\t\t{ root: getWorkTenantDir(agentDir, \"context\", \"gc\"), kind: \"gc\", managedRun: true },\n\t\t{ root: getWorkTenantDir(agentDir, \"context\", \"artifacts\"), kind: \"artifacts\", managedRun: true },\n\t];\n}\n\nfunction isRecognizedPayload(kind: ContextStoreKind, name: string): boolean {\n\tif (kind === \"gc\") return /^[0-9a-f]{1,64}\\.txt$/.test(name);\n\treturn /^[0-9a-f]{1,64}(?:\\.payload|\\.meta\\.json|\\.refs)$/.test(name);\n}\n\nfunction isRealDirectory(path: string): boolean {\n\ttry {\n\t\tconst stats = lstatSync(path);\n\t\treturn stats.isDirectory() && !stats.isSymbolicLink();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction recognizedPayloads(sourceDir: string, kind: ContextStoreKind): string[] | undefined {\n\ttry {\n\t\tconst entries = readdirSync(sourceDir, { withFileTypes: true });\n\t\tif (entries.length > MAX_LEGACY_FILES_PER_SESSION) return undefined;\n\t\treturn entries\n\t\t\t.filter(\n\t\t\t\t(entry) =>\n\t\t\t\t\t(entry.isFile() ||\n\t\t\t\t\t\t(kind === \"artifacts\" && entry.isDirectory() && /^[0-9a-f]{1,64}\\.refs$/.test(entry.name))) &&\n\t\t\t\t\t!entry.isSymbolicLink() &&\n\t\t\t\t\tisRecognizedPayload(kind, entry.name),\n\t\t\t)\n\t\t\t.map((entry) => entry.name);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction removeLegacyRunIfEmpty(sourceDir: string, managedRun: boolean): void {\n\ttry {\n\t\trmdirSync(join(sourceDir, \".leases\"));\n\t} catch {}\n\tif (managedRun) {\n\t\ttry {\n\t\t\tconst entries = readdirSync(sourceDir);\n\t\t\tif (entries.length === 1 && entries[0] === WORK_RUN_MANIFEST_FILE) {\n\t\t\t\tunlinkSync(join(sourceDir, WORK_RUN_MANIFEST_FILE));\n\t\t\t}\n\t\t} catch {}\n\t}\n\ttry {\n\t\trmdirSync(sourceDir);\n\t} catch {}\n}\n\nfunction migrateLegacySessionStore(agentDir: string, sessionId: string, store: LegacyContextStore): void {\n\tconst sourceDir = join(store.root, sessionId);\n\tif (!isRealDirectory(sourceDir)) return;\n\tif (store.managedRun && hasActiveWorkRunLease(sourceDir)) return;\n\tconst payloads = recognizedPayloads(sourceDir, store.kind);\n\tif (!payloads) return;\n\n\tif (payloads.length > 0) {\n\t\tlet lease: ReturnType<typeof acquireWorkRun> | undefined;\n\t\ttry {\n\t\t\tlease = acquireWorkRun({\n\t\t\t\tagentDir,\n\t\t\t\tcategory: \"context\",\n\t\t\t\ttenant: CONTEXT_WORK_TENANT,\n\t\t\t\trunId: sessionId,\n\t\t\t\tretention: false,\n\t\t\t});\n\t\t\tconst targetDir = join(lease.path, store.kind);\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t\tfor (const name of payloads) {\n\t\t\t\tconst sourcePath = join(sourceDir, name);\n\t\t\t\tconst targetPath = join(targetDir, name);\n\t\t\t\tif (existsSync(targetPath)) continue;\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(sourcePath, targetPath);\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t} catch {\n\t\t\treturn;\n\t\t} finally {\n\t\t\tlease?.release();\n\t\t}\n\t}\n\n\tremoveLegacyRunIfEmpty(sourceDir, store.managedRun);\n}\n\n/**\n * Move recognized context payloads from both historical layouts into the single leased session\n * namespace. Unknown files, symlinks, active runs, and conflicting destinations are left untouched.\n */\nexport function migrateLegacyContextStores(agentDir: string, onlySessionId?: string): void {\n\tfor (const store of legacyContextStores(agentDir)) {\n\t\tlet sessionIds: string[];\n\t\tif (onlySessionId) {\n\t\t\tsessionIds = [onlySessionId];\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tsessionIds = readdirSync(store.root, { withFileTypes: true })\n\t\t\t\t\t.slice(0, MAX_LEGACY_SESSION_DIRS)\n\t\t\t\t\t.filter((entry) => entry.isDirectory() && !entry.isSymbolicLink())\n\t\t\t\t\t.map((entry) => entry.name);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tmigrateLegacySessionStore(agentDir, sessionId, store);\n\t\t}\n\t\ttry {\n\t\t\trmdirSync(store.root);\n\t\t} catch {}\n\t}\n\ttry {\n\t\trmdirSync(join(agentDir, \"work\", \"context\"));\n\t} catch {}\n}\n\nexport function pruneContextStores(agentDir: string, options: ContextStoreRetentionOptions = {}): string[] {\n\treturn pruneWorkTenant(agentDir, \"context\", CONTEXT_WORK_TENANT, toWorkRetention(options));\n}\n\nexport function getContextStoreDir(agentDir: string, kind: ContextStoreKind, sessionId: string): string {\n\treturn join(getWorkRunDir(agentDir, \"context\", CONTEXT_WORK_TENANT, sessionId), kind);\n}\n\nexport function acquireContextStoreRetention(\n\tagentDir: string,\n\tsessionId: string,\n\toptions: ContextStoreRetentionOptions = {},\n): ContextStoreRetentionLease {\n\tmigrateLegacyContextStores(agentDir, sessionId);\n\tconst lease = acquireWorkRun({\n\t\tagentDir,\n\t\tcategory: \"context\",\n\t\ttenant: CONTEXT_WORK_TENANT,\n\t\trunId: sessionId,\n\t\tretention: toWorkRetention(options),\n\t});\n\tlet released = false;\n\treturn {\n\t\tgcDir: join(lease.path, \"gc\"),\n\t\tartifactsDir: join(lease.path, \"artifacts\"),\n\t\trelease(): void {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tlease.release();\n\t\t},\n\t};\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { basename } from "node:path";
3
- import { scanContextFileThreats, stripInvisibleUnicode } from "../resource-loader.js";
3
+ import { scanContextFileThreats, stripInvisibleUnicode } from "../security/context-threat-scanner.js";
4
4
  import { fetchLocalMemoryItem, searchLocalMemoryItems, tokenOverlapScore } from "./local-memory-search.js";
5
5
  export const PI_FILE_STORE_MEMORY_PROVIDER_ID = "pi-file-store";
6
6
  const FILE_STORE_MEMORY_CAPABILITIES = {
@@ -1 +1 @@
1
- {"version":3,"file":"file-store-memory-provider.js","sourceRoot":"","sources":["../../../src/core/context/file-store-memory-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { scanContextFileThreats, stripInvisibleUnicode } from \"../resource-loader.ts\";\nimport type { MemoryScope } from \"./context-item.ts\";\nimport { fetchLocalMemoryItem, searchLocalMemoryItems, tokenOverlapScore } from \"./local-memory-search.ts\";\nimport type {\n\tMemoryItem,\n\tMemoryItemKind,\n\tMemoryProvider,\n\tMemoryProviderCapabilities,\n\tMemoryRef,\n\tMemorySearchRequest,\n\tMemorySearchResult,\n} from \"./memory-provider-contract.ts\";\n\nexport const PI_FILE_STORE_MEMORY_PROVIDER_ID = \"pi-file-store\";\n\nexport interface FileStoreMemoryProviderOptions {\n\tmemoryFilePath: string;\n\tuserFilePath: string;\n\tproviderId?: string;\n}\n\ninterface FileStoreLineSource {\n\tpath: string;\n\tfileName: \"MEMORY.md\" | \"USER.md\";\n\tscope: MemoryScope;\n\tkind: MemoryItemKind;\n}\n\nconst FILE_STORE_MEMORY_CAPABILITIES: MemoryProviderCapabilities = {\n\tsearch: true,\n\tfetch: true,\n\twrite: false,\n\tdelete: false,\n\tshortTerm: false,\n\tlongTerm: true,\n\tgraph: false,\n\tcitations: true,\n\tscopes: [\"user\", \"global\"],\n\tlocalOnly: true,\n};\n\nfunction scoreItem(queryTokens: ReadonlySet<string>, item: MemoryItem): number {\n\tif (queryTokens.size === 0) return item.kind === \"user_preference\" ? 0.2 : 0;\n\tconst score = tokenOverlapScore(queryTokens, [item.title, item.summary]);\n\t// USER.md lines are standing preferences. When file-store retrieval is used as a compact-window\n\t// fallback for the static prompt, keep them eligible even if the latest query has no token overlap.\n\treturn item.kind === \"user_preference\" ? Math.max(0.2, Math.min(1, score + 0.05)) : score;\n}\n\nfunction refFor(providerId: string, source: FileStoreLineSource, lineNumber: number, kind: MemoryItemKind): MemoryRef {\n\treturn {\n\t\tproviderId,\n\t\titemId: `${source.fileName}:line-${lineNumber}`,\n\t\tscope: source.scope,\n\t\tkind,\n\t\turi: `file-store:${source.fileName}#line-${lineNumber}`,\n\t};\n}\n\nfunction readLines(source: FileStoreLineSource, providerId: string): MemoryItem[] {\n\tif (!existsSync(source.path)) return [];\n\tconst cleaned = stripInvisibleUnicode(readFileSync(source.path, \"utf8\")).cleaned;\n\treturn cleaned\n\t\t.split(\"\\n\")\n\t\t.map((rawLine, index) => ({ text: rawLine.trim(), lineNumber: index + 1 }))\n\t\t.filter((line) => line.text.length > 0 && !line.text.startsWith(\"#\"))\n\t\t.filter((line) => scanContextFileThreats(line.text).length === 0)\n\t\t.map((line) => {\n\t\t\tconst ref = refFor(providerId, source, line.lineNumber, source.kind);\n\t\t\treturn {\n\t\t\t\tid: ref.itemId,\n\t\t\t\tproviderId,\n\t\t\t\tsource: \"pi_native\" as const,\n\t\t\t\tkind: source.kind,\n\t\t\t\tscope: source.scope,\n\t\t\t\tdurability: \"durable\" as const,\n\t\t\t\ttitle: `${basename(source.path)} line ${line.lineNumber}`,\n\t\t\t\tsummary: line.text,\n\t\t\t\trefs: [ref],\n\t\t\t\tevidenceRefs: [{ type: \"memory\" as const, ref }],\n\t\t\t};\n\t\t});\n}\n\nexport function createFileStoreMemoryProvider(options: FileStoreMemoryProviderOptions): MemoryProvider {\n\tconst providerId = options.providerId ?? PI_FILE_STORE_MEMORY_PROVIDER_ID;\n\tconst sources: FileStoreLineSource[] = [\n\t\t{ path: options.userFilePath, fileName: \"USER.md\", scope: \"user\", kind: \"user_preference\" },\n\t\t{ path: options.memoryFilePath, fileName: \"MEMORY.md\", scope: \"global\", kind: \"fact\" },\n\t];\n\n\tfunction items(): MemoryItem[] {\n\t\treturn sources.flatMap((source) => readLines(source, providerId));\n\t}\n\n\treturn {\n\t\tid: providerId,\n\t\tlabel: \"Pi File-Store Memory\",\n\t\tsource: \"pi_native\",\n\t\tcapabilities: FILE_STORE_MEMORY_CAPABILITIES,\n\t\tasync search(request: MemorySearchRequest): Promise<MemorySearchResult[]> {\n\t\t\treturn searchLocalMemoryItems(items(), request, {\n\t\t\t\tscore: scoreItem,\n\t\t\t\treason: (score) => `file-store line match score ${score.toFixed(3)}`,\n\t\t\t});\n\t\t},\n\t\tasync fetch(ref: MemoryRef): Promise<MemoryItem | undefined> {\n\t\t\treturn fetchLocalMemoryItem(items(), providerId, ref);\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"file-store-memory-provider.js","sourceRoot":"","sources":["../../../src/core/context/file-store-memory-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { scanContextFileThreats, stripInvisibleUnicode } from \"../security/context-threat-scanner.ts\";\nimport type { MemoryScope } from \"./context-item.ts\";\nimport { fetchLocalMemoryItem, searchLocalMemoryItems, tokenOverlapScore } from \"./local-memory-search.ts\";\nimport type {\n\tMemoryItem,\n\tMemoryItemKind,\n\tMemoryProvider,\n\tMemoryProviderCapabilities,\n\tMemoryRef,\n\tMemorySearchRequest,\n\tMemorySearchResult,\n} from \"./memory-provider-contract.ts\";\n\nexport const PI_FILE_STORE_MEMORY_PROVIDER_ID = \"pi-file-store\";\n\nexport interface FileStoreMemoryProviderOptions {\n\tmemoryFilePath: string;\n\tuserFilePath: string;\n\tproviderId?: string;\n}\n\ninterface FileStoreLineSource {\n\tpath: string;\n\tfileName: \"MEMORY.md\" | \"USER.md\";\n\tscope: MemoryScope;\n\tkind: MemoryItemKind;\n}\n\nconst FILE_STORE_MEMORY_CAPABILITIES: MemoryProviderCapabilities = {\n\tsearch: true,\n\tfetch: true,\n\twrite: false,\n\tdelete: false,\n\tshortTerm: false,\n\tlongTerm: true,\n\tgraph: false,\n\tcitations: true,\n\tscopes: [\"user\", \"global\"],\n\tlocalOnly: true,\n};\n\nfunction scoreItem(queryTokens: ReadonlySet<string>, item: MemoryItem): number {\n\tif (queryTokens.size === 0) return item.kind === \"user_preference\" ? 0.2 : 0;\n\tconst score = tokenOverlapScore(queryTokens, [item.title, item.summary]);\n\t// USER.md lines are standing preferences. When file-store retrieval is used as a compact-window\n\t// fallback for the static prompt, keep them eligible even if the latest query has no token overlap.\n\treturn item.kind === \"user_preference\" ? Math.max(0.2, Math.min(1, score + 0.05)) : score;\n}\n\nfunction refFor(providerId: string, source: FileStoreLineSource, lineNumber: number, kind: MemoryItemKind): MemoryRef {\n\treturn {\n\t\tproviderId,\n\t\titemId: `${source.fileName}:line-${lineNumber}`,\n\t\tscope: source.scope,\n\t\tkind,\n\t\turi: `file-store:${source.fileName}#line-${lineNumber}`,\n\t};\n}\n\nfunction readLines(source: FileStoreLineSource, providerId: string): MemoryItem[] {\n\tif (!existsSync(source.path)) return [];\n\tconst cleaned = stripInvisibleUnicode(readFileSync(source.path, \"utf8\")).cleaned;\n\treturn cleaned\n\t\t.split(\"\\n\")\n\t\t.map((rawLine, index) => ({ text: rawLine.trim(), lineNumber: index + 1 }))\n\t\t.filter((line) => line.text.length > 0 && !line.text.startsWith(\"#\"))\n\t\t.filter((line) => scanContextFileThreats(line.text).length === 0)\n\t\t.map((line) => {\n\t\t\tconst ref = refFor(providerId, source, line.lineNumber, source.kind);\n\t\t\treturn {\n\t\t\t\tid: ref.itemId,\n\t\t\t\tproviderId,\n\t\t\t\tsource: \"pi_native\" as const,\n\t\t\t\tkind: source.kind,\n\t\t\t\tscope: source.scope,\n\t\t\t\tdurability: \"durable\" as const,\n\t\t\t\ttitle: `${basename(source.path)} line ${line.lineNumber}`,\n\t\t\t\tsummary: line.text,\n\t\t\t\trefs: [ref],\n\t\t\t\tevidenceRefs: [{ type: \"memory\" as const, ref }],\n\t\t\t};\n\t\t});\n}\n\nexport function createFileStoreMemoryProvider(options: FileStoreMemoryProviderOptions): MemoryProvider {\n\tconst providerId = options.providerId ?? PI_FILE_STORE_MEMORY_PROVIDER_ID;\n\tconst sources: FileStoreLineSource[] = [\n\t\t{ path: options.userFilePath, fileName: \"USER.md\", scope: \"user\", kind: \"user_preference\" },\n\t\t{ path: options.memoryFilePath, fileName: \"MEMORY.md\", scope: \"global\", kind: \"fact\" },\n\t];\n\n\tfunction items(): MemoryItem[] {\n\t\treturn sources.flatMap((source) => readLines(source, providerId));\n\t}\n\n\treturn {\n\t\tid: providerId,\n\t\tlabel: \"Pi File-Store Memory\",\n\t\tsource: \"pi_native\",\n\t\tcapabilities: FILE_STORE_MEMORY_CAPABILITIES,\n\t\tasync search(request: MemorySearchRequest): Promise<MemorySearchResult[]> {\n\t\t\treturn searchLocalMemoryItems(items(), request, {\n\t\t\t\tscore: scoreItem,\n\t\t\t\treason: (score) => `file-store line match score ${score.toFixed(3)}`,\n\t\t\t});\n\t\t},\n\t\tasync fetch(ref: MemoryRef): Promise<MemoryItem | undefined> {\n\t\t\treturn fetchLocalMemoryItem(items(), providerId, ref);\n\t\t},\n\t};\n}\n"]}
@@ -9,7 +9,7 @@
9
9
  * (grep/find) that never passes an `ArtifactStore` gets byte-for-byte its prior behavior --
10
10
  * packing is opt-in per call site, not a global switch.
11
11
  */
12
- import { type TruncationOptions, type TruncationResult } from "@caupulican/pi-agent-core/node";
12
+ import { type TruncationOptions, type TruncationResult } from "@caupulican/pi-agent-core/truncate";
13
13
  import type { ArtifactStore } from "./context-artifacts.ts";
14
14
  export interface PackToolOutputRequest {
15
15
  toolName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-output-packer.d.ts","sourceRoot":"","sources":["../../../src/core/context/tool-output-packer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAgB,MAAM,gCAAgC,CAAC;AAC7G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAChC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,qBAAqB,EAC9B,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,QAAQ,EAAE,MAAM,GACd,gBAAgB,CAuBlB;AAED,MAAM,WAAW,iBAAiB;IACjC,kGAAkG;IAClG,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtC;AAED,wBAAgB,+BAA+B,IAAI,iBAAiB,CASnE;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAET;AAID;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,GAAG,EAAE,MAAM,EACX,qBAAqB,EAAE,MAAM,GAC3B,MAAM,GAAG,SAAS,CAKpB"}
1
+ {"version":3,"file":"tool-output-packer.d.ts","sourceRoot":"","sources":["../../../src/core/context/tool-output-packer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAgB,MAAM,oCAAoC,CAAC;AACjH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAChC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,qBAAqB,EAC9B,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,QAAQ,EAAE,MAAM,GACd,gBAAgB,CAuBlB;AAED,MAAM,WAAW,iBAAiB;IACjC,kGAAkG;IAClG,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtC;AAED,wBAAgB,+BAA+B,IAAI,iBAAiB,CASnE;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAET;AAID;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,GAAG,EAAE,MAAM,EACX,qBAAqB,EAAE,MAAM,GAC3B,MAAM,GAAG,SAAS,CAKpB"}
@@ -9,7 +9,7 @@
9
9
  * (grep/find) that never passes an `ArtifactStore` gets byte-for-byte its prior behavior --
10
10
  * packing is opt-in per call site, not a global switch.
11
11
  */
12
- import { truncateHead } from "@caupulican/pi-agent-core/node";
12
+ import { truncateHead } from "@caupulican/pi-agent-core/truncate";
13
13
  /** Footer notice text for a packed artifact, for callers to fold into their own notices. */
14
14
  export function formatArtifactNotice(artifactId) {
15
15
  return `Full output: artifact tool-output:${artifactId}`;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-output-packer.js","sourceRoot":"","sources":["../../../src/core/context/tool-output-packer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAiD,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAiC7G,4FAA4F;AAC5F,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACtD,OAAO,qCAAqC,UAAU,EAAE,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC7B,OAA8B,EAC9B,aAAwC,EACxC,QAAgB;IAEhB,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAExE,IAAI,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC;QACnC,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO,CAAC,UAAU;QAC3B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,CAAC;QACzC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI;KAC1C,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACtF,CAAC;AAOD,MAAM,UAAU,+BAA+B;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,OAAO;QACN,gBAAgB,CAAC,GAAW;YAC3B,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACb,CAAC;KACD,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,sBAAsB,CAAC,KAKtC;IACA,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACzC,OAAsC,EACtC,GAAW,EACX,qBAA6B;IAE7B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,KAAK,GAAG,8BAA8B;QAAE,OAAO,SAAS,CAAC;IAC7D,OAAO,kBAAkB,qBAAqB,yCAAyC,KAAK,uDAAuD,CAAC;AACrJ,CAAC","sourcesContent":["/**\n * Tool output digesting and packing (Phase 3): \"measure -> digest/preview/artifact ->\n * prompt item\", per tool-output-artifacts.md's boundary rule. Large raw tool output is\n * captured to an artifact BEFORE truncation, so the artifact holds the exact raw payload;\n * the model only ever sees the bounded preview plus an artifact reference.\n *\n * This module is pure with respect to wiring: it takes an `ArtifactStore` by dependency\n * injection and does not know about sessions, transcripts, or prompt construction. A tool\n * (grep/find) that never passes an `ArtifactStore` gets byte-for-byte its prior behavior --\n * packing is opt-in per call site, not a global switch.\n */\n\nimport { type TruncationOptions, type TruncationResult, truncateHead } from \"@caupulican/pi-agent-core/node\";\nimport type { ArtifactStore } from \"./context-artifacts.ts\";\n\nexport interface PackToolOutputRequest {\n\ttoolName: string;\n\tcommand?: string;\n\tpath?: string;\n\trawContent: string;\n\tsessionEntryId?: string;\n\t/**\n\t * Turn number for artifact capture identity. Real session-turn wiring lands in a later\n\t * slice; callers that don't track turns yet may pass 0.\n\t */\n\tcreatedAtTurn?: number;\n\t/** Whether re-running the same tool call would reproduce this content. Default: true. */\n\treproducible?: boolean;\n\ttruncation?: TruncationOptions;\n}\n\nexport interface PackedToolOutput {\n\t/**\n\t * Bounded preview content -- exactly what `truncateHead` alone would have produced.\n\t * No footer/notice text is appended here; callers already have their own per-tool\n\t * footer conventions (grep's vs. find's bracket ordering differ) and own formatting\n\t * the artifact notice into their own notice list via `formatArtifactNotice`.\n\t */\n\tcontent: string;\n\ttruncation: TruncationResult;\n\t/** Present only if packing succeeded and the artifact is protected from cleanup. */\n\tartifactId?: string;\n\tpacked: boolean;\n}\n\n/** Footer notice text for a packed artifact, for callers to fold into their own notices. */\nexport function formatArtifactNotice(artifactId: string): string {\n\treturn `Full output: artifact tool-output:${artifactId}`;\n}\n\n/**\n * Measure `request.rawContent`; if it fits within the caps, return it unchanged (small\n * output stays exactly as readable as before this module existed). If it's oversized and\n * an `ArtifactStore` is provided, capture the exact raw payload as an artifact first, then\n * return the same bounded preview `truncateHead` would have produced anyway.\n *\n * Fails closed: if the artifact write succeeds but registering `holderId` as a reference\n * fails (`addReference` returns false), the artifact is not claimed in the result at all --\n * the caller falls back to the bounded/truncated content exactly as if no store had been\n * provided, since an unprotected artifact could be cleaned up at any time.\n */\nexport function packToolOutput(\n\trequest: PackToolOutputRequest,\n\tartifactStore: ArtifactStore | undefined,\n\tholderId: string,\n): PackedToolOutput {\n\tconst truncation = truncateHead(request.rawContent, request.truncation);\n\n\tif (!truncation.truncated || !artifactStore) {\n\t\treturn { content: truncation.content, truncation, packed: false };\n\t}\n\n\tconst { ref } = artifactStore.write({\n\t\tkind: \"tool_output\",\n\t\tcontent: request.rawContent,\n\t\ttoolName: request.toolName,\n\t\tcommand: request.command,\n\t\tpath: request.path,\n\t\tsessionEntryId: request.sessionEntryId,\n\t\tcreatedAtTurn: request.createdAtTurn ?? 0,\n\t\treproducible: request.reproducible ?? true,\n\t});\n\n\tif (!artifactStore.addReference(ref.id, holderId)) {\n\t\treturn { content: truncation.content, truncation, packed: false };\n\t}\n\n\treturn { content: truncation.content, truncation, artifactId: ref.id, packed: true };\n}\n\nexport interface BroadQueryTracker {\n\t/** Record one more broad occurrence of `key`; returns the cumulative count including this one. */\n\trecordBroadQuery(key: string): number;\n}\n\nexport function createInMemoryBroadQueryTracker(): BroadQueryTracker {\n\tconst counts = new Map<string, number>();\n\treturn {\n\t\trecordBroadQuery(key: string): number {\n\t\t\tconst next = (counts.get(key) ?? 0) + 1;\n\t\t\tcounts.set(key, next);\n\t\t\treturn next;\n\t\t},\n\t};\n}\n\n/** Normalize a search-tool call into a stable repetition key: same query, same broadness. */\nexport function normalizeBroadQueryKey(input: {\n\ttoolName: string;\n\tpattern?: string;\n\tpath?: string;\n\tglob?: string;\n}): string {\n\treturn [input.toolName, input.pattern ?? \"\", input.path ?? \"\", input.glob ?? \"\"].join(\"␟\");\n}\n\nconst REPEATED_BROAD_QUERY_THRESHOLD = 2;\n\n/**\n * When a broad-query condition (match/result limit hit, or byte truncation) repeats for\n * the same normalized query, produce a compact \"do not repeat\" style note. This is only\n * the Phase 3 signal; the durable invalidation ledger (supersession/expiry rules) is\n * Phase 6 per implementation-phases.md.\n */\nexport function broadQueryInvalidationNote(\n\ttracker: BroadQueryTracker | undefined,\n\tkey: string,\n\thumanQueryDescription: string,\n): string | undefined {\n\tif (!tracker) return undefined;\n\tconst count = tracker.recordBroadQuery(key);\n\tif (count < REPEATED_BROAD_QUERY_THRESHOLD) return undefined;\n\treturn `Do not repeat: ${humanQueryDescription} has produced broad/truncated results ${count} times in this session. Narrow the path/glob/pattern.`;\n}\n"]}
1
+ {"version":3,"file":"tool-output-packer.js","sourceRoot":"","sources":["../../../src/core/context/tool-output-packer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAiD,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAiCjH,4FAA4F;AAC5F,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACtD,OAAO,qCAAqC,UAAU,EAAE,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC7B,OAA8B,EAC9B,aAAwC,EACxC,QAAgB;IAEhB,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAExE,IAAI,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC;QACnC,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO,CAAC,UAAU;QAC3B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,CAAC;QACzC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI;KAC1C,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACtF,CAAC;AAOD,MAAM,UAAU,+BAA+B;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,OAAO;QACN,gBAAgB,CAAC,GAAW;YAC3B,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACb,CAAC;KACD,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,sBAAsB,CAAC,KAKtC;IACA,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACzC,OAAsC,EACtC,GAAW,EACX,qBAA6B;IAE7B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,KAAK,GAAG,8BAA8B;QAAE,OAAO,SAAS,CAAC;IAC7D,OAAO,kBAAkB,qBAAqB,yCAAyC,KAAK,uDAAuD,CAAC;AACrJ,CAAC","sourcesContent":["/**\n * Tool output digesting and packing (Phase 3): \"measure -> digest/preview/artifact ->\n * prompt item\", per tool-output-artifacts.md's boundary rule. Large raw tool output is\n * captured to an artifact BEFORE truncation, so the artifact holds the exact raw payload;\n * the model only ever sees the bounded preview plus an artifact reference.\n *\n * This module is pure with respect to wiring: it takes an `ArtifactStore` by dependency\n * injection and does not know about sessions, transcripts, or prompt construction. A tool\n * (grep/find) that never passes an `ArtifactStore` gets byte-for-byte its prior behavior --\n * packing is opt-in per call site, not a global switch.\n */\n\nimport { type TruncationOptions, type TruncationResult, truncateHead } from \"@caupulican/pi-agent-core/truncate\";\nimport type { ArtifactStore } from \"./context-artifacts.ts\";\n\nexport interface PackToolOutputRequest {\n\ttoolName: string;\n\tcommand?: string;\n\tpath?: string;\n\trawContent: string;\n\tsessionEntryId?: string;\n\t/**\n\t * Turn number for artifact capture identity. Real session-turn wiring lands in a later\n\t * slice; callers that don't track turns yet may pass 0.\n\t */\n\tcreatedAtTurn?: number;\n\t/** Whether re-running the same tool call would reproduce this content. Default: true. */\n\treproducible?: boolean;\n\ttruncation?: TruncationOptions;\n}\n\nexport interface PackedToolOutput {\n\t/**\n\t * Bounded preview content -- exactly what `truncateHead` alone would have produced.\n\t * No footer/notice text is appended here; callers already have their own per-tool\n\t * footer conventions (grep's vs. find's bracket ordering differ) and own formatting\n\t * the artifact notice into their own notice list via `formatArtifactNotice`.\n\t */\n\tcontent: string;\n\ttruncation: TruncationResult;\n\t/** Present only if packing succeeded and the artifact is protected from cleanup. */\n\tartifactId?: string;\n\tpacked: boolean;\n}\n\n/** Footer notice text for a packed artifact, for callers to fold into their own notices. */\nexport function formatArtifactNotice(artifactId: string): string {\n\treturn `Full output: artifact tool-output:${artifactId}`;\n}\n\n/**\n * Measure `request.rawContent`; if it fits within the caps, return it unchanged (small\n * output stays exactly as readable as before this module existed). If it's oversized and\n * an `ArtifactStore` is provided, capture the exact raw payload as an artifact first, then\n * return the same bounded preview `truncateHead` would have produced anyway.\n *\n * Fails closed: if the artifact write succeeds but registering `holderId` as a reference\n * fails (`addReference` returns false), the artifact is not claimed in the result at all --\n * the caller falls back to the bounded/truncated content exactly as if no store had been\n * provided, since an unprotected artifact could be cleaned up at any time.\n */\nexport function packToolOutput(\n\trequest: PackToolOutputRequest,\n\tartifactStore: ArtifactStore | undefined,\n\tholderId: string,\n): PackedToolOutput {\n\tconst truncation = truncateHead(request.rawContent, request.truncation);\n\n\tif (!truncation.truncated || !artifactStore) {\n\t\treturn { content: truncation.content, truncation, packed: false };\n\t}\n\n\tconst { ref } = artifactStore.write({\n\t\tkind: \"tool_output\",\n\t\tcontent: request.rawContent,\n\t\ttoolName: request.toolName,\n\t\tcommand: request.command,\n\t\tpath: request.path,\n\t\tsessionEntryId: request.sessionEntryId,\n\t\tcreatedAtTurn: request.createdAtTurn ?? 0,\n\t\treproducible: request.reproducible ?? true,\n\t});\n\n\tif (!artifactStore.addReference(ref.id, holderId)) {\n\t\treturn { content: truncation.content, truncation, packed: false };\n\t}\n\n\treturn { content: truncation.content, truncation, artifactId: ref.id, packed: true };\n}\n\nexport interface BroadQueryTracker {\n\t/** Record one more broad occurrence of `key`; returns the cumulative count including this one. */\n\trecordBroadQuery(key: string): number;\n}\n\nexport function createInMemoryBroadQueryTracker(): BroadQueryTracker {\n\tconst counts = new Map<string, number>();\n\treturn {\n\t\trecordBroadQuery(key: string): number {\n\t\t\tconst next = (counts.get(key) ?? 0) + 1;\n\t\t\tcounts.set(key, next);\n\t\t\treturn next;\n\t\t},\n\t};\n}\n\n/** Normalize a search-tool call into a stable repetition key: same query, same broadness. */\nexport function normalizeBroadQueryKey(input: {\n\ttoolName: string;\n\tpattern?: string;\n\tpath?: string;\n\tglob?: string;\n}): string {\n\treturn [input.toolName, input.pattern ?? \"\", input.path ?? \"\", input.glob ?? \"\"].join(\"␟\");\n}\n\nconst REPEATED_BROAD_QUERY_THRESHOLD = 2;\n\n/**\n * When a broad-query condition (match/result limit hit, or byte truncation) repeats for\n * the same normalized query, produce a compact \"do not repeat\" style note. This is only\n * the Phase 3 signal; the durable invalidation ledger (supersession/expiry rules) is\n * Phase 6 per implementation-phases.md.\n */\nexport function broadQueryInvalidationNote(\n\ttracker: BroadQueryTracker | undefined,\n\tkey: string,\n\thumanQueryDescription: string,\n): string | undefined {\n\tif (!tracker) return undefined;\n\tconst count = tracker.recordBroadQuery(key);\n\tif (count < REPEATED_BROAD_QUERY_THRESHOLD) return undefined;\n\treturn `Do not repeat: ${humanQueryDescription} has produced broad/truncated results ${count} times in this session. Narrow the path/glob/pattern.`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"context-gc.d.ts","sourceRoot":"","sources":["../../src/core/context-gc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context-gc.d.ts","sourceRoot":"","sources":["../../src/core/context-gc.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { existsSync } from "node:fs";
3
3
  import { isAbsolute, resolve } from "node:path";
4
- import { estimateTokens } from "@caupulican/pi-agent-core/node";
4
+ import { estimateTokens } from "@caupulican/pi-agent-core/compaction/compaction";
5
5
  import { normalizePath } from "../utils/paths.js";
6
6
  import { boundedTextPreview } from "./text-preview.js";
7
+ import { withFileLockSync, writeFileAtomicSync } from "./util/atomic-file.js";
7
8
  const DEFAULT_SEMANTIC_MEMORY_GC_SETTINGS = {
8
9
  enabled: true,
9
10
  preserveRecentPages: 1,
@@ -241,9 +242,10 @@ function maybeStoreOriginal(options, key, original) {
241
242
  const path = storagePathFor(storageDir, key);
242
243
  if (!path || !storageDir)
243
244
  return undefined;
244
- mkdirSync(storageDir, { recursive: true });
245
- if (!existsSync(path))
246
- writeFileSync(path, original, "utf8");
245
+ withFileLockSync(path, () => {
246
+ if (!existsSync(path))
247
+ writeFileAtomicSync(path, original);
248
+ });
247
249
  return path;
248
250
  }
249
251
  catch {