@code-yeongyu/senpi 2026.8.26 → 2026.8.28

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 (297) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +3 -3
  3. package/dist/cli/args.d.ts +3 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +10 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/bash-executor.d.ts.map +1 -1
  11. package/dist/core/bash-executor.js +67 -29
  12. package/dist/core/bash-executor.js.map +1 -1
  13. package/dist/core/credential-accounts.d.ts +31 -0
  14. package/dist/core/credential-accounts.d.ts.map +1 -0
  15. package/dist/core/credential-accounts.js +125 -0
  16. package/dist/core/credential-accounts.js.map +1 -0
  17. package/dist/core/credential-pool/classify.d.ts +42 -0
  18. package/dist/core/credential-pool/classify.d.ts.map +1 -0
  19. package/dist/core/credential-pool/classify.js +75 -0
  20. package/dist/core/credential-pool/classify.js.map +1 -0
  21. package/dist/core/credential-pool/env-slots.d.ts +22 -0
  22. package/dist/core/credential-pool/env-slots.d.ts.map +1 -0
  23. package/dist/core/credential-pool/env-slots.js +37 -0
  24. package/dist/core/credential-pool/env-slots.js.map +1 -0
  25. package/dist/core/credential-pool/failover.d.ts +54 -0
  26. package/dist/core/credential-pool/failover.d.ts.map +1 -0
  27. package/dist/core/credential-pool/failover.js +106 -0
  28. package/dist/core/credential-pool/failover.js.map +1 -0
  29. package/dist/core/credential-pool/rotation-stream.d.ts +43 -0
  30. package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -0
  31. package/dist/core/credential-pool/rotation-stream.js +96 -0
  32. package/dist/core/credential-pool/rotation-stream.js.map +1 -0
  33. package/dist/core/credential-pool/state-store.d.ts +89 -0
  34. package/dist/core/credential-pool/state-store.d.ts.map +1 -0
  35. package/dist/core/credential-pool/state-store.js +166 -0
  36. package/dist/core/credential-pool/state-store.js.map +1 -0
  37. package/dist/core/extensions/builtin/account/index.d.ts +9 -0
  38. package/dist/core/extensions/builtin/account/index.d.ts.map +1 -0
  39. package/dist/core/extensions/builtin/account/index.js +69 -0
  40. package/dist/core/extensions/builtin/account/index.js.map +1 -0
  41. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  42. package/dist/core/extensions/builtin/compaction/index.js +67 -0
  43. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  44. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  45. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  46. package/dist/core/extensions/builtin/compaction/log.js +1 -0
  47. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  48. package/dist/core/extensions/builtin/config-reload/index.js +14 -22
  49. package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
  50. package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts +1 -0
  51. package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/goal/continuation-recovery.js +2 -0
  53. package/dist/core/extensions/builtin/goal/continuation-recovery.js.map +1 -1
  54. package/dist/core/extensions/builtin/goal/continuation.d.ts +8 -1
  55. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  56. package/dist/core/extensions/builtin/goal/continuation.js +15 -0
  57. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  58. package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js +2 -2
  59. package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js.map +1 -1
  60. package/dist/core/extensions/builtin/goal/format.d.ts +6 -1
  61. package/dist/core/extensions/builtin/goal/format.d.ts.map +1 -1
  62. package/dist/core/extensions/builtin/goal/format.js +6 -0
  63. package/dist/core/extensions/builtin/goal/format.js.map +1 -1
  64. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +5 -2
  66. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  67. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/goal/monitor-continuation.js +31 -7
  69. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  70. package/dist/core/extensions/builtin/goal/persistence.js +2 -0
  71. package/dist/core/extensions/builtin/goal/persistence.js.map +1 -1
  72. package/dist/core/extensions/builtin/goal/renderers.d.ts +14 -0
  73. package/dist/core/extensions/builtin/goal/renderers.d.ts.map +1 -0
  74. package/dist/core/extensions/builtin/goal/renderers.js +153 -0
  75. package/dist/core/extensions/builtin/goal/renderers.js.map +1 -0
  76. package/dist/core/extensions/builtin/goal/store.d.ts +6 -2
  77. package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/goal/store.js +8 -2
  79. package/dist/core/extensions/builtin/goal/store.js.map +1 -1
  80. package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
  81. package/dist/core/extensions/builtin/goal/tool-registration.js +16 -6
  82. package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
  83. package/dist/core/extensions/builtin/goal/types.d.ts +1 -0
  84. package/dist/core/extensions/builtin/goal/types.d.ts.map +1 -1
  85. package/dist/core/extensions/builtin/goal/types.js.map +1 -1
  86. package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/imagegen/index.js +10 -3
  88. package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
  89. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  90. package/dist/core/extensions/builtin/index.js +4 -0
  91. package/dist/core/extensions/builtin/index.js.map +1 -1
  92. package/dist/core/extensions/builtin/todotools/index.js +1 -1
  93. package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
  94. package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts +1 -1
  95. package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts.map +1 -1
  96. package/dist/core/extensions/builtin/todotools/native-todo-mirror.js +1 -1
  97. package/dist/core/extensions/builtin/todotools/native-todo-mirror.js.map +1 -1
  98. package/dist/core/hidden-stdout-log.d.ts +10 -0
  99. package/dist/core/hidden-stdout-log.d.ts.map +1 -1
  100. package/dist/core/hidden-stdout-log.js +36 -5
  101. package/dist/core/hidden-stdout-log.js.map +1 -1
  102. package/dist/core/model-config-schema.d.ts +85 -12
  103. package/dist/core/model-config-schema.d.ts.map +1 -1
  104. package/dist/core/model-config-schema.js +25 -0
  105. package/dist/core/model-config-schema.js.map +1 -1
  106. package/dist/core/model-runtime.d.ts +34 -1
  107. package/dist/core/model-runtime.d.ts.map +1 -1
  108. package/dist/core/model-runtime.js +98 -5
  109. package/dist/core/model-runtime.js.map +1 -1
  110. package/dist/core/tools/output-accumulator.d.ts +2 -0
  111. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  112. package/dist/core/tools/output-accumulator.js +32 -7
  113. package/dist/core/tools/output-accumulator.js.map +1 -1
  114. package/dist/index.d.ts +1 -1
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +1 -1
  117. package/dist/index.js.map +1 -1
  118. package/dist/main.d.ts.map +1 -1
  119. package/dist/main.js +38 -3
  120. package/dist/main.js.map +1 -1
  121. package/dist/modes/app-server/server/account.d.ts.map +1 -1
  122. package/dist/modes/app-server/server/account.js +5 -5
  123. package/dist/modes/app-server/server/account.js.map +1 -1
  124. package/dist/modes/index.d.ts +1 -0
  125. package/dist/modes/index.d.ts.map +1 -1
  126. package/dist/modes/index.js +1 -0
  127. package/dist/modes/index.js.map +1 -1
  128. package/dist/modes/interactive/components/footer.d.ts +11 -3
  129. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/footer.js +31 -1
  131. package/dist/modes/interactive/components/footer.js.map +1 -1
  132. package/dist/modes/interactive/components/tool-execution-fallback.d.ts.map +1 -1
  133. package/dist/modes/interactive/components/tool-execution-fallback.js +82 -1
  134. package/dist/modes/interactive/components/tool-execution-fallback.js.map +1 -1
  135. package/dist/modes/interactive/grok/chrome.d.ts +4 -4
  136. package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
  137. package/dist/modes/interactive/grok/chrome.js.map +1 -1
  138. package/dist/modes/interactive/grok/footer.d.ts +3 -3
  139. package/dist/modes/interactive/grok/footer.d.ts.map +1 -1
  140. package/dist/modes/interactive/grok/footer.js.map +1 -1
  141. package/dist/modes/interactive/interactive-host-runtime.d.ts +44 -0
  142. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -0
  143. package/dist/modes/interactive/interactive-host-runtime.js +271 -0
  144. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -0
  145. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  146. package/dist/modes/interactive/interactive-mode.js +65 -21
  147. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  148. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  149. package/dist/modes/rpc/connection-handler.js +19 -6
  150. package/dist/modes/rpc/connection-handler.js.map +1 -1
  151. package/dist/modes/rpc/host-ensure.d.ts +41 -0
  152. package/dist/modes/rpc/host-ensure.d.ts.map +1 -0
  153. package/dist/modes/rpc/host-ensure.js +245 -0
  154. package/dist/modes/rpc/host-ensure.js.map +1 -0
  155. package/dist/modes/rpc/host-lifecycle.d.ts +57 -0
  156. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -0
  157. package/dist/modes/rpc/host-lifecycle.js +491 -0
  158. package/dist/modes/rpc/host-lifecycle.js.map +1 -0
  159. package/dist/modes/rpc/host-watchdog.d.ts +33 -0
  160. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -0
  161. package/dist/modes/rpc/host-watchdog.js +142 -0
  162. package/dist/modes/rpc/host-watchdog.js.map +1 -0
  163. package/dist/modes/rpc/multi-session-host.d.ts +7 -1
  164. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  165. package/dist/modes/rpc/multi-session-host.js +206 -32
  166. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  167. package/dist/modes/rpc/rpc-client.d.ts +41 -3
  168. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  169. package/dist/modes/rpc/rpc-client.js +125 -14
  170. package/dist/modes/rpc/rpc-client.js.map +1 -1
  171. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  172. package/dist/modes/rpc/rpc-mode.js +1 -1
  173. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  174. package/dist/modes/rpc/rpc-types.d.ts +6 -2
  175. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  176. package/dist/modes/rpc/rpc-types.js.map +1 -1
  177. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  178. package/dist/modes/rpc/session-command-router.js +24 -6
  179. package/dist/modes/rpc/session-command-router.js.map +1 -1
  180. package/dist/modes/rpc/session-event-writer.d.ts +13 -2
  181. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  182. package/dist/modes/rpc/session-event-writer.js +65 -25
  183. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  184. package/dist/modes/rpc/session-registry.d.ts +9 -0
  185. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  186. package/dist/modes/rpc/session-registry.js +31 -3
  187. package/dist/modes/rpc/session-registry.js.map +1 -1
  188. package/docs/providers.md +48 -0
  189. package/docs/rpc.md +59 -5
  190. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +44 -0
  191. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  192. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +13 -1
  193. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/inline-worker.ts +15 -1
  194. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +711 -1
  195. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +14 -1
  196. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +10 -10
  197. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-eval-result.ts +9 -3
  198. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +6 -1
  199. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
  200. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +20 -4
  201. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
  202. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts +1 -1
  203. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts.map +1 -1
  204. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.js.map +1 -1
  205. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts +21 -0
  206. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts.map +1 -0
  207. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js +27 -0
  208. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js.map +1 -0
  209. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts +24 -0
  210. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts.map +1 -1
  211. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js +7 -2
  214. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js.map +1 -1
  215. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  216. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.d.ts +1 -1
  217. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.d.ts.map +1 -1
  218. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.js +46 -14
  219. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.js.map +1 -1
  220. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +11 -0
  221. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  222. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +30 -16
  223. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  224. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
  225. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +2 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.d.ts +16 -0
  229. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.d.ts.map +1 -0
  230. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.js +75 -0
  231. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.js.map +1 -0
  232. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts +45 -0
  233. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts.map +1 -0
  234. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js +81 -0
  235. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js.map +1 -0
  236. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.d.ts +31 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.d.ts.map +1 -0
  238. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.js +65 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.js.map +1 -0
  240. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +12 -0
  241. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +37 -0
  243. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +6 -0
  245. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  246. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +32 -6
  247. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  248. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +3 -2
  249. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  251. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts +6 -0
  252. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  253. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +6 -1
  254. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
  255. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +75 -0
  256. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +75 -0
  258. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  259. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  260. package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
  261. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  262. package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  263. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  265. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  267. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -1
  270. package/node_modules/@earendil-works/pi-ai/dist/providers/data/mistral.json +1 -1
  271. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  272. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  274. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  277. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
  279. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  281. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  285. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +4 -0
  286. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  287. package/node_modules/@earendil-works/pi-ai/package.json +5 -5
  288. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  289. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  290. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +5 -0
  291. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  292. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +90 -1
  293. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  294. package/node_modules/@earendil-works/pi-tui/dist/tui.js +1 -1
  295. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  296. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  297. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\nexport const GOAL_USER_GRACE_DELAY_MS = 10_000;\n\nexport type GoalContinuationPath =\n\t| \"immediate\"\n\t| \"monitorDelayed\"\n\t| \"userGrace\"\n\t| \"sessionStart\"\n\t| \"systemRecovery\"\n\t| \"providerRecovery\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly continuationPending: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"repetition\" | \"length-exhausted\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nfunction didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\" || !isContinuableStopReason(lastAssistant.stopReason)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nexport function hasGoalContinuationProgress(\n\tinput: Pick<GoalContinuationInput, \"lastContinuationSignature\" | \"currentSignature\">,\n): boolean {\n\treturn (\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.currentSignature !== undefined &&\n\t\tinput.lastContinuationSignature !== input.currentSignature\n\t);\n}\n\nexport function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some((message) => {\n\t\tif (message?.role === \"toolResult\") return true;\n\t\treturn message?.role === \"assistant\" && message.content.some((content) => content.type === \"toolCall\");\n\t});\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"systemRecovery\" || input.path === \"providerRecovery\") return true;\n\tif (input.path === \"immediate\") {\n\t\treturn input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\n\t}\n\treturn input.isIdle;\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
