@code-yeongyu/senpi 2026.9.12-3 → 2026.9.13-2

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 (270) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +3 -1
  3. package/dist/bun/cli.js +2 -3
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/runtime-modules.d.ts +3 -0
  6. package/dist/bun/runtime-modules.d.ts.map +1 -0
  7. package/dist/bun/runtime-modules.js +17 -0
  8. package/dist/bun/runtime-modules.js.map +1 -0
  9. package/dist/bun/runtime-setup.js +2 -5
  10. package/dist/bun/runtime-setup.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +2 -2
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +38 -30
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/discovered-resource-scope.d.ts +23 -0
  16. package/dist/core/discovered-resource-scope.d.ts.map +1 -0
  17. package/dist/core/discovered-resource-scope.js +44 -0
  18. package/dist/core/discovered-resource-scope.js.map +1 -0
  19. package/dist/core/extensions/builtin/ask-user/notify.d.ts +24 -0
  20. package/dist/core/extensions/builtin/ask-user/notify.d.ts.map +1 -0
  21. package/dist/core/extensions/builtin/ask-user/notify.js +11 -0
  22. package/dist/core/extensions/builtin/ask-user/notify.js.map +1 -0
  23. package/dist/core/extensions/builtin/ask-user/registry.d.ts +2 -0
  24. package/dist/core/extensions/builtin/ask-user/registry.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/ask-user/registry.js.map +1 -1
  26. package/dist/core/extensions/builtin/ask-user/resume.d.ts +1 -1
  27. package/dist/core/extensions/builtin/ask-user/resume.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/ask-user/resume.js +10 -20
  29. package/dist/core/extensions/builtin/ask-user/resume.js.map +1 -1
  30. package/dist/core/extensions/builtin/ask-user/tool.d.ts +5 -2
  31. package/dist/core/extensions/builtin/ask-user/tool.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/ask-user/tool.js +41 -6
  33. package/dist/core/extensions/builtin/ask-user/tool.js.map +1 -1
  34. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.d.ts +2 -1
  35. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.js +1 -1
  37. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.js.map +1 -1
  38. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/goal/monitor-continuation.js +27 -13
  40. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  41. package/dist/core/extensions/builtin/hooks/config-loader.d.ts +2 -0
  42. package/dist/core/extensions/builtin/hooks/config-loader.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/hooks/config-loader.js +27 -0
  44. package/dist/core/extensions/builtin/hooks/config-loader.js.map +1 -1
  45. package/dist/core/extensions/builtin/hooks/dispatcher.js +1 -0
  46. package/dist/core/extensions/builtin/hooks/dispatcher.js.map +1 -1
  47. package/dist/core/extensions/builtin/hooks/index.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/hooks/index.js +51 -2
  49. package/dist/core/extensions/builtin/hooks/index.js.map +1 -1
  50. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts +18 -1
  51. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js +36 -1
  53. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js.map +1 -1
  54. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  55. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  56. package/dist/core/extensions/builtin/hooks/output-parser.js +6 -0
  57. package/dist/core/extensions/builtin/hooks/output-parser.js.map +1 -1
  58. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +2 -0
  59. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  60. package/dist/core/extensions/builtin/hooks/trust-storage.js +13 -0
  61. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  62. package/dist/core/extensions/builtin/hooks/types.d.ts +14 -2
  63. package/dist/core/extensions/builtin/hooks/types.d.ts.map +1 -1
  64. package/dist/core/extensions/builtin/hooks/types.js +1 -1
  65. package/dist/core/extensions/builtin/hooks/types.js.map +1 -1
  66. package/dist/core/extensions/builtin/monitor-state-event.d.ts +1 -0
  67. package/dist/core/extensions/builtin/monitor-state-event.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/monitor-state-event.js.map +1 -1
  69. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +1 -0
  70. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/terminal/tools/bash.js +13 -2
  72. package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
  73. package/dist/core/extensions/loader.d.ts.map +1 -1
  74. package/dist/core/extensions/loader.js +5 -1
  75. package/dist/core/extensions/loader.js.map +1 -1
  76. package/dist/core/extensions/runner.d.ts +5 -16
  77. package/dist/core/extensions/runner.d.ts.map +1 -1
  78. package/dist/core/extensions/runner.js +16 -5
  79. package/dist/core/extensions/runner.js.map +1 -1
  80. package/dist/core/extensions/types.d.ts +28 -5
  81. package/dist/core/extensions/types.d.ts.map +1 -1
  82. package/dist/core/extensions/types.js.map +1 -1
  83. package/dist/core/extensions/wrapper.d.ts +8 -3
  84. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  85. package/dist/core/extensions/wrapper.js +12 -6
  86. package/dist/core/extensions/wrapper.js.map +1 -1
  87. package/dist/core/keybindings.d.ts +8 -1
  88. package/dist/core/keybindings.d.ts.map +1 -1
  89. package/dist/core/keybindings.js +7 -1
  90. package/dist/core/keybindings.js.map +1 -1
  91. package/dist/core/package-manager.d.ts +4 -2
  92. package/dist/core/package-manager.d.ts.map +1 -1
  93. package/dist/core/package-manager.js +7 -2
  94. package/dist/core/package-manager.js.map +1 -1
  95. package/dist/core/pi-manifest.d.ts +2 -0
  96. package/dist/core/pi-manifest.d.ts.map +1 -1
  97. package/dist/core/pi-manifest.js +3 -0
  98. package/dist/core/pi-manifest.js.map +1 -1
  99. package/dist/core/resource-loader.d.ts +9 -0
  100. package/dist/core/resource-loader.d.ts.map +1 -1
  101. package/dist/core/resource-loader.js +69 -21
  102. package/dist/core/resource-loader.js.map +1 -1
  103. package/dist/core/settings-manager.d.ts +1 -0
  104. package/dist/core/settings-manager.d.ts.map +1 -1
  105. package/dist/core/settings-manager.js +1 -0
  106. package/dist/core/settings-manager.js.map +1 -1
  107. package/dist/core/settings-shapes.d.ts +1 -0
  108. package/dist/core/settings-shapes.d.ts.map +1 -1
  109. package/dist/core/settings-shapes.js.map +1 -1
  110. package/dist/core/source-info.d.ts +5 -1
  111. package/dist/core/source-info.d.ts.map +1 -1
  112. package/dist/core/source-info.js.map +1 -1
  113. package/dist/core/tools/bash.d.ts.map +1 -1
  114. package/dist/core/tools/bash.js +5 -0
  115. package/dist/core/tools/bash.js.map +1 -1
  116. package/dist/modes/app-server/server/skills.d.ts.map +1 -1
  117. package/dist/modes/app-server/server/skills.js +1 -0
  118. package/dist/modes/app-server/server/skills.js.map +1 -1
  119. package/dist/modes/interactive/components/ask-user-answer-chip.d.ts +17 -0
  120. package/dist/modes/interactive/components/ask-user-answer-chip.d.ts.map +1 -0
  121. package/dist/modes/interactive/components/ask-user-answer-chip.js +86 -0
  122. package/dist/modes/interactive/components/ask-user-answer-chip.js.map +1 -0
  123. package/dist/modes/interactive/components/ask-user-answer-key.d.ts +3 -1
  124. package/dist/modes/interactive/components/ask-user-answer-key.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/ask-user-answer-key.js +11 -1
  126. package/dist/modes/interactive/components/ask-user-answer-key.js.map +1 -1
  127. package/dist/modes/interactive/components/ask-user-async-widget.d.ts +5 -2
  128. package/dist/modes/interactive/components/ask-user-async-widget.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/ask-user-async-widget.js +18 -12
  130. package/dist/modes/interactive/components/ask-user-async-widget.js.map +1 -1
  131. package/dist/modes/interactive/components/ask-user-countdown.d.ts +8 -0
  132. package/dist/modes/interactive/components/ask-user-countdown.d.ts.map +1 -0
  133. package/dist/modes/interactive/components/ask-user-countdown.js +23 -0
  134. package/dist/modes/interactive/components/ask-user-countdown.js.map +1 -0
  135. package/dist/modes/interactive/components/ask-user-question-keys.d.ts.map +1 -1
  136. package/dist/modes/interactive/components/ask-user-question-keys.js +85 -17
  137. package/dist/modes/interactive/components/ask-user-question-keys.js.map +1 -1
  138. package/dist/modes/interactive/components/ask-user-question-render.d.ts.map +1 -1
  139. package/dist/modes/interactive/components/ask-user-question-render.js +22 -7
  140. package/dist/modes/interactive/components/ask-user-question-render.js.map +1 -1
  141. package/dist/modes/interactive/components/ask-user-question-state.d.ts +15 -0
  142. package/dist/modes/interactive/components/ask-user-question-state.d.ts.map +1 -1
  143. package/dist/modes/interactive/components/ask-user-question-state.js +57 -13
  144. package/dist/modes/interactive/components/ask-user-question-state.js.map +1 -1
  145. package/dist/modes/interactive/components/ask-user-question.d.ts +8 -2
  146. package/dist/modes/interactive/components/ask-user-question.d.ts.map +1 -1
  147. package/dist/modes/interactive/components/ask-user-question.js +16 -8
  148. package/dist/modes/interactive/components/ask-user-question.js.map +1 -1
  149. package/dist/modes/interactive/components/config-selector.d.ts +2 -1
  150. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  152. package/dist/modes/interactive/components/custom-editor.d.ts +2 -0
  153. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/custom-editor.js +10 -1
  155. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  156. package/dist/modes/interactive/components/loaded-resource-section.d.ts +14 -0
  157. package/dist/modes/interactive/components/loaded-resource-section.d.ts.map +1 -0
  158. package/dist/modes/interactive/components/loaded-resource-section.js +25 -0
  159. package/dist/modes/interactive/components/loaded-resource-section.js.map +1 -0
  160. package/dist/modes/interactive/components/user-message.d.ts +2 -1
  161. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/user-message.js +12 -2
  163. package/dist/modes/interactive/components/user-message.js.map +1 -1
  164. package/dist/modes/interactive/interactive-mode.d.ts +14 -11
  165. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  166. package/dist/modes/interactive/interactive-mode.js +263 -165
  167. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  168. package/dist/modes/interactive/loaded-resource-scopes.d.ts +28 -0
  169. package/dist/modes/interactive/loaded-resource-scopes.d.ts.map +1 -0
  170. package/dist/modes/interactive/loaded-resource-scopes.js +107 -0
  171. package/dist/modes/interactive/loaded-resource-scopes.js.map +1 -0
  172. package/dist/modes/interactive/tips/catalog/input-tips.d.ts +1 -1
  173. package/dist/modes/interactive/tips/catalog/input-tips.js +2 -2
  174. package/dist/modes/interactive/tips/catalog/input-tips.js.map +1 -1
  175. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  176. package/dist/modes/rpc/host-lifecycle.js +7 -0
  177. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  178. package/dist/modes/rpc/session-worker.js +5 -0
  179. package/dist/modes/rpc/session-worker.js.map +1 -1
  180. package/docs/environment-variables.md +5 -1
  181. package/docs/extensions.md +43 -5
  182. package/docs/keybindings.md +5 -2
  183. package/docs/packages.md +17 -0
  184. package/docs/rpc.md +6 -3
  185. package/docs/settings.md +5 -1
  186. package/docs/tui.md +15 -3
  187. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +28 -0
  188. package/node_modules/@code-yeongyu/senpi-codemode/README.md +16 -4
  189. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  190. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +2 -0
  191. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/session-env.ts +6 -0
  192. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +6 -1
  193. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +31 -12
  194. package/node_modules/@earendil-works/chord/package.json +1 -1
  195. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.d.ts +1 -1
  196. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.d.ts.map +1 -1
  197. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.js +1 -1
  198. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.js.map +1 -1
  199. package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
  200. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts +2 -0
  201. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts.map +1 -1
  202. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js +6 -1
  203. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js.map +1 -1
  204. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  205. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +55 -17
  206. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  207. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  208. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +2 -1
  209. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +2 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  212. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +9 -0
  213. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  214. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.d.ts +30 -0
  215. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.d.ts.map +1 -0
  216. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.js +94 -0
  217. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.js.map +1 -0
  218. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.d.ts +48 -0
  219. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.d.ts.map +1 -0
  220. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.js +104 -0
  221. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.js.map +1 -0
  222. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.d.ts +6 -0
  223. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.d.ts.map +1 -0
  224. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.js +4 -0
  225. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.js.map +1 -0
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  231. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +7 -3
  233. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  234. package/node_modules/@earendil-works/pi-ai/package.json +10 -2
  235. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  236. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  237. package/node_modules/@earendil-works/pi-tui/README.md +11 -3
  238. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +2 -1
  239. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -0
  241. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  242. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.d.ts +37 -0
  243. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.d.ts.map +1 -0
  244. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.js +97 -0
  245. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.js.map +1 -0
  246. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts +2 -0
  247. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  248. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js +38 -0
  249. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js.map +1 -1
  250. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +25 -1
  251. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  252. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +110 -4
  253. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  254. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts.map +1 -1
  255. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js +5 -50
  256. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js.map +1 -1
  257. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.d.ts +12 -0
  258. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.d.ts.map +1 -1
  259. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js +129 -3
  260. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js.map +1 -1
  261. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +28 -0
  262. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  263. package/node_modules/@earendil-works/pi-tui/dist/tui.js +160 -0
  264. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  265. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  266. package/package.json +13 -9
  267. package/dist/bun/register-cursor-agent.d.ts +0 -2
  268. package/dist/bun/register-cursor-agent.d.ts.map +0 -1
  269. package/dist/bun/register-cursor-agent.js +0 -4
  270. package/dist/bun/register-cursor-agent.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"session-worker.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { parentPort } from \"node:worker_threads\";\nimport { runWithProviderScope } from \"@earendil-works/pi-ai/node/provider-scope\";\nimport { WAKE_SOURCE_STATE_EVENT } from \"../../core/extensions/builtin/monitor-state-event.ts\";\nimport { takeOverStdout } from \"../../core/output-guard.ts\";\nimport { getDefaultSessionDir } from \"../../core/session-manager.ts\";\nimport { liveSessionWritePaths } from \"../../core/session-write-reservation.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { createCliRuntimeFactory } from \"../../main.ts\";\nimport { initTheme } from \"../interactive/theme/theme.ts\";\nimport { buildRpcSessionState } from \"./connection-handler.ts\";\nimport { createRpcSessionBinding, type RpcSessionBinding } from \"./session-binding.ts\";\nimport { SessionEventWriter } from \"./session-event-writer.ts\";\nimport { type RpcSessionEntry, RpcSessionRegistry } from \"./session-registry.ts\";\nimport { createWorkerCredit } from \"./session-worker-credit.ts\";\nimport {\n\ttype HostToSessionWorker,\n\tSESSION_WORKER_LIMITS,\n\ttype SessionWorkerToHost,\n\ttype WorkerDisplay,\n\ttype WorkerSnapshot,\n} from \"./session-worker-protocol.ts\";\n\ntakeOverStdout();\nconst port = parentPort;\nif (!port) throw new Error(\"Session worker requires a parent port\");\nconst send = (message: SessionWorkerToHost): void => port.postMessage(message);\n\nfunction failWorker(error: string): never {\n\tsend({ type: \"failure\", error });\n\tprocess.exit(1);\n}\n\nfunction canonicalPath(path: string): string {\n\tconst absolute = resolve(path);\n\treturn existsSync(absolute) ? realpathSync(absolute) : join(realpathSync(dirname(absolute)), basename(absolute));\n}\n\nconst { exchange, installWriteReservation } = createWorkerCredit(send, failWorker);\ninstallWriteReservation(canonicalPath);\n\nclass WorkerEventWriter extends SessionEventWriter {\n\tconstructor() {\n\t\tsuper(() => {});\n\t}\n\toverride enqueue(_sessionId: string, record: object): boolean {\n\t\tif (Buffer.byteLength(JSON.stringify(record)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\t\tfailWorker(\"session_worker_output_limit\");\n\t\tconst session = entry?.runtime?.session;\n\t\tif (!session) throw new Error(\"Session output preceded runtime creation\");\n\t\tconst activity = { busy: session.isSessionBusy, streaming: session.isStreaming };\n\t\tconst replacement =\n\t\t\t\"type\" in record &&\n\t\t\t(record.type === \"session_replaced\" ||\n\t\t\t\trecord.type === \"question_resolved\" ||\n\t\t\t\trecord.type === \"question_updated\" ||\n\t\t\t\t(record.type === \"extension_ui_request\" && \"method\" in record && record.method === \"question\"))\n\t\t\t\t? snapshot()\n\t\t\t\t: undefined;\n\t\tif (replacement && Buffer.byteLength(JSON.stringify(replacement)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\t\tfailWorker(\"session_worker_snapshot_limit\");\n\t\texchange((signal) => ({\n\t\t\ttype: \"output\",\n\t\t\trecord,\n\t\t\tconnection: this.currentConnection(),\n\t\t\tsignal,\n\t\t\tactivity,\n\t\t\tsnapshot: replacement,\n\t\t}));\n\t\treturn true;\n\t}\n}\n\nconst writer = new WorkerEventWriter();\nlet prepared: Extract<HostToSessionWorker, { type: \"prepare\" }> | undefined;\nlet registry: RpcSessionRegistry | undefined;\nlet entry: RpcSessionEntry | undefined;\nlet binding: RpcSessionBinding | undefined;\nlet display: WorkerDisplay = { revision: 0, width: 80, rendered: false, capabilities: [] };\nlet closing = false;\nlet unsubscribe: (() => void) | undefined;\nlet unsubscribeWake: (() => void) | undefined;\n\nfunction applyDisplay(next: WorkerDisplay): boolean {\n\tif (next.revision < display.revision) return false;\n\tdisplay = next;\n\treturn true;\n}\n\nfunction updateDisplay(message: (signal: SharedArrayBuffer) => SessionWorkerToHost): void {\n\tconst signal = new SharedArrayBuffer(24);\n\texchange(message, \"session_worker_display_denied\", signal);\n\tconst values = new Float64Array(signal);\n\tapplyDisplay({\n\t\t...display,\n\t\twidth: values[1],\n\t\trevision: values[2],\n\t\trendered: Atomics.load(new Int32Array(signal), 1) === 1,\n\t});\n}\n\nfunction publishSnapshot(settled = false): void {\n\tconst value = snapshot();\n\tif (Buffer.byteLength(JSON.stringify(value)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\tfailWorker(\"session_worker_snapshot_limit\");\n\texchange((signal) => ({ type: \"snapshot\", snapshot: value, signal, settled }));\n}\n\nfunction subscribeSession(): void {\n\tunsubscribe?.();\n\tunsubscribeWake?.();\n\tunsubscribeWake = entry?.runtime?.session.extensionRunner.onBusEvent(WAKE_SOURCE_STATE_EVENT, () =>\n\t\tpublishSnapshot(),\n\t);\n\tunsubscribe = entry?.runtime?.session.subscribe((event) =>\n\t\tpublishSnapshot(event.type === \"agent_settled\" || event.type === \"agent_idle\"),\n\t);\n}\n\nfunction snapshot(): WorkerSnapshot {\n\tif (!entry?.runtime) throw new Error(\"Session runtime is not ready\");\n\tconst session = entry.runtime.session;\n\tconst sessionPath = session.sessionFile ? canonicalPath(session.sessionFile) : undefined;\n\t// The host releases every granted path this list omits, so it must name each writer\n\t// still alive in this isolate, plus the session the runtime currently writes.\n\tconst live = new Set(liveSessionWritePaths().map(canonicalPath));\n\tif (sessionPath) live.add(sessionPath);\n\treturn {\n\t\tstate: buildRpcSessionState(session),\n\t\tsessionPath,\n\t\tliveSessionPaths: [...live],\n\t\tbusy: session.isSessionBusy,\n\t\tstreaming: session.isStreaming,\n\t};\n}\n\nasync function handle(message: HostToSessionWorker): Promise<void> {\n\tswitch (message.type) {\n\t\tcase \"prepare\": {\n\t\t\tif (prepared) throw new Error(\"Session worker already prepared\");\n\t\t\tconst path =\n\t\t\t\tmessage.profile.sessionPath ??\n\t\t\t\tjoin(\n\t\t\t\t\tgetDefaultSessionDir(message.profile.cwd, message.configuration.agentDir),\n\t\t\t\t\t`${new Date().toISOString().replace(/[:.]/g, \"-\")}_${randomUUID()}.jsonl`,\n\t\t\t\t);\n\t\t\tprepared = { ...message, profile: { ...message.profile, sessionPath: canonicalPath(path) } };\n\t\t\tsend({ type: \"prepared\", request: message.request, sessionPath: canonicalPath(path) });\n\t\t\treturn;\n\t\t}\n\t\tcase \"commit\": {\n\t\t\tif (!prepared || registry) throw new Error(\"Invalid session commit\");\n\t\t\tconst startupSettingsManager = SettingsManager.create(\n\t\t\t\tprepared.configuration.cwd,\n\t\t\t\tprepared.configuration.agentDir,\n\t\t\t);\n\t\t\tconst factory = createCliRuntimeFactory(prepared.configuration, { startupSettingsManager });\n\t\t\tinitTheme(startupSettingsManager.getTheme(), false);\n\t\t\tregistry = new RpcSessionRegistry({ agentDir: prepared.configuration.agentDir, createRuntime: factory });\n\t\t\tconst opened = await registry.openSession(prepared.profile);\n\t\t\tentry = registry.getForCommand(opened.sessionId, \"open_session\");\n\t\t\tsend({ type: \"ready\", request: message.request, snapshot: snapshot() });\n\t\t\treturn;\n\t\t}\n\t\tcase \"bind\": {\n\t\t\tif (!entry || binding) throw new Error(\"Invalid session binding\");\n\t\t\tdisplay = message.display;\n\t\t\tconst bindingEntry = entry;\n\t\t\tconst createBinding = () =>\n\t\t\t\tcreateRpcSessionBinding(message.sessionId, bindingEntry, writer, () => send({ type: \"request_close\" }), {\n\t\t\t\t\tcapabilities: display.capabilities,\n\t\t\t\t\tsharedWidth: {\n\t\t\t\t\t\tgetWidth: () => display.width,\n\t\t\t\t\t\tsetWidth: (connection, width) =>\n\t\t\t\t\t\t\tupdateDisplay((signal) => ({ type: \"width\", connection, width, signal })),\n\t\t\t\t\t\tonChange: () => binding?.rerenderComponents?.(),\n\t\t\t\t\t\tclearWidth: () => {},\n\t\t\t\t\t\tconnectionId: () => writer.currentConnection(),\n\t\t\t\t\t\thasRenderedComponents: () => display.rendered,\n\t\t\t\t\t\tsetCapabilities: (connection, capabilities) => {\n\t\t\t\t\t\t\tupdateDisplay((signal) => ({ type: \"capabilities\", connection, capabilities, signal }));\n\t\t\t\t\t\t\tbinding?.rerenderComponents?.();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\tbinding = await (message.connection === undefined\n\t\t\t\t? createBinding()\n\t\t\t\t: writer.withConnection(message.connection, createBinding));\n\t\t\tconst rebind = entry.rebindSession;\n\t\t\tentry.rebindSession = async (session) => {\n\t\t\t\tawait rebind?.(session);\n\t\t\t\tsubscribeSession();\n\t\t\t};\n\t\t\tentry.runtime?.setRebindSession(entry.rebindSession);\n\t\t\tsubscribeSession();\n\t\t\tpublishSnapshot();\n\t\t\tsend({ type: \"result\", request: message.request });\n\t\t\treturn;\n\t\t}\n\t\tcase \"command\": {\n\t\t\tconst privileged =\n\t\t\t\t\"type\" in message.command &&\n\t\t\t\t[\"abort\", \"abort_bash\", \"extension_ui_response\", \"extension_ui_progress\"].includes(\n\t\t\t\t\tString(message.command.type),\n\t\t\t\t);\n\t\t\tif (!binding || (closing && !privileged)) throw new Error(\"session_closing\");\n\t\t\tapplyDisplay(message.display);\n\t\t\tconst activeBinding = binding;\n\t\t\tawait (message.connection === undefined\n\t\t\t\t? activeBinding.handle(message.command)\n\t\t\t\t: writer.withConnection(message.connection, () => activeBinding.handle(message.command)));\n\t\t\tpublishSnapshot();\n\t\t\tsend({ type: \"result\", request: message.request });\n\t\t\treturn;\n\t\t}\n\t\tcase \"display\":\n\t\t\tif (applyDisplay(message.display)) binding?.rerenderComponents?.();\n\t\t\tsend({ type: \"control_done\", control: \"display\" });\n\t\t\treturn;\n\t\tcase \"cancel_ui\":\n\t\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\t\tsend({ type: \"control_done\", control: \"cancel_ui\" });\n\t\t\treturn;\n\t\tcase \"close\":\n\t\t\tclosing = true;\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribeWake?.();\n\t\t\tawait binding?.dispose();\n\t\t\tif (entry?.runtime) {\n\t\t\t\tconst current = entry;\n\t\t\t\tawait runWithProviderScope(current.scope, async () => {\n\t\t\t\t\tawait current.runtime?.session.abort();\n\t\t\t\t\tawait current.runtime?.session.waitForIdle();\n\t\t\t\t\tawait current.runtime?.dispose();\n\t\t\t\t\tawait current.scope.close();\n\t\t\t\t});\n\t\t\t}\n\t\t\tprocess.exit(0);\n\t}\n}\n\nport.on(\"message\", (message: HostToSessionWorker) => {\n\tvoid handle(message).catch((cause: unknown) => {\n\t\tconst error = cause instanceof Error ? cause.message : String(cause);\n\t\tif (error.startsWith(\"session_worker_\")) {\n\t\t\tsend({ type: \"failure\", error });\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (\"request\" in message) send({ type: \"result\", request: message.request, error });\n\t\telse {\n\t\t\tsend({ type: \"failure\", error });\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n});\n"]}
