@caupulican/pi-adaptative 0.80.103 → 0.81.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 (409) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/cli/session-picker.d.ts +1 -1
  3. package/dist/cli/session-picker.d.ts.map +1 -1
  4. package/dist/cli/session-picker.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +7 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/agent-session-runtime.d.ts +1 -1
  9. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  10. package/dist/core/agent-session-runtime.js +6 -6
  11. package/dist/core/agent-session-runtime.js.map +1 -1
  12. package/dist/core/agent-session-services.d.ts +1 -1
  13. package/dist/core/agent-session-services.d.ts.map +1 -1
  14. package/dist/core/agent-session-services.js.map +1 -1
  15. package/dist/core/agent-session.d.ts +154 -512
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +675 -4589
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/autonomy/session-lane-record.d.ts +1 -1
  20. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
  21. package/dist/core/autonomy/session-lane-record.js.map +1 -1
  22. package/dist/core/autonomy/status.d.ts +1 -0
  23. package/dist/core/autonomy/status.d.ts.map +1 -1
  24. package/dist/core/autonomy/status.js +1 -0
  25. package/dist/core/autonomy/status.js.map +1 -1
  26. package/dist/core/autonomy-telemetry.d.ts +80 -0
  27. package/dist/core/autonomy-telemetry.d.ts.map +1 -0
  28. package/dist/core/autonomy-telemetry.js +266 -0
  29. package/dist/core/autonomy-telemetry.js.map +1 -0
  30. package/dist/core/background-lane-controller.d.ts +186 -0
  31. package/dist/core/background-lane-controller.d.ts.map +1 -0
  32. package/dist/core/background-lane-controller.js +691 -0
  33. package/dist/core/background-lane-controller.js.map +1 -0
  34. package/dist/core/bash-execution-controller.d.ts +51 -0
  35. package/dist/core/bash-execution-controller.d.ts.map +1 -0
  36. package/dist/core/bash-execution-controller.js +96 -0
  37. package/dist/core/bash-execution-controller.js.map +1 -0
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +9 -2
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/compaction-support.d.ts +56 -0
  42. package/dist/core/compaction-support.d.ts.map +1 -0
  43. package/dist/core/compaction-support.js +99 -0
  44. package/dist/core/compaction-support.js.map +1 -0
  45. package/dist/core/context/artifact-retrieval.d.ts +1 -1
  46. package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
  47. package/dist/core/context/artifact-retrieval.js +1 -1
  48. package/dist/core/context/artifact-retrieval.js.map +1 -1
  49. package/dist/core/context/context-composition.d.ts.map +1 -1
  50. package/dist/core/context/context-composition.js +1 -1
  51. package/dist/core/context/context-composition.js.map +1 -1
  52. package/dist/core/context/tool-output-packer.d.ts +1 -1
  53. package/dist/core/context/tool-output-packer.d.ts.map +1 -1
  54. package/dist/core/context/tool-output-packer.js +1 -1
  55. package/dist/core/context/tool-output-packer.js.map +1 -1
  56. package/dist/core/context-gc.d.ts.map +1 -1
  57. package/dist/core/context-gc.js +1 -1
  58. package/dist/core/context-gc.js.map +1 -1
  59. package/dist/core/context-pipeline.d.ts +223 -0
  60. package/dist/core/context-pipeline.d.ts.map +1 -0
  61. package/dist/core/context-pipeline.js +594 -0
  62. package/dist/core/context-pipeline.js.map +1 -0
  63. package/dist/core/cost/daily-usage.d.ts +1 -1
  64. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  65. package/dist/core/cost/daily-usage.js +1 -1
  66. package/dist/core/cost/daily-usage.js.map +1 -1
  67. package/dist/core/cost/session-usage.d.ts +1 -1
  68. package/dist/core/cost/session-usage.d.ts.map +1 -1
  69. package/dist/core/cost/session-usage.js +1 -1
  70. package/dist/core/cost/session-usage.js.map +1 -1
  71. package/dist/core/delegation/session-worker-result.d.ts +1 -1
  72. package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
  73. package/dist/core/delegation/session-worker-result.js.map +1 -1
  74. package/dist/core/exec.d.ts +2 -0
  75. package/dist/core/exec.d.ts.map +1 -1
  76. package/dist/core/exec.js +15 -9
  77. package/dist/core/exec.js.map +1 -1
  78. package/dist/core/export-html/index.d.ts +1 -1
  79. package/dist/core/export-html/index.d.ts.map +1 -1
  80. package/dist/core/export-html/index.js +2 -2
  81. package/dist/core/export-html/index.js.map +1 -1
  82. package/dist/core/extensions/builtin.d.ts.map +1 -1
  83. package/dist/core/extensions/builtin.js +2 -2
  84. package/dist/core/extensions/builtin.js.map +1 -1
  85. package/dist/core/extensions/runner.d.ts +1 -1
  86. package/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/dist/core/extensions/runner.js.map +1 -1
  88. package/dist/core/extensions/types.d.ts +2 -4
  89. package/dist/core/extensions/types.d.ts.map +1 -1
  90. package/dist/core/extensions/types.js.map +1 -1
  91. package/dist/core/goal-loop-controller.d.ts +24 -0
  92. package/dist/core/goal-loop-controller.d.ts.map +1 -0
  93. package/dist/core/goal-loop-controller.js +83 -0
  94. package/dist/core/goal-loop-controller.js.map +1 -0
  95. package/dist/core/goals/goal-runtime-snapshot.d.ts +1 -1
  96. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  97. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  98. package/dist/core/goals/session-goal-state.d.ts +1 -1
  99. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  100. package/dist/core/goals/session-goal-state.js.map +1 -1
  101. package/dist/core/http-dispatcher.d.ts +4 -1
  102. package/dist/core/http-dispatcher.d.ts.map +1 -1
  103. package/dist/core/http-dispatcher.js +6 -1
  104. package/dist/core/http-dispatcher.js.map +1 -1
  105. package/dist/core/index.d.ts +1 -1
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js.map +1 -1
  108. package/dist/core/learning/learning-audit.d.ts +1 -1
  109. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  110. package/dist/core/learning/learning-audit.js.map +1 -1
  111. package/dist/core/learning/session-learning-decision.d.ts +1 -1
  112. package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
  113. package/dist/core/learning/session-learning-decision.js.map +1 -1
  114. package/dist/core/local-runtime-controller.d.ts +99 -0
  115. package/dist/core/local-runtime-controller.d.ts.map +1 -0
  116. package/dist/core/local-runtime-controller.js +214 -0
  117. package/dist/core/local-runtime-controller.js.map +1 -0
  118. package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
  119. package/dist/core/memory/providers/transcript-recall.js +1 -1
  120. package/dist/core/memory/providers/transcript-recall.js.map +1 -1
  121. package/dist/core/memory-controller.d.ts +139 -0
  122. package/dist/core/memory-controller.d.ts.map +1 -0
  123. package/dist/core/memory-controller.js +323 -0
  124. package/dist/core/memory-controller.js.map +1 -0
  125. package/dist/core/model-router/status.d.ts +1 -1
  126. package/dist/core/model-router/status.d.ts.map +1 -1
  127. package/dist/core/model-router/status.js.map +1 -1
  128. package/dist/core/model-router-controller.d.ts +140 -0
  129. package/dist/core/model-router-controller.d.ts.map +1 -0
  130. package/dist/core/model-router-controller.js +623 -0
  131. package/dist/core/model-router-controller.js.map +1 -0
  132. package/dist/core/model-selection-controller.d.ts +95 -0
  133. package/dist/core/model-selection-controller.d.ts.map +1 -0
  134. package/dist/core/model-selection-controller.js +252 -0
  135. package/dist/core/model-selection-controller.js.map +1 -0
  136. package/dist/core/models/model-ref.d.ts +13 -0
  137. package/dist/core/models/model-ref.d.ts.map +1 -1
  138. package/dist/core/models/model-ref.js +22 -0
  139. package/dist/core/models/model-ref.js.map +1 -1
  140. package/dist/core/profile-filter-controller.d.ts +77 -0
  141. package/dist/core/profile-filter-controller.d.ts.map +1 -0
  142. package/dist/core/profile-filter-controller.js +159 -0
  143. package/dist/core/profile-filter-controller.js.map +1 -0
  144. package/dist/core/reflection-controller.d.ts +111 -0
  145. package/dist/core/reflection-controller.d.ts.map +1 -0
  146. package/dist/core/reflection-controller.js +412 -0
  147. package/dist/core/reflection-controller.js.map +1 -0
  148. package/dist/core/research/model-fitness.d.ts +12 -0
  149. package/dist/core/research/model-fitness.d.ts.map +1 -1
  150. package/dist/core/research/model-fitness.js +21 -0
  151. package/dist/core/research/model-fitness.js.map +1 -1
  152. package/dist/core/research/session-evidence-bundle.d.ts +1 -1
  153. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
  154. package/dist/core/research/session-evidence-bundle.js.map +1 -1
  155. package/dist/core/runtime-builder.d.ts +222 -0
  156. package/dist/core/runtime-builder.d.ts.map +1 -0
  157. package/dist/core/runtime-builder.js +640 -0
  158. package/dist/core/runtime-builder.js.map +1 -0
  159. package/dist/core/sdk.d.ts +2 -2
  160. package/dist/core/sdk.d.ts.map +1 -1
  161. package/dist/core/sdk.js +3 -4
  162. package/dist/core/sdk.js.map +1 -1
  163. package/dist/core/session-analytics.d.ts +96 -0
  164. package/dist/core/session-analytics.d.ts.map +1 -0
  165. package/dist/core/session-analytics.js +331 -0
  166. package/dist/core/session-analytics.js.map +1 -0
  167. package/dist/core/session-manager-factory.d.ts +18 -0
  168. package/dist/core/session-manager-factory.d.ts.map +1 -0
  169. package/dist/core/session-manager-factory.js +32 -0
  170. package/dist/core/session-manager-factory.js.map +1 -0
  171. package/dist/core/session-tree-navigator.d.ts +68 -0
  172. package/dist/core/session-tree-navigator.d.ts.map +1 -0
  173. package/dist/core/session-tree-navigator.js +217 -0
  174. package/dist/core/session-tree-navigator.js.map +1 -0
  175. package/dist/core/settings-manager.d.ts +16 -0
  176. package/dist/core/settings-manager.d.ts.map +1 -1
  177. package/dist/core/settings-manager.js +22 -0
  178. package/dist/core/settings-manager.js.map +1 -1
  179. package/dist/core/system-prompt-builder.d.ts +63 -0
  180. package/dist/core/system-prompt-builder.d.ts.map +1 -0
  181. package/dist/core/system-prompt-builder.js +181 -0
  182. package/dist/core/system-prompt-builder.js.map +1 -0
  183. package/dist/core/tool-gate-controller.d.ts +36 -0
  184. package/dist/core/tool-gate-controller.d.ts.map +1 -0
  185. package/dist/core/tool-gate-controller.js +94 -0
  186. package/dist/core/tool-gate-controller.js.map +1 -0
  187. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
  188. package/dist/core/tools/artifact-retrieve.js +1 -1
  189. package/dist/core/tools/artifact-retrieve.js.map +1 -1
  190. package/dist/core/tools/bash.d.ts +4 -2
  191. package/dist/core/tools/bash.d.ts.map +1 -1
  192. package/dist/core/tools/bash.js +49 -7
  193. package/dist/core/tools/bash.js.map +1 -1
  194. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  195. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  196. package/dist/core/tools/file-mutation-queue.js +61 -1
  197. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  198. package/dist/core/tools/find.d.ts +1 -1
  199. package/dist/core/tools/find.d.ts.map +1 -1
  200. package/dist/core/tools/find.js +1 -1
  201. package/dist/core/tools/find.js.map +1 -1
  202. package/dist/core/tools/grep.d.ts +1 -1
  203. package/dist/core/tools/grep.d.ts.map +1 -1
  204. package/dist/core/tools/grep.js +1 -1
  205. package/dist/core/tools/grep.js.map +1 -1
  206. package/dist/core/tools/index.d.ts +1 -1
  207. package/dist/core/tools/index.d.ts.map +1 -1
  208. package/dist/core/tools/index.js +1 -1
  209. package/dist/core/tools/index.js.map +1 -1
  210. package/dist/core/tools/ls.d.ts +1 -1
  211. package/dist/core/tools/ls.d.ts.map +1 -1
  212. package/dist/core/tools/ls.js +1 -1
  213. package/dist/core/tools/ls.js.map +1 -1
  214. package/dist/core/tools/output-accumulator.d.ts +1 -1
  215. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  216. package/dist/core/tools/output-accumulator.js +1 -1
  217. package/dist/core/tools/output-accumulator.js.map +1 -1
  218. package/dist/core/tools/read.d.ts +1 -1
  219. package/dist/core/tools/read.d.ts.map +1 -1
  220. package/dist/core/tools/read.js +1 -1
  221. package/dist/core/tools/read.js.map +1 -1
  222. package/dist/core/tools/render-utils.d.ts.map +1 -1
  223. package/dist/core/tools/render-utils.js +1 -1
  224. package/dist/core/tools/render-utils.js.map +1 -1
  225. package/dist/index.d.ts +2 -3
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.js +3 -4
  228. package/dist/index.js.map +1 -1
  229. package/dist/main.d.ts.map +1 -1
  230. package/dist/main.js +13 -12
  231. package/dist/main.js.map +1 -1
  232. package/dist/modes/interactive/auth-dialogs-controller.d.ts +59 -0
  233. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -0
  234. package/dist/modes/interactive/auth-dialogs-controller.js +398 -0
  235. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -0
  236. package/dist/modes/interactive/auto-learn-controller.d.ts +168 -0
  237. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -0
  238. package/dist/modes/interactive/auto-learn-controller.js +1239 -0
  239. package/dist/modes/interactive/auto-learn-controller.js.map +1 -0
  240. package/dist/modes/interactive/autocomplete-provider.d.ts +26 -0
  241. package/dist/modes/interactive/autocomplete-provider.d.ts.map +1 -0
  242. package/dist/modes/interactive/autocomplete-provider.js +103 -0
  243. package/dist/modes/interactive/autocomplete-provider.js.map +1 -0
  244. package/dist/modes/interactive/autonomy-commands.d.ts +38 -0
  245. package/dist/modes/interactive/autonomy-commands.d.ts.map +1 -0
  246. package/dist/modes/interactive/autonomy-commands.js +142 -0
  247. package/dist/modes/interactive/autonomy-commands.js.map +1 -0
  248. package/dist/modes/interactive/clipboard-input.d.ts +37 -0
  249. package/dist/modes/interactive/clipboard-input.d.ts.map +1 -0
  250. package/dist/modes/interactive/clipboard-input.js +59 -0
  251. package/dist/modes/interactive/clipboard-input.js.map +1 -0
  252. package/dist/modes/interactive/compaction-queue.d.ts +30 -0
  253. package/dist/modes/interactive/compaction-queue.d.ts.map +1 -0
  254. package/dist/modes/interactive/compaction-queue.js +91 -0
  255. package/dist/modes/interactive/compaction-queue.js.map +1 -0
  256. package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
  257. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/bash-execution.js +1 -1
  259. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  260. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  261. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  262. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  263. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  264. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  265. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  266. package/dist/modes/interactive/components/custom-message.d.ts +1 -1
  267. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  269. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  270. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  271. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  272. package/dist/modes/interactive/components/session-selector.d.ts +1 -1
  273. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  274. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  275. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  276. package/dist/modes/interactive/components/tool-execution.js +2 -2
  277. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  278. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  279. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  281. package/dist/modes/interactive/config-backup.d.ts +27 -0
  282. package/dist/modes/interactive/config-backup.d.ts.map +1 -0
  283. package/dist/modes/interactive/config-backup.js +146 -0
  284. package/dist/modes/interactive/config-backup.js.map +1 -0
  285. package/dist/modes/interactive/editor-overlay-host.d.ts +48 -0
  286. package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -0
  287. package/dist/modes/interactive/editor-overlay-host.js +43 -0
  288. package/dist/modes/interactive/editor-overlay-host.js.map +1 -0
  289. package/dist/modes/interactive/extension-ui-host.d.ts +165 -0
  290. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -0
  291. package/dist/modes/interactive/extension-ui-host.js +610 -0
  292. package/dist/modes/interactive/extension-ui-host.js.map +1 -0
  293. package/dist/modes/interactive/external-editor.d.ts +18 -0
  294. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  295. package/dist/modes/interactive/external-editor.js +107 -0
  296. package/dist/modes/interactive/external-editor.js.map +1 -0
  297. package/dist/modes/interactive/history-reload-math.d.ts +24 -0
  298. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -0
  299. package/dist/modes/interactive/history-reload-math.js +129 -0
  300. package/dist/modes/interactive/history-reload-math.js.map +1 -0
  301. package/dist/modes/interactive/interactive-mode.d.ts +22 -238
  302. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  303. package/dist/modes/interactive/interactive-mode.js +714 -5910
  304. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  305. package/dist/modes/interactive/key-handlers.d.ts +46 -0
  306. package/dist/modes/interactive/key-handlers.d.ts.map +1 -0
  307. package/dist/modes/interactive/key-handlers.js +80 -0
  308. package/dist/modes/interactive/key-handlers.js.map +1 -0
  309. package/dist/modes/interactive/local-model-commands.d.ts +68 -0
  310. package/dist/modes/interactive/local-model-commands.d.ts.map +1 -0
  311. package/dist/modes/interactive/local-model-commands.js +288 -0
  312. package/dist/modes/interactive/local-model-commands.js.map +1 -0
  313. package/dist/modes/interactive/profile-menu-controller.d.ts +77 -0
  314. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -0
  315. package/dist/modes/interactive/profile-menu-controller.js +917 -0
  316. package/dist/modes/interactive/profile-menu-controller.js.map +1 -0
  317. package/dist/modes/interactive/report-commands.d.ts +46 -0
  318. package/dist/modes/interactive/report-commands.d.ts.map +1 -0
  319. package/dist/modes/interactive/report-commands.js +255 -0
  320. package/dist/modes/interactive/report-commands.js.map +1 -0
  321. package/dist/modes/interactive/resource-display.d.ts +73 -0
  322. package/dist/modes/interactive/resource-display.d.ts.map +1 -0
  323. package/dist/modes/interactive/resource-display.js +278 -0
  324. package/dist/modes/interactive/resource-display.js.map +1 -0
  325. package/dist/modes/interactive/resource-shell-commands.d.ts +64 -0
  326. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -0
  327. package/dist/modes/interactive/resource-shell-commands.js +202 -0
  328. package/dist/modes/interactive/resource-shell-commands.js.map +1 -0
  329. package/dist/modes/interactive/session-flow-commands.d.ts +139 -0
  330. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -0
  331. package/dist/modes/interactive/session-flow-commands.js +458 -0
  332. package/dist/modes/interactive/session-flow-commands.js.map +1 -0
  333. package/dist/modes/interactive/session-io-commands.d.ts +73 -0
  334. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -0
  335. package/dist/modes/interactive/session-io-commands.js +202 -0
  336. package/dist/modes/interactive/session-io-commands.js.map +1 -0
  337. package/dist/modes/interactive/settings-selector-flow.d.ts +42 -0
  338. package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -0
  339. package/dist/modes/interactive/settings-selector-flow.js +287 -0
  340. package/dist/modes/interactive/settings-selector-flow.js.map +1 -0
  341. package/dist/modes/interactive/signal-lifecycle.d.ts +55 -0
  342. package/dist/modes/interactive/signal-lifecycle.d.ts.map +1 -0
  343. package/dist/modes/interactive/signal-lifecycle.js +177 -0
  344. package/dist/modes/interactive/signal-lifecycle.js.map +1 -0
  345. package/dist/modes/interactive/startup-checks.d.ts +38 -0
  346. package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
  347. package/dist/modes/interactive/startup-checks.js +189 -0
  348. package/dist/modes/interactive/startup-checks.js.map +1 -0
  349. package/dist/modes/rpc/rpc-client.d.ts +1 -1
  350. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  351. package/dist/modes/rpc/rpc-client.js.map +1 -1
  352. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  353. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  354. package/dist/modes/rpc/rpc-types.js.map +1 -1
  355. package/dist/utils/paths.d.ts +2 -14
  356. package/dist/utils/paths.d.ts.map +1 -1
  357. package/dist/utils/paths.js +5 -30
  358. package/dist/utils/paths.js.map +1 -1
  359. package/dist/utils/process-memory.d.ts +8 -0
  360. package/dist/utils/process-memory.d.ts.map +1 -0
  361. package/dist/utils/process-memory.js +11 -0
  362. package/dist/utils/process-memory.js.map +1 -0
  363. package/dist/utils/shell.d.ts +0 -9
  364. package/dist/utils/shell.d.ts.map +1 -1
  365. package/dist/utils/shell.js +0 -37
  366. package/dist/utils/shell.js.map +1 -1
  367. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  368. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  369. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  370. package/examples/extensions/sandbox/package-lock.json +2 -2
  371. package/examples/extensions/sandbox/package.json +1 -1
  372. package/examples/extensions/with-deps/package-lock.json +2 -2
  373. package/examples/extensions/with-deps/package.json +1 -1
  374. package/examples/sdk/11-sessions.ts +8 -8
  375. package/examples/sdk/13-session-runtime.ts +1 -1
  376. package/npm-shrinkwrap.json +12 -12
  377. package/package.json +4 -4
  378. package/dist/core/compaction/branch-summarization.d.ts +0 -88
  379. package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
  380. package/dist/core/compaction/branch-summarization.js +0 -243
  381. package/dist/core/compaction/branch-summarization.js.map +0 -1
  382. package/dist/core/compaction/compaction.d.ts +0 -143
  383. package/dist/core/compaction/compaction.d.ts.map +0 -1
  384. package/dist/core/compaction/compaction.js +0 -659
  385. package/dist/core/compaction/compaction.js.map +0 -1
  386. package/dist/core/compaction/index.d.ts +0 -7
  387. package/dist/core/compaction/index.d.ts.map +0 -1
  388. package/dist/core/compaction/index.js +0 -7
  389. package/dist/core/compaction/index.js.map +0 -1
  390. package/dist/core/compaction/utils.d.ts +0 -38
  391. package/dist/core/compaction/utils.d.ts.map +0 -1
  392. package/dist/core/compaction/utils.js +0 -153
  393. package/dist/core/compaction/utils.js.map +0 -1
  394. package/dist/core/message-retention.d.ts +0 -26
  395. package/dist/core/message-retention.d.ts.map +0 -1
  396. package/dist/core/message-retention.js +0 -95
  397. package/dist/core/message-retention.js.map +0 -1
  398. package/dist/core/messages.d.ts +0 -77
  399. package/dist/core/messages.d.ts.map +0 -1
  400. package/dist/core/messages.js +0 -123
  401. package/dist/core/messages.js.map +0 -1
  402. package/dist/core/session-manager.d.ts +0 -337
  403. package/dist/core/session-manager.d.ts.map +0 -1
  404. package/dist/core/session-manager.js +0 -1328
  405. package/dist/core/session-manager.js.map +0 -1
  406. package/dist/core/tools/truncate.d.ts +0 -70
  407. package/dist/core/tools/truncate.d.ts.map +0 -1
  408. package/dist/core/tools/truncate.js +0 -215
  409. package/dist/core/tools/truncate.js.map +0 -1
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval
3
+ * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the
4
+ * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension
5
+ * contributions).
6
+ *
7
+ * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF
8
+ * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the
9
+ * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything
10
+ * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the
11
+ * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather
12
+ * than the whole AgentSession.
13
+ *
14
+ * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and
15
+ * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line
16
+ * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only
17
+ * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform
18
+ * stays the single owner of the pass ordering.
19
+ */
20
+ import { join } from "node:path";
21
+ import { defaultMemoryPromptInclusionReport, sanitizeMemoryRetrievalReportForDiagnostics, } from "./context/memory-diagnostics.js";
22
+ import { buildMemoryPromptBlock } from "./context/memory-prompt-block.js";
23
+ import { DEFAULT_LOCAL_MEMORY_EGRESS_POLICY, } from "./context/memory-provider-contract.js";
24
+ import { retrieveMemoryForContext } from "./context/memory-retrieval.js";
25
+ import { createOkfMemoryProvider } from "./context/okf-memory-provider.js";
26
+ import { EffectivenessTracker } from "./memory/effectiveness-tracker.js";
27
+ import { MemoryManager } from "./memory/memory-manager.js";
28
+ import { FileStoreProvider } from "./memory/providers/file-store.js";
29
+ import { TranscriptRecallProvider } from "./memory/providers/transcript-recall.js";
30
+ import { wrapUntrustedText } from "./security/untrusted-boundary.js";
31
+ /**
32
+ * Text of the most recent user message, or "" if there is none (e.g. goal-continuation
33
+ * turns with no new user input). An empty query degrades to zero memory-retrieval results
34
+ * by construction (see memory-provider-contract.ts's score-on-empty-query-tokens rule) --
35
+ * no special-casing needed here beyond returning "".
36
+ */
37
+ function latestUserMessageText(messages) {
38
+ for (let index = messages.length - 1; index >= 0; index--) {
39
+ const message = messages[index];
40
+ if (message.role !== "user")
41
+ continue;
42
+ if (typeof message.content === "string")
43
+ return message.content;
44
+ const parts = [];
45
+ for (const part of message.content) {
46
+ if (part.type === "text")
47
+ parts.push(part.text);
48
+ }
49
+ return parts.join("\n");
50
+ }
51
+ return "";
52
+ }
53
+ function emptyMemoryRetrievalReport(maxResults) {
54
+ return { request: { query: "", maxResults }, providerReports: [], results: [], contextItems: [] };
55
+ }
56
+ export class MemoryController {
57
+ _memoryOkfProvider = undefined;
58
+ _latestMemoryRetrievalReport = undefined;
59
+ _latestMemoryPromptInclusionReport = undefined;
60
+ /** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */
61
+ _memoryManager = new MemoryManager();
62
+ /** R4: tracks whether injected recall is actually used, to adapt the recall gate. */
63
+ _effectivenessTracker = new EffectivenessTracker();
64
+ /** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */
65
+ _pendingMemoryProviders = [];
66
+ deps;
67
+ constructor(deps) {
68
+ this.deps = deps;
69
+ }
70
+ /** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */
71
+ getMemoryManager() {
72
+ return this._memoryManager;
73
+ }
74
+ /**
75
+ * Fixed path for this slice's local Pi OKF memory documents, shared across sessions
76
+ * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF
77
+ * memory represents durable cross-session knowledge, not a per-session capture). Not
78
+ * yet user-configurable -- see the memory-retrieval settings doc comment.
79
+ */
80
+ _memoryOkfDir() {
81
+ return join(this.deps.getAgentDir(), "okf-memory");
82
+ }
83
+ /**
84
+ * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory
85
+ * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session
86
+ * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no
87
+ * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).
88
+ */
89
+ _getMemoryOkfProvider() {
90
+ this._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });
91
+ return this._memoryOkfProvider;
92
+ }
93
+ /**
94
+ * Observe-only local memory retrieval (see context/memory-retrieval.ts and
95
+ * context/okf-memory-provider.ts): default disabled, opt-in setting. When disabled,
96
+ * never constructs the OKF provider (no directory access under `_memoryOkfDir()` at
97
+ * all) and returns an empty report -- fully fail-closed. When enabled, queries the
98
+ * local, read-only OKF provider with the latest user message text (empty if there is
99
+ * none, e.g. a goal-continuation turn -- degrades to zero results by construction, see
100
+ * `latestUserMessageText`'s doc comment) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.
101
+ * Retrieved items are only ever stored in the report; nothing here touches `messages`,
102
+ * the transcript, or the provider-visible prompt. Never throws into a live turn: any
103
+ * failure (including a provider search error) degrades to an empty report.
104
+ */
105
+ async runMemoryRetrieval(messages) {
106
+ try {
107
+ const settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();
108
+ if (!settings.enabled) {
109
+ const report = emptyMemoryRetrievalReport(settings.maxResults);
110
+ this._latestMemoryRetrievalReport = report;
111
+ return report;
112
+ }
113
+ const report = await retrieveMemoryForContext([this._getMemoryOkfProvider()], { query: latestUserMessageText(messages), maxResults: settings.maxResults }, {
114
+ createdAtTurn: this.deps.getTurnIndex(),
115
+ maxResults: settings.maxResults,
116
+ defaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,
117
+ });
118
+ this._latestMemoryRetrievalReport = report;
119
+ return report;
120
+ }
121
+ catch {
122
+ const report = emptyMemoryRetrievalReport(0);
123
+ this._latestMemoryRetrievalReport = report;
124
+ return report;
125
+ }
126
+ }
127
+ /** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */
128
+ getMemoryRetrievalReport() {
129
+ return this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);
130
+ }
131
+ /**
132
+ * Bounded prompt-surfacing pilot for local memory evidence (see
133
+ * context/memory-prompt-block.ts): opt-in, default disabled, and gated on TWO settings
134
+ * (`enabled` AND `includeInPrompt`) plus a non-empty `report.contextItems` -- the first
135
+ * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already
136
+ * leaves `contextItems` empty whenever `enabled` is false, regardless of
137
+ * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already
138
+ * computed -- never re-queries the provider here.
139
+ *
140
+ * Appends exactly one ephemeral `custom`/"memory_evidence" message wrapped by
141
+ * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule
142
+ * used for other untrusted content) to the END of `messages`. This is purely additive
143
+ * (never mutates an existing message) and purely transient: `messages` here is the
144
+ * array about to be sent to the provider, not `this.agent.state.messages` or anything
145
+ * persisted via `sessionManager` -- so the injected message can never reach the
146
+ * transcript, regardless of how many times this pass runs.
147
+ *
148
+ * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each
149
+ * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping
150
+ * alongside the existing branches, not a new branch/condition: the messages returned
151
+ * are unchanged by this recording.
152
+ */
153
+ maybeAppendMemoryEvidenceBlock(messages, report) {
154
+ try {
155
+ const settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();
156
+ const base = {
157
+ enabled: settings.enabled,
158
+ includeInPrompt: settings.includeInPrompt,
159
+ selectedItemCount: report.contextItems.length,
160
+ };
161
+ if (!settings.enabled) {
162
+ this._latestMemoryPromptInclusionReport = {
163
+ ...base,
164
+ status: "disabled",
165
+ includedCount: 0,
166
+ omittedCount: 0,
167
+ blockChars: 0,
168
+ };
169
+ return messages;
170
+ }
171
+ if (!settings.includeInPrompt) {
172
+ this._latestMemoryPromptInclusionReport = {
173
+ ...base,
174
+ status: "include_disabled",
175
+ includedCount: 0,
176
+ omittedCount: 0,
177
+ blockChars: 0,
178
+ };
179
+ return messages;
180
+ }
181
+ if (report.contextItems.length === 0) {
182
+ this._latestMemoryPromptInclusionReport = {
183
+ ...base,
184
+ status: "no_results",
185
+ includedCount: 0,
186
+ omittedCount: 0,
187
+ blockChars: 0,
188
+ };
189
+ return messages;
190
+ }
191
+ const block = buildMemoryPromptBlock(report.contextItems);
192
+ if (!block.text) {
193
+ this._latestMemoryPromptInclusionReport = {
194
+ ...base,
195
+ status: "empty_block",
196
+ includedCount: block.includedCount,
197
+ omittedCount: block.omittedCount,
198
+ blockChars: 0,
199
+ };
200
+ return messages;
201
+ }
202
+ const wrapped = wrapUntrustedText(block.text, "memory:pi-okf");
203
+ const evidenceMessage = {
204
+ role: "custom",
205
+ customType: "memory_evidence",
206
+ content: [{ type: "text", text: wrapped }],
207
+ display: false,
208
+ timestamp: Date.now(),
209
+ };
210
+ this._latestMemoryPromptInclusionReport = {
211
+ ...base,
212
+ status: "included",
213
+ includedCount: block.includedCount,
214
+ omittedCount: block.omittedCount,
215
+ blockChars: wrapped.length,
216
+ sourceLabel: "memory:pi-okf",
217
+ };
218
+ return [...messages, evidenceMessage];
219
+ }
220
+ catch {
221
+ // `base` may not exist yet if the throw happened before it was computed (e.g.
222
+ // settings access or `report.contextItems` itself threw), so this branch cannot
223
+ // rely on it -- fall back to safe, fixed defaults rather than risk referencing
224
+ // a partially-evaluated value.
225
+ this._latestMemoryPromptInclusionReport = {
226
+ enabled: false,
227
+ includeInPrompt: false,
228
+ selectedItemCount: 0,
229
+ status: "failed",
230
+ includedCount: 0,
231
+ omittedCount: 0,
232
+ blockChars: 0,
233
+ };
234
+ return messages;
235
+ }
236
+ }
237
+ /** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */
238
+ getMemoryPromptInclusionReport() {
239
+ return this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();
240
+ }
241
+ /**
242
+ * Combines the already-stored, no-arg latest reports (never re-queries the provider or
243
+ * touches the OKF directory) into the safe, allow-list-projected shape context_audit
244
+ * exposes. See context/memory-diagnostics.ts for why this projection is allow-list
245
+ * based rather than a spread-then-delete of the raw report.
246
+ */
247
+ getMemoryAuditDiagnostics() {
248
+ const settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();
249
+ return {
250
+ retrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),
251
+ promptInclusion: this.getMemoryPromptInclusionReport(),
252
+ };
253
+ }
254
+ /**
255
+ * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so
256
+ * recall only runs when it could plausibly help. The provider's similarity cutoff is the real
257
+ * filter — this just avoids the index query on turns that obviously don't warrant it.
258
+ */
259
+ shouldAttemptRecall(text) {
260
+ const t = text.trim();
261
+ if (t.length < 12 || t.startsWith("/"))
262
+ return false;
263
+ const words = t.split(/\s+/).filter((w) => w.length >= 3);
264
+ // R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),
265
+ // raise the bar so we only recall on clearly substantial turns — and relax it again once recall
266
+ // starts paying off. Never fully disabled, so the loop can recover.
267
+ const recallRarelyUseful = this._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;
268
+ return words.length >= (recallRarelyUseful ? 6 : 3);
269
+ }
270
+ /** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */
271
+ recordRecallOutcome(recallText, queryText, responseText) {
272
+ this._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);
273
+ }
274
+ /**
275
+ * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled
276
+ * file-store + any extension-contributed providers, initialize, then surface the memory tools and
277
+ * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.
278
+ */
279
+ async initialize() {
280
+ try {
281
+ // Release the previous generation's providers (locks/handles) before recreating, so a
282
+ // reload does not orphan the old MemoryManager. No-op on first init / for file-store.
283
+ await this._memoryManager.shutdownAll().catch(() => { });
284
+ const manager = new MemoryManager();
285
+ manager.registerProvider(new FileStoreProvider());
286
+ // Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers
287
+ // prefetch() with a <memory_context> page. Never writes.
288
+ manager.registerProvider(new TranscriptRecallProvider());
289
+ for (const provider of this._pendingMemoryProviders) {
290
+ try {
291
+ manager.registerProvider(provider);
292
+ }
293
+ catch {
294
+ // Duplicate name or reserved-tool collision — skip this provider, keep the rest.
295
+ }
296
+ }
297
+ this._memoryManager = manager;
298
+ await manager.initializeAll(this.deps.getSessionId(), {
299
+ agentDir: this.deps.getAgentDir(),
300
+ cwd: this.deps.getCwd(),
301
+ isChildSession: this.deps.isChildSession(),
302
+ });
303
+ // Surface memory tools + the frozen memory block now that providers are initialized.
304
+ // refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the
305
+ // system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.
306
+ this.deps.refreshToolRegistry();
307
+ }
308
+ catch (error) {
309
+ console.error("Memory subsystem init failed:", error instanceof Error ? error.message : String(error));
310
+ }
311
+ }
312
+ /** Register a memory provider contributed by an extension; applied on the next memory (re)init. */
313
+ registerMemoryProvider(provider) {
314
+ if (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {
315
+ this._pendingMemoryProviders.push(provider);
316
+ }
317
+ }
318
+ /** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */
319
+ clearPendingProviders() {
320
+ this._pendingMemoryProviders = [];
321
+ }
322
+ }
323
+ //# sourceMappingURL=memory-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-controller.js","sourceRoot":"","sources":["../../src/core/memory-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval\n * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the\n * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension\n * contributions).\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF\n * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the\n * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything\n * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the\n * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather\n * than the whole AgentSession.\n *\n * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and\n * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line\n * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only\n * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform\n * stays the single owner of the pass ordering.\n */\n\nimport { join } from \"node:path\";\nimport type { AgentMessage, CustomMessage } from \"@caupulican/pi-agent-core\";\nimport {\n\tdefaultMemoryPromptInclusionReport,\n\ttype MemoryPromptInclusionReport,\n\ttype MemoryRetrievalDiagnostics,\n\tsanitizeMemoryRetrievalReportForDiagnostics,\n} from \"./context/memory-diagnostics.ts\";\nimport { buildMemoryPromptBlock } from \"./context/memory-prompt-block.ts\";\nimport {\n\ttype MemoryProvider as ContextMemoryProvider,\n\tDEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n} from \"./context/memory-provider-contract.ts\";\nimport { type MemoryRetrievalReport, retrieveMemoryForContext } from \"./context/memory-retrieval.ts\";\nimport { createOkfMemoryProvider } from \"./context/okf-memory-provider.ts\";\nimport { EffectivenessTracker } from \"./memory/effectiveness-tracker.ts\";\nimport { MemoryManager } from \"./memory/memory-manager.ts\";\nimport type { MemoryProvider } from \"./memory/memory-provider.ts\";\nimport { FileStoreProvider } from \"./memory/providers/file-store.ts\";\nimport { TranscriptRecallProvider } from \"./memory/providers/transcript-recall.ts\";\nimport { wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * Text of the most recent user message, or \"\" if there is none (e.g. goal-continuation\n * turns with no new user input). An empty query degrades to zero memory-retrieval results\n * by construction (see memory-provider-contract.ts's score-on-empty-query-tokens rule) --\n * no special-casing needed here beyond returning \"\".\n */\nfunction latestUserMessageText(messages: AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message.role !== \"user\") continue;\n\t\tif (typeof message.content === \"string\") return message.content;\n\t\tconst parts: string[] = [];\n\t\tfor (const part of message.content) {\n\t\t\tif (part.type === \"text\") parts.push(part.text);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\treturn \"\";\n}\n\nfunction emptyMemoryRetrievalReport(maxResults: number): MemoryRetrievalReport {\n\treturn { request: { query: \"\", maxResults }, providerReports: [], results: [], contextItems: [] };\n}\n\nexport interface MemoryControllerDeps {\n\t/** Memory-retrieval + prompt-inclusion settings (the opt-in gates for retrieval and surfacing). */\n\tgetSettingsManager(): SettingsManager;\n\t/** Current turn index, stamped into a retrieval request's `createdAtTurn`. */\n\tgetTurnIndex(): number;\n\t/** Agent root — the durable OKF memory docs live under `<agentDir>/okf-memory`. */\n\tgetAgentDir(): string;\n\t/** Workspace root, passed to provider initialization. */\n\tgetCwd(): string;\n\t/** This session's id, passed to provider initialization. */\n\tgetSessionId(): string;\n\t/** Child sessions gate durable memory writes; passed to provider initialization. */\n\tisChildSession(): boolean;\n\t/** Re-derive the tool registry after (re)init so the newly-surfaced memory tools take effect. */\n\trefreshToolRegistry(): void;\n}\n\nexport class MemoryController {\n\tprivate _memoryOkfProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _latestMemoryRetrievalReport: MemoryRetrievalReport | undefined = undefined;\n\tprivate _latestMemoryPromptInclusionReport: MemoryPromptInclusionReport | undefined = undefined;\n\t/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */\n\tprivate _memoryManager: MemoryManager = new MemoryManager();\n\t/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */\n\tprivate readonly _effectivenessTracker = new EffectivenessTracker();\n\t/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */\n\tprivate _pendingMemoryProviders: MemoryProvider[] = [];\n\n\tprivate readonly deps: MemoryControllerDeps;\n\n\tconstructor(deps: MemoryControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\t/** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */\n\tgetMemoryManager(): MemoryManager {\n\t\treturn this._memoryManager;\n\t}\n\n\t/**\n\t * Fixed path for this slice's local Pi OKF memory documents, shared across sessions\n\t * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF\n\t * memory represents durable cross-session knowledge, not a per-session capture). Not\n\t * yet user-configurable -- see the memory-retrieval settings doc comment.\n\t */\n\tprivate _memoryOkfDir(): string {\n\t\treturn join(this.deps.getAgentDir(), \"okf-memory\");\n\t}\n\n\t/**\n\t * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory\n\t * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session\n\t * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no\n\t * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).\n\t */\n\tprivate _getMemoryOkfProvider(): ContextMemoryProvider {\n\t\tthis._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });\n\t\treturn this._memoryOkfProvider;\n\t}\n\n\t/**\n\t * Observe-only local memory retrieval (see context/memory-retrieval.ts and\n\t * context/okf-memory-provider.ts): default disabled, opt-in setting. When disabled,\n\t * never constructs the OKF provider (no directory access under `_memoryOkfDir()` at\n\t * all) and returns an empty report -- fully fail-closed. When enabled, queries the\n\t * local, read-only OKF provider with the latest user message text (empty if there is\n\t * none, e.g. a goal-continuation turn -- degrades to zero results by construction, see\n\t * `latestUserMessageText`'s doc comment) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.\n\t * Retrieved items are only ever stored in the report; nothing here touches `messages`,\n\t * the transcript, or the provider-visible prompt. Never throws into a live turn: any\n\t * failure (including a provider search error) degrades to an empty report.\n\t */\n\tasync runMemoryRetrieval(messages: AgentMessage[]): Promise<MemoryRetrievalReport> {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tif (!settings.enabled) {\n\t\t\t\tconst report = emptyMemoryRetrievalReport(settings.maxResults);\n\t\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\t\treturn report;\n\t\t\t}\n\t\t\tconst report = await retrieveMemoryForContext(\n\t\t\t\t[this._getMemoryOkfProvider()],\n\t\t\t\t{ query: latestUserMessageText(messages), maxResults: settings.maxResults },\n\t\t\t\t{\n\t\t\t\t\tcreatedAtTurn: this.deps.getTurnIndex(),\n\t\t\t\t\tmaxResults: settings.maxResults,\n\t\t\t\t\tdefaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t} catch {\n\t\t\tconst report = emptyMemoryRetrievalReport(0);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */\n\tgetMemoryRetrievalReport(): MemoryRetrievalReport {\n\t\treturn this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);\n\t}\n\n\t/**\n\t * Bounded prompt-surfacing pilot for local memory evidence (see\n\t * context/memory-prompt-block.ts): opt-in, default disabled, and gated on TWO settings\n\t * (`enabled` AND `includeInPrompt`) plus a non-empty `report.contextItems` -- the first\n\t * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already\n\t * leaves `contextItems` empty whenever `enabled` is false, regardless of\n\t * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already\n\t * computed -- never re-queries the provider here.\n\t *\n\t * Appends exactly one ephemeral `custom`/\"memory_evidence\" message wrapped by\n\t * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule\n\t * used for other untrusted content) to the END of `messages`. This is purely additive\n\t * (never mutates an existing message) and purely transient: `messages` here is the\n\t * array about to be sent to the provider, not `this.agent.state.messages` or anything\n\t * persisted via `sessionManager` -- so the injected message can never reach the\n\t * transcript, regardless of how many times this pass runs.\n\t *\n\t * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each\n\t * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping\n\t * alongside the existing branches, not a new branch/condition: the messages returned\n\t * are unchanged by this recording.\n\t */\n\tmaybeAppendMemoryEvidenceBlock(messages: AgentMessage[], report: MemoryRetrievalReport): AgentMessage[] {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tconst base = {\n\t\t\t\tenabled: settings.enabled,\n\t\t\t\tincludeInPrompt: settings.includeInPrompt,\n\t\t\t\tselectedItemCount: report.contextItems.length,\n\t\t\t};\n\t\t\tif (!settings.enabled) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (!settings.includeInPrompt) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"include_disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (report.contextItems.length === 0) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"no_results\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst block = buildMemoryPromptBlock(report.contextItems);\n\t\t\tif (!block.text) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"empty_block\",\n\t\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst wrapped = wrapUntrustedText(block.text, \"memory:pi-okf\");\n\t\t\tconst evidenceMessage: CustomMessage = {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: \"memory_evidence\",\n\t\t\t\tcontent: [{ type: \"text\", text: wrapped }],\n\t\t\t\tdisplay: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t...base,\n\t\t\t\tstatus: \"included\",\n\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\tblockChars: wrapped.length,\n\t\t\t\tsourceLabel: \"memory:pi-okf\",\n\t\t\t};\n\t\t\treturn [...messages, evidenceMessage];\n\t\t} catch {\n\t\t\t// `base` may not exist yet if the throw happened before it was computed (e.g.\n\t\t\t// settings access or `report.contextItems` itself threw), so this branch cannot\n\t\t\t// rely on it -- fall back to safe, fixed defaults rather than risk referencing\n\t\t\t// a partially-evaluated value.\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\tenabled: false,\n\t\t\t\tincludeInPrompt: false,\n\t\t\t\tselectedItemCount: 0,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tincludedCount: 0,\n\t\t\t\tomittedCount: 0,\n\t\t\t\tblockChars: 0,\n\t\t\t};\n\t\t\treturn messages;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */\n\tgetMemoryPromptInclusionReport(): MemoryPromptInclusionReport {\n\t\treturn this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();\n\t}\n\n\t/**\n\t * Combines the already-stored, no-arg latest reports (never re-queries the provider or\n\t * touches the OKF directory) into the safe, allow-list-projected shape context_audit\n\t * exposes. See context/memory-diagnostics.ts for why this projection is allow-list\n\t * based rather than a spread-then-delete of the raw report.\n\t */\n\tgetMemoryAuditDiagnostics(): {\n\t\tretrieval: MemoryRetrievalDiagnostics;\n\t\tpromptInclusion: MemoryPromptInclusionReport;\n\t} {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\treturn {\n\t\t\tretrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),\n\t\t\tpromptInclusion: this.getMemoryPromptInclusionReport(),\n\t\t};\n\t}\n\n\t/**\n\t * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so\n\t * recall only runs when it could plausibly help. The provider's similarity cutoff is the real\n\t * filter — this just avoids the index query on turns that obviously don't warrant it.\n\t */\n\tshouldAttemptRecall(text: string): boolean {\n\t\tconst t = text.trim();\n\t\tif (t.length < 12 || t.startsWith(\"/\")) return false;\n\t\tconst words = t.split(/\\s+/).filter((w) => w.length >= 3);\n\t\t// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),\n\t\t// raise the bar so we only recall on clearly substantial turns — and relax it again once recall\n\t\t// starts paying off. Never fully disabled, so the loop can recover.\n\t\tconst recallRarelyUseful =\n\t\t\tthis._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;\n\t\treturn words.length >= (recallRarelyUseful ? 6 : 3);\n\t}\n\n\t/** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */\n\trecordRecallOutcome(recallText: string, queryText: string, responseText: string): void {\n\t\tthis._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);\n\t}\n\n\t/**\n\t * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled\n\t * file-store + any extension-contributed providers, initialize, then surface the memory tools and\n\t * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.\n\t */\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\t// Release the previous generation's providers (locks/handles) before recreating, so a\n\t\t\t// reload does not orphan the old MemoryManager. No-op on first init / for file-store.\n\t\t\tawait this._memoryManager.shutdownAll().catch(() => {});\n\t\t\tconst manager = new MemoryManager();\n\t\t\tmanager.registerProvider(new FileStoreProvider());\n\t\t\t// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers\n\t\t\t// prefetch() with a <memory_context> page. Never writes.\n\t\t\tmanager.registerProvider(new TranscriptRecallProvider());\n\t\t\tfor (const provider of this._pendingMemoryProviders) {\n\t\t\t\ttry {\n\t\t\t\t\tmanager.registerProvider(provider);\n\t\t\t\t} catch {\n\t\t\t\t\t// Duplicate name or reserved-tool collision — skip this provider, keep the rest.\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._memoryManager = manager;\n\t\t\tawait manager.initializeAll(this.deps.getSessionId(), {\n\t\t\t\tagentDir: this.deps.getAgentDir(),\n\t\t\t\tcwd: this.deps.getCwd(),\n\t\t\t\tisChildSession: this.deps.isChildSession(),\n\t\t\t});\n\t\t\t// Surface memory tools + the frozen memory block now that providers are initialized.\n\t\t\t// refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the\n\t\t\t// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.\n\t\t\tthis.deps.refreshToolRegistry();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Memory subsystem init failed:\", error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */\n\tregisterMemoryProvider(provider: MemoryProvider): void {\n\t\tif (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {\n\t\t\tthis._pendingMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\t/** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */\n\tclearPendingProviders(): void {\n\t\tthis._pendingMemoryProviders = [];\n\t}\n}\n"]}
@@ -1,5 +1,5 @@
1
+ import type { SessionEntry } from "@caupulican/pi-agent-core/node";
1
2
  import type { RouteDecision } from "../autonomy/contracts.ts";