1
+ {"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\n/**\n * Hard budget of automatic continuations without accepted direct user input (#1139).\n * Progress and tool use never refill it: only direct input does. Stays above the\n * #447 distinct-progress pin (50) and an 8-hour monitor-backstop cadence\n * (~120 deliveries at 240s), below the observed 289-continuation incident run.\n */\nexport const GOAL_UNATTENDED_CONTINUATION_LIMIT = 150;\nexport const GOAL_USER_GRACE_DELAY_MS = 10_000;\n\nexport type GoalContinuationPath =\n\t| \"immediate\"\n\t| \"monitorDelayed\"\n\t| \"userGrace\"\n\t| \"sessionStart\"\n\t| \"systemRecovery\"\n\t| \"providerRecovery\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly continuationPending: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"repetition\" | \"length-exhausted\" | \"unattended\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nfunction didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\" || !isContinuableStopReason(lastAssistant.stopReason)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (isUnattendedBudgetExhausted(input)) return { kind: \"deny\", reason: \"unattended\" };\n\tif (input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nexport function hasGoalContinuationProgress(\n\tinput: Pick<GoalContinuationInput, \"lastContinuationSignature\" | \"currentSignature\">,\n): boolean {\n\treturn (\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.currentSignature !== undefined &&\n\t\tinput.lastContinuationSignature !== input.currentSignature\n\t);\n}\n\nexport function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some((message) => {\n\t\tif (message?.role === \"toolResult\") return true;\n\t\treturn message?.role === \"assistant\" && message.content.some((content) => content.type === \"toolCall\");\n\t});\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"systemRecovery\" || input.path === \"providerRecovery\") return true;\n\tif (input.path === \"immediate\") {\n\t\treturn input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\n\t}\n\treturn input.isIdle;\n}\n\n/** Monitor-delayed deliveries are exempt: armed-wake waiting is by-design and rate-limited by the cache-aware timer. */\nfunction isUnattendedBudgetExhausted(input: GoalContinuationInput): boolean {\n\tif (input.path === \"monitorDelayed\") return false;\n\treturn (input.goal?.unattendedContinuations ?? 0) >= GOAL_UNATTENDED_CONTINUATION_LIMIT;\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
@@ -38,7 +38,7 @@ export class GoalDirectInputLifecycle {
38
38
  if (currentGoal?.id !== candidate.goalId)
39
39
  return;
40
40
  if (currentGoal.status === "blocked" && isMechanicalContinuationBlock(currentGoal.blockedReason)) {
41
- await resetContinuationStreak(ref);
41
+ await resetContinuationStreak(ref, { unattended: true });
42
42
  const reactivated = await updateGoal(ref, { status: "active" }, "user");
43
43
  this.#dependencies.beginAgentGoalAccounting(reactivated);
44
44
  this.#dependencies.refreshGoalUi(ctx, reactivated);
@@ -46,7 +46,7 @@ export class GoalDirectInputLifecycle {
46
46
  }
47
47
  if (currentGoal.status !== "active")
48
48
  return;
49
- const reset = await resetContinuationStreak(ref);
49
+ const reset = await resetContinuationStreak(ref, { unattended: true });
50
50
  if (reset !== null)
51
51
  this.#dependencies.refreshGoalUi(ctx, reset);
52
52
  if (this.#suppressedLoadResumeArmed) {
@@ -1 +1 @@
1
- {"version":3,"file":"direct-input-lifecycle.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionContext, InputDispositionEvent, InputEvent } from \"../../types.ts\";\nimport { isMechanicalContinuationBlock } from \"./continuation-recovery.ts\";\nimport type { MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { readGoal, resetContinuationStreak, updateGoal } from \"./store.ts\";\nimport type { Goal, GoalStoreRef } from \"./types.ts\";\n\ntype DirectInputCandidate = {\n\treadonly goalId: string | null;\n};\n\ntype DirectInputLifecycleDependencies = {\n\treadonly monitor: MonitorAwareGoalContinuation;\n\treadonly goalStoreRef: (ctx: ExtensionContext) => GoalStoreRef;\n\treadonly beginAgentGoalAccounting: (goal: Goal) => void;\n\treadonly refreshGoalUi: (ctx: ExtensionContext, goal: Goal) => void;\n\t/**\n\t * One-shot resume fired when the first user message after a suppressed\n\t * flooded load is accepted. The load-time suppression notice tells the user\n\t * to \"send a message to resume\"; this callback is what keeps that promise.\n\t */\n\treadonly resumeAfterSuppressedLoad?: (ctx: ExtensionContext, goal: Goal) => Promise<void>;\n};\n\n/** Correlates raw input with admission before changing persisted Goal state. */\nexport class GoalDirectInputLifecycle {\n\treadonly #dependencies: DirectInputLifecycleDependencies;\n\treadonly #candidates = new Map<string, DirectInputCandidate>();\n\t#suppressedLoadResumeArmed = false;\n\n\tconstructor(dependencies: DirectInputLifecycleDependencies) {\n\t\tthis.#dependencies = dependencies;\n\t}\n\n\treset(): void {\n\t\tthis.#candidates.clear();\n\t\tthis.#suppressedLoadResumeArmed = false;\n\t}\n\n\t/** Arms the one-shot resume for a goal parked by load-time flood suppression. */\n\tarmSuppressedLoadResume(): void {\n\t\tthis.#suppressedLoadResumeArmed = true;\n\t}\n\n\tasync onInput(event: InputEvent, ctx: ExtensionContext): Promise<void> {\n\t\tif (event.source === \"extension\") return;\n\n\t\tthis.#dependencies.monitor.holdDirectInput(event.inputId);\n\t\tthis.#candidates.set(event.inputId, { goalId: null });\n\t\tconst goal = await readGoal(this.#dependencies.goalStoreRef(ctx));\n\t\tthis.#candidates.set(event.inputId, { goalId: goal?.id ?? null });\n\t}\n\n\tasync onDisposition(event: InputDispositionEvent, ctx: ExtensionContext): Promise<void> {\n\t\tconst candidate = this.#candidates.get(event.inputId);\n\t\tif (candidate === undefined) return;\n\t\tthis.#candidates.delete(event.inputId);\n\t\tconst accepted = event.disposition === \"started\" || event.disposition === \"queued\";\n\t\tthis.#dependencies.monitor.resolveDirectInput(event.inputId, accepted);\n\t\tif (!accepted || candidate.goalId === null) return;\n\n\t\tconst ref = this.#dependencies.goalStoreRef(ctx);\n\t\tconst currentGoal = await readGoal(ref);\n\t\tif (currentGoal?.id !== candidate.goalId) return;\n\n\t\tif (currentGoal.status === \"blocked\" && isMechanicalContinuationBlock(currentGoal.blockedReason)) {\n\t\t\tawait resetContinuationStreak(ref);\n\t\t\tconst reactivated = await updateGoal(ref, { status: \"active\" }, \"user\");\n\t\t\tthis.#dependencies.beginAgentGoalAccounting(reactivated);\n\t\t\tthis.#dependencies.refreshGoalUi(ctx, reactivated);\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentGoal.status !== \"active\") return;\n\t\tconst reset = await resetContinuationStreak(ref);\n\t\tif (reset !== null) this.#dependencies.refreshGoalUi(ctx, reset);\n\t\tif (this.#suppressedLoadResumeArmed) {\n\t\t\tthis.#suppressedLoadResumeArmed = false;\n\t\t\tawait this.#dependencies.resumeAfterSuppressedLoad?.(ctx, reset ?? currentGoal);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"direct-input-lifecycle.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionContext, InputDispositionEvent, InputEvent } from \"../../types.ts\";\nimport { isMechanicalContinuationBlock } from \"./continuation-recovery.ts\";\nimport type { MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { readGoal, resetContinuationStreak, updateGoal } from \"./store.ts\";\nimport type { Goal, GoalStoreRef } from \"./types.ts\";\n\ntype DirectInputCandidate = {\n\treadonly goalId: string | null;\n};\n\ntype DirectInputLifecycleDependencies = {\n\treadonly monitor: MonitorAwareGoalContinuation;\n\treadonly goalStoreRef: (ctx: ExtensionContext) => GoalStoreRef;\n\treadonly beginAgentGoalAccounting: (goal: Goal) => void;\n\treadonly refreshGoalUi: (ctx: ExtensionContext, goal: Goal) => void;\n\t/**\n\t * One-shot resume fired when the first user message after a suppressed\n\t * flooded load is accepted. The load-time suppression notice tells the user\n\t * to \"send a message to resume\"; this callback is what keeps that promise.\n\t */\n\treadonly resumeAfterSuppressedLoad?: (ctx: ExtensionContext, goal: Goal) => Promise<void>;\n};\n\n/** Correlates raw input with admission before changing persisted Goal state. */\nexport class GoalDirectInputLifecycle {\n\treadonly #dependencies: DirectInputLifecycleDependencies;\n\treadonly #candidates = new Map<string, DirectInputCandidate>();\n\t#suppressedLoadResumeArmed = false;\n\n\tconstructor(dependencies: DirectInputLifecycleDependencies) {\n\t\tthis.#dependencies = dependencies;\n\t}\n\n\treset(): void {\n\t\tthis.#candidates.clear();\n\t\tthis.#suppressedLoadResumeArmed = false;\n\t}\n\n\t/** Arms the one-shot resume for a goal parked by load-time flood suppression. */\n\tarmSuppressedLoadResume(): void {\n\t\tthis.#suppressedLoadResumeArmed = true;\n\t}\n\n\tasync onInput(event: InputEvent, ctx: ExtensionContext): Promise<void> {\n\t\tif (event.source === \"extension\") return;\n\n\t\tthis.#dependencies.monitor.holdDirectInput(event.inputId);\n\t\tthis.#candidates.set(event.inputId, { goalId: null });\n\t\tconst goal = await readGoal(this.#dependencies.goalStoreRef(ctx));\n\t\tthis.#candidates.set(event.inputId, { goalId: goal?.id ?? null });\n\t}\n\n\tasync onDisposition(event: InputDispositionEvent, ctx: ExtensionContext): Promise<void> {\n\t\tconst candidate = this.#candidates.get(event.inputId);\n\t\tif (candidate === undefined) return;\n\t\tthis.#candidates.delete(event.inputId);\n\t\tconst accepted = event.disposition === \"started\" || event.disposition === \"queued\";\n\t\tthis.#dependencies.monitor.resolveDirectInput(event.inputId, accepted);\n\t\tif (!accepted || candidate.goalId === null) return;\n\n\t\tconst ref = this.#dependencies.goalStoreRef(ctx);\n\t\tconst currentGoal = await readGoal(ref);\n\t\tif (currentGoal?.id !== candidate.goalId) return;\n\n\t\tif (currentGoal.status === \"blocked\" && isMechanicalContinuationBlock(currentGoal.blockedReason)) {\n\t\t\tawait resetContinuationStreak(ref, { unattended: true });\n\t\t\tconst reactivated = await updateGoal(ref, { status: \"active\" }, \"user\");\n\t\t\tthis.#dependencies.beginAgentGoalAccounting(reactivated);\n\t\t\tthis.#dependencies.refreshGoalUi(ctx, reactivated);\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentGoal.status !== \"active\") return;\n\t\tconst reset = await resetContinuationStreak(ref, { unattended: true });\n\t\tif (reset !== null) this.#dependencies.refreshGoalUi(ctx, reset);\n\t\tif (this.#suppressedLoadResumeArmed) {\n\t\t\tthis.#suppressedLoadResumeArmed = false;\n\t\t\tawait this.#dependencies.resumeAfterSuppressedLoad?.(ctx, reset ?? currentGoal);\n\t\t}\n\t}\n}\n"]}
@@ -1,8 +1,13 @@
1
- import type { Goal, GoalStatus, GoalToolResponse } from "./types.ts";
1
+ import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from "./types.ts";
2
2
  export declare function formatGoalElapsedSeconds(value: number): string;
3
3
  export declare function formatTokensCompact(value: number): string;
4
4
  export declare function goalStatusLabel(status: GoalStatus): string;
5
5
  export declare function formatGoalForTool(goal: Goal | null): string;
6
+ export type GoalToolRenderDetails = {
7
+ goal: GoalToolSnapshot | null;
8
+ notice?: string;
9
+ };
10
+ export declare function goalToolRenderDetails(goal: Goal | null, notice?: string): GoalToolRenderDetails;
6
11
  export declare function goalToolResponse(goal: Goal | null): GoalToolResponse;
7
12
  export declare function formatGoalToolResponse(goal: Goal | null, notice?: string): string;
8
13
  //# sourceMappingURL=format.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAEvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB9D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAW1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,gBAAgB,CAEpE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAGjF"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB9D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAW1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAW3D;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAK/F;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,gBAAgB,CAEpE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAGjF"}
@@ -51,6 +51,12 @@ export function formatGoalForTool(goal) {
51
51
  lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);
52
52
  return lines.join("\n");
53
53
  }
54
+ export function goalToolRenderDetails(goal, notice) {
55
+ return {
56
+ goal: goal === null ? null : goalToolSnapshot(goal),
57
+ ...(notice === undefined ? {} : { notice }),
58
+ };
59
+ }
54
60
  export function goalToolResponse(goal) {
55
61
  return { goal: goal === null ? null : goalToolSnapshot(goal) };
56
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from \"./types.ts\";\n\nexport function formatGoalElapsedSeconds(value: number): string {\n\tconst seconds = Math.max(0, Math.trunc(value));\n\tif (seconds < 60) return `${seconds}s`;\n\n\tconst minutes = Math.trunc(seconds / 60);\n\tif (minutes < 60) return `${minutes}m`;\n\n\tconst hours = Math.trunc(minutes / 60);\n\tconst remainingMinutes = minutes % 60;\n\tif (hours >= 24) {\n\t\tconst days = Math.trunc(hours / 24);\n\t\tconst remainingHours = hours % 24;\n\t\treturn `${days}d ${remainingHours}h ${remainingMinutes}m`;\n\t}\n\n\tif (remainingMinutes === 0) return `${hours}h`;\n\treturn `${hours}h ${remainingMinutes}m`;\n}\n\nexport function formatTokensCompact(value: number): string {\n\tconst abs = Math.abs(value);\n\tif (abs >= 1_000_000) return `${formatOneDecimal(value / 1_000_000)}M`;\n\tif (abs >= 1_000) return `${formatOneDecimal(value / 1_000)}K`;\n\treturn `${Math.trunc(value)}`;\n}\n\nexport function goalStatusLabel(status: GoalStatus): string {\n\tswitch (status) {\n\t\tcase \"active\":\n\t\t\treturn \"active\";\n\t\tcase \"paused\":\n\t\t\treturn \"paused\";\n\t\tcase \"blocked\":\n\t\t\treturn \"blocked\";\n\t\tcase \"complete\":\n\t\t\treturn \"complete\";\n\t}\n}\n\nexport function formatGoalForTool(goal: Goal | null): string {\n\tif (!goal) return \"No active goal is set.\";\n\tconst lines = [\n\t\t`Objective: ${goal.objective}`,\n\t\t`Status: ${goalStatusLabel(goal.status)}`,\n\t\t`Time used: ${formatGoalElapsedSeconds(goal.timeUsedSeconds)}`,\n\t\t`Tokens used: ${formatTokensCompact(goal.tokensUsed)}`,\n\t];\n\tif (goal.blockedReason) lines.push(`Blocked reason: ${goal.blockedReason}`);\n\tif (goal.completedAt) lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport function goalToolResponse(goal: Goal | null): GoalToolResponse {\n\treturn { goal: goal === null ? null : goalToolSnapshot(goal) };\n}\n\nexport function formatGoalToolResponse(goal: Goal | null, notice?: string): string {\n\tconst response = JSON.stringify(goalToolResponse(goal), null, 2);\n\treturn notice === undefined ? response : `${response}\\n${notice}`;\n}\n\nfunction goalToolSnapshot(goal: Goal): GoalToolSnapshot {\n\treturn {\n\t\tthreadId: goal.threadId,\n\t\tobjective: goal.objective,\n\t\tstatus: goal.status,\n\t\ttokensUsed: goal.tokensUsed,\n\t\ttimeUsedSeconds: goal.timeUsedSeconds,\n\t\tcreatedAt: goal.createdAt,\n\t\tupdatedAt: goal.updatedAt,\n\t\t...(goal.blockedReason === undefined ? {} : { blockedReason: goal.blockedReason }),\n\t\t...(goal.blockedAt === undefined ? {} : { blockedAt: goal.blockedAt }),\n\t};\n}\n\nfunction formatOneDecimal(value: number): string {\n\tconst rounded = value.toFixed(1);\n\treturn rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n}\n"]}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from \"./types.ts\";\n\nexport function formatGoalElapsedSeconds(value: number): string {\n\tconst seconds = Math.max(0, Math.trunc(value));\n\tif (seconds < 60) return `${seconds}s`;\n\n\tconst minutes = Math.trunc(seconds / 60);\n\tif (minutes < 60) return `${minutes}m`;\n\n\tconst hours = Math.trunc(minutes / 60);\n\tconst remainingMinutes = minutes % 60;\n\tif (hours >= 24) {\n\t\tconst days = Math.trunc(hours / 24);\n\t\tconst remainingHours = hours % 24;\n\t\treturn `${days}d ${remainingHours}h ${remainingMinutes}m`;\n\t}\n\n\tif (remainingMinutes === 0) return `${hours}h`;\n\treturn `${hours}h ${remainingMinutes}m`;\n}\n\nexport function formatTokensCompact(value: number): string {\n\tconst abs = Math.abs(value);\n\tif (abs >= 1_000_000) return `${formatOneDecimal(value / 1_000_000)}M`;\n\tif (abs >= 1_000) return `${formatOneDecimal(value / 1_000)}K`;\n\treturn `${Math.trunc(value)}`;\n}\n\nexport function goalStatusLabel(status: GoalStatus): string {\n\tswitch (status) {\n\t\tcase \"active\":\n\t\t\treturn \"active\";\n\t\tcase \"paused\":\n\t\t\treturn \"paused\";\n\t\tcase \"blocked\":\n\t\t\treturn \"blocked\";\n\t\tcase \"complete\":\n\t\t\treturn \"complete\";\n\t}\n}\n\nexport function formatGoalForTool(goal: Goal | null): string {\n\tif (!goal) return \"No active goal is set.\";\n\tconst lines = [\n\t\t`Objective: ${goal.objective}`,\n\t\t`Status: ${goalStatusLabel(goal.status)}`,\n\t\t`Time used: ${formatGoalElapsedSeconds(goal.timeUsedSeconds)}`,\n\t\t`Tokens used: ${formatTokensCompact(goal.tokensUsed)}`,\n\t];\n\tif (goal.blockedReason) lines.push(`Blocked reason: ${goal.blockedReason}`);\n\tif (goal.completedAt) lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport type GoalToolRenderDetails = {\n\tgoal: GoalToolSnapshot | null;\n\tnotice?: string;\n};\n\nexport function goalToolRenderDetails(goal: Goal | null, notice?: string): GoalToolRenderDetails {\n\treturn {\n\t\tgoal: goal === null ? null : goalToolSnapshot(goal),\n\t\t...(notice === undefined ? {} : { notice }),\n\t};\n}\n\nexport function goalToolResponse(goal: Goal | null): GoalToolResponse {\n\treturn { goal: goal === null ? null : goalToolSnapshot(goal) };\n}\n\nexport function formatGoalToolResponse(goal: Goal | null, notice?: string): string {\n\tconst response = JSON.stringify(goalToolResponse(goal), null, 2);\n\treturn notice === undefined ? response : `${response}\\n${notice}`;\n}\n\nfunction goalToolSnapshot(goal: Goal): GoalToolSnapshot {\n\treturn {\n\t\tthreadId: goal.threadId,\n\t\tobjective: goal.objective,\n\t\tstatus: goal.status,\n\t\ttokensUsed: goal.tokensUsed,\n\t\ttimeUsedSeconds: goal.timeUsedSeconds,\n\t\tcreatedAt: goal.createdAt,\n\t\tupdatedAt: goal.updatedAt,\n\t\t...(goal.blockedReason === undefined ? {} : { blockedReason: goal.blockedReason }),\n\t\t...(goal.blockedAt === undefined ? {} : { blockedAt: goal.blockedAt }),\n\t};\n}\n\nfunction formatOneDecimal(value: number): string {\n\tconst rounded = value.toFixed(1);\n\treturn rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErE,OAAO,EAGN,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAE5B,MAAM,mBAAmB,CAAC;AAW3B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,iCAAiC,GAAG,OAAO,CAAC,uBAAuB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEhG,KAAK,+BAA+B,GAAG;IACtC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iCAAiC,KAAK,MAAM,CAAC;IACzE,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC7C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACpC,GAAG,EAAE,gBAAgB,EACrB,kBAAkB,EAAE,MAAM,EAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,GACf,IAAI,IAAI,IAAI,CASd;AAED,sFAAsF;AACtF,wBAAsB,6BAA6B,CAClD,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAgBtB;AAED,mHAAmH;AACnH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAuBtB;AAED,wBAAgB,qCAAqC,CACpD,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,MAAM,GACvB,MAAM,CAKR;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAM3E;AA0DD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK7E"}
1
+ {"version":3,"file":"lifecycle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErE,OAAO,EAGN,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAE5B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,iCAAiC,GAAG,OAAO,CAAC,uBAAuB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEhG,KAAK,+BAA+B,GAAG;IACtC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iCAAiC,KAAK,MAAM,CAAC;IACzE,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC7C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACpC,GAAG,EAAE,gBAAgB,EACrB,kBAAkB,EAAE,MAAM,EAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,GACf,IAAI,IAAI,IAAI,CASd;AAED,sFAAsF;AACtF,wBAAsB,6BAA6B,CAClD,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAiBtB;AAED,mHAAmH;AACnH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAuBtB;AAED,wBAAgB,qCAAqC,CACpD,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,MAAM,GACvB,MAAM,CAKR;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAM3E;AA6DD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK7E"}
@@ -1,7 +1,7 @@
1
1
  import { GOAL_CONTINUATION_MESSAGE_TYPE } from "../../../messages.js";