1
+ {"version":3,"file":"session-worker.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { parentPort } from \"node:worker_threads\";\nimport { runWithProviderScope } from \"@earendil-works/pi-ai/node/provider-scope\";\nimport { isBunBinary } from \"../../config.ts\";\nimport { WAKE_SOURCE_STATE_EVENT } from \"../../core/extensions/builtin/monitor-state-event.ts\";\nimport { takeOverStdout } from \"../../core/output-guard.ts\";\nimport { getDefaultSessionDir } from \"../../core/session-manager.ts\";\nimport { liveSessionWritePaths } from \"../../core/session-write-reservation.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { createCliRuntimeFactory } from \"../../main.ts\";\nimport { initTheme } from \"../interactive/theme/theme.ts\";\nimport { buildRpcSessionState } from \"./connection-handler.ts\";\nimport { createRpcSessionBinding, type RpcSessionBinding } from \"./session-binding.ts\";\nimport { SessionEventWriter } from \"./session-event-writer.ts\";\nimport { type RpcSessionEntry, RpcSessionRegistry } from \"./session-registry.ts\";\nimport { createWorkerCredit } from \"./session-worker-credit.ts\";\nimport {\n\ttype HostToSessionWorker,\n\tSESSION_WORKER_LIMITS,\n\ttype SessionWorkerToHost,\n\ttype WorkerDisplay,\n\ttype WorkerSnapshot,\n} from \"./session-worker-protocol.ts\";\n\nif (isBunBinary) {\n\tconst { registerBunRuntimeModules } = await import(\"../../bun/runtime-modules.ts\");\n\tregisterBunRuntimeModules();\n}\n\ntakeOverStdout();\nconst port = parentPort;\nif (!port) throw new Error(\"Session worker requires a parent port\");\nconst send = (message: SessionWorkerToHost): void => port.postMessage(message);\n\nfunction failWorker(error: string): never {\n\tsend({ type: \"failure\", error });\n\tprocess.exit(1);\n}\n\nfunction canonicalPath(path: string): string {\n\tconst absolute = resolve(path);\n\treturn existsSync(absolute) ? realpathSync(absolute) : join(realpathSync(dirname(absolute)), basename(absolute));\n}\n\nconst { exchange, installWriteReservation } = createWorkerCredit(send, failWorker);\ninstallWriteReservation(canonicalPath);\n\nclass WorkerEventWriter extends SessionEventWriter {\n\tconstructor() {\n\t\tsuper(() => {});\n\t}\n\toverride enqueue(_sessionId: string, record: object): boolean {\n\t\tif (Buffer.byteLength(JSON.stringify(record)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\t\tfailWorker(\"session_worker_output_limit\");\n\t\tconst session = entry?.runtime?.session;\n\t\tif (!session) throw new Error(\"Session output preceded runtime creation\");\n\t\tconst activity = { busy: session.isSessionBusy, streaming: session.isStreaming };\n\t\tconst replacement =\n\t\t\t\"type\" in record &&\n\t\t\t(record.type === \"session_replaced\" ||\n\t\t\t\trecord.type === \"question_resolved\" ||\n\t\t\t\trecord.type === \"question_updated\" ||\n\t\t\t\t(record.type === \"extension_ui_request\" && \"method\" in record && record.method === \"question\"))\n\t\t\t\t? snapshot()\n\t\t\t\t: undefined;\n\t\tif (replacement && Buffer.byteLength(JSON.stringify(replacement)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\t\tfailWorker(\"session_worker_snapshot_limit\");\n\t\texchange((signal) => ({\n\t\t\ttype: \"output\",\n\t\t\trecord,\n\t\t\tconnection: this.currentConnection(),\n\t\t\tsignal,\n\t\t\tactivity,\n\t\t\tsnapshot: replacement,\n\t\t}));\n\t\treturn true;\n\t}\n}\n\nconst writer = new WorkerEventWriter();\nlet prepared: Extract<HostToSessionWorker, { type: \"prepare\" }> | undefined;\nlet registry: RpcSessionRegistry | undefined;\nlet entry: RpcSessionEntry | undefined;\nlet binding: RpcSessionBinding | undefined;\nlet display: WorkerDisplay = { revision: 0, width: 80, rendered: false, capabilities: [] };\nlet closing = false;\nlet unsubscribe: (() => void) | undefined;\nlet unsubscribeWake: (() => void) | undefined;\n\nfunction applyDisplay(next: WorkerDisplay): boolean {\n\tif (next.revision < display.revision) return false;\n\tdisplay = next;\n\treturn true;\n}\n\nfunction updateDisplay(message: (signal: SharedArrayBuffer) => SessionWorkerToHost): void {\n\tconst signal = new SharedArrayBuffer(24);\n\texchange(message, \"session_worker_display_denied\", signal);\n\tconst values = new Float64Array(signal);\n\tapplyDisplay({\n\t\t...display,\n\t\twidth: values[1],\n\t\trevision: values[2],\n\t\trendered: Atomics.load(new Int32Array(signal), 1) === 1,\n\t});\n}\n\nfunction publishSnapshot(settled = false): void {\n\tconst value = snapshot();\n\tif (Buffer.byteLength(JSON.stringify(value)) > SESSION_WORKER_LIMITS.outputBytes)\n\t\tfailWorker(\"session_worker_snapshot_limit\");\n\texchange((signal) => ({ type: \"snapshot\", snapshot: value, signal, settled }));\n}\n\nfunction subscribeSession(): void {\n\tunsubscribe?.();\n\tunsubscribeWake?.();\n\tunsubscribeWake = entry?.runtime?.session.extensionRunner.onBusEvent(WAKE_SOURCE_STATE_EVENT, () =>\n\t\tpublishSnapshot(),\n\t);\n\tunsubscribe = entry?.runtime?.session.subscribe((event) =>\n\t\tpublishSnapshot(event.type === \"agent_settled\" || event.type === \"agent_idle\"),\n\t);\n}\n\nfunction snapshot(): WorkerSnapshot {\n\tif (!entry?.runtime) throw new Error(\"Session runtime is not ready\");\n\tconst session = entry.runtime.session;\n\tconst sessionPath = session.sessionFile ? canonicalPath(session.sessionFile) : undefined;\n\t// The host releases every granted path this list omits, so it must name each writer\n\t// still alive in this isolate, plus the session the runtime currently writes.\n\tconst live = new Set(liveSessionWritePaths().map(canonicalPath));\n\tif (sessionPath) live.add(sessionPath);\n\treturn {\n\t\tstate: buildRpcSessionState(session),\n\t\tsessionPath,\n\t\tliveSessionPaths: [...live],\n\t\tbusy: session.isSessionBusy,\n\t\tstreaming: session.isStreaming,\n\t};\n}\n\nasync function handle(message: HostToSessionWorker): Promise<void> {\n\tswitch (message.type) {\n\t\tcase \"prepare\": {\n\t\t\tif (prepared) throw new Error(\"Session worker already prepared\");\n\t\t\tconst path =\n\t\t\t\tmessage.profile.sessionPath ??\n\t\t\t\tjoin(\n\t\t\t\t\tgetDefaultSessionDir(message.profile.cwd, message.configuration.agentDir),\n\t\t\t\t\t`${new Date().toISOString().replace(/[:.]/g, \"-\")}_${randomUUID()}.jsonl`,\n\t\t\t\t);\n\t\t\tprepared = { ...message, profile: { ...message.profile, sessionPath: canonicalPath(path) } };\n\t\t\tsend({ type: \"prepared\", request: message.request, sessionPath: canonicalPath(path) });\n\t\t\treturn;\n\t\t}\n\t\tcase \"commit\": {\n\t\t\tif (!prepared || registry) throw new Error(\"Invalid session commit\");\n\t\t\tconst startupSettingsManager = SettingsManager.create(\n\t\t\t\tprepared.configuration.cwd,\n\t\t\t\tprepared.configuration.agentDir,\n\t\t\t);\n\t\t\tconst factory = createCliRuntimeFactory(prepared.configuration, { startupSettingsManager });\n\t\t\tinitTheme(startupSettingsManager.getTheme(), false);\n\t\t\tregistry = new RpcSessionRegistry({ agentDir: prepared.configuration.agentDir, createRuntime: factory });\n\t\t\tconst opened = await registry.openSession(prepared.profile);\n\t\t\tentry = registry.getForCommand(opened.sessionId, \"open_session\");\n\t\t\tsend({ type: \"ready\", request: message.request, snapshot: snapshot() });\n\t\t\treturn;\n\t\t}\n\t\tcase \"bind\": {\n\t\t\tif (!entry || binding) throw new Error(\"Invalid session binding\");\n\t\t\tdisplay = message.display;\n\t\t\tconst bindingEntry = entry;\n\t\t\tconst createBinding = () =>\n\t\t\t\tcreateRpcSessionBinding(message.sessionId, bindingEntry, writer, () => send({ type: \"request_close\" }), {\n\t\t\t\t\tcapabilities: display.capabilities,\n\t\t\t\t\tsharedWidth: {\n\t\t\t\t\t\tgetWidth: () => display.width,\n\t\t\t\t\t\tsetWidth: (connection, width) =>\n\t\t\t\t\t\t\tupdateDisplay((signal) => ({ type: \"width\", connection, width, signal })),\n\t\t\t\t\t\tonChange: () => binding?.rerenderComponents?.(),\n\t\t\t\t\t\tclearWidth: () => {},\n\t\t\t\t\t\tconnectionId: () => writer.currentConnection(),\n\t\t\t\t\t\thasRenderedComponents: () => display.rendered,\n\t\t\t\t\t\tsetCapabilities: (connection, capabilities) => {\n\t\t\t\t\t\t\tupdateDisplay((signal) => ({ type: \"capabilities\", connection, capabilities, signal }));\n\t\t\t\t\t\t\tbinding?.rerenderComponents?.();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\tbinding = await (message.connection === undefined\n\t\t\t\t? createBinding()\n\t\t\t\t: writer.withConnection(message.connection, createBinding));\n\t\t\tconst rebind = entry.rebindSession;\n\t\t\tentry.rebindSession = async (session) => {\n\t\t\t\tawait rebind?.(session);\n\t\t\t\tsubscribeSession();\n\t\t\t};\n\t\t\tentry.runtime?.setRebindSession(entry.rebindSession);\n\t\t\tsubscribeSession();\n\t\t\tpublishSnapshot();\n\t\t\tsend({ type: \"result\", request: message.request });\n\t\t\treturn;\n\t\t}\n\t\tcase \"command\": {\n\t\t\tconst privileged =\n\t\t\t\t\"type\" in message.command &&\n\t\t\t\t[\"abort\", \"abort_bash\", \"extension_ui_response\", \"extension_ui_progress\"].includes(\n\t\t\t\t\tString(message.command.type),\n\t\t\t\t);\n\t\t\tif (!binding || (closing && !privileged)) throw new Error(\"session_closing\");\n\t\t\tapplyDisplay(message.display);\n\t\t\tconst activeBinding = binding;\n\t\t\tawait (message.connection === undefined\n\t\t\t\t? activeBinding.handle(message.command)\n\t\t\t\t: writer.withConnection(message.connection, () => activeBinding.handle(message.command)));\n\t\t\tpublishSnapshot();\n\t\t\tsend({ type: \"result\", request: message.request });\n\t\t\treturn;\n\t\t}\n\t\tcase \"display\":\n\t\t\tif (applyDisplay(message.display)) binding?.rerenderComponents?.();\n\t\t\tsend({ type: \"control_done\", control: \"display\" });\n\t\t\treturn;\n\t\tcase \"cancel_ui\":\n\t\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\t\tsend({ type: \"control_done\", control: \"cancel_ui\" });\n\t\t\treturn;\n\t\tcase \"close\":\n\t\t\tclosing = true;\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribeWake?.();\n\t\t\tawait binding?.dispose();\n\t\t\tif (entry?.runtime) {\n\t\t\t\tconst current = entry;\n\t\t\t\tawait runWithProviderScope(current.scope, async () => {\n\t\t\t\t\tawait current.runtime?.session.abort();\n\t\t\t\t\tawait current.runtime?.session.waitForIdle();\n\t\t\t\t\tawait current.runtime?.dispose();\n\t\t\t\t\tawait current.scope.close();\n\t\t\t\t});\n\t\t\t}\n\t\t\tprocess.exit(0);\n\t}\n}\n\nport.on(\"message\", (message: HostToSessionWorker) => {\n\tvoid handle(message).catch((cause: unknown) => {\n\t\tconst error = cause instanceof Error ? cause.message : String(cause);\n\t\tif (error.startsWith(\"session_worker_\")) {\n\t\t\tsend({ type: \"failure\", error });\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (\"request\" in message) send({ type: \"result\", request: message.request, error });\n\t\telse {\n\t\t\tsend({ type: \"failure\", error });\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n});\n"]}
@@ -25,6 +25,8 @@ Commands run by the `bash` and `powershell` tools receive the current Pi session
25
25
  |----------|-------------|