2
- import type { SessionEntry } from "../session-manager.ts";
3
3
  import type { ModelRouterIntent } from "./intent-classifier.ts";
4
4
  export declare const MODEL_ROUTER_DECISION_CUSTOM_TYPE = "model_router_decision";
5
5
  export type ModelRouterStatusSettings = {
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,aAAa,EAAa,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,eAAO,MAAM,iCAAiC,0BAA0B,CAAC;AAEzE,MAAM,MAAM,yBAAyB,GAAG;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAiDF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,SAAI,GAAG,yBAAyB,EAAE,CAQ7G;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,yBAAyB,EACnC,YAAY,CAAC,EAAE,yBAAyB,EACxC,WAAW,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAyB,EACzD,eAAe,GAAE,yBAAyB,EAAO,EACjD,cAAc,CAAC,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,iBAAiB,GAC9B,MAAM,CA+BR","sourcesContent":["import type { ModelTier, RouteDecision, RouteRisk } from \"../autonomy/contracts.ts\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport type { ModelRouterIntent } from \"./intent-classifier.ts\";\n\nexport const MODEL_ROUTER_DECISION_CUSTOM_TYPE = \"model_router_decision\";\n\nexport type ModelRouterStatusSettings = {\n\tenabled: boolean;\n\tcheapModel?: string;\n\tmediumModel?: string;\n\texpensiveModel?: string;\n\tlearningModel?: string;\n};\n\nexport type ModelRouterDecisionStatus = {\n\troute: RouteDecision;\n\troutedModel: string;\n\toutcome: \"routed\" | \"escalated\" | \"failed\";\n\tretryModel?: string;\n\tintent?: ModelRouterIntent;\n};\n\nfunction isRouteDecision(value: unknown): value is RouteDecision {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst route = value as Partial<RouteDecision>;\n\tconst validTiers = new Set<ModelTier>([\"cheap\", \"medium\", \"expensive\", \"learning\"]);\n\tconst validRisks = new Set<RouteRisk>([\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"]);\n\n\treturn (\n\t\ttypeof route.confidence === \"number\" &&\n\t\ttypeof route.reasonCode === \"string\" &&\n\t\tArray.isArray(route.reasons) &&\n\t\troute.reasons.every((r) => typeof r === \"string\") &&\n\t\tvalidTiers.has(route.tier as ModelTier) &&\n\t\tvalidRisks.has(route.risk as RouteRisk) &&\n\t\t(route.model === undefined || typeof route.model === \"string\") &&\n\t\t(route.fallbackFrom === undefined ||\n\t\t\troute.fallbackFrom === \"cheap\" ||\n\t\t\troute.fallbackFrom === \"medium\" ||\n\t\t\troute.fallbackFrom === \"expensive\" ||\n\t\t\troute.fallbackFrom === \"learning\") &&\n\t\t(route.createdAt === undefined || typeof route.createdAt === \"string\")\n\t);\n}\n\nfunction isModelRouterDecisionStatus(data: unknown): data is ModelRouterDecisionStatus {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst record = data as Partial<ModelRouterDecisionStatus>;\n\treturn (\n\t\tisRouteDecision(record.route) &&\n\t\trecord.route.tier !== \"learning\" && // Validate user prompt decisions never need learning tier in runtime\n\t\ttypeof record.routedModel === \"string\" &&\n\t\t(record.outcome === \"routed\" || record.outcome === \"escalated\" || record.outcome === \"failed\") &&\n\t\t(record.retryModel === undefined || typeof record.retryModel === \"string\") &&\n\t\t(record.intent === undefined || record.intent === \"research\" || record.intent === \"modify\")\n\t);\n}\n\nfunction formatDecision(decision: ModelRouterDecisionStatus): string {\n\tconst { tier, risk, reasonCode } = decision.route;\n\tlet outcomeText: string = decision.outcome;\n\tif (decision.outcome === \"escalated\" && decision.retryModel) {\n\t\toutcomeText = `escalated -> ${decision.retryModel}`;\n\t} else if (decision.outcome === \"failed\") {\n\t\toutcomeText = \"failed\";\n\t}\n\treturn `${tier}/${risk} -> ${decision.routedModel} (${reasonCode}, ${outcomeText})`;\n}\n\nexport function getRecentModelRouterDecisions(entries: SessionEntry[], limit = 3): ModelRouterDecisionStatus[] {\n\tconst decisions: ModelRouterDecisionStatus[] = [];\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== MODEL_ROUTER_DECISION_CUSTOM_TYPE) continue;\n\t\tif (!isModelRouterDecisionStatus(entry.data)) continue;\n\t\tdecisions.push(entry.data);\n\t}\n\treturn decisions.slice(-limit);\n}\n\nexport function formatModelRouterStatus(\n\tsettings: ModelRouterStatusSettings,\n\tlastDecision?: ModelRouterDecisionStatus,\n\tformatLabel: (label: string) => string = (label) => label,\n\trecentDecisions: ModelRouterDecisionStatus[] = [],\n\tlastSkipReason?: string,\n\tlatestIntent?: ModelRouterIntent,\n): string {\n\tconst effectiveLastDecision = lastSkipReason ? undefined : lastDecision;\n\tconst lines = [\n\t\t`${formatLabel(\"Status:\")} ${settings.enabled ? \"enabled\" : \"disabled\"}`,\n\t\t`${formatLabel(\"Cheap model:\")} ${settings.cheapModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Medium model:\")} ${settings.mediumModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Expensive model:\")} ${settings.expensiveModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Learning model:\")} ${settings.learningModel ?? \"active\"}`,\n\t];\n\tif (!settings.enabled) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} inactive (disabled)`);\n\t} else if (lastSkipReason) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} skipped (${lastSkipReason})`);\n\t} else if (effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} active`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Routing:\")} waiting for prompt`);\n\t}\n\tlines.push(`${formatLabel(\"Latest intent:\")} ${latestIntent ?? \"none\"}`);\n\tif (!effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} none`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} ${formatDecision(effectiveLastDecision)}`);\n\t}\n\tif (recentDecisions.length > 0) {\n\t\tlines.push(formatLabel(\"Recent decisions:\"));\n\t\tfor (const decision of recentDecisions) {\n\t\t\tlines.push(`- ${formatDecision(decision)}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAa,aAAa,EAAa,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,eAAO,MAAM,iCAAiC,0BAA0B,CAAC;AAEzE,MAAM,MAAM,yBAAyB,GAAG;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAiDF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,SAAI,GAAG,yBAAyB,EAAE,CAQ7G;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,yBAAyB,EACnC,YAAY,CAAC,EAAE,yBAAyB,EACxC,WAAW,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAyB,EACzD,eAAe,GAAE,yBAAyB,EAAO,EACjD,cAAc,CAAC,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,iBAAiB,GAC9B,MAAM,CA+BR","sourcesContent":["import type { SessionEntry } from \"@caupulican/pi-agent-core/node\";\nimport type { ModelTier, RouteDecision, RouteRisk } from \"../autonomy/contracts.ts\";\nimport type { ModelRouterIntent } from \"./intent-classifier.ts\";\n\nexport const MODEL_ROUTER_DECISION_CUSTOM_TYPE = \"model_router_decision\";\n\nexport type ModelRouterStatusSettings = {\n\tenabled: boolean;\n\tcheapModel?: string;\n\tmediumModel?: string;\n\texpensiveModel?: string;\n\tlearningModel?: string;\n};\n\nexport type ModelRouterDecisionStatus = {\n\troute: RouteDecision;\n\troutedModel: string;\n\toutcome: \"routed\" | \"escalated\" | \"failed\";\n\tretryModel?: string;\n\tintent?: ModelRouterIntent;\n};\n\nfunction isRouteDecision(value: unknown): value is RouteDecision {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst route = value as Partial<RouteDecision>;\n\tconst validTiers = new Set<ModelTier>([\"cheap\", \"medium\", \"expensive\", \"learning\"]);\n\tconst validRisks = new Set<RouteRisk>([\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"]);\n\n\treturn (\n\t\ttypeof route.confidence === \"number\" &&\n\t\ttypeof route.reasonCode === \"string\" &&\n\t\tArray.isArray(route.reasons) &&\n\t\troute.reasons.every((r) => typeof r === \"string\") &&\n\t\tvalidTiers.has(route.tier as ModelTier) &&\n\t\tvalidRisks.has(route.risk as RouteRisk) &&\n\t\t(route.model === undefined || typeof route.model === \"string\") &&\n\t\t(route.fallbackFrom === undefined ||\n\t\t\troute.fallbackFrom === \"cheap\" ||\n\t\t\troute.fallbackFrom === \"medium\" ||\n\t\t\troute.fallbackFrom === \"expensive\" ||\n\t\t\troute.fallbackFrom === \"learning\") &&\n\t\t(route.createdAt === undefined || typeof route.createdAt === \"string\")\n\t);\n}\n\nfunction isModelRouterDecisionStatus(data: unknown): data is ModelRouterDecisionStatus {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst record = data as Partial<ModelRouterDecisionStatus>;\n\treturn (\n\t\tisRouteDecision(record.route) &&\n\t\trecord.route.tier !== \"learning\" && // Validate user prompt decisions never need learning tier in runtime\n\t\ttypeof record.routedModel === \"string\" &&\n\t\t(record.outcome === \"routed\" || record.outcome === \"escalated\" || record.outcome === \"failed\") &&\n\t\t(record.retryModel === undefined || typeof record.retryModel === \"string\") &&\n\t\t(record.intent === undefined || record.intent === \"research\" || record.intent === \"modify\")\n\t);\n}\n\nfunction formatDecision(decision: ModelRouterDecisionStatus): string {\n\tconst { tier, risk, reasonCode } = decision.route;\n\tlet outcomeText: string = decision.outcome;\n\tif (decision.outcome === \"escalated\" && decision.retryModel) {\n\t\toutcomeText = `escalated -> ${decision.retryModel}`;\n\t} else if (decision.outcome === \"failed\") {\n\t\toutcomeText = \"failed\";\n\t}\n\treturn `${tier}/${risk} -> ${decision.routedModel} (${reasonCode}, ${outcomeText})`;\n}\n\nexport function getRecentModelRouterDecisions(entries: SessionEntry[], limit = 3): ModelRouterDecisionStatus[] {\n\tconst decisions: ModelRouterDecisionStatus[] = [];\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== MODEL_ROUTER_DECISION_CUSTOM_TYPE) continue;\n\t\tif (!isModelRouterDecisionStatus(entry.data)) continue;\n\t\tdecisions.push(entry.data);\n\t}\n\treturn decisions.slice(-limit);\n}\n\nexport function formatModelRouterStatus(\n\tsettings: ModelRouterStatusSettings,\n\tlastDecision?: ModelRouterDecisionStatus,\n\tformatLabel: (label: string) => string = (label) => label,\n\trecentDecisions: ModelRouterDecisionStatus[] = [],\n\tlastSkipReason?: string,\n\tlatestIntent?: ModelRouterIntent,\n): string {\n\tconst effectiveLastDecision = lastSkipReason ? undefined : lastDecision;\n\tconst lines = [\n\t\t`${formatLabel(\"Status:\")} ${settings.enabled ? \"enabled\" : \"disabled\"}`,\n\t\t`${formatLabel(\"Cheap model:\")} ${settings.cheapModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Medium model:\")} ${settings.mediumModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Expensive model:\")} ${settings.expensiveModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Learning model:\")} ${settings.learningModel ?? \"active\"}`,\n\t];\n\tif (!settings.enabled) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} inactive (disabled)`);\n\t} else if (lastSkipReason) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} skipped (${lastSkipReason})`);\n\t} else if (effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} active`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Routing:\")} waiting for prompt`);\n\t}\n\tlines.push(`${formatLabel(\"Latest intent:\")} ${latestIntent ?? \"none\"}`);\n\tif (!effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} none`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} ${formatDecision(effectiveLastDecision)}`);\n\t}\n\tif (recentDecisions.length > 0) {\n\t\tlines.push(formatLabel(\"Recent decisions:\"));\n\t\tfor (const decision of recentDecisions) {\n\t\t\tlines.push(`- ${formatDecision(decision)}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/core/model-router/status.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,iCAAiC,GAAG,uBAAuB,CAAC;AAkBzE,SAAS,eAAe,CAAC,KAAc,EAA0B;IAChE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,KAAK,GAAG,KAA+B,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAY,CAAC,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAEzG,OAAO,CACN,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACpC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACpC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACjD,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAiB,CAAC;QACvC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAiB,CAAC;QACvC,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC;QAC9D,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS;YAChC,KAAK,CAAC,YAAY,KAAK,OAAO;YAC9B,KAAK,CAAC,YAAY,KAAK,QAAQ;YAC/B,KAAK,CAAC,YAAY,KAAK,WAAW;YAClC,KAAK,CAAC,YAAY,KAAK,UAAU,CAAC;QACnC,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CACtE,CAAC;AAAA,CACF;AAED,SAAS,2BAA2B,CAAC,IAAa,EAAqC;IACtF,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,MAAM,GAAG,IAA0C,CAAC;IAC1D,OAAO,CACN,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,qEAAqE;QACzG,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;QACtC,CAAC,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC;QAC9F,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC;QAC1E,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAC3F,CAAC;AAAA,CACF;AAED,SAAS,cAAc,CAAC,QAAmC,EAAU;IACpE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC;IAClD,IAAI,WAAW,GAAW,QAAQ,CAAC,OAAO,CAAC;IAC3C,IAAI,QAAQ,CAAC,OAAO,KAAK,WAAW,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC7D,WAAW,GAAG,gBAAgB,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrD,CAAC;SAAM,IAAI,QAAQ,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1C,WAAW,GAAG,QAAQ,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,UAAU,KAAK,WAAW,GAAG,CAAC;AAAA,CACpF;AAED,MAAM,UAAU,6BAA6B,CAAC,OAAuB,EAAE,KAAK,GAAG,CAAC,EAA+B;IAC9G,MAAM,SAAS,GAAgC,EAAE,CAAC;IAClD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,iCAAiC;YAAE,SAAS;QAChG,IAAI,CAAC,2BAA2B,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QACvD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;AAAA,CAC/B;AAED,MAAM,UAAU,uBAAuB,CACtC,QAAmC,EACnC,YAAwC,EACxC,WAAW,GAA8B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EACzD,eAAe,GAAgC,EAAE,EACjD,cAAuB,EACvB,YAAgC,EACvB;IACT,MAAM,qBAAqB,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IACxE,MAAM,KAAK,GAAG;QACb,GAAG,WAAW,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE;QACxE,GAAG,WAAW,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,UAAU,IAAI,OAAO,EAAE;QAClE,GAAG,WAAW,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,WAAW,IAAI,OAAO,EAAE;QACpE,GAAG,WAAW,CAAC,kBAAkB,CAAC,IAAI,QAAQ,CAAC,cAAc,IAAI,OAAO,EAAE;QAC1E,GAAG,WAAW,CAAC,iBAAiB,CAAC,IAAI,QAAQ,CAAC,aAAa,IAAI,QAAQ,EAAE;KACzE,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;IAC9D,CAAC;SAAM,IAAI,cAAc,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,UAAU,CAAC,aAAa,cAAc,GAAG,CAAC,CAAC;IACtE,CAAC;SAAM,IAAI,qBAAqB,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,IAAI,YAAY,IAAI,MAAM,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,IAAI,cAAc,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC7C,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB","sourcesContent":["import type { ModelTier, RouteDecision, RouteRisk } from \"../autonomy/contracts.ts\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport type { ModelRouterIntent } from \"./intent-classifier.ts\";\n\nexport const MODEL_ROUTER_DECISION_CUSTOM_TYPE = \"model_router_decision\";\n\nexport type ModelRouterStatusSettings = {\n\tenabled: boolean;\n\tcheapModel?: string;\n\tmediumModel?: string;\n\texpensiveModel?: string;\n\tlearningModel?: string;\n};\n\nexport type ModelRouterDecisionStatus = {\n\troute: RouteDecision;\n\troutedModel: string;\n\toutcome: \"routed\" | \"escalated\" | \"failed\";\n\tretryModel?: string;\n\tintent?: ModelRouterIntent;\n};\n\nfunction isRouteDecision(value: unknown): value is RouteDecision {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst route = value as Partial<RouteDecision>;\n\tconst validTiers = new Set<ModelTier>([\"cheap\", \"medium\", \"expensive\", \"learning\"]);\n\tconst validRisks = new Set<RouteRisk>([\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"]);\n\n\treturn (\n\t\ttypeof route.confidence === \"number\" &&\n\t\ttypeof route.reasonCode === \"string\" &&\n\t\tArray.isArray(route.reasons) &&\n\t\troute.reasons.every((r) => typeof r === \"string\") &&\n\t\tvalidTiers.has(route.tier as ModelTier) &&\n\t\tvalidRisks.has(route.risk as RouteRisk) &&\n\t\t(route.model === undefined || typeof route.model === \"string\") &&\n\t\t(route.fallbackFrom === undefined ||\n\t\t\troute.fallbackFrom === \"cheap\" ||\n\t\t\troute.fallbackFrom === \"medium\" ||\n\t\t\troute.fallbackFrom === \"expensive\" ||\n\t\t\troute.fallbackFrom === \"learning\") &&\n\t\t(route.createdAt === undefined || typeof route.createdAt === \"string\")\n\t);\n}\n\nfunction isModelRouterDecisionStatus(data: unknown): data is ModelRouterDecisionStatus {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst record = data as Partial<ModelRouterDecisionStatus>;\n\treturn (\n\t\tisRouteDecision(record.route) &&\n\t\trecord.route.tier !== \"learning\" && // Validate user prompt decisions never need learning tier in runtime\n\t\ttypeof record.routedModel === \"string\" &&\n\t\t(record.outcome === \"routed\" || record.outcome === \"escalated\" || record.outcome === \"failed\") &&\n\t\t(record.retryModel === undefined || typeof record.retryModel === \"string\") &&\n\t\t(record.intent === undefined || record.intent === \"research\" || record.intent === \"modify\")\n\t);\n}\n\nfunction formatDecision(decision: ModelRouterDecisionStatus): string {\n\tconst { tier, risk, reasonCode } = decision.route;\n\tlet outcomeText: string = decision.outcome;\n\tif (decision.outcome === \"escalated\" && decision.retryModel) {\n\t\toutcomeText = `escalated -> ${decision.retryModel}`;\n\t} else if (decision.outcome === \"failed\") {\n\t\toutcomeText = \"failed\";\n\t}\n\treturn `${tier}/${risk} -> ${decision.routedModel} (${reasonCode}, ${outcomeText})`;\n}\n\nexport function getRecentModelRouterDecisions(entries: SessionEntry[], limit = 3): ModelRouterDecisionStatus[] {\n\tconst decisions: ModelRouterDecisionStatus[] = [];\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== MODEL_ROUTER_DECISION_CUSTOM_TYPE) continue;\n\t\tif (!isModelRouterDecisionStatus(entry.data)) continue;\n\t\tdecisions.push(entry.data);\n\t}\n\treturn decisions.slice(-limit);\n}\n\nexport function formatModelRouterStatus(\n\tsettings: ModelRouterStatusSettings,\n\tlastDecision?: ModelRouterDecisionStatus,\n\tformatLabel: (label: string) => string = (label) => label,\n\trecentDecisions: ModelRouterDecisionStatus[] = [],\n\tlastSkipReason?: string,\n\tlatestIntent?: ModelRouterIntent,\n): string {\n\tconst effectiveLastDecision = lastSkipReason ? undefined : lastDecision;\n\tconst lines = [\n\t\t`${formatLabel(\"Status:\")} ${settings.enabled ? \"enabled\" : \"disabled\"}`,\n\t\t`${formatLabel(\"Cheap model:\")} ${settings.cheapModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Medium model:\")} ${settings.mediumModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Expensive model:\")} ${settings.expensiveModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Learning model:\")} ${settings.learningModel ?? \"active\"}`,\n\t];\n\tif (!settings.enabled) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} inactive (disabled)`);\n\t} else if (lastSkipReason) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} skipped (${lastSkipReason})`);\n\t} else if (effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} active`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Routing:\")} waiting for prompt`);\n\t}\n\tlines.push(`${formatLabel(\"Latest intent:\")} ${latestIntent ?? \"none\"}`);\n\tif (!effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} none`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} ${formatDecision(effectiveLastDecision)}`);\n\t}\n\tif (recentDecisions.length > 0) {\n\t\tlines.push(formatLabel(\"Recent decisions:\"));\n\t\tfor (const decision of recentDecisions) {\n\t\t\tlines.push(`- ${formatDecision(decision)}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/core/model-router/status.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionEntry } from \"@caupulican/pi-agent-core/node\";\nimport type { ModelTier, RouteDecision, RouteRisk } from \"../autonomy/contracts.ts\";\nimport type { ModelRouterIntent } from \"./intent-classifier.ts\";\n\nexport const MODEL_ROUTER_DECISION_CUSTOM_TYPE = \"model_router_decision\";\n\nexport type ModelRouterStatusSettings = {\n\tenabled: boolean;\n\tcheapModel?: string;\n\tmediumModel?: string;\n\texpensiveModel?: string;\n\tlearningModel?: string;\n};\n\nexport type ModelRouterDecisionStatus = {\n\troute: RouteDecision;\n\troutedModel: string;\n\toutcome: \"routed\" | \"escalated\" | \"failed\";\n\tretryModel?: string;\n\tintent?: ModelRouterIntent;\n};\n\nfunction isRouteDecision(value: unknown): value is RouteDecision {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst route = value as Partial<RouteDecision>;\n\tconst validTiers = new Set<ModelTier>([\"cheap\", \"medium\", \"expensive\", \"learning\"]);\n\tconst validRisks = new Set<RouteRisk>([\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"]);\n\n\treturn (\n\t\ttypeof route.confidence === \"number\" &&\n\t\ttypeof route.reasonCode === \"string\" &&\n\t\tArray.isArray(route.reasons) &&\n\t\troute.reasons.every((r) => typeof r === \"string\") &&\n\t\tvalidTiers.has(route.tier as ModelTier) &&\n\t\tvalidRisks.has(route.risk as RouteRisk) &&\n\t\t(route.model === undefined || typeof route.model === \"string\") &&\n\t\t(route.fallbackFrom === undefined ||\n\t\t\troute.fallbackFrom === \"cheap\" ||\n\t\t\troute.fallbackFrom === \"medium\" ||\n\t\t\troute.fallbackFrom === \"expensive\" ||\n\t\t\troute.fallbackFrom === \"learning\") &&\n\t\t(route.createdAt === undefined || typeof route.createdAt === \"string\")\n\t);\n}\n\nfunction isModelRouterDecisionStatus(data: unknown): data is ModelRouterDecisionStatus {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst record = data as Partial<ModelRouterDecisionStatus>;\n\treturn (\n\t\tisRouteDecision(record.route) &&\n\t\trecord.route.tier !== \"learning\" && // Validate user prompt decisions never need learning tier in runtime\n\t\ttypeof record.routedModel === \"string\" &&\n\t\t(record.outcome === \"routed\" || record.outcome === \"escalated\" || record.outcome === \"failed\") &&\n\t\t(record.retryModel === undefined || typeof record.retryModel === \"string\") &&\n\t\t(record.intent === undefined || record.intent === \"research\" || record.intent === \"modify\")\n\t);\n}\n\nfunction formatDecision(decision: ModelRouterDecisionStatus): string {\n\tconst { tier, risk, reasonCode } = decision.route;\n\tlet outcomeText: string = decision.outcome;\n\tif (decision.outcome === \"escalated\" && decision.retryModel) {\n\t\toutcomeText = `escalated -> ${decision.retryModel}`;\n\t} else if (decision.outcome === \"failed\") {\n\t\toutcomeText = \"failed\";\n\t}\n\treturn `${tier}/${risk} -> ${decision.routedModel} (${reasonCode}, ${outcomeText})`;\n}\n\nexport function getRecentModelRouterDecisions(entries: SessionEntry[], limit = 3): ModelRouterDecisionStatus[] {\n\tconst decisions: ModelRouterDecisionStatus[] = [];\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== MODEL_ROUTER_DECISION_CUSTOM_TYPE) continue;\n\t\tif (!isModelRouterDecisionStatus(entry.data)) continue;\n\t\tdecisions.push(entry.data);\n\t}\n\treturn decisions.slice(-limit);\n}\n\nexport function formatModelRouterStatus(\n\tsettings: ModelRouterStatusSettings,\n\tlastDecision?: ModelRouterDecisionStatus,\n\tformatLabel: (label: string) => string = (label) => label,\n\trecentDecisions: ModelRouterDecisionStatus[] = [],\n\tlastSkipReason?: string,\n\tlatestIntent?: ModelRouterIntent,\n): string {\n\tconst effectiveLastDecision = lastSkipReason ? undefined : lastDecision;\n\tconst lines = [\n\t\t`${formatLabel(\"Status:\")} ${settings.enabled ? \"enabled\" : \"disabled\"}`,\n\t\t`${formatLabel(\"Cheap model:\")} ${settings.cheapModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Medium model:\")} ${settings.mediumModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Expensive model:\")} ${settings.expensiveModel ?? \"unset\"}`,\n\t\t`${formatLabel(\"Learning model:\")} ${settings.learningModel ?? \"active\"}`,\n\t];\n\tif (!settings.enabled) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} inactive (disabled)`);\n\t} else if (lastSkipReason) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} skipped (${lastSkipReason})`);\n\t} else if (effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Routing:\")} active`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Routing:\")} waiting for prompt`);\n\t}\n\tlines.push(`${formatLabel(\"Latest intent:\")} ${latestIntent ?? \"none\"}`);\n\tif (!effectiveLastDecision) {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} none`);\n\t} else {\n\t\tlines.push(`${formatLabel(\"Last decision:\")} ${formatDecision(effectiveLastDecision)}`);\n\t}\n\tif (recentDecisions.length > 0) {\n\t\tlines.push(formatLabel(\"Recent decisions:\"));\n\t\tfor (const decision of recentDecisions) {\n\t\t\tlines.push(`- ${formatDecision(decision)}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Model-router turn routing: the session's per-turn model-selection subsystem — the regex/executor
3
+ * route resolver, the optional bounded routing judge, the executor lane (Level-0 toolkit direct hit
4
+ * + speculative brain-refined retry), the per-tier thinking/tool-surface swap around a routed turn,
5
+ * the cheap-research-turn session buffer with mutating-tool escalation to an expensive retry, and
6
+ * the router status/diagnostics report.
7
+ *
8
+ * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the transient per-turn
9
+ * route state — the active intent/route, the cheap-turn session buffer, the escalation-requested and
10
+ * retry-in-flight flags — and the sticky last-decision/last-skip-reason/last-intent used by the
11
+ * status report. Everything else it needs — the live agent + its state, the current model, the
12
+ * session/settings managers, the model registry, the agent dir, the reflection abort signal, the
13
+ * base system prompt, the isolated-completion primitive, spawned-usage accounting, the event/telemetry
14
+ * emitters, and the recently-extracted BackgroundLaneController (resolveLaneModel) / ContextPipeline
15
+ * (resolveCurationModelIfFit) collaborators — is reached through narrow deps accessors rather than the
16
+ * whole AgentSession.
17
+ *
18
+ * Drive-path boundary (deliberate): the actual agent.prompt()/continue() loop stays host-side in
19
+ * AgentSession._runAgentPrompt; this controller's parallel routed drive path ({@link runRoutedTurn})
20
+ * owns only the route decision/escalation/tier bookkeeping and delegates every agent turn back through
21
+ * {@link ModelRouterControllerDeps.runAgentPrompt}, so the drive-loop logic is never duplicated. The
22
+ * host keeps a one-line delegation at each call-in: the routing prep + routed-turn entry in
23
+ * _promptUnserialized, the beforeToolCall escalation branch ({@link maybeEscalateToolCall}), the
24
+ * message_end cheap-turn buffering ({@link captureSessionMessage}), the retry-event suppression
25
+ * ({@link isRetryInFlight}), and the public getModelRouterStatus / autonomy-telemetry reads.
26
+ */
27
+ import type { Agent, AgentMessage } from "@caupulican/pi-agent-core";
28
+ import type { SessionManager } from "@caupulican/pi-agent-core/node";
29
+ import type { Api, Model, Usage } from "@caupulican/pi-ai";
30
+ import type { AgentSessionEvent, IsolatedCompletionOptions, IsolatedCompletionResult } from "./agent-session.ts";
31
+ import type { RouteDecision } from "./autonomy/contracts.ts";
32
+ import { type AutonomyTelemetryEvent } from "./autonomy/telemetry-events.ts";
33
+ import type { ModelRegistry } from "./model-registry.ts";
34
+ import { type ModelRouterDecisionStatus } from "./model-router/status.ts";
35
+ import type { SettingsManager } from "./settings-manager.ts";
36
+ /** Canonical `provider/id` label for a routed/resolved model, as it appears in decisions and status. */
37
+ export declare function formatModelRouterModel(model: Model<Api>): string;
38
+ export interface ModelRouterControllerDeps {
39
+ /** Live agent — the controller reads/writes agent.state.{model,thinkingLevel,tools,systemPrompt,messages}
40
+ * for the per-turn tier swap and aborts it on a mutating-tool escalation. */
41
+ getAgent(): Agent;
42
+ /** Current session model, used to decide whether a routed turn actually swaps the model. */
43
+ getModel(): Model<Api> | undefined;
44
+ /** Router/executor/judge/thinking settings + capability mode (all opt-in gates). */
45
+ getSettingsManager(): SettingsManager;
46
+ /** Session log: routed-turn message buffering/persistence, decision persistence, recent-decision status. */
47
+ getSessionManager(): SessionManager;
48
+ /** Resolves configured route/judge/executor model patterns against configured auth. */
49
+ getModelRegistry(): ModelRegistry;
50
+ /** Root dir the host-keyed {@link FitnessStore} lives under (executor tool-call fitness gate). */
51
+ getAgentDir(): string;
52
+ /** Aborts the judge's bounded completion when the session is disposed. */
53
+ getReflectionSignal(): AbortSignal;
54
+ /** Base (extension-free) system prompt — the tier swap only sheds tools when the turn is on it. */
55
+ getBaseSystemPrompt(): string;
56
+ /** The host-side drive loop (agent.prompt()/continue()); the routed drive path delegates every turn here. */
57
+ runAgentPrompt(messages: AgentMessage | AgentMessage[]): Promise<void>;
58
+ /** Rebuilds the system prompt for a filtered tool surface (routed-model capability shedding). */
59
+ buildSystemPromptForToolNames(toolNames: string[]): string;
60
+ /** Re-resolves the restored model against the registry after a routed turn (provider override safety). */
61
+ refreshCurrentModelFromRegistry(): void;
62
+ /** One-shot, tool-less LLM call — the routing judge and the executor reflex-brain warmup ride this. */
63
+ runIsolatedCompletion(opts: IsolatedCompletionOptions): Promise<IsolatedCompletionResult>;
64
+ /** Rolls judge/brain spend into spawned-usage accounting. */
65
+ addSpawnedUsage(usage: Usage, opts?: {
66
+ label?: string;
67
+ sourceSessionId?: string;
68
+ reportId?: string;
69
+ }): string | undefined;
70
+ /** Session event stream (executor-miss warning). */
71
+ emit(event: AgentSessionEvent): void;
72
+ /** Autonomy telemetry stream (one route-decision event per user-facing routed turn). */
73
+ emitAutonomyTelemetry(event: AutonomyTelemetryEvent): void;
74
+ /** Resolves the judge model pattern via {@link BackgroundLaneController}. */
75
+ resolveLaneModel(pattern: string): Model<Api> | undefined;
76
+ /** Fitness-gated reflex-brain model via {@link ContextPipeline} (executor speculative refinement). */
77
+ resolveCurationModelIfFit(): Model<Api> | undefined;
78
+ }
79
+ /**
80
+ * Owns the model-router turn routing extracted from {@link AgentSession}. See the module header for the
81
+ * drive-path boundary that keeps the agent.prompt()/continue() loop host-side.
82
+ */
83
+ export declare class ModelRouterController {
84
+ /** Active model-router intent for the current transient routed turn, if any. */
85
+ private _activeModelRouterIntent?;
86
+ private _activeModelRouterRoute?;
87
+ private _modelRouterSessionBuffer?;
88
+ private _modelRouterEscalationRequested;
89
+ private _isModelRouterRetry;
90
+ private _lastModelRouterDecision?;
91
+ private _lastModelRouterSkipReason?;
92
+ private _lastModelRouterIntent?;
93
+ private readonly deps;
94
+ constructor(deps: ModelRouterControllerDeps);
95
+ /** True while the escalation retry turn is running, so the host can suppress its duplicate prompt events. */
96
+ isRetryInFlight(): boolean;
97
+ /** Latest completed route decision (sticky), for the autonomy telemetry snapshot. */
98
+ getLastDecision(): ModelRouterDecisionStatus | undefined;
99
+ /**
100
+ * beforeToolCall escalation gate: a cheap research turn that reaches for a mutating tool aborts the
101
+ * turn and requests a retry on the expensive model. Returns the block result the host hook forwards,
102
+ * or undefined when no escalation is required.
103
+ */
104
+ maybeEscalateToolCall(toolName: string, args: unknown): {
105
+ block: true;
106
+ reason: string;
107
+ } | undefined;
108
+ /**
109
+ * message_end hook: while a cheap routed turn is buffering, capture its messages into the session
110
+ * buffer instead of persisting them (they are flushed on success or discarded on escalation).
111
+ * Returns true when the message was buffered, so the host skips its own persistence.
112
+ */
113
+ captureSessionMessage(message: AgentMessage): boolean;
114
+ private _isModelAvailableAndAuthed;
115
+ private _resolveExecutorRoute;
116
+ /** True if a run_toolkit_script tool result since `fromIndex` actually EXECUTED (not error/ambiguous). */
117
+ private _executorTurnExecutedScript;
118
+ private _buildExecutorRefinedPrompt;
119
+ private _resolveModelRouterTurnRoute;
120
+ private _resolveModelRouterModelForIntent;
121
+ resolveConfiguredTierModel(tier: "cheap" | "medium" | "expensive"): Model<Api> | undefined;
122
+ /**
123
+ * Router resolution with the routing judge (auto-on with the router): the regex classifier's
124
+ * decision is the baseline; when a judge model resolves (judgeModel, else mediumModel), one
125
+ * bounded, tool-less completion may move the tier between cheap/medium/expensive — never to
126
+ * learning. Core rule encoded in the judge prompt: planning is never cheap unless genuinely
127
+ * trivial. Every fallback stays visible in the decision reasons, and judge spend reports
128
+ * through spawned-usage accounting.
129
+ */
130
+ resolveTurnRouteJudged(prompt: string, options?: {
131
+ skipJudge?: boolean;
132
+ }): Promise<{
133
+ decision: RouteDecision;
134
+ model: Model<Api>;
135
+ } | undefined>;
136
+ private _resolveModelRouterTurnModel;
137
+ getStatus(formatLabel?: (label: string) => string): string;
138
+ runRoutedTurn(messages: AgentMessage | AgentMessage[], routedModel: Model<Api> | undefined, routeDecision: RouteDecision | undefined, persistDecision?: boolean): Promise<void>;
139
+ }
140
+ //# sourceMappingURL=model-router-controller.d.ts.map