2
2
  import { getLatestPhasesFromBranchEntries } from "../todotools/state.js";
3
3
  import { buildGoalContinuationSignature, evaluateGoalContinuation, hashAssistantText, } from "./continuation.js";
4
- import { CONTINUATION_CAP_BLOCKED_REASON, continuationCapRecoveryHint, LENGTH_EXHAUSTED_BLOCKED_REASON, REPETITION_BLOCKED_REASON, } from "./continuation-recovery.js";
4
+ import { CONTINUATION_CAP_BLOCKED_REASON, continuationCapRecoveryHint, LENGTH_EXHAUSTED_BLOCKED_REASON, REPETITION_BLOCKED_REASON, UNATTENDED_CONTINUATION_BLOCKED_REASON, } from "./continuation-recovery.js";
5
5
  import { buildContinuationPrompt } from "./prompt.js";
6
6
  import { recordContinuationDelivered, updateGoal } from "./store.js";
7
7
  import { goalStoreRef } from "./store-ref.js";
@@ -33,7 +33,7 @@ export async function admitAndQueueGoalContinuation(pi, ctx, goal, options) {
33
33
  if (options.input.currentSignature === undefined) {
34
34
  throw new Error("Cannot queue a goal continuation without a progress signature");
35
35
  }
36
- const recordedGoal = await recordContinuationDelivered(goalStoreRef(ctx.sessionManager, ctx.cwd), options.input.currentSignature, goal.id);
36
+ const recordedGoal = await recordContinuationDelivered(goalStoreRef(ctx.sessionManager, ctx.cwd), options.input.currentSignature, goal.id, { countUnattended: options.input.path !== "monitorDelayed" });
37
37
  if (recordedGoal === null)
38
38
  return null;
39
39
  options.markContinuationPending();
@@ -100,6 +100,7 @@ async function handleDeniedContinuation(pi, ctx, goal, input, reason) {
100
100
  goalId: goal.id,
101
101
  reason,
102
102
  count: input.consecutiveContinuations,
103
+ unattendedContinuations: goal.unattendedContinuations ?? 0,
103
104
  });