26
26
  | `PI_SESSION_ID` | Current session ID |
27
27
  | `PI_SESSION_FILE` | Absolute path to the current session JSONL file; unset for ephemeral sessions |
28
+ | `PI_SESSION_CWD` | Current session working directory, independent of the shell child's working directory |
29
+ | `PI_GOAL_STORE_FILE` | Absolute path to the session's authoritative goal-store file; the file need not exist yet |
28
30
  | `PI_PROVIDER` | Currently selected model provider |
29
31
  | `PI_MODEL` | Currently selected model ID |
30
32
  | `PI_REASONING_LEVEL` | Current effective reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` |
@@ -46,7 +48,9 @@ if [ -n "$PI_SESSION_FILE" ]; then
46
48
  fi
47
49
  ```
48
50
 
49
- These variables are injected into the LLM-callable `bash` and `powershell` tools. They are not injected into user-entered `!` or `!!` commands.
51
+ These variables are injected into the LLM-callable `bash` (including terminal-extension PTY sessions) and `powershell` tools. They are not injected into user-entered `!` or `!!` commands. Eval kernels receive the same session environment at kernel start, and their children inherit it. Inherited values for `PI_SESSION_CWD` and `PI_GOAL_STORE_FILE` are cleared before session values are applied; an unavailable optional goal-store path stays unset.
52
+
53
+ `PI_GOAL_STORE_FILE` comes from `ExtensionContext.goalStoreFile`, not from the session JSONL filename. Persisted sessions use the session manager's directory, including an explicit `SessionManager.open(path, otherSessionDir)` override. In-memory sessions use a cwd-hashed `extensions/goal/no-session/<hash>` bucket under the agent state directory. Reading the path does not create a goal or its file.
50
54
 