104
105
  return blocked;
105
106
  }
@@ -107,6 +108,8 @@ function blockedReasonForContinuationGuard(reason) {
107
108
  switch (reason) {
108
109
  case "cap":
109
110
  return CONTINUATION_CAP_BLOCKED_REASON;
111
+ case "unattended":
112
+ return UNATTENDED_CONTINUATION_BLOCKED_REASON;
110
113
  case "repetition":
111
114
  return REPETITION_BLOCKED_REASON;
112
115
  case "length-exhausted":
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-helpers.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { getLatestPhasesFromBranchEntries } from \"../todotools/state.ts\";\nimport {\n\tbuildGoalContinuationSignature,\n\tevaluateGoalContinuation,\n\ttype GoalContinuationInput,\n\ttype GoalContinuationVerdict,\n\thashAssistantText,\n} from \"./continuation.ts\";\nimport {\n\tCONTINUATION_CAP_BLOCKED_REASON,\n\tcontinuationCapRecoveryHint,\n\tLENGTH_EXHAUSTED_BLOCKED_REASON,\n\tREPETITION_BLOCKED_REASON,\n} from \"./continuation-recovery.ts\";\nimport { buildContinuationPrompt } from \"./prompt.ts\";\nimport { recordContinuationDelivered, updateGoal } from \"./store.ts\";\nimport { goalStoreRef } from \"./store-ref.ts\";\nimport { openTodoTaskContents } from \"./todo-gate.ts\";\nimport type { Goal } from \"./types.ts\";\n\ntype ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\n\ntype GoalContinuationDeliveryOptions = {\n\treadonly input: Omit<GoalContinuationInput, \"goal\">;\n\treadonly content: (verdict: ContinuingGoalContinuationVerdict) => string;\n\treadonly markContinuationPending: () => void;\n};\n\nexport type SessionStartContinuationOptions = {\n\treadonly continuationPending: boolean;\n\treadonly markContinuationPending: () => void;\n};\n\n/**\n * Statuses that leave a goal stopped without finishing it. A restart is the only\n * moment the user can act on them, so both earn the resume prompt.\n */\nconst STOPPED_UNFINISHED_GOAL_STATUSES: readonly Goal[\"status\"][] = [\"paused\", \"blocked\"];\n\n/**\n * Mirrors codex `maybe_prompt_resume_paused_goal_after_resume`\n * (codex-rs/tui/src/app/thread_goal_actions.rs), which prompts on resume for every\n * stopped-but-unfinished status. senpi is budget-free, so codex's `UsageLimited`\n * has no counterpart here and the stopped set is `paused | blocked`.\n */\nexport function isResumeOfStoppedGoal(\n\tctx: ExtensionContext,\n\tsessionStartReason: string,\n\tgoal: Goal | null,\n): goal is Goal {\n\treturn (\n\t\tsessionStartReason === \"resume\" &&\n\t\tgoal !== null &&\n\t\tSTOPPED_UNFINISHED_GOAL_STATUSES.includes(goal.status) &&\n\t\tctx.hasUI &&\n\t\tctx.isIdle() &&\n\t\t!ctx.hasPendingMessages()\n\t);\n}\n\n/** Evaluates and delivers a continuation only after all guardrail checks admit it. */\nexport async function admitAndQueueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: GoalContinuationDeliveryOptions,\n): Promise<Goal | null> {\n\tconst verdict = evaluateGoalContinuation({ goal, ...options.input });\n\tif (verdict.kind === \"deny\") return handleDeniedContinuation(pi, ctx, goal, options.input, verdict.reason);\n\n\tif (options.input.currentSignature === undefined) {\n\t\tthrow new Error(\"Cannot queue a goal continuation without a progress signature\");\n\t}\n\tconst recordedGoal = await recordContinuationDelivered(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\toptions.input.currentSignature,\n\t\tgoal.id,\n\t);\n\tif (recordedGoal === null) return null;\n\toptions.markContinuationPending();\n\tqueueHiddenGoalPrompt(pi, options.content(verdict));\n\treturn recordedGoal;\n}\n\n/** Routes startup and resume continuations through the same verdict and delivery accounting as agent-end paths. */\nexport async function queueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: SessionStartContinuationOptions,\n): Promise<Goal | null> {\n\tconst signature = buildCurrentGoalContinuationSignature(\n\t\tctx,\n\t\tgoal,\n\t\tlastAssistantTextFromEntries(ctx.sessionManager.getBranch()),\n\t);\n\treturn admitAndQueueGoalContinuation(pi, ctx, goal, {\n\t\tinput: {\n\t\t\tisIdle: ctx.isIdle(),\n\t\t\thasPendingMessages: ctx.hasPendingMessages(),\n\t\t\tpath: \"sessionStart\",\n\t\t\tlastStopReason: undefined,\n\t\t\tconsecutiveContinuations: goal.consecutiveContinuations ?? 0,\n\t\t\tlastContinuationSignature: goal.lastContinuationSignature,\n\t\t\tcurrentSignature: signature,\n\t\t\tconsecutiveLengthRecoveries: 0,\n\t\t\trecentNormalizedOutputHashes: [],\n\t\t\ttoollessContinuationStreak: 0,\n\t\t\tcontinuationPending: options.continuationPending,\n\t\t},\n\t\tcontent: () => buildContinuationPrompt(goal),\n\t\tmarkContinuationPending: options.markContinuationPending,\n\t});\n}\n\nexport function buildCurrentGoalContinuationSignature(\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tlastAssistantText: string,\n): string {\n\tconst entries = ctx.sessionManager.getBranch();\n\tconst openTodos = openTodoTaskContents(entries).length;\n\tconst totalTodos = getLatestPhasesFromBranchEntries(entries).reduce((count, phase) => count + phase.tasks.length, 0);\n\treturn buildGoalContinuationSignature(goal, openTodos, totalTodos, hashAssistantText(lastAssistantText));\n}\n\nexport function lastAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") return textContent(message);\n\t}\n\treturn \"\";\n}\n\nfunction lastAssistantTextFromEntries(entries: readonly SessionEntry[]): string {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"assistant\") return textContent(entry.message);\n\t}\n\treturn \"\";\n}\n\nfunction textContent(message: Extract<AgentMessage, { role: \"assistant\" }>): string {\n\treturn message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\");\n}\n\nasync function handleDeniedContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tinput: Omit<GoalContinuationInput, \"goal\">,\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): Promise<Goal> {\n\tconst blockedReason = blockedReasonForContinuationGuard(reason);\n\tif (blockedReason === undefined) return goal;\n\n\tconst blocked = await updateGoal(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\t{ status: \"blocked\", reason: blockedReason },\n\t\t\"model\",\n\t);\n\tif (ctx.hasUI) ctx.ui.notify(continuationCapRecoveryHint(blockedReason), \"warning\");\n\tpi.events?.emit(\"goal_continuation_guard_tripped\", {\n\t\tgoalId: goal.id,\n\t\treason,\n\t\tcount: input.consecutiveContinuations,\n\t});\n\treturn blocked;\n}\n\nfunction blockedReasonForContinuationGuard(\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): string | undefined {\n\tswitch (reason) {\n\t\tcase \"cap\":\n\t\t\treturn CONTINUATION_CAP_BLOCKED_REASON;\n\t\tcase \"repetition\":\n\t\t\treturn REPETITION_BLOCKED_REASON;\n\t\tcase \"length-exhausted\":\n\t\t\treturn LENGTH_EXHAUSTED_BLOCKED_REASON;\n\t\tcase \"not-eligible\":\n\t\tcase \"single-flight\":\n\t\tcase \"stale\":\n\t\t\treturn undefined;\n\t}\n}\n\nexport function queueHiddenGoalPrompt(pi: ExtensionAPI, content: string): void {\n\tpi.sendMessage(\n\t\t{ customType: GOAL_CONTINUATION_MESSAGE_TYPE, content, display: false },\n\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t);\n}\n"]}
1
+ {"version":3,"file":"lifecycle-helpers.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { getLatestPhasesFromBranchEntries } from \"../todotools/state.ts\";\nimport {\n\tbuildGoalContinuationSignature,\n\tevaluateGoalContinuation,\n\ttype GoalContinuationInput,\n\ttype GoalContinuationVerdict,\n\thashAssistantText,\n} from \"./continuation.ts\";\nimport {\n\tCONTINUATION_CAP_BLOCKED_REASON,\n\tcontinuationCapRecoveryHint,\n\tLENGTH_EXHAUSTED_BLOCKED_REASON,\n\tREPETITION_BLOCKED_REASON,\n\tUNATTENDED_CONTINUATION_BLOCKED_REASON,\n} from \"./continuation-recovery.ts\";\nimport { buildContinuationPrompt } from \"./prompt.ts\";\nimport { recordContinuationDelivered, updateGoal } from \"./store.ts\";\nimport { goalStoreRef } from \"./store-ref.ts\";\nimport { openTodoTaskContents } from \"./todo-gate.ts\";\nimport type { Goal } from \"./types.ts\";\n\ntype ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\n\ntype GoalContinuationDeliveryOptions = {\n\treadonly input: Omit<GoalContinuationInput, \"goal\">;\n\treadonly content: (verdict: ContinuingGoalContinuationVerdict) => string;\n\treadonly markContinuationPending: () => void;\n};\n\nexport type SessionStartContinuationOptions = {\n\treadonly continuationPending: boolean;\n\treadonly markContinuationPending: () => void;\n};\n\n/**\n * Statuses that leave a goal stopped without finishing it. A restart is the only\n * moment the user can act on them, so both earn the resume prompt.\n */\nconst STOPPED_UNFINISHED_GOAL_STATUSES: readonly Goal[\"status\"][] = [\"paused\", \"blocked\"];\n\n/**\n * Mirrors codex `maybe_prompt_resume_paused_goal_after_resume`\n * (codex-rs/tui/src/app/thread_goal_actions.rs), which prompts on resume for every\n * stopped-but-unfinished status. senpi is budget-free, so codex's `UsageLimited`\n * has no counterpart here and the stopped set is `paused | blocked`.\n */\nexport function isResumeOfStoppedGoal(\n\tctx: ExtensionContext,\n\tsessionStartReason: string,\n\tgoal: Goal | null,\n): goal is Goal {\n\treturn (\n\t\tsessionStartReason === \"resume\" &&\n\t\tgoal !== null &&\n\t\tSTOPPED_UNFINISHED_GOAL_STATUSES.includes(goal.status) &&\n\t\tctx.hasUI &&\n\t\tctx.isIdle() &&\n\t\t!ctx.hasPendingMessages()\n\t);\n}\n\n/** Evaluates and delivers a continuation only after all guardrail checks admit it. */\nexport async function admitAndQueueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: GoalContinuationDeliveryOptions,\n): Promise<Goal | null> {\n\tconst verdict = evaluateGoalContinuation({ goal, ...options.input });\n\tif (verdict.kind === \"deny\") return handleDeniedContinuation(pi, ctx, goal, options.input, verdict.reason);\n\n\tif (options.input.currentSignature === undefined) {\n\t\tthrow new Error(\"Cannot queue a goal continuation without a progress signature\");\n\t}\n\tconst recordedGoal = await recordContinuationDelivered(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\toptions.input.currentSignature,\n\t\tgoal.id,\n\t\t{ countUnattended: options.input.path !== \"monitorDelayed\" },\n\t);\n\tif (recordedGoal === null) return null;\n\toptions.markContinuationPending();\n\tqueueHiddenGoalPrompt(pi, options.content(verdict));\n\treturn recordedGoal;\n}\n\n/** Routes startup and resume continuations through the same verdict and delivery accounting as agent-end paths. */\nexport async function queueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: SessionStartContinuationOptions,\n): Promise<Goal | null> {\n\tconst signature = buildCurrentGoalContinuationSignature(\n\t\tctx,\n\t\tgoal,\n\t\tlastAssistantTextFromEntries(ctx.sessionManager.getBranch()),\n\t);\n\treturn admitAndQueueGoalContinuation(pi, ctx, goal, {\n\t\tinput: {\n\t\t\tisIdle: ctx.isIdle(),\n\t\t\thasPendingMessages: ctx.hasPendingMessages(),\n\t\t\tpath: \"sessionStart\",\n\t\t\tlastStopReason: undefined,\n\t\t\tconsecutiveContinuations: goal.consecutiveContinuations ?? 0,\n\t\t\tlastContinuationSignature: goal.lastContinuationSignature,\n\t\t\tcurrentSignature: signature,\n\t\t\tconsecutiveLengthRecoveries: 0,\n\t\t\trecentNormalizedOutputHashes: [],\n\t\t\ttoollessContinuationStreak: 0,\n\t\t\tcontinuationPending: options.continuationPending,\n\t\t},\n\t\tcontent: () => buildContinuationPrompt(goal),\n\t\tmarkContinuationPending: options.markContinuationPending,\n\t});\n}\n\nexport function buildCurrentGoalContinuationSignature(\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tlastAssistantText: string,\n): string {\n\tconst entries = ctx.sessionManager.getBranch();\n\tconst openTodos = openTodoTaskContents(entries).length;\n\tconst totalTodos = getLatestPhasesFromBranchEntries(entries).reduce((count, phase) => count + phase.tasks.length, 0);\n\treturn buildGoalContinuationSignature(goal, openTodos, totalTodos, hashAssistantText(lastAssistantText));\n}\n\nexport function lastAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") return textContent(message);\n\t}\n\treturn \"\";\n}\n\nfunction lastAssistantTextFromEntries(entries: readonly SessionEntry[]): string {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"assistant\") return textContent(entry.message);\n\t}\n\treturn \"\";\n}\n\nfunction textContent(message: Extract<AgentMessage, { role: \"assistant\" }>): string {\n\treturn message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\");\n}\n\nasync function handleDeniedContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tinput: Omit<GoalContinuationInput, \"goal\">,\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): Promise<Goal> {\n\tconst blockedReason = blockedReasonForContinuationGuard(reason);\n\tif (blockedReason === undefined) return goal;\n\n\tconst blocked = await updateGoal(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\t{ status: \"blocked\", reason: blockedReason },\n\t\t\"model\",\n\t);\n\tif (ctx.hasUI) ctx.ui.notify(continuationCapRecoveryHint(blockedReason), \"warning\");\n\tpi.events?.emit(\"goal_continuation_guard_tripped\", {\n\t\tgoalId: goal.id,\n\t\treason,\n\t\tcount: input.consecutiveContinuations,\n\t\tunattendedContinuations: goal.unattendedContinuations ?? 0,\n\t});\n\treturn blocked;\n}\n\nfunction blockedReasonForContinuationGuard(\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): string | undefined {\n\tswitch (reason) {\n\t\tcase \"cap\":\n\t\t\treturn CONTINUATION_CAP_BLOCKED_REASON;\n\t\tcase \"unattended\":\n\t\t\treturn UNATTENDED_CONTINUATION_BLOCKED_REASON;\n\t\tcase \"repetition\":\n\t\t\treturn REPETITION_BLOCKED_REASON;\n\t\tcase \"length-exhausted\":\n\t\t\treturn LENGTH_EXHAUSTED_BLOCKED_REASON;\n\t\tcase \"not-eligible\":\n\t\tcase \"single-flight\":\n\t\tcase \"stale\":\n\t\t\treturn undefined;\n\t}\n}\n\nexport function queueHiddenGoalPrompt(pi: ExtensionAPI, content: string): void {\n\tpi.sendMessage(\n\t\t{ customType: GOAL_CONTINUATION_MESSAGE_TYPE, content, display: false },\n\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAarE,OAAO,EAAE,2CAA2C,EAAE,MAAM,iBAAiB,CAAC;AAkB9E,OAAO,KAAK,EACX,eAAe,EAIf,uBAAuB,EAEvB,kBAAkB,EAClB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,KAAK,EAAE,IAAI,EAAsB,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,iCAAiC,gCAAgC,CAAC;AAC/E,eAAO,MAAM,+BAA+B,8BAA8B,CAAC;AAC3E,eAAO,MAAM,mCAAmC,kCAAkC,CAAC;AACnF,eAAO,MAAM,wBAAwB,oCAAoC,CAAC;AAE1E,qBAAa,4BAA4B;;gBAiCvC,EAAE,EAAE,YAAY,EAChB,qBAAqB,GAAE,MAAM,OAAqB,EAClD,uBAAuB,GAAE,MAAM,IAAe,EAC9C,UAAU,CAAC,EAAE,cAAc;IAS5B,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAW5B,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAyD7D,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAoBnE,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAgB5E,iBAAiB,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IA2B3D,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IASjC,sGAAsG;IACtG,oBAAoB,IAAI,OAAO;IAI/B;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAMtC,mGAAmG;IACnG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBtC,6FAA6F;IAC7F,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAc5D,sEAAsE;IACtE,cAAc,IAAI,IAAI;IAOtB,mGAAmG;IACnG,uBAAuB,IAAI,IAAI;IAI/B,OAAO,IAAI,IAAI;CA8Uf"}
1
+ {"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAarE,OAAO,EAAE,2CAA2C,EAAE,MAAM,iBAAiB,CAAC;AAkB9E,OAAO,KAAK,EACX,eAAe,EAIf,uBAAuB,EAEvB,kBAAkB,EAClB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,KAAK,EAAE,IAAI,EAAsB,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,iCAAiC,gCAAgC,CAAC;AAC/E,eAAO,MAAM,+BAA+B,8BAA8B,CAAC;AAC3E,eAAO,MAAM,mCAAmC,kCAAkC,CAAC;AACnF,eAAO,MAAM,wBAAwB,oCAAoC,CAAC;AAE1E,qBAAa,4BAA4B;;gBAiCvC,EAAE,EAAE,YAAY,EAChB,qBAAqB,GAAE,MAAM,OAAqB,EAClD,uBAAuB,GAAE,MAAM,IAAe,EAC9C,UAAU,CAAC,EAAE,cAAc;IAS5B,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAW5B,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IA0D7D,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAoBnE,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAgB5E,iBAAiB,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IA2B3D,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IASjC,sGAAsG;IACtG,oBAAoB,IAAI,OAAO;IAI/B;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAMtC,mGAAmG;IACnG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBtC,6FAA6F;IAC7F,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAc5D,sEAAsE;IACtE,cAAc,IAAI,IAAI;IAOtB,mGAAmG;IACnG,uBAAuB,IAAI,IAAI;IAI/B,OAAO,IAAI,IAAI;CAkWf"}
@@ -5,6 +5,7 @@ import { continuationTurnUsedTools, evaluateGoalContinuation, GOAL_USER_GRACE_DE
5
5
  import { lastAssistantMessage } from "./last-assistant-message.js";
6
6
  import { admitAndQueueGoalContinuation, buildCurrentGoalContinuationSignature, lastAssistantText, } from "./lifecycle-helpers.js";
7
7
  import { buildContinuationPrompt, buildGoalStallNotice, buildTruncationRecoveryPrompt } from "./prompt.js";
8
+ import { isStaleExtensionContextError } from "./stale-context.js";
8
9
  import { resetContinuationStreak } from "./store.js";
9
10
  import { goalStoreRef } from "./store-ref.js";
10
11
  import { collectAssistantUsage } from "./turn-usage.js";
@@ -100,7 +101,8 @@ export class MonitorAwareGoalContinuation {
100
101
  return goal;
101
102
  case "cap":
102
103
  case "repetition":
103
- case "length-exhausted": {
104
+ case "length-exhausted":
105
+ case "unattended": {
104
106
  const admission = await this.#admitAndQueue(options.ctx, goal, "immediate", options.messages);
105
107
  return admission.goal;
106
108
  }
@@ -300,10 +302,28 @@ export class MonitorAwareGoalContinuation {
300
302
  }
301
303
  this.#armTimer(kind, delayMs, delayMs);
302
304
  }
305
+ /**
306
+ * `hasUI` is an `assertActive()`-guarded getter, so a ctx retired by session
307
+ * replacement or reload THROWS instead of reporting false. Optional chaining
308
+ * only guards an undefined ctx (what `dispose()` leaves behind), never a stale
309
+ * object left by a replacement that never disposed this monitor. Callers reach
310
+ * this from timer and event callbacks where a throw is fatal, so a retired ctx
311
+ * reports "no UI" and any other failure keeps its current behavior.
312
+ */
313
+ #ctxHasUI(ctx = this.#ctx) {
314
+ try {
315
+ return ctx?.hasUI === true;
316
+ }
317
+ catch (error) {
318
+ if (isStaleExtensionContextError(error))
319
+ return false;
320
+ throw error;
321
+ }
322
+ }
303
323
  #armTimer(kind, delayMs, totalMs, drainFire = false) {
304
324
  this.#scheduledDueAtMs = Date.now() + delayMs;
305
325
  const ctx = this.#ctx;
306
- if (ctx?.hasUI) {
326
+ if (ctx !== undefined && this.#ctxHasUI(ctx)) {
307
327
  this.#waitTicker?.sync(ctx, {
308
328
  kind,
309
329
  remainingMs: delayMs,
@@ -313,10 +333,14 @@ export class MonitorAwareGoalContinuation {
313
333
  }
314
334
  this.#timer = setTimeout(() => {
315
335
  void this.#continueIfEligible(kind, drainFire).catch((error) => {
316
- if (this.#ctx?.hasUI) {
317
- const message = error instanceof Error ? error.message : String(error);
318
- this.#ctx.ui.notify(`Goal continuation delivery failed: ${message}`, "error");
319
- }
336
+ // Runs from a bare setTimeout: anything thrown here escapes as an
337
+ // uncaughtException and kills the session. A retired ctx cannot be
338
+ // notified, and its own staleness is the expected cause of this
339
+ // rejection after a session replacement, so drop it quietly.
340
+ if (isStaleExtensionContextError(error) || !this.#ctxHasUI())
341
+ return;
342
+ const message = error instanceof Error ? error.message : String(error);
343
+ this.#ctx?.ui.notify(`Goal continuation delivery failed: ${message}`, "error");
320
344
  });
321
345
  }, delayMs);
322
346
  }
@@ -420,7 +444,7 @@ export class MonitorAwareGoalContinuation {
420
444
  consecutiveContinuations: this.#toollessContinuationStreak,
421
445
  toolless: true,
422
446
  });
423
- if (ctx.hasUI) {
447
+ if (this.#ctxHasUI(ctx)) {
424
448
  const context = liveSources.length > 0 ? `while ${liveSources.join(", ")} channels stayed active` : "without tool use";
425
449
  ctx.ui.notify(`Goal continuation repeated ${this.#toollessContinuationStreak} toolless turns ${context} - injected a stall check.`, "info");
426
450
  }