51
55
  ### Custom Shell Tools
52
56
 
@@ -425,13 +425,14 @@ A `project_trust` handler must return `{ trusted: "yes" | "no" | "undecided" }`.
425
425
 
426
426
  #### resources_discover
427
427
 
428
- Fired after `session_start` so extensions can contribute additional skill, prompt, and theme paths.
428
+ Fired after `session_start` so extensions can contribute additional skill, prompt, theme, and hook config paths.
429
429
  The startup path uses `reason: "startup"`. Reload uses `reason: "reload"`.
430
430
 
431
431
  ```typescript
432
432
  pi.on("resources_discover", async (event, _ctx) => {
433
433
  // event.cwd - current working directory
434
434
  // event.reason - "startup" | "reload"
435
+ // event.scopedEntries - true: this host accepts { path, scope } entries (absent on older hosts)
435
436
  return {
436
437
  skillPaths: ["/path/to/skills"],
437
438
  promptPaths: ["/path/to/prompts"],
@@ -440,6 +441,24 @@ pi.on("resources_discover", async (event, _ctx) => {
440
441
  });
441
442
  ```
442
443
 
444
+ Each entry in `skillPaths`, `promptPaths`, `themePaths`, and `hookPaths` is a `ResourceDiscoverEntry`: either a path string or `{ path, scope? }`.
445
+
446
+ A bare string inherits its scope from the contributing extension. It becomes `system` when the extension is builtin, or when the extension comes from a system package (see [`pi.system`](packages.md#creating-a-pi-package)) and the path lies inside that package. Otherwise the path keeps the `temporary` scope contributed paths have always had.
447
+
448
+ Use the object form to pin the scope explicitly, for example when a system extension surfaces data the user owns. Hosts that accept the object form set `event.scopedEntries` to `true`; a host that predates it omits the field and would treat an object as a path string, so an extension that must load on both returns plain paths when the field is absent:
449
+
450
+ ```typescript
451
+ pi.on("resources_discover", async (event) => {
452
+ const userSkills = join(homedir(), "my-skills");
453
+ return {
454
+ skillPaths: [
455
+ "/path/inside/this/package/skills", // inherits the extension's scope
456
+ event.scopedEntries ? { path: userSkills, scope: "user" } : userSkills, // pinned where supported
457
+ ],
458
+ };
459
+ });
460
+ ```
461
+
443
462
  ### Session Events
444
463
 
445
464
  See [Session Format](session-format.md) for session storage internals and the SessionManager API.
@@ -677,6 +696,19 @@ pi.on("ui_prompt_end", async (event, ctx) => {
677
696
  });
678
697
  ```
679
698
 
699
+ #### Pending-question bus events
700
+
701
+ These additive events use `pi.events.on(...)`, not `pi.on(...)`:
702
+
703
+ | Channel | Payload | Meaning |
704
+ |---------|---------|---------|
705
+ | `ask-user:asked` | `{ ctx, request, variant }` | One fresh runtime registration of a built-in question, in either `waitForAnswer` mode. The hooks builtin dispatches a `Notification` with `kind: "ask-user-asked"`, the request ID and question headers. |
706
+ | `herdr:blocked` | `{ active: true, label, id }` or `{ active: false, id }` | A built-in question or host select/confirm/input/editor dialog opens or settles. Question labels are `<header> — <question>`; dialog labels are their titles. |
707
+
708
+ Track blocked IDs as a set, not a boolean: requests can overlap. Each question registration emits one active/inactive pair, including cancellation, timeout, abort and orphaned restart recovery. A dangling disk call recovered after restart gets one new runtime registration; its persisted recovery marker prevents registering it again. Reconnect replay and UI hydration reuse an existing registration and do not repeat arrival events or the terminal bell. The builtin owns question events, so UI integrations must not emit a second pair when resolving the question.
709
+
710
+ Question registration also retains an `ask-user:question` custom session entry containing `{ requestId, headers }`. This is display-only metadata, excluded from model context, for labeling compact answer chips during replay; it is not another bus event. The model-facing `[Answer to question ...]` message stays unchanged.
711
+
680
712
  #### turn_start / turn_end
681
713
 
682
714
  Fired for each turn (one LLM response + tool calls).
@@ -1089,6 +1121,12 @@ ctx.sessionManager.buildContextEntries() // Active branch entries with compac
1089
1121
  ctx.sessionManager.getLeafId() // Current leaf entry ID
1090
1122
  ```
1091
1123
 
1124
+ ### ctx.goalStoreFile
1125
+
1126
+ Optional read-only getter for the absolute path to the current session's authoritative goal-store file. The host resolves it from the session manager and `ctx.cwd`; reading it performs no file creation. Persisted sessions honor session-directory overrides, while in-memory sessions use a cwd-hashed `extensions/goal/no-session/<hash>` bucket under the agent state directory. Do not derive it from `getSessionFile()`.
1127
+
1128
+ Shell tools and eval kernels expose this value as `PI_GOAL_STORE_FILE` and `ctx.cwd` as `PI_SESSION_CWD`. Hand-built contexts and older hosts may omit the getter, in which case `PI_GOAL_STORE_FILE` is unset.
1129
+
1092
1130
  ### ctx.modelRegistry / ctx.model / ctx.thinkingLevel / ctx.scopedModels
1093
1131
 
1094
1132
  Access to models, providers, and resolved authentication. `ctx.modelRegistry.getProvider(id)` returns the effective pi-ai provider, while `getProviderAuth(id)` resolves its current API key, headers, base URL, and provider-scoped environment without requiring a loaded model. `ctx.model` is the active model, and `ctx.thinkingLevel` is its current effective thinking level.
@@ -1846,14 +1884,14 @@ Each entry has this shape:
1846
1884
  sourceInfo: {
1847
1885
  path: string;
1848
1886
  source: string;
1849
- scope: "user" | "project" | "temporary";
1887
+ scope: "user" | "project" | "temporary" | "system";
1850
1888
  origin: "package" | "top-level";
1851
1889
  baseDir?: string;
1852
1890
  };
1853
1891
  }
1854
1892
  ```
1855
1893
 
1856
- Use `sourceInfo` as the canonical provenance field. Do not infer ownership from command names or from ad hoc path parsing.
1894
+ Use `sourceInfo` as the canonical provenance field. Do not infer ownership from command names or from ad hoc path parsing. The `system` scope marks resources the harness itself provides: builtin and bundled extensions, the generated global-default extension shims in the agent extensions directory, command-line packages whose manifest declares `pi.system`, and what those contribute.
1857
1895
 
1858
1896
  Built-in interactive commands (like `/model` and `/settings`) are not included here. They are handled only in interactive
1859
1897
  mode and would not execute if sent via `prompt`.
@@ -1954,7 +1992,7 @@ const all = pi.getAllTools();
1954
1992
  // description: "Read file contents...",
1955
1993
  // parameters: ...,
1956
1994
  // promptGuidelines: ["Use read to examine files instead of cat or sed."],
1957
- // sourceInfo: { path: "<builtin:read>", source: "builtin", scope: "temporary", origin: "top-level" }
1995
+ // sourceInfo: { path: "<builtin:read>", source: "builtin", scope: "system", origin: "top-level" }
1958
1996
  // }, ...]
1959
1997
  const builtinTools = all.filter((t) => t.sourceInfo.source === "builtin");
1960
1998
  const extensionTools = all.filter((t) => t.sourceInfo.source !== "builtin" && t.sourceInfo.source !== "sdk");
@@ -2505,7 +2543,7 @@ const bashTool = createBashTool(cwd, {
2505
2543
  });
2506
2544
  ```
2507
2545
 
2508
- `createBashTool()` and `createPowerShellTool()` expose the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2546
+ `createBashTool()` and `createPowerShellTool()` expose the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_SESSION_CWD`, `PI_GOAL_STORE_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2509
2547
 
2510
2548
  ```typescript
2511
2549
  const bashTool = createBashTool(cwd, {
@@ -164,8 +164,11 @@ This routing remains configurable through the ordinary action bindings. For exam
164
164
  | `app.tools.expand` | `ctrl+o` | Collapse or expand tool output |
165
165
  | `app.message.copy` | `ctrl+x` | Copy the selected message in `/tree`; otherwise copy the last assistant message, or the active fullscreen text selection when `fullscreenCopyOnSelect` is disabled |
166
166
  | `app.message.followUp` | `alt+enter` | Queue follow-up message |
167
- | `app.message.dequeue` | `alt+up` | Restore queued messages to editor |
168
- | `app.question.answer` | `alt+a` | Open the pending async question (Enter on an empty editor and `/answer` do the same without a chord; on macOS the Option-composed glyph of the bound letter is accepted too, except for the dead keys e, i, n, u) |
167
+ | `app.message.dequeue` | `alt+up` (`alt+q` on Windows and WSL) | Restore queued messages to editor when no pending question claims the chord |
168
+ | `app.question.answer` | `alt+up`, `alt+a` | Open the pending async question before dequeue. Enter on an empty editor also opens it; `/answer` lists multiple requests. On macOS, the Option-composed glyph of a bound letter is also accepted (except dead keys e, i, n, u). |
169
+ | `app.question.next` | `alt+down` | Cycle pending requests while the composer is empty and no overlay or autocomplete is open |
170
+
171
+ The question hint prefers `alt+up` (`option+up` on macOS). In tmux, Apple Terminal, Warp, and VS Code it shows the retained `alt+a` alternative. Both bindings remain active; there is no third fallback chord. On Windows and WSL, dequeue uses `alt+q`, so `alt+up` does not conflict with it. Tab completion and Shift+Tab thinking-level cycling are unchanged.
169
172
 
170
173
  ### Tree Navigation
171
174
 
package/docs/packages.md CHANGED
@@ -132,6 +132,23 @@ Add a `pi` manifest to `package.json` or use conventional directories. Include t
132
132
 
133
133
  Paths are relative to the package root. Arrays support glob patterns and `!exclusions`. Positive manifest globs discover visible paths in lexical order. List dot-prefixed paths directly. If a glob would need to continue through a symlink, list the symlinked resource root directly.
134
134
 
135
+ ### System Packages
136
+
137
+ A distribution that launches pi with its own package can mark that package as part of the harness:
138
+
139
+ ```json
140
+ {
141
+ "name": "my-harness",
142
+ "pi": {
143
+ "system": true,
144
+ "extensions": ["./extensions"],
145
+ "skills": ["./skills"]
146
+ }
147
+ }
148
+ ```
149
+
150
+ `system` must be a boolean; any other value is ignored. The flag is honored only when the package is supplied on the command line with `--extension` / `-e`. Its resources then resolve to the `system` scope (with the package root as `baseDir`) instead of `temporary`, so the interactive startup banner lists them under `system` in the expanded view and leaves them out of the compact one. Packages installed through settings keep their `user` or `project` scope even with the flag set, so a project package cannot hide itself from the trust surface.
151
+
135
152
  ### Gallery Metadata
136
153
 
137
154
  The [package gallery](https://pi.dev/packages) displays packages tagged with `pi-package`. Add `video` or `image` fields to show a preview:
package/docs/rpc.md CHANGED
@@ -269,8 +269,11 @@ Canonical reservations and worker capacity remain held until native exit, includ
269
269
  The classic handler, extension UI bridge, renderer callbacks and provider scope run inside the owning worker; only
270
270
  plain data crosses IPC. Inline `main()` extension factories cannot be cloned and are rejected in shared mode: use
271
271
  file-backed extensions. Classic single-session RPC remains in-process. Standalone Bun builds must embed
272
- `src/modes/rpc/session-worker.ts` as an explicit entrypoint; Node bundles must ship `session-worker.js` beside the
273
- chunk containing its worker client. Third-party/rebranded Bun wrappers must pass the published
272
+ `src/modes/rpc/session-worker.ts` as an explicit entrypoint. Bun 1.4.2 supports `--compile --splitting`
273
+ with `--minify --keep-names`; standalone release and package binary builds use these flags to share code
274
+ between embedded entries. Splitting does not change the worker-entry define contract below.
275
+ Node bundles must ship `session-worker.js` beside the chunk containing its worker client.
276
+ Third-party/rebranded Bun wrappers must pass the published
274
277
  `dist/modes/rpc/session-worker.js` as an additional compile entry, set an explicit `--root`, and set
275
278
  `--define=SENPI_RPC_SESSION_WORKER_ENTRY='"./<worker-path-relative-to-root>"'`. The define is a build-time
276
279
  contract, not an environment variable. Its path must match Bun's embedded entry name, not the source machine's
@@ -1326,7 +1329,7 @@ Each command has:
1326
1329
  - `sourceInfo`: Provenance metadata for the owning resource (present for all sources, including extensions):
1327
1330
  - `path`: Absolute file path to the command source
1328
1331
  - `source`: Source identifier string (for example `"auto"` for auto-discovered locations, `"local"` for settings entries, `"cli"` for CLI paths, `"builtin"`, `"sdk"`, or a package source)
1329
- - `scope`: `"user"`, `"project"`, or `"temporary"`
1332
+ - `scope`: `"user"`, `"project"`, `"temporary"`, or `"system"` (harness-provided: builtin and bundled extensions, command-line packages declaring `pi.system`, and what they contribute)
1330
1333
  - `origin`: `"package"` or `"top-level"`
1331
1334
  - `baseDir`: Base directory of the owning resource (optional)
1332
1335
 
package/docs/settings.md CHANGED
@@ -480,6 +480,7 @@ This is the default and has no setting. Hooks and permission checks apply unchan
480
480
  |---------|------|---------|-------------|
481
481
  | `askUser.enabled` | boolean | `true` | Enable the built-in question tool (`request_user_input` / `ask_user_question`) |
482
482
  | `askUser.timeoutMinutes` | number | `30` | Idle minutes before an unanswered question times out, clamped to 1–120 |
483
+ | `askUser.bell` | boolean | `true` | Ring the terminal bell once for a newly displayed question; reconnect hydration does not ring |
483
484
 
484
485
  Disable for one run without changing settings with `--no-ask-user` (wins over `askUser.enabled: true`). `disabledBuiltinExtensions: ["ask-user"]` remains the coarse switch that skips loading the extension.
485
486
 
@@ -487,11 +488,14 @@ Disable for one run without changing settings with `--no-ask-user` (wins over `a
487
488
  {
488
489
  "askUser": {
489
490
  "enabled": true,
490
- "timeoutMinutes": 30
491
+ "timeoutMinutes": 30,
492
+ "bell": true
491
493
  }
492
494
  }
493
495
  ```
494
496
 
497
+ While a question is pending, the terminal title shows `? <header>` unless an active tool title takes precedence. Settlement restores the previous title layer. Set `askUser.bell: false` to keep the title and question display without a bell.
498
+
495
499
  ### Sessions
496
500
 
497
501
  | Setting | Type | Default | Description |
package/docs/tui.md CHANGED
@@ -182,7 +182,15 @@ Use `handle.unfocus()` when a visible overlay should stop owning input and let T
182
182
 
183
183
  When the agent asks a blocking question (`waitForAnswer: true`), a full-screen overlay appears with a tab for each question and a final Submit tab. Use digits or arrows to choose options, Space to toggle multi-select choices, and Enter to confirm and advance. The Submit tab contains the optional comment editor and accepts partial answers after confirmation; unanswered questions are reported back as unanswered. Esc backs out of an editor or asks for confirmation before discarding a draft.
184
184
 
185
- For async questions (`waitForAnswer: false`), a widget appears above the editor while the agent keeps working: the unanswered count with a countdown, the first unanswered question with its options (and how many more questions wait behind it), and a hint listing every way in. Open the full overlay with Enter on an empty editor, with `/answer`, or with the `app.question.answer` shortcut (default `alt+a`, shown as `option+a` on macOS, rebindable in `keybindings.json`; on macOS the Option-composed glyph of the bound letter also works, so the shortcut needs no terminal settings change). Esc collapses the overlay back to the widget with your draft kept. Typing a reply in the editor and pressing Enter sends it as a comment instead.
185
+ Async questions (`waitForAnswer: false`) queue above the editor without taking focus or replacing earlier requests. The widget shows the pending count, the shown question and options, its countdown, and `+N more`. `alt+down` cycles requests from an empty composer; Tab still completes and Shift+Tab still cycles thinking. Each request keeps its own draft and idle deadline.
186
+
187
+ Open the shown request with empty Enter or `app.question.answer` (defaults `alt+up` and `alt+a`, shown as Option on macOS). A pending question wins the shared `alt+up` chord; without one it restores queued messages. Windows/WSL dequeue uses `alt+q` instead. The hint prefers `alt+a` in tmux, Apple Terminal, Warp and VS Code; the macOS `å` fallback still works. Rebind either action in `keybindings.json`.
188
+
189
+ A valid digit on an empty composer selects the corresponding option of the first unanswered sub-question. A single-question single-select digit or Enter submits immediately; multiple sub-questions advance through the component. `/answer` lists multiple pending requests, `/answer <n>` opens the n-th, and `/answer skip` dismisses the shown request. Esc collapses the component with its draft kept.
190
+
191
+ An answered question collapses in the transcript to a compact `↳ <header>: <answer>` chip; comments render quoted and dismissed or timed-out questions render `(no answer)`. Click the chip to expand the original message and click again to collapse it. `/answer skip` also tells the agent that you dismissed the question. While a question is pending, the terminal title shows `? <header>`, and `askUser.bell` controls the one-time arrival bell.
192
+
193
+ Text first typed or pasted into an empty composer binds to the shown request and labels the border `↳ reply to <header>`. Enter sends that comment only to its bound request; the follow-up chord (`alt+enter`, or `ctrl+q` on Windows/WSL) sends an ordinary message instead. Text present before arrival and recalled history stay chat. If a bound request settles, the text is preserved, the label clears with a notice, and the next Enter sends chat rather than answering another request.
186
194
 
187
195
  ### Overlay Lifecycle
188
196
 
@@ -323,13 +331,17 @@ Fullscreen mode routes normalized press, release, click, move, drag, and wheel e
323
331
  import { MouseRegion } from "@earendil-works/pi-tui";
324
332
 
325
333
  const clickable = new MouseRegion(content, (event) => {
326
- if (event.type !== "click" || event.button !== "left") return undefined;
334
+ if (event.button !== "left") return undefined;
335
+ if (event.type === "press") return { handled: true };
336
+ if (event.type !== "click") return undefined;
327
337
  expanded = !expanded;
328
338
  return { handled: true };
329
339
  });
330
340
  ```
331
341
 
332
- Unhandled wheel input scrolls the nearest `ScrollView`; unhandled primary-button drags retain transcript selection. OSC 8 links take precedence over parent click regions. `Input`, `Editor`, `SelectList`, and `SettingsList` include fullscreen mouse behavior. Regular mode does not capture mouse input because the terminal owns its scrollback.
342
+ In fullscreen mode, unhandled wheel input scrolls the nearest `ScrollView`; unhandled primary-button drags retain transcript selection. OSC 8 links take precedence over parent click regions. `Input`, `Editor`, `SelectList`, and `SettingsList` include fullscreen mouse behavior.
343
+
344
+ Regular mode supports scoped capture through `const release = tui.acquireMouseCapture("pending-question")`; the host releases it when the interactive surface closes and reapplies its intent to a replacement renderer after a mode switch. Only an acknowledged, unmodified left press followed by release in the same cell within 500 ms produces a click. Wheel, motion, other buttons, and modified reports are consumed without action. Native selection and scrollback remain unchanged outside the lease; while captured, use the terminal's selection bypass (usually Shift-drag, or Option-drag in iTerm2/Terminal.app). Unknown, stale, resized, or image-bearing frame placement disables click dispatch rather than guessing. Short frames use private cursor-position calibration; after external output the next render appends a fresh frame before recalibration, preserving diagnostics and scrollback. Keyboard paths remain available. This library foundation does not itself enable capture for every regular-mode component.
333
345
 
334
346
  ## Line Width
335
347
 
@@ -12,6 +12,34 @@
12
12
 
13
13
  ### Removed
14
14
 
15
+ ## [2026.9.13-2] - 2026-09-13
16
+
17
+ ### Breaking Changes
18
+
19
+ ### Added
20
+
21
+ - Added `PI_SESSION_CWD` and `PI_GOAL_STORE_FILE` session environment keys for kernels and shell children, including clearing of inherited values when absent (fixes #1663).
22
+
23
+ - Interactive foreground eval cells detach on queued steering without cancelling their computation or in-flight tools. An occupied detached slot keeps the call waiting ([#1637](https://github.com/code-yeongyu/senpi/issues/1637)).
24
+
25
+ ### Changed
26
+
27
+ ### Fixed
28
+
29
+ ### Removed
30
+
31
+ ## [2026.9.13] - 2026-09-13
32
+
33
+ ### Breaking Changes
34
+
35
+ ### Added
36
+
37
+ ### Changed
38
+
39
+ ### Fixed
40
+
41
+ ### Removed
42
+
15
43
  ## [2026.9.12-3] - 2026-09-12
16
44
 
17
45
  ### Breaking Changes
@@ -57,8 +57,9 @@ schema; it is not an installation failure.
57
57
  ### Session environment
58
58
 
59
59
  Every kernel starts with the active session's `PI_*` environment — `PI_SESSION_ID`,
60
- `PI_SESSION_FILE` (when the session is persistent), `PI_PROVIDER`, `PI_MODEL`, and
61
- `PI_REASONING_LEVEL` (when set) — resolved at session start, mirroring the bash tool's
60
+ `PI_SESSION_FILE` (when the session is persistent), `PI_SESSION_CWD` (the session's
61
+ working directory), `PI_GOAL_STORE_FILE` (the authoritative goal-store path, when the
62
+ host provides it), `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL` (when set) — resolved at session start, mirroring the bash tool's
62
63
  session environment contract. The values are visible to `env()`/`process.env`/`os.environ`
63
64
  inside cells and are inherited by every child process a cell spawns
64
65
  (`Bun.$`, `Bun.spawn`, `child_process`, `subprocess`, ...). Inherited `PI_*` values from
@@ -67,6 +68,11 @@ what a child spawned from the bash tool sees. The values snapshot at kernel star
67
68
  mid-session model switch updates the bash tool's next command but not already-running
68
69
  kernels; a new session starts fresh kernels with fresh values.
69
70
 
71
+ `PI_GOAL_STORE_FILE` is supplied by the host's optional `ExtensionContext.goalStoreFile`
72
+ getter and may name a file that does not exist yet. It honors session-directory overrides
73
+ and in-memory sessions; it cannot be derived reliably from `PI_SESSION_FILE`. If the host
74
+ omits the getter, the variable is unset rather than inherited from the launching process.
75
+
70
76
  ## Settings
71
77
 
72
78
  Configuration is loaded in this order:
@@ -177,6 +183,12 @@ cell keeps only its own language kernel busy. A new same-language call returns
177
183
  a busy error with its cell id and output tail; calls in other languages continue
178
184
  normally. Do not re-run the cell.
179
185
 
186
+ Queued steering also detaches an eligible interactive foreground call, including
187
+ one paused in a host tool bridge, without cancelling its computation. If the
188
+ language's detached slot is occupied, steering leaves the call waiting. Follow-up
189
+ messages, explicit `on_timeout: "error"`, and print/JSON calls do not trigger this
190
+ transition; caller abort and existing deadlines retain their cancellation behavior.
191
+
180
192
  Every cell, detached or not, is bounded by two kill deadlines. The run budget
181
193
  (`runBudgetSeconds`, or the call's `timeout`) charges only the cell's own
182
194
  execution time and is paused while a host tool call is in flight, so a cell
@@ -185,8 +197,8 @@ The hard limit (`hardLimitSeconds`, raised by a larger `timeout`) is wall-clock
185
197
  and bounds parked cells too. A cell killed by either deadline reports which one
186
198
  in its result or completion notification, together with whether kernel state
187
199
  survived; the tool schema states the configured numbers. The `timeout` value
188
- never changes when an interactive call detaches: that is `cellTimeoutSeconds`
189
- capped by `foregroundWindowSeconds`.
200
+ never changes the idle detach deadline: that is `cellTimeoutSeconds` capped by
201
+ `foregroundWindowSeconds`; queued steering can detach the call earlier.
190
202
 
191
203
  While any cell is detached, the interactive footer shows a highlighted
192
204
  `↗ <language> · <summary>` status on the extension status line (the cell id
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-codemode",
3
- "version": "2026.9.12-3",
3
+ "version": "2026.9.13-2",
4
4
  "private": true,
5
5
  "description": "Source-only senpi extension package for codemode evaluation tools",
6
6
  "type": "module",
@@ -31,14 +31,14 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@babel/parser": "8.0.4",
34
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.12-3",
34
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.13-2",
35
35
  "typebox": "1.3.27"
36
36
  },
37
37
  "peerDependencies": {
38
- "@code-yeongyu/senpi": "2026.9.12-3"
38
+ "@code-yeongyu/senpi": "2026.9.13-2"
39
39
  },
40
40
  "devDependencies": {
41
- "@code-yeongyu/senpi": "2026.9.12-3"
41
+ "@code-yeongyu/senpi": "2026.9.13-2"
42
42
  },
43
43
  "keywords": [
44
44
  "senpi",
@@ -9,6 +9,8 @@ const INTERRUPT_ACK_OP = "interrupt-ack";
9
9
  const SESSION_ENVIRONMENT_KEYS = [
10
10
  "PI_SESSION_ID",
11
11
  "PI_SESSION_FILE",
12
+ "PI_SESSION_CWD",
13
+ "PI_GOAL_STORE_FILE",
12
14
  "PI_PROVIDER",
13
15
  "PI_MODEL",
14
16
  "PI_REASONING_LEVEL",
@@ -12,6 +12,8 @@
12
12
  export const SESSION_ENVIRONMENT_KEYS = [
13
13
  "PI_SESSION_ID",
14
14
  "PI_SESSION_FILE",
15
+ "PI_SESSION_CWD",
16
+ "PI_GOAL_STORE_FILE",
15
17
  "PI_PROVIDER",
16
18
  "PI_MODEL",
17
19
  "PI_REASONING_LEVEL",
@@ -22,6 +24,8 @@ export type SessionEnvironment = Readonly<Record<string, string>>;
22
24
 
23
25
  /** Structural slice of `ExtensionContext` the session environment is resolved from. */
24
26
  export interface SessionEnvironmentSource {
27
+ readonly cwd: string;
28
+ readonly goalStoreFile?: string;
25
29
  readonly sessionManager: {
26
30
  getSessionId(): string;
27
31
  getSessionFile(): string | undefined;
@@ -33,6 +37,8 @@ export interface SessionEnvironmentSource {
33
37
  export function sessionEnvironmentFrom(source: SessionEnvironmentSource): SessionEnvironment {
34
38
  const env: Record<string, string> = {};
35
39
  env.PI_SESSION_ID = source.sessionManager.getSessionId();
40
+ env.PI_SESSION_CWD = source.cwd;
41
+ if (source.goalStoreFile) env.PI_GOAL_STORE_FILE = source.goalStoreFile;
36
42
  const sessionFile = source.sessionManager.getSessionFile();
37
43
  if (sessionFile) env.PI_SESSION_FILE = sessionFile;
38
44
  const model = source.model;
@@ -144,7 +144,12 @@ export class EvalDetachedCellManager {
144
144
  }
145
145
 
146
146
  detach(cell: ManagedCell): boolean {
147
- if (!cell.canDetach || !allowsDetachedCellTransition(cell.state, "detached")) return false;
147
+ if (
148
+ !cell.canDetach ||
149
+ !allowsDetachedCellTransition(cell.state, "detached") ||
150
+ this.#detachedByLanguage.has(cell.input.language)
151
+ )
152
+ return false;
148
153
  cell.state = "detached";
149
154
  cell.wasDetached = true;
150
155
  this.#detachedByLanguage.set(cell.input.language, cell);
@@ -49,6 +49,12 @@ export async function runEvalCell(
49
49
  let detached = false;
50
50
  let execution: CellExecution;
51
51
  const cell = cellManager.create(invocation.cellId, invocation.input, (error) => execution.cancel(error));
52
+ const detach = (): boolean => {
53
+ if (!cellManager.detach(cell)) return false;
54
+ detached = true;
55
+ execution.detach();
56
+ return true;
57
+ };
52
58
  execution = new CellExecution({
53
59
  callerSignal: invocation.signal,
54
60
  cellId: invocation.cellId,
@@ -58,12 +64,7 @@ export async function runEvalCell(
58
64
  timeoutMs: detachAfterMs,
59
65
  maxPauseGraceMs: foregroundWindowMs,
60
66
  onTimeout: (error: Error) => {
61
- if (cellManager.detach(cell)) {
62
- detached = true;
63
- execution.detach();
64
- return;
65
- }
66
- execution.cancel(error);
67
+ if (!detach()) execution.cancel(error);
67
68
  },
68
69
  },
69
70
  }
@@ -74,6 +75,16 @@ export async function runEvalCell(
74
75
  bridgeAbortController.abort(error);
75
76
  },
76
77
  });
78
+ const steeringSignal =
79
+ detaches && invocation.ctx.mode !== "print" && invocation.ctx.mode !== "json"
80
+ ? invocation.ctx.steeringSignal
81
+ : undefined;
82
+ const onSteering = (): void => {
83
+ if (!steeringSignal?.aborted || detached || !state.active || invocation.signal.aborted) return;
84
+ // Losing the slot keeps this call foreground; only the existing deadlines/caller may cancel it.
85
+ detach();
86
+ };
87
+ steeringSignal?.addEventListener("abort", onSteering, { once: true });
77
88
  const running = executeCell(
78
89
  options,
79
90
  invocation,
@@ -83,6 +94,7 @@ export async function runEvalCell(
83
94
  execution,
84
95
  bridgeContext,
85
96
  bridgeAbortController,
97
+ onSteering,
86
98
  );
87
99
  let settleEventEmitted = false;
88
100
  const emitSettled = (outcome: EvalExecutionSettleOutcome): void => {
@@ -110,12 +122,16 @@ export async function runEvalCell(
110
122
  throw error;
111
123
  },
112
124
  );
113
- const outcome = await Promise.race([
114
- finalized.then((result) => ({ kind: "result" as const, result })),
115
- execution.detached.then(() => ({ kind: "detached" as const })),
116
- ]);
117
- if (outcome.kind === "detached") return resultAfterDetach(cellManager.peek(invocation.cellId), invocation.input);
118
- return outcome.result;
125
+ try {
126
+ const outcome = await Promise.race([
127
+ finalized.then((result) => ({ kind: "result" as const, result })),
128
+ execution.detached.then(() => ({ kind: "detached" as const })),
129
+ ]);
130
+ if (outcome.kind === "detached") return resultAfterDetach(cellManager.peek(invocation.cellId), invocation.input);
131
+ return outcome.result;
132
+ } finally {
133
+ steeringSignal?.removeEventListener("abort", onSteering);
134
+ }
119
135
  }
120
136
 
121
137
  async function executeCell(
@@ -127,6 +143,7 @@ async function executeCell(
127
143
  execution: CellExecution,
128
144
  bridgeContext: ExtensionContext,
129
145
  bridgeAbortController: AbortController,
146
+ onReady: () => void,
130
147
  ): Promise<AgentToolResult<EvalToolDetails>> {
131
148
  let handler: CellHandler | undefined;
132
149
  try {
@@ -168,6 +185,8 @@ async function executeCell(
168
185
  () => activeHandler.liveResult(),
169
186
  (error) => execution.cancel(error),
170
187
  );
188
+ // Includes a steer already queued at execute start or received while acquiring the kernel.
189
+ onReady();
171
190
  if ("setContext" in options.kernelManager && typeof options.kernelManager.setContext === "function") {
172
191
  options.kernelManager.setContext(bridgeContext);
173
192
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/chord",
3
- "version": "2026.9.12-3",
3
+ "version": "0.85.1",
4
4
  "description": "Application composition runtime for services, replicated state, RPC, and plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",