@code-yeongyu/senpi 2026.11.2-3 → 2026.11.3-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 (307) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/bundle/chunks/anthropic-messages-LJAKRKMX.js +11 -0
  3. package/dist/bundle/chunks/{args-AOI4NEA6.js → args-GQTXDYS3.js} +1 -1
  4. package/dist/bundle/chunks/{azure-openai-responses-YLBBQXI7.js → azure-openai-responses-HDEKTPMZ.js} +1 -1
  5. package/dist/bundle/chunks/chatgpt-subscription.js +10 -2
  6. package/dist/bundle/chunks/{chunk-ED7VJGL4.js → chunk-2PGSRQBF.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-LMIETUPG.js → chunk-3LDASCJN.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-PIAY636U.js → chunk-3QPE75AR.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-FQZZGSYH.js → chunk-4ZGQUOBV.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-S2M5D5GS.js → chunk-5BMIET5O.js} +2 -2
  11. package/dist/bundle/chunks/{chunk-XLLQJALL.js → chunk-67M7HKXO.js} +1 -1
  12. package/dist/bundle/chunks/chunk-6ISOXWH2.js +2 -0
  13. package/dist/bundle/chunks/{chunk-IWM5QRAE.js → chunk-6NPK2O3C.js} +2 -2
  14. package/dist/bundle/chunks/{chunk-FO56LSUK.js → chunk-7C4W5HMU.js} +1 -1
  15. package/dist/bundle/chunks/chunk-7KIHKE2T.js +2 -0
  16. package/dist/bundle/chunks/{chunk-BW4YXS7X.js → chunk-A4KOQUHT.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-FJSJUVQQ.js → chunk-A5PZGQCP.js} +3 -3
  18. package/dist/bundle/chunks/{chunk-TBARMJ75.js → chunk-AVP6DDBF.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-KVPRQ5KN.js → chunk-B3GTID4P.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-2XBKE2BZ.js → chunk-BIWFWGUA.js} +1 -1
  21. package/dist/bundle/chunks/{chunk-6LDUM5CL.js → chunk-DCI4QOUX.js} +1 -1
  22. package/dist/bundle/chunks/{chunk-2YFPDNNP.js → chunk-DNZKKG4V.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-W2V7RIBF.js → chunk-E7SA75PP.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-YWD54RHU.js → chunk-EBZ6IP4V.js} +1 -1
  25. package/dist/bundle/chunks/{chunk-N4TSAHRL.js → chunk-EVTTLPIY.js} +1 -1
  26. package/dist/bundle/chunks/{chunk-J2OBN7TI.js → chunk-G5XUGK4B.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-IHOQR7TU.js → chunk-GKP34H3C.js} +2 -2
  28. package/dist/bundle/chunks/{chunk-PP52OWBB.js → chunk-GLTOBXZY.js} +1 -1
  29. package/dist/bundle/chunks/{chunk-ZSVWKOAJ.js → chunk-IJGXAACA.js} +263 -237
  30. package/dist/bundle/chunks/{chunk-LGO25HPL.js → chunk-JCTODLUP.js} +1 -1
  31. package/dist/bundle/chunks/{chunk-3ESZE3DG.js → chunk-KHBCZ6TR.js} +1 -1
  32. package/dist/bundle/chunks/chunk-KJR3XXMI.js +2 -0
  33. package/dist/bundle/chunks/{chunk-TVMW2SUP.js → chunk-KY4V3TSO.js} +2 -2
  34. package/dist/bundle/chunks/{chunk-T5ZJ2Q4O.js → chunk-MCXOJHN2.js} +1 -1
  35. package/dist/bundle/chunks/{chunk-GIY7PGOH.js → chunk-NKI7L5UM.js} +3 -3
  36. package/dist/bundle/chunks/{chunk-L3V65XW7.js → chunk-OD7RT7G7.js} +1 -1
  37. package/dist/bundle/chunks/{chunk-NYXXKS6D.js → chunk-OOU3BRUY.js} +3 -2
  38. package/dist/bundle/chunks/{chunk-LPHUMR6R.js → chunk-OT6ALXSJ.js} +1 -1
  39. package/dist/bundle/chunks/{chunk-XGBRBCIQ.js → chunk-Q5CKFBQT.js} +1 -1
  40. package/dist/bundle/chunks/{chunk-F7GBSQRV.js → chunk-QPYDQ4QK.js} +1 -1
  41. package/dist/bundle/chunks/{chunk-7FUO655J.js → chunk-QSMT5KVJ.js} +1 -1
  42. package/dist/bundle/chunks/{chunk-SAZ6E74O.js → chunk-RUOTFZQR.js} +1 -1
  43. package/dist/bundle/chunks/chunk-RWF6IJQL.js +448 -0
  44. package/dist/bundle/chunks/{chunk-P4AT7SBE.js → chunk-S5Y7NEHB.js} +1 -1
  45. package/dist/bundle/chunks/{chunk-QLTQ3UUI.js → chunk-SCBTASM4.js} +1 -1
  46. package/dist/bundle/chunks/chunk-SJWTZ3Z2.js +2 -0
  47. package/dist/bundle/chunks/{chunk-ISZ4EWIS.js → chunk-SODMQEHO.js} +1 -1
  48. package/dist/bundle/chunks/{chunk-WEGTCUO3.js → chunk-SQAQEITV.js} +1 -1
  49. package/dist/bundle/chunks/{chunk-UFVZTQKN.js → chunk-TQQG5L4D.js} +1 -1
  50. package/dist/bundle/chunks/{chunk-662SCMTH.js → chunk-U6A4X3FV.js} +1 -1
  51. package/dist/bundle/chunks/{chunk-ACIFXWJ6.js → chunk-UHUM55TR.js} +1 -1
  52. package/dist/bundle/chunks/{chunk-L5OFGHDA.js → chunk-USKWGPA6.js} +1 -1
  53. package/dist/bundle/chunks/{chunk-7ORS33CE.js → chunk-VDDJADPV.js} +1 -1
  54. package/dist/bundle/chunks/{chunk-R65P6LAT.js → chunk-VIHXG53S.js} +1 -1
  55. package/dist/bundle/chunks/{chunk-SGS76663.js → chunk-VPVD5G32.js} +1 -1
  56. package/dist/bundle/chunks/chunk-WO6I5PRF.js +3 -0
  57. package/dist/bundle/chunks/{chunk-ETCYVVVO.js → chunk-WVEIJ437.js} +1 -1
  58. package/dist/bundle/chunks/{chunk-VRWJJMHO.js → chunk-XKFG4N3Z.js} +1 -1
  59. package/dist/bundle/chunks/{chunk-57MRFI6E.js → chunk-XMWPCJU6.js} +1 -1
  60. package/dist/bundle/chunks/{chunk-GDPWQJDQ.js → chunk-XPSXUKSD.js} +1 -1
  61. package/dist/bundle/chunks/{chunk-FNBEICAA.js → chunk-YI6KRJDC.js} +1 -1
  62. package/dist/bundle/chunks/{chunk-UURGXV5B.js → chunk-YP47G4YP.js} +1 -1
  63. package/dist/bundle/chunks/{chunk-TXOR5BQL.js → chunk-YRYDCKUI.js} +1 -1
  64. package/dist/bundle/chunks/{chunk-QAM6AXA2.js → chunk-YTKZSGMQ.js} +12 -9
  65. package/dist/bundle/chunks/{chunk-V36CXIIB.js → chunk-YXL3PNTL.js} +1 -1
  66. package/dist/bundle/chunks/chunk-Z7HTHT6K.js +2 -0
  67. package/dist/bundle/chunks/{chunk-27XEDYQA.js → chunk-ZTPG27EJ.js} +1 -1
  68. package/dist/bundle/chunks/{cli-main-534A3WSC.js → cli-main-RN7YB427.js} +1 -1
  69. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-FC7QLRU2.js → cloudflare-workers-ai-system-one-N5KFNKK4.js} +1 -1
  70. package/dist/bundle/chunks/credential-accounts-BJX55MTT.js +2 -0
  71. package/dist/bundle/chunks/devin.js +10 -2
  72. package/dist/bundle/chunks/{dispatch-UY6LBJJE.js → dispatch-M7UAPGVY.js} +1 -1
  73. package/dist/bundle/chunks/{google-generative-ai-7PQ4QRHJ.js → google-generative-ai-2TZSCSIS.js} +1 -1
  74. package/dist/bundle/chunks/{google-vertex-DY7EO4EJ.js → google-vertex-7NJJOI7V.js} +1 -1
  75. package/dist/bundle/chunks/{health-write-EB4CPHXN.js → health-write-YUSPVH7U.js} +1 -1
  76. package/dist/bundle/chunks/{help-fast-path-U2PSNNWO.js → help-fast-path-DWCA77QP.js} +1 -1
  77. package/dist/bundle/chunks/host-command-KJXUTSQ7.js +2 -0
  78. package/dist/bundle/chunks/{host-lifecycle-TGG7KGQH.js → host-lifecycle-QHIJ4G2K.js} +1 -1
  79. package/dist/bundle/chunks/host-lifecycle.js +1 -1
  80. package/dist/bundle/chunks/{host-session-command-PWVPQ2OV.js → host-session-command-IPH3WXSG.js} +1 -1
  81. package/dist/bundle/chunks/{host-socket-request-F2R5P34M.js → host-socket-request-XPXJV3CS.js} +1 -1
  82. package/dist/bundle/chunks/interactive-mode-XUXMDYLA.js +2 -0
  83. package/dist/bundle/chunks/{list-tips-3D3A6GFK.js → list-tips-XJY7EL5S.js} +1 -1
  84. package/dist/bundle/chunks/{login-health-7G2DZVOV.js → login-health-226NO44U.js} +1 -1
  85. package/dist/bundle/chunks/main-P7PKMJUG.js +2 -0
  86. package/dist/bundle/chunks/{mistral-conversations-6F2RAIB2.js → mistral-conversations-QMHMHSUF.js} +1 -1
  87. package/dist/bundle/chunks/{multi-session-host-7E26R5JF.js → multi-session-host-ZQY4AN46.js} +4 -4
  88. package/dist/bundle/chunks/{native-loader-NMDTMHMA.js → native-loader-A6DNMGCK.js} +1 -1
  89. package/dist/bundle/chunks/openai-chatgpt.js +11 -3
  90. package/dist/bundle/chunks/{openai-codex-responses-VNBMMIL3.js → openai-codex-responses-GUAHKQE2.js} +1 -1
  91. package/dist/bundle/chunks/{openai-completions-JLR32APM.js → openai-completions-UPRTFM54.js} +1 -1
  92. package/dist/bundle/chunks/{openai-images-LEBNERSM.js → openai-images-IKWNS6VB.js} +1 -1
  93. package/dist/bundle/chunks/{openai-responses-JCDUNMHA.js → openai-responses-AXN5NUHH.js} +1 -1
  94. package/dist/bundle/chunks/openrouter.js +10 -2
  95. package/dist/bundle/chunks/{package-manager-cli-CBSDV36M.js → package-manager-cli-PP7L2Q5M.js} +1 -1
  96. package/dist/bundle/chunks/radius.js +10 -2
  97. package/dist/bundle/chunks/{rg-engine-JDUYBM6L.js → rg-engine-VRSXT6HG.js} +1 -1
  98. package/dist/bundle/chunks/{role-LP6LVNCY.js → role-L5J7ZPCF.js} +1 -1
  99. package/dist/bundle/chunks/rotation-stream-6INZXQFC.js +2 -0
  100. package/dist/bundle/chunks/rpc-mode-W4UATRAT.js +2 -0
  101. package/dist/bundle/chunks/{rpc-monitor-source-5TUR27NY.js → rpc-monitor-source-RMMUPBMS.js} +1 -1
  102. package/dist/bundle/chunks/{run-attached-tui-PVLUHHJX.js → run-attached-tui-RLXFGCEP.js} +1 -1
  103. package/dist/bundle/chunks/{schedule-command-W45NYTTK.js → schedule-command-ZNFEJNTT.js} +1 -1
  104. package/dist/bundle/chunks/{session-control-endpoint-LFLUNALC.js → session-control-endpoint-TWTONJWF.js} +1 -1
  105. package/dist/bundle/chunks/{session-picker-OZUINLD7.js → session-picker-KRUVCHOV.js} +1 -1
  106. package/dist/bundle/chunks/session-slot-NJOZCOHQ.js +2 -0
  107. package/dist/bundle/chunks/session-worker.js +492 -461
  108. package/dist/bundle/chunks/{state-store-SZARKD36.js → state-store-ZAFZ4JOM.js} +1 -1
  109. package/dist/bundle/chunks/{typesafe-system-one-5JYDJK6S.js → typesafe-system-one-CICIRAYN.js} +1 -1
  110. package/dist/bundle/cli.js +2 -2
  111. package/dist/bundle/host-supervisor.js +1 -1
  112. package/dist/bundle/index.js +1 -1
  113. package/dist/bundle/rpc-entry.js +1 -1
  114. package/dist/bundle/runtime-manifest.json +1 -1
  115. package/dist/core/agent-session.d.ts +8 -0
  116. package/dist/core/agent-session.js +73 -63
  117. package/dist/core/auth-storage.d.ts +19 -0
  118. package/dist/core/auth-storage.js +99 -24
  119. package/dist/core/auth-store-load-error.d.ts +29 -0
  120. package/dist/core/auth-store-load-error.js +74 -0
  121. package/dist/core/brand.d.ts +2 -0
  122. package/dist/core/brand.js +1 -0
  123. package/dist/core/credential-pool/classify.d.ts +3 -2
  124. package/dist/core/credential-pool/classify.js +10 -3
  125. package/dist/core/credential-pool/failover.d.ts +8 -0
  126. package/dist/core/credential-pool/failover.js +18 -5
  127. package/dist/core/credential-pool/rotation-stream.d.ts +1 -1
  128. package/dist/core/credential-pool/rotation-stream.js +2 -7
  129. package/dist/core/credential-pool/session-slot.d.ts +20 -0
  130. package/dist/core/credential-pool/session-slot.js +26 -0
  131. package/dist/core/credential-recovery-revision.d.ts +10 -0
  132. package/dist/core/credential-recovery-revision.js +19 -0
  133. package/dist/core/dynamic-prompt/build.d.ts +2 -1
  134. package/dist/core/dynamic-prompt/build.js +1 -2
  135. package/dist/core/dynamic-prompt/handoff.d.ts +1 -1
  136. package/dist/core/dynamic-prompt/handoff.js +9 -9
  137. package/dist/core/dynamic-prompt/identity.js +1 -1
  138. package/dist/core/dynamic-prompt/intent-gate.d.ts +1 -1
  139. package/dist/core/dynamic-prompt/intent-gate.js +8 -8
  140. package/dist/core/dynamic-prompt/policies.d.ts +1 -1
  141. package/dist/core/dynamic-prompt/policies.js +5 -7
  142. package/dist/core/dynamic-prompt/style.js +5 -5
  143. package/dist/core/dynamic-prompt/tool-section.d.ts +5 -0
  144. package/dist/core/dynamic-prompt/tool-section.js +8 -6
  145. package/dist/core/dynamic-prompt/verification.d.ts +6 -6
  146. package/dist/core/dynamic-prompt/verification.js +12 -12
  147. package/dist/core/dynamic-prompt/working-task.d.ts +1 -1
  148. package/dist/core/dynamic-prompt/working-task.js +3 -3
  149. package/dist/core/dynamic-prompt/workstation.js +1 -1
  150. package/dist/core/execution/executor-body.d.ts +22 -0
  151. package/dist/core/execution/executor-body.js +73 -0
  152. package/dist/core/execution/executor-freeze.d.ts +17 -0
  153. package/dist/core/execution/executor-freeze.js +53 -0
  154. package/dist/core/execution/executor-pipeline.d.ts +9 -0
  155. package/dist/core/execution/executor-pipeline.js +25 -0
  156. package/dist/core/execution/executor-types.d.ts +82 -0
  157. package/dist/core/execution/executor-types.js +2 -0
  158. package/dist/core/execution/executor.d.ts +8 -0
  159. package/dist/core/execution/executor.js +216 -0
  160. package/dist/core/extensions/builtin/anthropic-subscription/account-block-log.d.ts +15 -0
  161. package/dist/core/extensions/builtin/anthropic-subscription/account-block-log.js +18 -0
  162. package/dist/core/extensions/builtin/anthropic-subscription/affinity.d.ts +9 -1
  163. package/dist/core/extensions/builtin/anthropic-subscription/affinity.js +15 -4
  164. package/dist/core/extensions/builtin/anthropic-subscription/failover.d.ts +7 -1
  165. package/dist/core/extensions/builtin/anthropic-subscription/failover.js +19 -2
  166. package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts +8 -2
  167. package/dist/core/extensions/builtin/anthropic-subscription/guidance.js +25 -1
  168. package/dist/core/extensions/builtin/anthropic-subscription/provider-diagnostic.d.ts +9 -0
  169. package/dist/core/extensions/builtin/anthropic-subscription/provider-diagnostic.js +59 -0
  170. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-pump.d.ts +13 -0
  171. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-pump.js +64 -2
  172. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-wiring.js +7 -0
  173. package/dist/core/extensions/builtin/anthropic-subscription/session-stream.js +5 -1
  174. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-attempt.d.ts +7 -0
  175. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-attempt.js +28 -1
  176. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-types.d.ts +2 -0
  177. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +5 -3
  178. package/dist/core/extensions/builtin/anthropic-subscription/stream.js +4 -0
  179. package/dist/core/extensions/builtin/bash-timeout/index.d.ts +1 -1
  180. package/dist/core/extensions/builtin/bash-timeout/index.js +3 -28
  181. package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts +0 -11
  182. package/dist/core/extensions/builtin/bash-timeout/timeout.js +0 -11
  183. package/dist/core/extensions/builtin/btw/index.js +3 -1
  184. package/dist/core/extensions/builtin/cache-keepalive/index.js +3 -1
  185. package/dist/core/extensions/builtin/compaction/index.js +1 -1
  186. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -1
  187. package/dist/core/extensions/builtin/compaction/openai-remote.js +1 -1
  188. package/dist/core/extensions/builtin/compaction/speculative.js +3 -2
  189. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +3 -1
  190. package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.js +3 -1
  191. package/dist/core/extensions/builtin/imagegen/index.d.ts +0 -1
  192. package/dist/core/extensions/builtin/imagegen/index.js +0 -11
  193. package/dist/core/extensions/builtin/look-at/runner.js +3 -1
  194. package/dist/core/extensions/builtin/mcp/auth/callback.js +3 -4
  195. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +2 -1
  196. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +5 -5
  197. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +5 -5
  198. package/dist/core/extensions/builtin/prompt-preset/glm-5.d.ts +1 -1
  199. package/dist/core/extensions/builtin/prompt-preset/glm-5.js +1 -1
  200. package/dist/core/extensions/builtin/terminal/extension.js +8 -1
  201. package/dist/core/extensions/builtin/terminal/notify.js +9 -3
  202. package/dist/core/extensions/builtin/terminal/prompt.d.ts +7 -1
  203. package/dist/core/extensions/builtin/terminal/prompt.js +27 -60
  204. package/dist/core/extensions/builtin/terminal/tools/bash.js +10 -2
  205. package/dist/core/extensions/builtin/todotools/normalize.d.ts +20 -3
  206. package/dist/core/extensions/builtin/todotools/normalize.js +251 -5
  207. package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -2
  208. package/dist/core/extensions/builtin/todotools/prompt.js +5 -5
  209. package/dist/core/extensions/builtin/todotools/tools/todo.js +9 -8
  210. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +0 -5
  211. package/dist/core/extensions/builtin/websearch/index.js +9 -4
  212. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts +2 -0
  213. package/dist/core/extensions/builtin/websearch/websearch/tool.js +3 -1
  214. package/dist/core/model-registry.d.ts +10 -2
  215. package/dist/core/model-registry.js +12 -4
  216. package/dist/core/model-runtime.d.ts +8 -0
  217. package/dist/core/model-runtime.js +39 -1
  218. package/dist/core/provider-failure.d.ts +6 -0
  219. package/dist/core/provider-failure.js +6 -2
  220. package/dist/core/retry-fallback/controller-types.d.ts +7 -0
  221. package/dist/core/retry-fallback/controller.d.ts +2 -0
  222. package/dist/core/retry-fallback/controller.js +13 -4
  223. package/dist/core/retry-fallback/credential-recovery.d.ts +18 -0
  224. package/dist/core/retry-fallback/credential-recovery.js +32 -0
  225. package/dist/core/retry-fallback/exhaustion.d.ts +18 -0
  226. package/dist/core/retry-fallback/exhaustion.js +20 -0
  227. package/dist/core/retry-fallback/settings.d.ts +8 -1
  228. package/dist/core/retry-fallback/settings.js +12 -6
  229. package/dist/core/session-log.js +1 -1
  230. package/dist/core/settings-manager.js +4 -1
  231. package/dist/core/system-prompt.js +1 -1
  232. package/dist/core/tools/bash.d.ts +3 -1
  233. package/dist/core/tools/bash.js +14 -4
  234. package/dist/core/tools/edit.d.ts +1 -1
  235. package/dist/core/tools/edit.js +1 -6
  236. package/dist/core/tools/grep/index.js +2 -3
  237. package/dist/core/tools/powershell.d.ts +1 -1
  238. package/dist/core/tools/powershell.js +1 -1
  239. package/dist/core/tools/read.d.ts +1 -1
  240. package/dist/core/tools/read.js +1 -1
  241. package/dist/core/tools/write.d.ts +1 -1
  242. package/dist/core/tools/write.js +1 -1
  243. package/dist/engine-trust/shell-trust.d.ts +36 -0
  244. package/dist/engine-trust/shell-trust.js +44 -0
  245. package/dist/engine-trust/transport-failure.d.ts +12 -0
  246. package/dist/engine-trust/transport-failure.js +48 -0
  247. package/dist/modes/interactive/interactive-mode.js +9 -3
  248. package/dist/modes/print-mode.js +2 -1
  249. package/dist/modes/rpc/compact-catalog-families.d.ts +5 -2
  250. package/dist/modes/rpc/compact-catalog-families.js +5 -2
  251. package/dist/modes/rpc/compact-catalog-registry.d.ts +9 -1
  252. package/dist/modes/rpc/compact-catalog-registry.js +9 -2
  253. package/dist/modes/rpc/compact-recovery-manifest-kinds.d.ts +17 -0
  254. package/dist/modes/rpc/compact-recovery-manifest-kinds.js +21 -0
  255. package/dist/modes/rpc/compact-recovery-manifest-shape.d.ts +7 -0
  256. package/dist/modes/rpc/compact-recovery-manifest.js +11 -3
  257. package/dist/modes/rpc/compact-socket-commands.js +6 -0
  258. package/dist/modes/rpc/connection-handler.js +24 -6
  259. package/dist/modes/rpc/connection-question-bridge.d.ts +3 -1
  260. package/dist/modes/rpc/connection-question-bridge.js +4 -1
  261. package/dist/modes/rpc/connection-roles.d.ts +8 -0
  262. package/dist/modes/rpc/connection-roles.js +18 -0
  263. package/dist/modes/rpc/effect-commands.d.ts +1 -0
  264. package/dist/modes/rpc/loopless-execute-grant.d.ts +20 -0
  265. package/dist/modes/rpc/loopless-execute-grant.js +26 -0
  266. package/dist/modes/rpc/loopless-runtime-settings.d.ts +30 -0
  267. package/dist/modes/rpc/loopless-runtime-settings.js +69 -0
  268. package/dist/modes/rpc/loopless-tool-call.d.ts +12 -0
  269. package/dist/modes/rpc/loopless-tool-call.js +22 -0
  270. package/dist/modes/rpc/method-classes-schema-session.d.ts +4 -0
  271. package/dist/modes/rpc/method-classes-schema-session.js +1 -0
  272. package/dist/modes/rpc/method-classes-schema.d.ts +4 -0
  273. package/dist/modes/rpc/protocol-identity.js +2 -0
  274. package/dist/modes/rpc/remote-origin.d.ts +31 -0
  275. package/dist/modes/rpc/remote-origin.js +58 -0
  276. package/dist/modes/rpc/rpc-protocol-info-types.d.ts +8 -0
  277. package/dist/modes/rpc/rpc-question-types.d.ts +7 -0
  278. package/dist/modes/rpc/rpc-question-types.js +0 -3
  279. package/dist/modes/rpc/rpc-read-response-types.d.ts +2 -1
  280. package/dist/modes/rpc/rpc-session-command-types.d.ts +3 -0
  281. package/dist/modes/rpc/rpc-session-state-types.d.ts +10 -0
  282. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  283. package/dist/modes/rpc/runtime-factory-loopless.d.ts +57 -0
  284. package/dist/modes/rpc/runtime-factory-loopless.js +131 -0
  285. package/dist/modes/rpc/session-registry.js +12 -3
  286. package/dist/modes/rpc/session-worker-client.js +2 -0
  287. package/dist/modes/rpc/session-worker-protocol.d.ts +3 -0
  288. package/dist/modes/rpc/session-worker.js +2 -0
  289. package/docs/development.md +1 -1
  290. package/docs/engine-socket/fixtures/admission-routes/c-baseline.json +3 -3
  291. package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
  292. package/docs/engine-socket/fixtures/admission-routes/i-reset-stream.json +3 -3
  293. package/docs/engine-socket/fixtures/recovery-manifest/index.json +32 -0
  294. package/docs/engine-socket/fixtures/recovery-manifest/one-partial-family.json +118 -0
  295. package/docs/rpc.md +95 -3
  296. package/package.json +6 -6
  297. package/dist/bundle/chunks/anthropic-messages-WUPLDYD6.js +0 -10
  298. package/dist/bundle/chunks/chunk-7UC4W2T2.js +0 -2
  299. package/dist/bundle/chunks/chunk-O4GRBX4R.js +0 -3
  300. package/dist/bundle/chunks/chunk-R23WXN4L.js +0 -448
  301. package/dist/bundle/chunks/chunk-W5NLCRB3.js +0 -2
  302. package/dist/bundle/chunks/credential-accounts-OAK2E5O2.js +0 -2
  303. package/dist/bundle/chunks/host-command-WJIMRBGN.js +0 -2
  304. package/dist/bundle/chunks/interactive-mode-NPHFDPGH.js +0 -2
  305. package/dist/bundle/chunks/main-I6FJAFUP.js +0 -2
  306. package/dist/bundle/chunks/rotation-stream-ZDCNHIBE.js +0 -2
  307. package/dist/bundle/chunks/rpc-mode-GBBTN2WP.js +0 -2
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
2
- import{Text,truncateToWidth,visibleWidth}from"./chunk-D2ROBVZ4.js";import{getShellConfig}from"./chunk-T5ZJ2Q4O.js";import{redactSecrets}from"./chunk-LNAZ7XEU.js";import{HOST_CALL_KINDS,TOOL_CHILD_LIMITS,connectChannel,isRefId,isStaleExtensionContextError}from"./chunk-UKSFF47T.js";import{typebox_exports}from"./chunk-MIENF2YK.js";import{TOOL_CHILD_LEDGER_ENV,TOOL_CHILD_REENTRY_ENV,TOOL_CHILD_REFS_ROOT_ENV,rememberToolChildReentry,scrubToolChildEnv,toolChildReentry}from"./chunk-OXNWERO4.js";import{BACKGROUND_START_GRACE_MS,DEFAULT_COLS,DEFAULT_MAX_SESSIONS,DEFAULT_ROWS,FOREGROUND_ENV_OVERRIDES,KILLED_SESSION_EXIT_GRACE_MS,SecretOutputRedactor,TERMINAL_BASH_TOOL,TERMINAL_INPUT_TOOL,TERMINAL_KILL_TOOL,TERMINAL_OUTPUT_TOOL,TERMINAL_RESIZE_TOOL,encodeKeys,loadPty,safeRegExp}from"./chunk-AOTHPTMU.js";import{processIsRunning,processStartTimeMs,readProcessStartTime,sameProcessStartMs}from"./chunk-O5RYI3IW.js";var ToolChildJobError=class extends Error{constructor(code,message){super(message),this.code=code,this.name="ToolChildJobError"}};var WakeAdmissionError=class extends Error{constructor(bytes){super(`wake_too_large: ${bytes} bytes exceeds the ${TOOL_CHILD_LIMITS.wakePendingBytes}-byte pending budget`),this.code="wake_too_large",this.name="WakeAdmissionError"}},WakeAdmission=class{#pending=new Map;#blocked=[];#pendingBytes=0;get pending(){return this.#pending.size}get blocked(){return this.#blocked.length}send(wakeId,bytes){return bytes>TOOL_CHILD_LIMITS.wakePendingBytes?Promise.reject(new WakeAdmissionError(bytes)):this.#blocked.length===0&&this.#fits(bytes)?(this.#admit(wakeId,bytes),Promise.resolve()):new Promise(release=>{this.#blocked.push({wakeId,bytes,release})})}ack(wakeId){let bytes=this.#pending.get(wakeId);if(bytes!==void 0){this.#pending.delete(wakeId),this.#pendingBytes-=bytes;for(let next=this.#blocked[0];next!==void 0&&this.#fits(next.bytes);next=this.#blocked[0])this.#blocked.shift(),this.#admit(next.wakeId,next.bytes),next.release()}}#fits(bytes){return this.#pending.size<TOOL_CHILD_LIMITS.wakePending&&this.#pendingBytes+bytes<=TOOL_CHILD_LIMITS.wakePendingBytes}#admit(wakeId,bytes){this.#pending.set(wakeId,bytes),this.#pendingBytes+=bytes}};function hostCallCapacity(){return TOOL_CHILD_LIMITS.HOST_CALL_ACTIVE+TOOL_CHILD_LIMITS.HOST_CALL_WAITING}var HostCallAdmission=class{#active=new Set;#waiting=[];get active(){return this.#active.size}get waiting(){return this.#waiting.length}submit(callId){return this.#active.has(callId)||this.#waiting.includes(callId)?refuse(callId,"host_call_duplicate"):this.#active.size<TOOL_CHILD_LIMITS.HOST_CALL_ACTIVE&&this.#waiting.length===0?(this.#active.add(callId),{state:"active"}):this.#active.size+this.#waiting.length>=hostCallCapacity()?refuse(callId,"host_call_capacity"):(this.#waiting.push(callId),{state:"waiting"})}settle(callId){if(!this.#active.delete(callId)){let index=this.#waiting.indexOf(callId);index>=0&&this.#waiting.splice(index,1);return}let next=this.#waiting.shift();return next!==void 0&&this.#active.add(next),next}};function refuse(callId,code){return{state:"refused",frame:{type:"host_call_refused",callId,code}}}import{createHash,randomBytes}from"node:crypto";import{createReadStream}from"node:fs";import{mkdir,readFile,rm as rm2,stat,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{readdir,rm}from"node:fs/promises";import{join}from"node:path";function refGenerationDir(root,generation){return join(root,`gen-${generation}`)}function refFilePath(root,ref){if(!isRefId(ref.refId))throw new Error(`invalid ref id: ${JSON.stringify(ref.refId)}`);return join(refGenerationDir(root,ref.generation),"refs",ref.refId)}async function teardownRefGeneration(root,generation){await rm(refGenerationDir(root,generation),{recursive:!0,force:!0})}var PayloadRefError=class extends Error{constructor(code,message,reason){super(`${code}: ${message}`),this.name="PayloadRefError",this.code=code,this.reason=reason}},PayloadRefWriter=class{#root;#now;#pending=new Map;#ownedBytes=0;constructor(options){this.generation=options.generation,this.budget=options.budget??TOOL_CHILD_LIMITS.refsBudget,this.#root=options.root,this.#now=options.now??Date.now}get ownedBytes(){return this.#ownedBytes}async create(payload){let size=payload.byteLength;if(this.#ownedBytes+size>this.budget)throw new PayloadRefError("ref_budget_exceeded",`${size} bytes on top of ${this.#ownedBytes} owned exceeds ${this.budget}`);this.#ownedBytes+=size;let ref={refId:randomBytes(12).toString("hex"),generation:this.generation,bytes:size,sha256:createHash("sha256").update(payload).digest("hex")},path=refFilePath(this.#root,ref);try{await mkdir(dirname(path),{recursive:!0,mode:448}),await writeFile(path,payload,{flag:"wx",mode:384})}catch(error){throw this.#ownedBytes-=size,await rm2(path,{force:!0}),error}return this.#pending.set(ref.refId,{bytes:size,createdAtMs:this.#now()}),ref}async handle(control){let pending=this.#pending.get(control.refId);pending!==void 0&&(this.#pending.delete(control.refId),this.#ownedBytes-=pending.bytes,control.type==="ref_nack"&&await rm2(refFilePath(this.#root,{refId:control.refId,generation:this.generation}),{force:!0}))}pendingIds(){return[...this.#pending.keys()]}overdue(){let deadline=this.#now()-TOOL_CHILD_LIMITS.refAckMs;return[...this.#pending].filter(([,ref])=>ref.createdAtMs<=deadline).map(([refId])=>refId)}async teardown(){this.#pending.clear(),this.#ownedBytes=0,await teardownRefGeneration(this.#root,this.generation)}},isMissingFile=error=>error instanceof Error&&"code"in error&&(error.code==="ENOENT"||error.code==="ENOTDIR");async function hashFile(path,signal){let hash=createHash("sha256");for await(let chunk of createReadStream(path)){if(signal?.aborted)return"cancelled";hash.update(chunk)}return hash.digest("hex")}var PayloadRefReader=class{#root;#generation;#budget;#send;#owned=new Map;#ownedBytes=0;constructor(options){this.#root=options.root,this.#generation=options.generation,this.#budget=options.budget??TOOL_CHILD_LIMITS.refsBudget,this.#send=options.send}async accept(ref,signal){let reason=await this.#verify(ref,signal);return reason!==void 0?(this.refuse(ref,reason),{ok:!1,reason}):(this.#owned.set(ref.refId,ref),this.#ownedBytes+=ref.bytes,this.#send({type:"ref_ack",refId:ref.refId}),{ok:!0})}refuse(ref,reason){this.#owned.has(ref.refId)||this.#send({type:"ref_nack",refId:ref.refId,reason})}async consume(refId){let ref=this.#owned.get(refId);if(ref===void 0)throw new PayloadRefError("ref_not_owned",`ref ${refId} is not owned by this side`);let path=refFilePath(this.#root,ref),bytes=await readFile(path);return await rm2(path,{force:!0}),this.#owned.delete(refId),this.#ownedBytes-=ref.bytes,bytes}ownedIds(){return[...this.#owned.keys()]}async#verify(ref,signal){if(signal?.aborted)return"cancelled";if(ref.generation!==this.#generation||!isRefId(ref.refId)||this.#owned.has(ref.refId))return"foreign";if(this.#ownedBytes+ref.bytes>this.#budget)return"budget";let path=refFilePath(this.#root,ref);try{if((await stat(path)).size!==ref.bytes)return"corrupt";let digest=await hashFile(path,signal);return digest==="cancelled"?"cancelled":digest===ref.sha256?void 0:"corrupt"}catch(error){if(isMissingFile(error))return"missing";throw error}}};async function packPayload(value,writer){let normalized=value===void 0?null:value,json=JSON.stringify(normalized);return json===void 0||Buffer.byteLength(json,"utf8")<=TOOL_CHILD_LIMITS.REF_THRESHOLD?{inline:!0,value:normalized}:{inline:!1,ref:await writer.create(Buffer.from(json,"utf8"))}}async function unpackPayload(ref,reader,signal){let acceptance=await reader.accept(ref,signal);if(!acceptance.ok)throw new PayloadRefError("ref_rejected",`ref ${ref.refId} was refused (${acceptance.reason})`,acceptance.reason);let bytes=await reader.consume(ref.refId);return JSON.parse(Buffer.from(bytes.buffer,bytes.byteOffset,bytes.byteLength).toString("utf8"))}var ChildHostCalls=class{#channel;#admissions=new Map;#pending=new Map;#refs;#next=0;constructor(channel,refs){this.#channel=channel,this.#refs=refs}load(jobId){let admission=this.#admissions.get(jobId);return{active:admission?.active??0,waiting:admission?.waiting??0}}async call(jobId,target,signal){let label=target.name??target.kind;if(signal.aborted)throw new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`);let callId=`h${++this.#next}`,packed=target.args===void 0||this.#refs===void 0?{inline:!0,value:target.args}:await packPayload(target.args,this.#refs.writer),frame={type:"host_call",callId,jobId,kind:target.kind,...target.name===void 0?{}:{name:target.name},...packed.inline?packed.value===void 0?{}:{args:packed.value}:{argsRef:packed.ref}};if(signal.aborted)throw this.#releaseUnsent(frame),new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`);return new Promise((resolve,reject)=>{let decision=this.#admission(jobId).submit(callId);if(decision.state==="refused"){this.#forgetIdle(jobId),this.#releaseUnsent(frame),reject(new ToolChildJobError(decision.frame.code,`${label}: host call ${callId} refused`));return}let pending={frame,resolve,reject,sent:!1};this.#pending.set(callId,pending),signal.addEventListener("abort",()=>this.#settle(callId,call=>{call.sent||this.#releaseUnsent(call.frame),call.reject(new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`))}),{once:!0}),decision.state==="active"&&this.#send(pending)})}handle(frame){if(frame.type==="host_reply"){let{valueRef}=frame;return this.#settle(frame.callId,call=>{frame.error!==void 0?call.reject(new ToolChildJobError("host_call_failed",frame.error)):valueRef===void 0?call.resolve(frame.value??null):this.#refs===void 0?call.reject(new ToolChildJobError("host_call_failed","a valueRef reply on a side that reads no refs")):unpackPayload(valueRef,this.#refs.reader).then(call.resolve,error=>call.reject(new ToolChildJobError("host_call_failed",error instanceof Error?error.message:String(error))))}),!0}return frame.type==="host_call_refused"?(this.#settle(frame.callId,call=>call.reject(new ToolChildJobError(frame.code,`host call ${frame.callId} refused by the server`))),!0):!1}close(){for(let callId of[...this.#pending.keys()])this.#settle(callId,call=>call.reject(new ToolChildJobError("tool_child_exited","the channel closed")))}#admission(jobId){let admission=this.#admissions.get(jobId);return admission===void 0&&(admission=new HostCallAdmission,this.#admissions.set(jobId,admission)),admission}#forgetIdle(jobId){let admission=this.#admissions.get(jobId);admission!==void 0&&admission.active===0&&admission.waiting===0&&this.#admissions.delete(jobId)}#send(call){call.sent=!0,this.#channel.send(call.frame)}#releaseUnsent(frame){frame.argsRef!==void 0&&this.#refs?.writer.handle({type:"ref_nack",refId:frame.argsRef.refId,reason:"cancelled"})}#settle(callId,apply){let call=this.#pending.get(callId);if(call===void 0)return;this.#pending.delete(callId);let{jobId}=call.frame,promoted=this.#admissions.get(jobId)?.settle(callId);if(this.#forgetIdle(jobId),apply(call),promoted!==void 0){let next=this.#pending.get(promoted);next!==void 0&&this.#send(next)}}};var JobUpdates=class{#jobId;#channel;#writer;#window;#nextSeq=0;#acked=0;#waiters=[];#ended=!1;#tail=Promise.resolve();constructor(options){this.#jobId=options.jobId,this.#channel=options.channel,this.#writer=options.writer,this.#window=options.window??TOOL_CHILD_LIMITS.updatesInFlight}update(value){let sent=this.#tail.then(()=>this.#send(value));return this.#tail=sent.catch(()=>{}),sent}async#send(value){for(;!this.#ended&&this.#nextSeq-this.#acked>=this.#window;)await new Promise(resolve=>this.#waiters.push(resolve));if(this.#ended)throw new Error(`update after job ${this.#jobId} ended`);let packed=this.#writer===void 0?{inline:!0,value}:await packPayload(value,this.#writer);if(this.#ended)throw new Error(`update after job ${this.#jobId} ended`);let seq=++this.#nextSeq;this.#channel.send(packed.inline?{type:"update",jobId:this.#jobId,seq,...packed.value===void 0?{}:{value:packed.value}}:{type:"update",jobId:this.#jobId,seq,valueRef:packed.ref})}acked(seq){seq<=this.#acked||(this.#acked=Math.min(seq,this.#nextSeq),this.#wake())}end(){this.#ended=!0,this.#wake()}#wake(){for(let resolve of this.#waiters.splice(0))resolve()}};var BarrierClock=class _BarrierClock{constructor(buffer){if(buffer.byteLength%Int32Array.BYTES_PER_ELEMENT!==0)throw new Error("barrier clock buffer is misaligned");let length=buffer.byteLength/Int32Array.BYTES_PER_ELEMENT;if(length<5||(length-1)%4!==0)throw new Error("barrier clock buffer has no slots");this.buffer=buffer,this.cells=new Int32Array(buffer),this.slots=(length-1)/4}static create(slots=256){if(!Number.isInteger(slots)||slots<1)throw new Error(`barrier clock needs at least one slot, got ${slots}`);return new _BarrierClock(new SharedArrayBuffer((1+slots*4)*Int32Array.BYTES_PER_ELEMENT))}tick(){return Atomics.add(this.cells,0,1)+1}claimSlot(){for(let slot=0;slot<this.slots;slot++)if(Atomics.compareExchange(this.cells,this.index(slot,3),0,1)===0)return Atomics.store(this.cells,this.index(slot,0),0),Atomics.store(this.cells,this.index(slot,1),0),Atomics.store(this.cells,this.index(slot,2),0),slot}releaseSlot(slot){Atomics.store(this.cells,this.index(slot,3),0)}recordAck(slot){let tick=this.tick();return Atomics.store(this.cells,this.index(slot,0),tick),Atomics.notify(this.cells,this.index(slot,0)),tick}recordInvoke(slot){let ackTick=Atomics.load(this.cells,this.index(slot,0)),invokeTick=this.tick();return Atomics.store(this.cells,this.index(slot,1),invokeTick),Atomics.add(this.cells,this.index(slot,2),1),{ackTick:ackTick===0?null:ackTick,invokeTick}}waitForAck(slot,timeoutMs=Number.POSITIVE_INFINITY){let at=this.index(slot,0);for(;Atomics.load(this.cells,at)===0;)if(Atomics.wait(this.cells,at,0,timeoutMs)==="timed-out")return"timed-out";return"acked"}read(slot){let ackTick=Atomics.load(this.cells,this.index(slot,0)),invokeTick=Atomics.load(this.cells,this.index(slot,1));return{ackTick:ackTick===0?null:ackTick,invokeTick:invokeTick===0?null:invokeTick,invocations:Atomics.load(this.cells,this.index(slot,2))}}index(slot,field){if(!Number.isInteger(slot)||slot<0||slot>=this.slots)throw new Error(`no barrier slot ${slot}`);return 1+slot*4+field}};function proofIsOrdered(proof){return proof.ackTick!==null&&proof.ackTick<proof.invokeTick}import{randomUUID}from"node:crypto";import{existsSync,readdirSync,rmSync,watch}from"node:fs";import{writeFile as writeFile2}from"node:fs/promises";import{join as join2}from"node:path";var PREFIX="SENPI_TOOL_CHILD_TEST_",TEST_CONTROL_DIR_ENV=`${PREFIX}CONTROL_DIR`;function readTestControls(env){let dir=env[TEST_CONTROL_DIR_ENV],value=name=>{let raw=env[`${PREFIX}${name}`];return raw===void 0||raw===""||raw==="0"?void 0:raw};return{enabled:name=>value(name)!==void 0,value,released:file=>dir===void 0?Promise.reject(new Error(`${TEST_CONTROL_DIR_ENV} is not set`)):waitForFile(dir,file),watchPrefix:(prefix,onFile)=>dir===void 0?{ready:Promise.reject(new Error(`${TEST_CONTROL_DIR_ENV} is not set`)),close:()=>{}}:watchPrefix(dir,prefix,onFile)}}function watchPrefix(dir,prefix,onFile){let seen=new Set,report=name=>{!name.startsWith(prefix)||seen.has(name)||(seen.add(name),onFile(name))},sentinel=`.watch-${process.pid}-${randomUUID()}`,resend,live=!1,markReady=()=>{},failReady=()=>{},ready=new Promise((resolve,reject)=>{markReady=resolve,failReady=reject}),watcher=watch(dir,(_event,name)=>{if(name!==null){if(name===sentinel){live=!0,clearTimeout(resend),rmSync(join2(dir,sentinel),{force:!0});for(let existing of readdirSync(dir))report(existing);markReady();return}existsSync(join2(dir,name))&&report(name)}}),touch=()=>{live||writeFile2(join2(dir,sentinel),String(Date.now())).then(()=>{live||(resend=setTimeout(touch,50))},error=>failReady(error))};return touch(),{ready,close:()=>{live=!0,clearTimeout(resend),watcher.close(),rmSync(join2(dir,sentinel),{force:!0})}}}function waitForFile(dir,file){let path=join2(dir,file),sentinel=join2(dir,`.watch-${process.pid}-${randomUUID()}`);return new Promise((resolve,reject)=>{let done=!1,resend,finish=()=>{done||(done=!0,clearTimeout(resend),watcher.close(),rmSync(sentinel,{force:!0}),resolve())},watcher=watch(dir,(_event,name)=>{if(existsSync(path)){finish();return}name!==null&&join2(dir,name)===sentinel&&clearTimeout(resend)}),touch=()=>{done||writeFile2(sentinel,String(Date.now())).then(()=>{done||(existsSync(path)?finish():resend=setTimeout(touch,50))},error=>{done||(done=!0,watcher.close(),reject(error))})};touch()})}var WindowsJobError=class extends Error{constructor(step,win32Error){super(`tool_child_job_assign_failed: ${step} failed (win32 error ${win32Error})`),this.code="tool_child_job_assign_failed",this.name="WindowsJobError",this.win32Error=win32Error}};function extendedLimitInformation(){let info=new Uint8Array(144);return new DataView(info.buffer).setUint32(16,10240,!0),info}var WindowsJob=class _WindowsJob{constructor(kernel,handle){this.closed=!1,this.kernel=kernel,this.handle=handle}static create(kernel){let handle=kernel.CreateJobObjectW(null,null);if(!handle)throw new WindowsJobError("CreateJobObjectW",kernel.GetLastError());let info=extendedLimitInformation();if(kernel.SetInformationJobObject(handle,9,info,info.byteLength)===0){let error=kernel.GetLastError();throw kernel.CloseHandle(handle),new WindowsJobError("SetInformationJobObject",error)}return new _WindowsJob(kernel,handle)}assign(pid){let process2=this.kernel.OpenProcess(4353,0,pid);if(!process2)throw new WindowsJobError("OpenProcess",this.kernel.GetLastError());try{if(this.kernel.AssignProcessToJobObject(this.handle,process2)===0)throw new WindowsJobError("AssignProcessToJobObject",this.kernel.GetLastError());let inJob=new Uint8Array(4);if(this.kernel.IsProcessInJob(process2,this.handle,inJob)===0||new DataView(inJob.buffer).getInt32(0,!0)===0)throw new WindowsJobError("IsProcessInJob",this.kernel.GetLastError())}finally{this.kernel.CloseHandle(process2)}}memberPids(){let list=new Uint8Array(8200);if(this.kernel.QueryInformationJobObject(this.handle,3,list,list.byteLength,null)===0)return[];let view=new DataView(list.buffer),count=Math.min(view.getUint32(4,!0),1024);return Array.from({length:count},(_,index)=>Number(view.getBigUint64(8+index*8,!0)))}terminate(exitCode=1){this.closed||this.kernel.TerminateJobObject(this.handle,exitCode)}close(){this.closed||(this.closed=!0,this.kernel.CloseHandle(this.handle))}};function loadKernel32Job(){if(process.platform!=="win32")return;let ffi=process.getBuiltinModule("bun:ffi");if(ffi===void 0)return;let lib=ffi.dlopen("kernel32.dll",{CreateJobObjectW:{args:["ptr","ptr"],returns:"ptr"},SetInformationJobObject:{args:["ptr","i32","ptr","u32"],returns:"i32"},QueryInformationJobObject:{args:["ptr","i32","ptr","u32","ptr"],returns:"i32"},OpenProcess:{args:["u32","i32","u32"],returns:"ptr"},AssignProcessToJobObject:{args:["ptr","ptr"],returns:"i32"},IsProcessInJob:{args:["ptr","ptr","ptr"],returns:"i32"},TerminateJobObject:{args:["ptr","u32"],returns:"i32"},CloseHandle:{args:["ptr"],returns:"i32"},GetLastError:{args:[],returns:"u32"},GetCurrentProcess:{args:[],returns:"ptr"}}),call=(name,...args)=>{let fn=lib.symbols[name];if(fn===void 0)throw new Error(`kernel32 has no ${name}`);return fn(...args.map(arg=>arg instanceof Uint8Array?ffi.ptr(arg):arg))};return{CreateJobObjectW:()=>call("CreateJobObjectW",null,null),SetInformationJobObject:(job,infoClass,info,length)=>Number(call("SetInformationJobObject",job,infoClass,info,length)),QueryInformationJobObject:(job,infoClass,info,length)=>Number(call("QueryInformationJobObject",job,infoClass,info,length,null)),OpenProcess:(access,inherit,pid)=>call("OpenProcess",access,inherit,pid),AssignProcessToJobObject:(job,process2)=>Number(call("AssignProcessToJobObject",job,process2)),IsProcessInJob:(process2,job,result)=>Number(call("IsProcessInJob",process2,job,result)),TerminateJobObject:(job,exitCode)=>Number(call("TerminateJobObject",job,exitCode)),CloseHandle:handle=>Number(call("CloseHandle",handle)),GetLastError:()=>Number(call("GetLastError")),GetCurrentProcess:()=>call("GetCurrentProcess")}}var defaultInJob;function currentProcessInJob(kernel){if(kernel!==void 0)return queryInJob(kernel);if(defaultInJob===void 0){let loaded=loadKernel32Job();defaultInJob=loaded===void 0?!1:queryInJob(loaded)}return defaultInJob}function queryInJob(kernel){let result=new Uint8Array(4);return kernel.IsProcessInJob(kernel.GetCurrentProcess(),null,result)!==0&&new DataView(result.buffer).getInt32(0,!0)!==0}var FINISHED_SLOT_STATES=256,LaunchGateError=class extends Error{constructor(code,message){super(`${code}: ${message}`),this.name="LaunchGateError",this.code=code}},LaunchGate=class{#channel;#slots=new Map;#finished=new Map;#controls;#next=0;constructor(channel,clock=BarrierClock.create(),env=process.env,creatorInJob=currentProcessInJob){this.#channel=channel,this.clock=clock,this.#controls=readTestControls(env),this.#creatorInJob=creatorInJob}#creatorInJob;started(launchId,pid,breakaway=!1){this.#slots.has(launchId)&&this.#channel.send({type:"command_started",launchId,pid,startedAtMs:Date.now(),creatorInJob:this.#creatorInJob(),breakaway})}get skipsAckWait(){return this.#controls.enabled("SKIP_ACK_WAIT")}request(request){let slot=this.clock.claimSlot();if(slot===void 0)throw new LaunchGateError("tool_child_launch_capacity",`${this.clock.slots} launches in flight`);let launchId=`L${process.pid}-${++this.#next}`,ack,acked=new Promise(resolve=>{ack=resolve});return this.#slots.set(launchId,{slot,ack,lifetime:request.lifetime,request}),this.#channel.send({type:"launch",launchId,...request}),this.#controls.enabled("STOP_AFTER_SPAWN")&&process.kill(process.pid,"SIGSTOP"),{launchId,slot,acked}}adopt(launchId,slot,request){this.#slots.set(launchId,{slot,ack:()=>{},lifetime:request.lifetime,request}),this.#channel.send({type:"launch",launchId,...request})}handleWorker(message){message.kind==="launch"?this.adopt(message.launchId,message.slot,message.request):message.kind==="invoking"?this.invoking(message.launchId):message.kind==="started"?this.started(message.launchId,message.pid,message.breakaway):this.done(message.launchId,{...message.exitCode===void 0?{}:{exitCode:message.exitCode},...message.signal===void 0?{}:{signal:message.signal}})}handle(message){if(message.type==="launch_ack"){let entry=this.#slots.get(message.launchId);return entry!==void 0&&(this.clock.recordAck(entry.slot),entry.ack()),!0}if(message.type==="slot_query"){let entry=this.#slots.get(message.launchId),state=entry===void 0?this.#finished.get(message.launchId)??{ackTick:null,invokeTick:null,invocations:0}:this.clock.read(entry.slot);return this.#channel.send({type:"slot_state",launchId:message.launchId,...state}),!0}return!1}invokeNow(launchId){let entry=this.#slots.get(launchId);if(entry===void 0)throw new LaunchGateError("tool_child_launch_unknown",launchId);this.clock.recordInvoke(entry.slot),this.invoking(launchId)}invoking(launchId){let entry=this.#slots.get(launchId);if(entry===void 0)return;let state=this.clock.read(entry.slot),invokeTick=state.invokeTick;if(invokeTick===null)return;let send=()=>this.#channel.send({type:"launch_proof",launchId,ackTick:state.ackTick,invokeTick}),hold=this.#controls.value("HOLD_LAUNCH_PROOF");if(hold!==void 0&&(hold!=="detached"||entry.lifetime==="detached")){this.#controls.released(`release-proof-${launchId}`).then(send);return}send()}endJobGroups(jobId){let ended=[];for(let[launchId,{request}]of this.#slots)if(!(request.jobId!==jobId||request.lifetime!=="owned"||request.containment!=="own-group")&&!(request.pgid===void 0||request.pgid<=1))try{process.kill(-request.pgid,"SIGKILL"),ended.push({launchId,pgid:request.pgid})}catch{}for(let{launchId}of ended)this.done(launchId,{signal:"SIGKILL"});return ended.map(({pgid})=>pgid)}done(launchId,outcome){let entry=this.#slots.get(launchId);entry!==void 0&&(this.#slots.delete(launchId),this.#finished.set(launchId,this.clock.read(entry.slot)),this.#finished.size>FINISHED_SLOT_STATES&&this.#finished.delete(this.#finished.keys().next().value??""),this.clock.releaseSlot(entry.slot),this.#channel.send({type:"launch_done",launchId,...outcome.exitCode===void 0?{}:{exitCode:outcome.exitCode},...outcome.signal===void 0?{}:{signal:outcome.signal}}))}};import{mkdir as mkdir3,readdir as readdir2,readFile as readFile3,rm as rm4,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname3,join as join4}from"node:path";import{appendFile,mkdir as mkdir2,open,readFile as readFile2,rm as rm3}from"node:fs/promises";import{dirname as dirname2,join as join3}from"node:path";function generationLedgerPath(dir,generation){return join3(dir,`g${generation}`,"descendants.ledger")}var DescendantsLedger=class{#path;#durableDir=!1;#entries=new Map;constructor(path){this.#path=path}get path(){return this.#path}entries(){return[...this.#entries.values()]}async append(entry){if(!this.#durableDir){let directory=dirname2(this.#path);await mkdir2(directory,{recursive:!0,mode:448}),await(await open(this.#path,"a",384)).close(),await syncDirectory(directory),await syncDirectory(dirname2(directory)),this.#durableDir=!0}let handle=await open(this.#path,"a",384);try{await handle.write(`${JSON.stringify(entry)}
2
+ import{Text,truncateToWidth,visibleWidth}from"./chunk-D2ROBVZ4.js";import{getShellConfig}from"./chunk-MCXOJHN2.js";import{adoptedEngineTrust,engineTrustAction}from"./chunk-EVTTLPIY.js";import{redactSecrets}from"./chunk-LNAZ7XEU.js";import{HOST_CALL_KINDS,TOOL_CHILD_LIMITS,connectChannel,isRefId,isStaleExtensionContextError}from"./chunk-UKSFF47T.js";import{typebox_exports}from"./chunk-MIENF2YK.js";import{TOOL_CHILD_LEDGER_ENV,TOOL_CHILD_REENTRY_ENV,TOOL_CHILD_REFS_ROOT_ENV,rememberToolChildReentry,scrubToolChildEnv,toolChildReentry}from"./chunk-OXNWERO4.js";import{BACKGROUND_START_GRACE_MS,DEFAULT_COLS,DEFAULT_MAX_SESSIONS,DEFAULT_ROWS,FOREGROUND_ENV_OVERRIDES,KILLED_SESSION_EXIT_GRACE_MS,SecretOutputRedactor,TERMINAL_BASH_TOOL,TERMINAL_INPUT_TOOL,TERMINAL_KILL_TOOL,TERMINAL_OUTPUT_TOOL,TERMINAL_RESIZE_TOOL,encodeKeys,loadPty,safeRegExp}from"./chunk-AOTHPTMU.js";import{processIsRunning,processStartTimeMs,readProcessStartTime,sameProcessStartMs}from"./chunk-O5RYI3IW.js";var ToolChildJobError=class extends Error{constructor(code,message){super(message),this.code=code,this.name="ToolChildJobError"}};var WakeAdmissionError=class extends Error{constructor(bytes){super(`wake_too_large: ${bytes} bytes exceeds the ${TOOL_CHILD_LIMITS.wakePendingBytes}-byte pending budget`),this.code="wake_too_large",this.name="WakeAdmissionError"}},WakeAdmission=class{#pending=new Map;#blocked=[];#pendingBytes=0;get pending(){return this.#pending.size}get blocked(){return this.#blocked.length}send(wakeId,bytes){return bytes>TOOL_CHILD_LIMITS.wakePendingBytes?Promise.reject(new WakeAdmissionError(bytes)):this.#blocked.length===0&&this.#fits(bytes)?(this.#admit(wakeId,bytes),Promise.resolve()):new Promise(release=>{this.#blocked.push({wakeId,bytes,release})})}ack(wakeId){let bytes=this.#pending.get(wakeId);if(bytes!==void 0){this.#pending.delete(wakeId),this.#pendingBytes-=bytes;for(let next=this.#blocked[0];next!==void 0&&this.#fits(next.bytes);next=this.#blocked[0])this.#blocked.shift(),this.#admit(next.wakeId,next.bytes),next.release()}}#fits(bytes){return this.#pending.size<TOOL_CHILD_LIMITS.wakePending&&this.#pendingBytes+bytes<=TOOL_CHILD_LIMITS.wakePendingBytes}#admit(wakeId,bytes){this.#pending.set(wakeId,bytes),this.#pendingBytes+=bytes}};function hostCallCapacity(){return TOOL_CHILD_LIMITS.HOST_CALL_ACTIVE+TOOL_CHILD_LIMITS.HOST_CALL_WAITING}var HostCallAdmission=class{#active=new Set;#waiting=[];get active(){return this.#active.size}get waiting(){return this.#waiting.length}submit(callId){return this.#active.has(callId)||this.#waiting.includes(callId)?refuse(callId,"host_call_duplicate"):this.#active.size<TOOL_CHILD_LIMITS.HOST_CALL_ACTIVE&&this.#waiting.length===0?(this.#active.add(callId),{state:"active"}):this.#active.size+this.#waiting.length>=hostCallCapacity()?refuse(callId,"host_call_capacity"):(this.#waiting.push(callId),{state:"waiting"})}settle(callId){if(!this.#active.delete(callId)){let index=this.#waiting.indexOf(callId);index>=0&&this.#waiting.splice(index,1);return}let next=this.#waiting.shift();return next!==void 0&&this.#active.add(next),next}};function refuse(callId,code){return{state:"refused",frame:{type:"host_call_refused",callId,code}}}import{createHash,randomBytes}from"node:crypto";import{createReadStream}from"node:fs";import{mkdir,readFile,rm as rm2,stat,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{readdir,rm}from"node:fs/promises";import{join}from"node:path";function refGenerationDir(root,generation){return join(root,`gen-${generation}`)}function refFilePath(root,ref){if(!isRefId(ref.refId))throw new Error(`invalid ref id: ${JSON.stringify(ref.refId)}`);return join(refGenerationDir(root,ref.generation),"refs",ref.refId)}async function teardownRefGeneration(root,generation){await rm(refGenerationDir(root,generation),{recursive:!0,force:!0})}var PayloadRefError=class extends Error{constructor(code,message,reason){super(`${code}: ${message}`),this.name="PayloadRefError",this.code=code,this.reason=reason}},PayloadRefWriter=class{#root;#now;#pending=new Map;#ownedBytes=0;constructor(options){this.generation=options.generation,this.budget=options.budget??TOOL_CHILD_LIMITS.refsBudget,this.#root=options.root,this.#now=options.now??Date.now}get ownedBytes(){return this.#ownedBytes}async create(payload){let size=payload.byteLength;if(this.#ownedBytes+size>this.budget)throw new PayloadRefError("ref_budget_exceeded",`${size} bytes on top of ${this.#ownedBytes} owned exceeds ${this.budget}`);this.#ownedBytes+=size;let ref={refId:randomBytes(12).toString("hex"),generation:this.generation,bytes:size,sha256:createHash("sha256").update(payload).digest("hex")},path=refFilePath(this.#root,ref);try{await mkdir(dirname(path),{recursive:!0,mode:448}),await writeFile(path,payload,{flag:"wx",mode:384})}catch(error){throw this.#ownedBytes-=size,await rm2(path,{force:!0}),error}return this.#pending.set(ref.refId,{bytes:size,createdAtMs:this.#now()}),ref}async handle(control){let pending=this.#pending.get(control.refId);pending!==void 0&&(this.#pending.delete(control.refId),this.#ownedBytes-=pending.bytes,control.type==="ref_nack"&&await rm2(refFilePath(this.#root,{refId:control.refId,generation:this.generation}),{force:!0}))}pendingIds(){return[...this.#pending.keys()]}overdue(){let deadline=this.#now()-TOOL_CHILD_LIMITS.refAckMs;return[...this.#pending].filter(([,ref])=>ref.createdAtMs<=deadline).map(([refId])=>refId)}async teardown(){this.#pending.clear(),this.#ownedBytes=0,await teardownRefGeneration(this.#root,this.generation)}},isMissingFile=error=>error instanceof Error&&"code"in error&&(error.code==="ENOENT"||error.code==="ENOTDIR");async function hashFile(path,signal){let hash=createHash("sha256");for await(let chunk of createReadStream(path)){if(signal?.aborted)return"cancelled";hash.update(chunk)}return hash.digest("hex")}var PayloadRefReader=class{#root;#generation;#budget;#send;#owned=new Map;#ownedBytes=0;constructor(options){this.#root=options.root,this.#generation=options.generation,this.#budget=options.budget??TOOL_CHILD_LIMITS.refsBudget,this.#send=options.send}async accept(ref,signal){let reason=await this.#verify(ref,signal);return reason!==void 0?(this.refuse(ref,reason),{ok:!1,reason}):(this.#owned.set(ref.refId,ref),this.#ownedBytes+=ref.bytes,this.#send({type:"ref_ack",refId:ref.refId}),{ok:!0})}refuse(ref,reason){this.#owned.has(ref.refId)||this.#send({type:"ref_nack",refId:ref.refId,reason})}async consume(refId){let ref=this.#owned.get(refId);if(ref===void 0)throw new PayloadRefError("ref_not_owned",`ref ${refId} is not owned by this side`);let path=refFilePath(this.#root,ref),bytes=await readFile(path);return await rm2(path,{force:!0}),this.#owned.delete(refId),this.#ownedBytes-=ref.bytes,bytes}ownedIds(){return[...this.#owned.keys()]}async#verify(ref,signal){if(signal?.aborted)return"cancelled";if(ref.generation!==this.#generation||!isRefId(ref.refId)||this.#owned.has(ref.refId))return"foreign";if(this.#ownedBytes+ref.bytes>this.#budget)return"budget";let path=refFilePath(this.#root,ref);try{if((await stat(path)).size!==ref.bytes)return"corrupt";let digest=await hashFile(path,signal);return digest==="cancelled"?"cancelled":digest===ref.sha256?void 0:"corrupt"}catch(error){if(isMissingFile(error))return"missing";throw error}}};async function packPayload(value,writer){let normalized=value===void 0?null:value,json=JSON.stringify(normalized);return json===void 0||Buffer.byteLength(json,"utf8")<=TOOL_CHILD_LIMITS.REF_THRESHOLD?{inline:!0,value:normalized}:{inline:!1,ref:await writer.create(Buffer.from(json,"utf8"))}}async function unpackPayload(ref,reader,signal){let acceptance=await reader.accept(ref,signal);if(!acceptance.ok)throw new PayloadRefError("ref_rejected",`ref ${ref.refId} was refused (${acceptance.reason})`,acceptance.reason);let bytes=await reader.consume(ref.refId);return JSON.parse(Buffer.from(bytes.buffer,bytes.byteOffset,bytes.byteLength).toString("utf8"))}var ChildHostCalls=class{#channel;#admissions=new Map;#pending=new Map;#refs;#next=0;constructor(channel,refs){this.#channel=channel,this.#refs=refs}load(jobId){let admission=this.#admissions.get(jobId);return{active:admission?.active??0,waiting:admission?.waiting??0}}async call(jobId,target,signal){let label=target.name??target.kind;if(signal.aborted)throw new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`);let callId=`h${++this.#next}`,packed=target.args===void 0||this.#refs===void 0?{inline:!0,value:target.args}:await packPayload(target.args,this.#refs.writer),frame={type:"host_call",callId,jobId,kind:target.kind,...target.name===void 0?{}:{name:target.name},...packed.inline?packed.value===void 0?{}:{args:packed.value}:{argsRef:packed.ref}};if(signal.aborted)throw this.#releaseUnsent(frame),new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`);return new Promise((resolve,reject)=>{let decision=this.#admission(jobId).submit(callId);if(decision.state==="refused"){this.#forgetIdle(jobId),this.#releaseUnsent(frame),reject(new ToolChildJobError(decision.frame.code,`${label}: host call ${callId} refused`));return}let pending={frame,resolve,reject,sent:!1};this.#pending.set(callId,pending),signal.addEventListener("abort",()=>this.#settle(callId,call=>{call.sent||this.#releaseUnsent(call.frame),call.reject(new ToolChildJobError("tool_child_cancelled",`${label}: job cancelled`))}),{once:!0}),decision.state==="active"&&this.#send(pending)})}handle(frame){if(frame.type==="host_reply"){let{valueRef}=frame;return this.#settle(frame.callId,call=>{frame.error!==void 0?call.reject(new ToolChildJobError("host_call_failed",frame.error)):valueRef===void 0?call.resolve(frame.value??null):this.#refs===void 0?call.reject(new ToolChildJobError("host_call_failed","a valueRef reply on a side that reads no refs")):unpackPayload(valueRef,this.#refs.reader).then(call.resolve,error=>call.reject(new ToolChildJobError("host_call_failed",error instanceof Error?error.message:String(error))))}),!0}return frame.type==="host_call_refused"?(this.#settle(frame.callId,call=>call.reject(new ToolChildJobError(frame.code,`host call ${frame.callId} refused by the server`))),!0):!1}close(){for(let callId of[...this.#pending.keys()])this.#settle(callId,call=>call.reject(new ToolChildJobError("tool_child_exited","the channel closed")))}#admission(jobId){let admission=this.#admissions.get(jobId);return admission===void 0&&(admission=new HostCallAdmission,this.#admissions.set(jobId,admission)),admission}#forgetIdle(jobId){let admission=this.#admissions.get(jobId);admission!==void 0&&admission.active===0&&admission.waiting===0&&this.#admissions.delete(jobId)}#send(call){call.sent=!0,this.#channel.send(call.frame)}#releaseUnsent(frame){frame.argsRef!==void 0&&this.#refs?.writer.handle({type:"ref_nack",refId:frame.argsRef.refId,reason:"cancelled"})}#settle(callId,apply){let call=this.#pending.get(callId);if(call===void 0)return;this.#pending.delete(callId);let{jobId}=call.frame,promoted=this.#admissions.get(jobId)?.settle(callId);if(this.#forgetIdle(jobId),apply(call),promoted!==void 0){let next=this.#pending.get(promoted);next!==void 0&&this.#send(next)}}};var JobUpdates=class{#jobId;#channel;#writer;#window;#nextSeq=0;#acked=0;#waiters=[];#ended=!1;#tail=Promise.resolve();constructor(options){this.#jobId=options.jobId,this.#channel=options.channel,this.#writer=options.writer,this.#window=options.window??TOOL_CHILD_LIMITS.updatesInFlight}update(value){let sent=this.#tail.then(()=>this.#send(value));return this.#tail=sent.catch(()=>{}),sent}async#send(value){for(;!this.#ended&&this.#nextSeq-this.#acked>=this.#window;)await new Promise(resolve=>this.#waiters.push(resolve));if(this.#ended)throw new Error(`update after job ${this.#jobId} ended`);let packed=this.#writer===void 0?{inline:!0,value}:await packPayload(value,this.#writer);if(this.#ended)throw new Error(`update after job ${this.#jobId} ended`);let seq=++this.#nextSeq;this.#channel.send(packed.inline?{type:"update",jobId:this.#jobId,seq,...packed.value===void 0?{}:{value:packed.value}}:{type:"update",jobId:this.#jobId,seq,valueRef:packed.ref})}acked(seq){seq<=this.#acked||(this.#acked=Math.min(seq,this.#nextSeq),this.#wake())}end(){this.#ended=!0,this.#wake()}#wake(){for(let resolve of this.#waiters.splice(0))resolve()}};var BarrierClock=class _BarrierClock{constructor(buffer){if(buffer.byteLength%Int32Array.BYTES_PER_ELEMENT!==0)throw new Error("barrier clock buffer is misaligned");let length=buffer.byteLength/Int32Array.BYTES_PER_ELEMENT;if(length<5||(length-1)%4!==0)throw new Error("barrier clock buffer has no slots");this.buffer=buffer,this.cells=new Int32Array(buffer),this.slots=(length-1)/4}static create(slots=256){if(!Number.isInteger(slots)||slots<1)throw new Error(`barrier clock needs at least one slot, got ${slots}`);return new _BarrierClock(new SharedArrayBuffer((1+slots*4)*Int32Array.BYTES_PER_ELEMENT))}tick(){return Atomics.add(this.cells,0,1)+1}claimSlot(){for(let slot=0;slot<this.slots;slot++)if(Atomics.compareExchange(this.cells,this.index(slot,3),0,1)===0)return Atomics.store(this.cells,this.index(slot,0),0),Atomics.store(this.cells,this.index(slot,1),0),Atomics.store(this.cells,this.index(slot,2),0),slot}releaseSlot(slot){Atomics.store(this.cells,this.index(slot,3),0)}recordAck(slot){let tick=this.tick();return Atomics.store(this.cells,this.index(slot,0),tick),Atomics.notify(this.cells,this.index(slot,0)),tick}recordInvoke(slot){let ackTick=Atomics.load(this.cells,this.index(slot,0)),invokeTick=this.tick();return Atomics.store(this.cells,this.index(slot,1),invokeTick),Atomics.add(this.cells,this.index(slot,2),1),{ackTick:ackTick===0?null:ackTick,invokeTick}}waitForAck(slot,timeoutMs=Number.POSITIVE_INFINITY){let at=this.index(slot,0);for(;Atomics.load(this.cells,at)===0;)if(Atomics.wait(this.cells,at,0,timeoutMs)==="timed-out")return"timed-out";return"acked"}read(slot){let ackTick=Atomics.load(this.cells,this.index(slot,0)),invokeTick=Atomics.load(this.cells,this.index(slot,1));return{ackTick:ackTick===0?null:ackTick,invokeTick:invokeTick===0?null:invokeTick,invocations:Atomics.load(this.cells,this.index(slot,2))}}index(slot,field){if(!Number.isInteger(slot)||slot<0||slot>=this.slots)throw new Error(`no barrier slot ${slot}`);return 1+slot*4+field}};function proofIsOrdered(proof){return proof.ackTick!==null&&proof.ackTick<proof.invokeTick}import{randomUUID}from"node:crypto";import{existsSync,readdirSync,rmSync,watch}from"node:fs";import{writeFile as writeFile2}from"node:fs/promises";import{join as join2}from"node:path";var PREFIX="SENPI_TOOL_CHILD_TEST_",TEST_CONTROL_DIR_ENV=`${PREFIX}CONTROL_DIR`;function readTestControls(env){let dir=env[TEST_CONTROL_DIR_ENV],value=name=>{let raw=env[`${PREFIX}${name}`];return raw===void 0||raw===""||raw==="0"?void 0:raw};return{enabled:name=>value(name)!==void 0,value,released:file=>dir===void 0?Promise.reject(new Error(`${TEST_CONTROL_DIR_ENV} is not set`)):waitForFile(dir,file),watchPrefix:(prefix,onFile)=>dir===void 0?{ready:Promise.reject(new Error(`${TEST_CONTROL_DIR_ENV} is not set`)),close:()=>{}}:watchPrefix(dir,prefix,onFile)}}function watchPrefix(dir,prefix,onFile){let seen=new Set,report=name=>{!name.startsWith(prefix)||seen.has(name)||(seen.add(name),onFile(name))},sentinel=`.watch-${process.pid}-${randomUUID()}`,resend,live=!1,markReady=()=>{},failReady=()=>{},ready=new Promise((resolve,reject)=>{markReady=resolve,failReady=reject}),watcher=watch(dir,(_event,name)=>{if(name!==null){if(name===sentinel){live=!0,clearTimeout(resend),rmSync(join2(dir,sentinel),{force:!0});for(let existing of readdirSync(dir))report(existing);markReady();return}existsSync(join2(dir,name))&&report(name)}}),touch=()=>{live||writeFile2(join2(dir,sentinel),String(Date.now())).then(()=>{live||(resend=setTimeout(touch,50))},error=>failReady(error))};return touch(),{ready,close:()=>{live=!0,clearTimeout(resend),watcher.close(),rmSync(join2(dir,sentinel),{force:!0})}}}function waitForFile(dir,file){let path=join2(dir,file),sentinel=join2(dir,`.watch-${process.pid}-${randomUUID()}`);return new Promise((resolve,reject)=>{let done=!1,resend,finish=()=>{done||(done=!0,clearTimeout(resend),watcher.close(),rmSync(sentinel,{force:!0}),resolve())},watcher=watch(dir,(_event,name)=>{if(existsSync(path)){finish();return}name!==null&&join2(dir,name)===sentinel&&clearTimeout(resend)}),touch=()=>{done||writeFile2(sentinel,String(Date.now())).then(()=>{done||(existsSync(path)?finish():resend=setTimeout(touch,50))},error=>{done||(done=!0,watcher.close(),reject(error))})};touch()})}var WindowsJobError=class extends Error{constructor(step,win32Error){super(`tool_child_job_assign_failed: ${step} failed (win32 error ${win32Error})`),this.code="tool_child_job_assign_failed",this.name="WindowsJobError",this.win32Error=win32Error}};function extendedLimitInformation(){let info=new Uint8Array(144);return new DataView(info.buffer).setUint32(16,10240,!0),info}var WindowsJob=class _WindowsJob{constructor(kernel,handle){this.closed=!1,this.kernel=kernel,this.handle=handle}static create(kernel){let handle=kernel.CreateJobObjectW(null,null);if(!handle)throw new WindowsJobError("CreateJobObjectW",kernel.GetLastError());let info=extendedLimitInformation();if(kernel.SetInformationJobObject(handle,9,info,info.byteLength)===0){let error=kernel.GetLastError();throw kernel.CloseHandle(handle),new WindowsJobError("SetInformationJobObject",error)}return new _WindowsJob(kernel,handle)}assign(pid){let process2=this.kernel.OpenProcess(4353,0,pid);if(!process2)throw new WindowsJobError("OpenProcess",this.kernel.GetLastError());try{if(this.kernel.AssignProcessToJobObject(this.handle,process2)===0)throw new WindowsJobError("AssignProcessToJobObject",this.kernel.GetLastError());let inJob=new Uint8Array(4);if(this.kernel.IsProcessInJob(process2,this.handle,inJob)===0||new DataView(inJob.buffer).getInt32(0,!0)===0)throw new WindowsJobError("IsProcessInJob",this.kernel.GetLastError())}finally{this.kernel.CloseHandle(process2)}}memberPids(){let list=new Uint8Array(8200);if(this.kernel.QueryInformationJobObject(this.handle,3,list,list.byteLength,null)===0)return[];let view=new DataView(list.buffer),count=Math.min(view.getUint32(4,!0),1024);return Array.from({length:count},(_,index)=>Number(view.getBigUint64(8+index*8,!0)))}terminate(exitCode=1){this.closed||this.kernel.TerminateJobObject(this.handle,exitCode)}close(){this.closed||(this.closed=!0,this.kernel.CloseHandle(this.handle))}};function loadKernel32Job(){if(process.platform!=="win32")return;let ffi=process.getBuiltinModule("bun:ffi");if(ffi===void 0)return;let lib=ffi.dlopen("kernel32.dll",{CreateJobObjectW:{args:["ptr","ptr"],returns:"ptr"},SetInformationJobObject:{args:["ptr","i32","ptr","u32"],returns:"i32"},QueryInformationJobObject:{args:["ptr","i32","ptr","u32","ptr"],returns:"i32"},OpenProcess:{args:["u32","i32","u32"],returns:"ptr"},AssignProcessToJobObject:{args:["ptr","ptr"],returns:"i32"},IsProcessInJob:{args:["ptr","ptr","ptr"],returns:"i32"},TerminateJobObject:{args:["ptr","u32"],returns:"i32"},CloseHandle:{args:["ptr"],returns:"i32"},GetLastError:{args:[],returns:"u32"},GetCurrentProcess:{args:[],returns:"ptr"}}),call=(name,...args)=>{let fn=lib.symbols[name];if(fn===void 0)throw new Error(`kernel32 has no ${name}`);return fn(...args.map(arg=>arg instanceof Uint8Array?ffi.ptr(arg):arg))};return{CreateJobObjectW:()=>call("CreateJobObjectW",null,null),SetInformationJobObject:(job,infoClass,info,length)=>Number(call("SetInformationJobObject",job,infoClass,info,length)),QueryInformationJobObject:(job,infoClass,info,length)=>Number(call("QueryInformationJobObject",job,infoClass,info,length,null)),OpenProcess:(access,inherit,pid)=>call("OpenProcess",access,inherit,pid),AssignProcessToJobObject:(job,process2)=>Number(call("AssignProcessToJobObject",job,process2)),IsProcessInJob:(process2,job,result)=>Number(call("IsProcessInJob",process2,job,result)),TerminateJobObject:(job,exitCode)=>Number(call("TerminateJobObject",job,exitCode)),CloseHandle:handle=>Number(call("CloseHandle",handle)),GetLastError:()=>Number(call("GetLastError")),GetCurrentProcess:()=>call("GetCurrentProcess")}}var defaultInJob;function currentProcessInJob(kernel){if(kernel!==void 0)return queryInJob(kernel);if(defaultInJob===void 0){let loaded=loadKernel32Job();defaultInJob=loaded===void 0?!1:queryInJob(loaded)}return defaultInJob}function queryInJob(kernel){let result=new Uint8Array(4);return kernel.IsProcessInJob(kernel.GetCurrentProcess(),null,result)!==0&&new DataView(result.buffer).getInt32(0,!0)!==0}var FINISHED_SLOT_STATES=256,LaunchGateError=class extends Error{constructor(code,message){super(`${code}: ${message}`),this.name="LaunchGateError",this.code=code}},LaunchGate=class{#channel;#slots=new Map;#finished=new Map;#controls;#next=0;constructor(channel,clock=BarrierClock.create(),env=process.env,creatorInJob=currentProcessInJob){this.#channel=channel,this.clock=clock,this.#controls=readTestControls(env),this.#creatorInJob=creatorInJob}#creatorInJob;started(launchId,pid,breakaway=!1){this.#slots.has(launchId)&&this.#channel.send({type:"command_started",launchId,pid,startedAtMs:Date.now(),creatorInJob:this.#creatorInJob(),breakaway})}get skipsAckWait(){return this.#controls.enabled("SKIP_ACK_WAIT")}request(request){let slot=this.clock.claimSlot();if(slot===void 0)throw new LaunchGateError("tool_child_launch_capacity",`${this.clock.slots} launches in flight`);let launchId=`L${process.pid}-${++this.#next}`,ack,acked=new Promise(resolve=>{ack=resolve});return this.#slots.set(launchId,{slot,ack,lifetime:request.lifetime,request}),this.#channel.send({type:"launch",launchId,...request}),this.#controls.enabled("STOP_AFTER_SPAWN")&&process.kill(process.pid,"SIGSTOP"),{launchId,slot,acked}}adopt(launchId,slot,request){this.#slots.set(launchId,{slot,ack:()=>{},lifetime:request.lifetime,request}),this.#channel.send({type:"launch",launchId,...request})}handleWorker(message){message.kind==="launch"?this.adopt(message.launchId,message.slot,message.request):message.kind==="invoking"?this.invoking(message.launchId):message.kind==="started"?this.started(message.launchId,message.pid,message.breakaway):this.done(message.launchId,{...message.exitCode===void 0?{}:{exitCode:message.exitCode},...message.signal===void 0?{}:{signal:message.signal}})}handle(message){if(message.type==="launch_ack"){let entry=this.#slots.get(message.launchId);return entry!==void 0&&(this.clock.recordAck(entry.slot),entry.ack()),!0}if(message.type==="slot_query"){let entry=this.#slots.get(message.launchId),state=entry===void 0?this.#finished.get(message.launchId)??{ackTick:null,invokeTick:null,invocations:0}:this.clock.read(entry.slot);return this.#channel.send({type:"slot_state",launchId:message.launchId,...state}),!0}return!1}invokeNow(launchId){let entry=this.#slots.get(launchId);if(entry===void 0)throw new LaunchGateError("tool_child_launch_unknown",launchId);this.clock.recordInvoke(entry.slot),this.invoking(launchId)}invoking(launchId){let entry=this.#slots.get(launchId);if(entry===void 0)return;let state=this.clock.read(entry.slot),invokeTick=state.invokeTick;if(invokeTick===null)return;let send=()=>this.#channel.send({type:"launch_proof",launchId,ackTick:state.ackTick,invokeTick}),hold=this.#controls.value("HOLD_LAUNCH_PROOF");if(hold!==void 0&&(hold!=="detached"||entry.lifetime==="detached")){this.#controls.released(`release-proof-${launchId}`).then(send);return}send()}endJobGroups(jobId){let ended=[];for(let[launchId,{request}]of this.#slots)if(!(request.jobId!==jobId||request.lifetime!=="owned"||request.containment!=="own-group")&&!(request.pgid===void 0||request.pgid<=1))try{process.kill(-request.pgid,"SIGKILL"),ended.push({launchId,pgid:request.pgid})}catch{}for(let{launchId}of ended)this.done(launchId,{signal:"SIGKILL"});return ended.map(({pgid})=>pgid)}done(launchId,outcome){let entry=this.#slots.get(launchId);entry!==void 0&&(this.#slots.delete(launchId),this.#finished.set(launchId,this.clock.read(entry.slot)),this.#finished.size>FINISHED_SLOT_STATES&&this.#finished.delete(this.#finished.keys().next().value??""),this.clock.releaseSlot(entry.slot),this.#channel.send({type:"launch_done",launchId,...outcome.exitCode===void 0?{}:{exitCode:outcome.exitCode},...outcome.signal===void 0?{}:{signal:outcome.signal}}))}};import{mkdir as mkdir3,readdir as readdir2,readFile as readFile3,rm as rm4,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname3,join as join4}from"node:path";import{appendFile,mkdir as mkdir2,open,readFile as readFile2,rm as rm3}from"node:fs/promises";import{dirname as dirname2,join as join3}from"node:path";function generationLedgerPath(dir,generation){return join3(dir,`g${generation}`,"descendants.ledger")}var DescendantsLedger=class{#path;#durableDir=!1;#entries=new Map;constructor(path){this.#path=path}get path(){return this.#path}entries(){return[...this.#entries.values()]}async append(entry){if(!this.#durableDir){let directory=dirname2(this.#path);await mkdir2(directory,{recursive:!0,mode:448}),await(await open(this.#path,"a",384)).close(),await syncDirectory(directory),await syncDirectory(dirname2(directory)),this.#durableDir=!0}let handle=await open(this.#path,"a",384);try{await handle.write(`${JSON.stringify(entry)}
3
3
  `),await handle.datasync()}finally{await handle.close()}this.#entries.set(entry.launchId,entry)}static async readPersisted(path){let text;try{text=await readFile2(path,"utf8")}catch{return[]}let entries=[];for(let line of text.split(`
4
4
  `))if(line.trim()!=="")try{entries.push(JSON.parse(line))}catch{}return entries}async remove(){this.#entries.clear(),await rm3(this.#path,{force:!0})}};async function syncDirectory(directory){if(process.platform==="win32")return;let handle=await open(directory,"r");try{await handle.sync()}finally{await handle.close()}}var LaunchLog=class{#path;#chain=Promise.resolve();#failedWrites=0;constructor(path){this.#path=path}get path(){return this.#path}get failedWrites(){return this.#failedWrites}settled(){return this.#chain}record(record){let line=`${JSON.stringify({atMs:Date.now(),...record})}
5
5
  `;return this.#chain=this.#chain.then(async()=>{try{await mkdir2(dirname2(this.#path),{recursive:!0,mode:448}),await appendFile(this.#path,line,{mode:384})}catch{this.#failedWrites+=1}}),this.#chain}};import{execFile}from"node:child_process";async function classifyGroup(group,ownGroup,probes){if(group.lifetime==="detached")return"detached";if(ownGroup===void 0||group.pgid===ownGroup||group.pgid<=1)return"own-group";if(!probes.groupHasMembers(group.pgid))return"empty";if(!probes.isAlive(group.pgid))return"sweep";let observed=await probes.startOf(group.pgid).catch(()=>{}),recorded=group.leaderStart===void 0?void 0:processStartTimeMs(group.leaderStart);return sameProcessStartMs(recorded,observed===void 0?void 0:processStartTimeMs(observed))?"sweep":"leader-reused"}async function sweepGroups(groups,options,probes=defaultGroupProbes){let ownGroup=await probes.ownGroup(),verdicts=await Promise.all(groups.map(async group=>({group,verdict:await classifyGroup(group,ownGroup,probes)}))),targets=verdicts.filter(entry=>entry.verdict==="sweep").map(entry=>entry.group.pgid);for(let pgid of targets)probes.signalGroup(pgid,"SIGTERM");let remaining=await drain(targets,options.graceMs,options.pollMs??25,probes);for(let pgid of remaining)probes.signalGroup(pgid,"SIGKILL");return remaining=await drain(remaining,options.killWaitMs,options.pollMs??25,probes),verdicts.map(({group,verdict})=>({launchId:group.launchId,pgid:group.pgid,verdict,...verdict==="sweep"?{survived:remaining.includes(group.pgid)}:{}}))}async function drain(pgids,budgetMs,pollMs,probes){let remaining=pgids.filter(pgid=>probes.groupHasMembers(pgid));for(let waited=0;remaining.length>0&&waited<budgetMs;waited+=pollMs)await probes.wait(pollMs),remaining=remaining.filter(pgid=>probes.groupHasMembers(pgid));return remaining}function processGroupOf(pid){return process.platform==="win32"?Promise.resolve(void 0):new Promise(resolve=>{execFile("ps",["-o","pgid=","-p",String(pid)],{timeout:2e3},(error,stdout)=>{let text=String(stdout).trim();resolve(error===null&&/^\d+$/u.test(text)?Number(text):void 0)})})}function groupHasMembers(pgid){try{return process.kill(-pgid,0),!0}catch(error){return error instanceof Error&&"code"in error&&error.code==="EPERM"}}var defaultGroupProbes={groupHasMembers,isAlive:processIsRunning,startOf:pid=>readProcessStartTime(pid),ownGroup:()=>processGroupOf(process.pid),signalGroup:(pgid,signal)=>{try{process.kill(-pgid,signal)}catch{}},wait:ms=>new Promise(resolve=>setTimeout(resolve,ms))};var SWEEP_TIMING={graceMs:500,killWaitMs:1e3};async function sweepLedger(path){let groups=(await DescendantsLedger.readPersisted(path)).flatMap(entry=>entry.pgid===void 0?[]:[{launchId:entry.launchId,pgid:entry.pgid,leaderStart:entry.leaderStart,lifetime:entry.lifetime}]);return groups.length===0?[]:sweepGroups(groups,SWEEP_TIMING)}var GENERATION_CHILD_FILE="child.pid";async function recordGenerationChild(dir,generation,pid){let generationDir=dirname3(generationLedgerPath(dir,generation));await mkdir3(generationDir,{recursive:!0,mode:448}),await writeFile3(join4(generationDir,GENERATION_CHILD_FILE),String(pid),{mode:384})}async function childAlive(file){let pid=Number(await readFile3(file,"utf8").catch(()=>""));if(!Number.isSafeInteger(pid)||pid<=1)return!1;try{return process.kill(pid,0),!0}catch(error){return Reflect.get(Object(error),"code")==="EPERM"}}async function sweepStaleGenerations(dir){let names=await readdir2(dir).catch(()=>[]),outcomes=[];for(let name of names){let generation=/^g(\d+)$/.exec(name)?.[1];generation!==void 0&&(await childAlive(join4(dir,name,GENERATION_CHILD_FILE))||(outcomes.push(...await sweepLedger(generationLedgerPath(dir,Number(generation)))),await rm4(join4(dir,name),{recursive:!0,force:!0})))}return outcomes}var TOOL_CHILD_GENERATION_ENV="SENPI_TOOL_CHILD_GENERATION",TOOL_CHILD_PROTOCOL_VERSION=2,NEVER_CANCELLED=new AbortController().signal;async function runToolChild(options){let env={...options.env??process.env},exit=options.exit??(code=>process.exit(code)),generation=Number(env[TOOL_CHILD_GENERATION_ENV]);(!Number.isSafeInteger(generation)||generation<0)&&(process.stderr.write(`tool-child: invalid generation
@@ -7,7 +7,7 @@ import{Text,truncateToWidth,visibleWidth}from"./chunk-D2ROBVZ4.js";import{getShe
7
7
  `);return content.endsWith(`
8
8
  `)&&lines.pop(),lines}function formatSize(bytes){return bytes<1024?`${bytes}B`:bytes<1024*1024?`${(bytes/1024).toFixed(1)}KB`:`${(bytes/(1024*1024)).toFixed(1)}MB`}function truncateHead(content,options={}){let maxLines=options.maxLines??2e3,maxBytes=options.maxBytes??51200,totalBytes=Buffer.byteLength(content,"utf-8"),lines=splitLinesForCounting(content),totalLines=lines.length;if(totalLines<=maxLines&&totalBytes<=maxBytes)return{content,truncated:!1,truncatedBy:null,totalLines,totalBytes,outputLines:totalLines,outputBytes:totalBytes,lastLinePartial:!1,firstLineExceedsLimit:!1,maxLines,maxBytes};if(Buffer.byteLength(lines[0],"utf-8")>maxBytes)return{content:"",truncated:!0,truncatedBy:"bytes",totalLines,totalBytes,outputLines:0,outputBytes:0,lastLinePartial:!1,firstLineExceedsLimit:!0,maxLines,maxBytes};let outputLinesArr=[],outputBytesCount=0,truncatedBy="lines";for(let i=0;i<lines.length&&i<maxLines;i++){let line=lines[i],lineBytes=Buffer.byteLength(line,"utf-8")+(i>0?1:0);if(outputBytesCount+lineBytes>maxBytes){truncatedBy="bytes";break}outputLinesArr.push(line),outputBytesCount+=lineBytes}outputLinesArr.length>=maxLines&&outputBytesCount<=maxBytes&&(truncatedBy="lines");let outputContent=outputLinesArr.join(`
9
9
  `),finalOutputBytes=Buffer.byteLength(outputContent,"utf-8");return{content:outputContent,truncated:!0,truncatedBy,totalLines,totalBytes,outputLines:outputLinesArr.length,outputBytes:finalOutputBytes,lastLinePartial:!1,firstLineExceedsLimit:!1,maxLines,maxBytes}}function truncateTail(content,options={}){let maxLines=options.maxLines??2e3,maxBytes=options.maxBytes??51200,totalBytes=Buffer.byteLength(content,"utf-8"),lines=splitLinesForCounting(content),totalLines=lines.length;if(totalLines<=maxLines&&totalBytes<=maxBytes)return{content,truncated:!1,truncatedBy:null,totalLines,totalBytes,outputLines:totalLines,outputBytes:totalBytes,lastLinePartial:!1,firstLineExceedsLimit:!1,maxLines,maxBytes};let outputLinesArr=[],outputBytesCount=0,truncatedBy="lines",lastLinePartial=!1;for(let i=lines.length-1;i>=0&&outputLinesArr.length<maxLines;i--){let line=lines[i],lineBytes=Buffer.byteLength(line,"utf-8")+(outputLinesArr.length>0?1:0);if(outputBytesCount+lineBytes>maxBytes){if(truncatedBy="bytes",outputLinesArr.length===0){let truncatedLine=truncateStringToBytesFromEnd(line,maxBytes);outputLinesArr.unshift(truncatedLine),outputBytesCount=Buffer.byteLength(truncatedLine,"utf-8"),lastLinePartial=!0}break}outputLinesArr.unshift(line),outputBytesCount+=lineBytes}outputLinesArr.length>=maxLines&&outputBytesCount<=maxBytes&&(truncatedBy="lines");let outputContent=outputLinesArr.join(`
10
- `),finalOutputBytes=Buffer.byteLength(outputContent,"utf-8");return{content:outputContent,truncated:!0,truncatedBy,totalLines,totalBytes,outputLines:outputLinesArr.length,outputBytes:finalOutputBytes,lastLinePartial,firstLineExceedsLimit:!1,maxLines,maxBytes}}function truncateStringToBytesFromEnd(str,maxBytes){let buf=Buffer.from(str,"utf-8");if(buf.length<=maxBytes)return str;let start=buf.length-maxBytes;for(;start<buf.length&&(buf[start]&192)===128;)start++;return buf.slice(start).toString("utf-8")}function truncateLine(line,maxChars=500){return line.length<=maxChars?{text:line,wasTruncated:!1}:{text:`${line.slice(0,maxChars)}... [truncated]`,wasTruncated:!0}}var PRIVATE_KEY_MARKER="[REDACTED private key]",LABEL=String.raw`((?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?)`,BEGIN=new RegExp(`-----BEGIN ${LABEL}-----`),END=new RegExp(`-----END ${LABEL}-----`),BODY=/^[A-Za-z0-9+/]{16,}={0,2}$/,PREFIXED_BODY_MIN=60,UPPER=/[A-Z]/,LOWER=/[a-z]/,BODY_CONTINUED=/^(?:[A-Za-z0-9+/]+={0,2}|=[A-Za-z0-9+/]{4})$/,ARMOR_HEADER=/^[A-Za-z][A-Za-z0-9-]*: \S/,BASE64_RUN=/[A-Za-z0-9+/]{40,}/,MAX_HELD_LINES=512;function isBase64Char(code){return code>=65&&code<=90||code>=97&&code<=122||code>=48&&code<=57||code===43||code===47}function prefixShape(prefix){return prefix.trim().replace(/\d+/g,"0")}function bodyParts(line){let trimmed=line.trim(),start=trimmed.length,pad=0;for(;start>0&&pad<2&&trimmed[start-1]==="=";)start--,pad++;let runEnd=start;for(;start>0&&isBase64Char(trimmed.charCodeAt(start-1));)start--;if(start!==runEnd)return pad===0&&runEnd-start===4&&trimmed[start-1]==="="&&start--,{shape:prefixShape(trimmed.slice(0,start)),token:trimmed.slice(start)}}function startsBody(parts){let{shape,token}=parts;return shape.length>0&&token.length<PREFIXED_BODY_MIN?!1:BODY.test(token)&&UPPER.test(token)&&LOWER.test(token)}function keyLike(line,shape){let trimmed=line.trim();if(trimmed.length===0||BODY_CONTINUED.test(trimmed)||ARMOR_HEADER.test(trimmed)||BASE64_RUN.test(trimmed))return!0;if(shape.length===0)return!1;if(prefixShape(trimmed)===shape)return!0;let parts=bodyParts(trimmed);return parts!==void 0&&parts.shape===shape&&BODY_CONTINUED.test(parts.token)}function startsWithEnd(line){let end=END.exec(line);if(!end)return!1;let begin=BEGIN.exec(line);return!begin||end.index<begin.index}var PrivateKeyLineFilter=class{#block;#blockShape="";#blockCrossedGap=!1;#gapBeforeHeld=!1;#held=[];#heldShape="";push(line){if(this.#block===void 0){let parts=bodyParts(line);if(parts&&this.#held.length>0&&parts.shape===this.#heldShape&&BODY_CONTINUED.test(parts.token))return this.#hold(line);if(parts&&startsBody(parts)){let out2=this.#releaseHeld();return this.#heldShape=parts.shape,out2.push(...this.#hold(line)),out2}}let out=[];this.#block===void 0&&startsWithEnd(line)?this.#held=[]:out.push(...this.#releaseHeld());let trimmed=line.trim();trimmed!==""&&!ARMOR_HEADER.test(trimmed)&&(this.#gapBeforeHeld=!1);let kept=this.#scan(line);return kept!==void 0&&out.push(kept),out}cut(){return this.#block!==void 0&&(this.#blockCrossedGap=!0),this.#gapBeforeHeld=!0,this.#held.length===0?[]:(this.#held=[],[PRIVATE_KEY_MARKER])}finish(){let out=this.#releaseHeld();return this.#block=void 0,this.#blockCrossedGap=!1,this.#gapBeforeHeld=!1,out}#hold(line){return this.#held.push(line),this.#held.length>MAX_HELD_LINES?[this.#held.shift()]:[]}#releaseHeld(){let held=this.#held;return this.#held=[],held.length===0?[]:this.#gapBeforeHeld?[PRIVATE_KEY_MARKER]:held}#scan(line){let rest=line,kept="",touched=!1,marked=!1;for(;;){if(this.#block!==void 0){touched=!0;let close=`-----END ${this.#block}-----`,at=rest.indexOf(close);if(at!==-1){this.#closeBlock(),rest=rest.slice(at+close.length);continue}if(this.#blockCrossedGap&&!keyLike(rest,this.#blockShape)){this.#closeBlock();continue}break}let begin=BEGIN.exec(rest),end=END.exec(rest);if(end&&(!begin||end.index<begin.index)){kept+=PRIVATE_KEY_MARKER,touched=marked=!0,rest=rest.slice(end.index+end[0].length);continue}if(begin){kept+=rest.slice(0,begin.index)+PRIVATE_KEY_MARKER,touched=marked=!0,this.#block=begin[1],this.#blockShape=prefixShape(rest.slice(0,begin.index)),rest=rest.slice(begin.index+begin[0].length);continue}kept+=rest;break}return touched?marked||kept.trim().length>0?kept:void 0:line}#closeBlock(){this.#block=void 0,this.#blockCrossedGap=!1}};var secretOutputObfuscator=()=>new SecretOutputRedactor,JobWidgetSourceRedactor=class{#keys=new PrivateKeyLineFilter;#obfuscator;#stream;#partial="";constructor(obfuscator){this.#obfuscator=obfuscator}push(line){return this.#obfuscate(this.#keys.push(line))}cut(){return this.#obfuscate(this.#keys.cut())}finish(){let out=this.#obfuscate(this.#keys.finish());return this.#stream&&(this.#partial+=this.#stream.finish(),this.#stream=void 0),this.#partial.length>0&&out.push(redactSecrets(this.#partial)),this.#partial="",out}#obfuscate(lines){if(!this.#obfuscator)return lines.map(line=>redactSecrets(line));if(lines.length===0)return[];this.#stream??=this.#obfuscator();let stream=this.#stream,out=[];for(let line of lines){let parts=(this.#partial+stream.push(`${line}
10
+ `),finalOutputBytes=Buffer.byteLength(outputContent,"utf-8");return{content:outputContent,truncated:!0,truncatedBy,totalLines,totalBytes,outputLines:outputLinesArr.length,outputBytes:finalOutputBytes,lastLinePartial,firstLineExceedsLimit:!1,maxLines,maxBytes}}function truncateStringToBytesFromEnd(str,maxBytes){let buf=Buffer.from(str,"utf-8");if(buf.length<=maxBytes)return str;let start=buf.length-maxBytes;for(;start<buf.length&&(buf[start]&192)===128;)start++;return buf.slice(start).toString("utf-8")}function truncateLine(line,maxChars=500){return line.length<=maxChars?{text:line,wasTruncated:!1}:{text:`${line.slice(0,maxChars)}... [truncated]`,wasTruncated:!0}}var PRIVATE_KEY_MARKER="[REDACTED private key]",LABEL=String.raw`((?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?)`,BEGIN=new RegExp(`-----BEGIN ${LABEL}-----`),END=new RegExp(`-----END ${LABEL}-----`),BODY=/^[A-Za-z0-9+/]{16,}={0,2}$/,PREFIXED_BODY_MIN=60,UPPER=/[A-Z]/,LOWER=/[a-z]/,BODY_CONTINUED=/^(?:[A-Za-z0-9+/]+={0,2}|=[A-Za-z0-9+/]{4})$/,ARMOR_HEADER=/^[A-Za-z][A-Za-z0-9-]*: \S/,BASE64_RUN=/[A-Za-z0-9+/]{40,}/,MAX_HELD_LINES=512;function isBase64Char(code){return code>=65&&code<=90||code>=97&&code<=122||code>=48&&code<=57||code===43||code===47}function prefixShape(prefix){return prefix.trim().replace(/\d+/g,"0")}function bodyParts(line){let trimmed=line.trim(),start=trimmed.length,pad=0;for(;start>0&&pad<2&&trimmed[start-1]==="=";)start--,pad++;let runEnd=start;for(;start>0&&isBase64Char(trimmed.charCodeAt(start-1));)start--;if(start!==runEnd)return pad===0&&runEnd-start===4&&trimmed[start-1]==="="&&start--,{shape:prefixShape(trimmed.slice(0,start)),token:trimmed.slice(start)}}function startsBody(parts){let{shape,token:token2}=parts;return shape.length>0&&token2.length<PREFIXED_BODY_MIN?!1:BODY.test(token2)&&UPPER.test(token2)&&LOWER.test(token2)}function keyLike(line,shape){let trimmed=line.trim();if(trimmed.length===0||BODY_CONTINUED.test(trimmed)||ARMOR_HEADER.test(trimmed)||BASE64_RUN.test(trimmed))return!0;if(shape.length===0)return!1;if(prefixShape(trimmed)===shape)return!0;let parts=bodyParts(trimmed);return parts!==void 0&&parts.shape===shape&&BODY_CONTINUED.test(parts.token)}function startsWithEnd(line){let end=END.exec(line);if(!end)return!1;let begin=BEGIN.exec(line);return!begin||end.index<begin.index}var PrivateKeyLineFilter=class{#block;#blockShape="";#blockCrossedGap=!1;#gapBeforeHeld=!1;#held=[];#heldShape="";push(line){if(this.#block===void 0){let parts=bodyParts(line);if(parts&&this.#held.length>0&&parts.shape===this.#heldShape&&BODY_CONTINUED.test(parts.token))return this.#hold(line);if(parts&&startsBody(parts)){let out2=this.#releaseHeld();return this.#heldShape=parts.shape,out2.push(...this.#hold(line)),out2}}let out=[];this.#block===void 0&&startsWithEnd(line)?this.#held=[]:out.push(...this.#releaseHeld());let trimmed=line.trim();trimmed!==""&&!ARMOR_HEADER.test(trimmed)&&(this.#gapBeforeHeld=!1);let kept=this.#scan(line);return kept!==void 0&&out.push(kept),out}cut(){return this.#block!==void 0&&(this.#blockCrossedGap=!0),this.#gapBeforeHeld=!0,this.#held.length===0?[]:(this.#held=[],[PRIVATE_KEY_MARKER])}finish(){let out=this.#releaseHeld();return this.#block=void 0,this.#blockCrossedGap=!1,this.#gapBeforeHeld=!1,out}#hold(line){return this.#held.push(line),this.#held.length>MAX_HELD_LINES?[this.#held.shift()]:[]}#releaseHeld(){let held=this.#held;return this.#held=[],held.length===0?[]:this.#gapBeforeHeld?[PRIVATE_KEY_MARKER]:held}#scan(line){let rest=line,kept="",touched=!1,marked=!1;for(;;){if(this.#block!==void 0){touched=!0;let close=`-----END ${this.#block}-----`,at=rest.indexOf(close);if(at!==-1){this.#closeBlock(),rest=rest.slice(at+close.length);continue}if(this.#blockCrossedGap&&!keyLike(rest,this.#blockShape)){this.#closeBlock();continue}break}let begin=BEGIN.exec(rest),end=END.exec(rest);if(end&&(!begin||end.index<begin.index)){kept+=PRIVATE_KEY_MARKER,touched=marked=!0,rest=rest.slice(end.index+end[0].length);continue}if(begin){kept+=rest.slice(0,begin.index)+PRIVATE_KEY_MARKER,touched=marked=!0,this.#block=begin[1],this.#blockShape=prefixShape(rest.slice(0,begin.index)),rest=rest.slice(begin.index+begin[0].length);continue}kept+=rest;break}return touched?marked||kept.trim().length>0?kept:void 0:line}#closeBlock(){this.#block=void 0,this.#blockCrossedGap=!1}};var secretOutputObfuscator=()=>new SecretOutputRedactor,JobWidgetSourceRedactor=class{#keys=new PrivateKeyLineFilter;#obfuscator;#stream;#partial="";constructor(obfuscator){this.#obfuscator=obfuscator}push(line){return this.#obfuscate(this.#keys.push(line))}cut(){return this.#obfuscate(this.#keys.cut())}finish(){let out=this.#obfuscate(this.#keys.finish());return this.#stream&&(this.#partial+=this.#stream.finish(),this.#stream=void 0),this.#partial.length>0&&out.push(redactSecrets(this.#partial)),this.#partial="",out}#obfuscate(lines){if(!this.#obfuscator)return lines.map(line=>redactSecrets(line));if(lines.length===0)return[];this.#stream??=this.#obfuscator();let stream=this.#stream,out=[];for(let line of lines){let parts=(this.#partial+stream.push(`${line}
11
11
  `)).split(`
12
12
  `);this.#partial=parts.pop()??"";for(let part of parts)out.push(redactSecrets(part))}return out}};function createWidgetRedactor(obfuscate){let source=()=>new JobWidgetSourceRedactor(obfuscate);return{source,text:text=>{let lines=source(),out=text.split(`
13
13
  `).flatMap(line=>lines.push(line));return redactSecrets([...out,...lines.finish()].join(`
@@ -31,7 +31,7 @@ import{Text,truncateToWidth,visibleWidth}from"./chunk-D2ROBVZ4.js";import{getShe
31
31
  `));lastBreak>=0&&(this.#partialAfterCr=combined[lastBreak]==="\r");let raw=combined.replace(/\r\n?/g,`
32
32
  `).split(`
33
33
  `);this.#partial=(raw.pop()??"").slice(0,4096*2),(flush||!chunk.open)&&this.#partial.length>0&&(raw.push(this.#partial),this.#partial="");let clean=raw.map(sanitizeLine),redactor=this.#redactor;return{lines:(redactor?[...skipped?redactor.cut():[],...clean.flatMap(line=>redactor.push(line)),...flush||!chunk.open?redactor.finish():[]]:clean).map(line=>line.slice(0,4096)),open:chunk.open,end:chunk.end}}get progress(){if(!this.#partialAfterCr||this.#partial.length===0)return;let line=sanitizeLine(this.#partial.replace(UNFINISHED_ESCAPE,"")).slice(0,4096).replace(OPEN_TOKEN_TAIL,"").trim();return line.length>0?line:void 0}};function ruleReadsSource(from,id){return from==="*"?!0:from.endsWith("*")?id.startsWith(from.slice(0,-1)):from===id}function ruleFields(rule){let fields=[];for(let group of new Set(patternGroupNames(rule.match)))group!==rule.key&&fields.push({field:group,text:group===rule.text,count:!1});return rule.count!==void 0&&fields.push({field:rule.count,text:!1,count:!0}),fields}function aggNeedsValue(agg){return agg!=="count"&&agg!=="rate"}function fieldFeeds(spec){let fields=new Map;for(let rule of spec.rules)for(let{field,text,count}of ruleFields(rule)){let feed=fields.get(field)??{value:!1,text:!1,keyGroups:new Set};feed.value||=!text&&!count,feed.text||=text,rule.key!==void 0&&feed.keyGroups.add(rule.key),fields.set(field,feed)}return fields}function keyedFields(spec){let keyed=new Set;for(let rule of spec?.rules??[])if(rule.key!==void 0)for(let{field}of ruleFields(rule))keyed.add(field);return keyed}function pinnedKeys(spec){let pinned=new Map,pin=ref=>{if(ref?.key===void 0)return;let keys=pinned.get(ref.field)??new Set;keys.add(ref.key),pinned.set(ref.field,keys)};pin(spec?.headline);for(let block of spec?.blocks??[])if(block.kind==="spark")pin(block);else if(block.kind==="meter")pin(block),typeof block.total!="number"&&pin(block.total);else if(block.kind==="stat")for(let item of block.items)pin(item);return pinned}var NUMBER_PREFIX=/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/,SUFFIX_SCALE={k:1e3,K:1e3,M:1e6,G:1e9},WRITTEN_NUMBER=/\d[\d,_]*(?:\.\d+)?[kKMG]?/g;function parseWidgetValue(text){let first=text.charCodeAt(0);if(first>=48&&first<=57&&!/[xXbBoO]/.test(text.charAt(1))){let plain2=Number(text);if(Number.isFinite(plain2))return plain2}let compact=text.trim().replace(/[,_]/g,""),match=NUMBER_PREFIX.exec(compact);return match?Number.parseFloat(match[0])*(SUFFIX_SCALE[compact.charAt(match[0].length)]??1):Number.NaN}function statedNumbers(texts){let stated=new Set;for(let text of texts)for(let match of text.matchAll(WRITTEN_NUMBER))stated.add(parseWidgetValue(match[0]));return stated}function compileRule(rule,groups){let captures=[];return groups.forEach((field,index)=>{field!==rule.key&&captures.push({index,field,text:field===rule.text})}),{key:rule.key===void 0?-1:groups.indexOf(rule.key),captures,count:rule.count,scale:rule.scale??1}}function compileSourceMatcher(spec,matcher,sourceId){let byPattern=new Map;for(let rule of spec.rules){if(!ruleReadsSource(rule.from,sourceId))continue;let rules=byPattern.get(rule.match);rules?rules.push(rule):byPattern.set(rule.match,[rule])}if(byPattern.size===0)return;let patterns=[...byPattern.keys()],compiled=compilePatterns(matcher,patterns);return{compiled,rules:patterns.map((pattern,index)=>(byPattern.get(pattern)??[]).map(rule=>compileRule(rule,compiled.groupNames[index])))}}function applyMatches(entry,lines,t,store){let matched=new Set;for(let hit of entry.compiled.matchLines(lines)){matched.add(hit.line);let line=lines[hit.line];for(let rule of entry.rules[hit.pattern]){let keySpan=rule.key<0?void 0:hit.spans[rule.key],key=keySpan?line.slice(keySpan.start,keySpan.end).trim():"";for(let capture of rule.captures){let span=hit.spans[capture.index];if(!span)continue;let captured=line.slice(span.start,span.end),value=capture.text?Number.NaN:parseWidgetValue(captured)*rule.scale;Number.isFinite(value)?store.push(capture.field,key,{value,text:void 0,line,t}):store.push(capture.field,key,{value:void 0,text:captured.trim(),line,t})}rule.count!==void 0&&store.push(rule.count,key,{value:void 0,text:void 0,line,t})}}return matched}var SAMPLE_HEAD_LINES=30,SAMPLE_TAIL_LINES=60,MAX_STAGE_CHARS=200;function newSourceStats(id,label){return{id,label,size:0,lines:0,head:[],tail:[],lastActiveAt:0,recent:[]}}function recordLines(stats,lines,t){let fresh=0,tailFrom=0;for(let index=0;index<lines.length;index++)lines[index].trim().length!==0&&(fresh+=1,stats.head.length<SAMPLE_HEAD_LINES&&(stats.head.push(lines[index]),tailFrom=index+1));if(fresh===0)return!1;let newest=[];for(let index=lines.length-1;index>=tailFrom&&newest.length<SAMPLE_TAIL_LINES;index--)lines[index].trim().length>0&&newest.push(lines[index]);return newest.length>0?(stats.lastLine=newest[0],newest.reverse(),stats.tail=[...stats.tail,...newest].slice(-SAMPLE_TAIL_LINES)):stats.lastLine=stats.head.at(-1),stats.lines+=fresh,stats.lastActiveAt=t,stats.recent.push({t,n:fresh}),trimWindow(stats.recent,t),!0}function latestLine(all){let best,bestIsPipe=!1;for(let stats of all){if(!stats.lastLine)continue;let isPipe=/(?:^|:)pipe:/.test(stats.id);(!best||isPipe&&!bestIsPipe||isPipe===bestIsPipe&&stats.lastActiveAt>=best.lastActiveAt)&&(best=stats,bestIsPipe=isPipe)}return best?.lastLine?truncateText(best.lastLine.trim(),MAX_STAGE_CHARS):void 0}function sourceSample(stats){return{id:stats.id,label:stats.label,size:stats.size,lines:stats.lines,head:stats.head.slice(),tail:stats.tail.slice()}}function sampleLines(samples){return samples.map(sample=>({id:sample.id,lines:[...sample.head,...sample.tail]}))}var JOB_WIDGET_AGGS=["last","first","min","max","mean","sum","count","rate","delta","change"];var FIELD_NAME=/^[a-z][a-z0-9_]{0,23}$/,GROUP_NAME=/^[A-Za-z_][A-Za-z0-9_]{0,31}$/,SOURCE_ID=/^(?:\*|[A-Za-z0-9_:.-]{1,64}\*?)$/;var SPARK_POINTS=48,MAX_BAR_ITEMS=16,MAX_GRID_CELLS=48,MAX_TEXT_CHARS=200,TREND_AGGS=new Set(["last","min","max"]);function buildValue(ref,ctx){let series=ctx.store.series(ref.field,ref.key),value=aggregateSeries(series,ref.agg,ctx.now,ctx.startTime),unit=ref.agg==="change"?"%":ref.unit,text=value===void 0?MISSING_VALUE_TEXT:formatWidgetNumber(value,unit,ref.digits),trend=ref.better&&TREND_AGGS.has(ref.agg)&&series.values>=2?formatWidgetTrend(series.first,series.last,ref.better,ref.unit):void 0;return{text,value,...trend?{trend}:{}}}function buildHeadline(ref,ctx){let{text,value,trend}=buildValue(ref,ctx);if(value!==void 0)return{text,...ref.label?{label:ref.label}:{},...trend?{trend}:{}}}function buildBlock(block,ctx){switch(block.kind){case"spark":return buildSpark(block,ctx);case"bars":{let entries=ctx.store.keys(block.field,MAX_BAR_ITEMS),unit=block.agg==="change"?"%":block.unit,values=entries.map(([,series])=>aggregateSeries(series,block.agg,ctx.now,ctx.startTime)??0),labels=keyLabels(entries.map(([key])=>key)),items=entries.map(([key],index)=>({key:labels[index]||key||block.label,value:values[index],text:formatWidgetNumber(values[index],unit)})),peak=Math.max(0,...values);return{kind:"bars",label:block.label,items,max:block.max??(peak>0?peak:1)}}case"meter":{let series=ctx.store.series(block.field,block.key),value=aggregateSeries(series,block.agg,ctx.now,ctx.startTime)??0,total=typeof block.total=="number"?block.total:buildValue(block.total,ctx).value??0,fraction=total>0?Math.min(1,Math.max(0,value/total)):0,text=`${formatWidgetNumber(value)}/${formatWidgetNumber(total,meterUnit(block.unit,total))}`;return{kind:"meter",label:block.label,value:fraction,text}}case"stat":return{kind:"stat",items:block.items.map(item=>{let{text,trend}=buildValue(item,ctx);return{label:item.label,text,...trend?{trend}:{}}})};case"grid":{let entries=ctx.store.keys(block.field,MAX_GRID_CELLS),labels=keyLabels(entries.map(([key])=>key));return{kind:"grid",label:block.label,cells:entries.map(([key,series],index)=>{let raw=series.text??(series.values>0?formatWidgetNumber(series.last):series.line?.trim()??""),text=truncateText(raw,MAX_TEXT_CHARS);return{key:labels[index]||key||block.label,tone:gridTone(block.tones,text),text}})}}case"text":{let series=ctx.store.series(block.field);return{kind:"text",text:truncateText(series.text??series.line?.trim()??"",MAX_TEXT_CHARS)}}}}function meterUnit(unit,total){if(!unit)return;let match=/^\s*(?:\/|out of\b|of\b)?\s*([^\s/]+)\s*(.*)$/i.exec(unit);return!match||!new Set([String(total),formatWidgetNumber(total)]).has(match[1].replaceAll(",",""))?unit:match[2].trim()||void 0}function buildSpark(block,ctx){let series=ctx.store.series(block.field,block.key),ring=series.ring.length>240?series.ring.slice(-240):series.ring,values=downsample(ring,SPARK_POINTS).map(point=>point.v),marks=block.target===void 0?void 0:[{value:block.target,label:block.targetLabel??`target ${formatWidgetNumber(block.target,block.unit)}`}],{min,max}=sparkDomain([...values,...(marks??[]).map(mark=>mark.value)],block.min,block.max);return{kind:"spark",label:block.label,values,min,max,...marks?{marks}:{},last:series.values>0?formatWidgetNumber(series.last,block.unit):MISSING_VALUE_TEXT}}function sparkDomain(bounds,specMin,specMax){let min=0,max=1;if(bounds.length>0){let lo=Math.min(...bounds),hi=Math.max(...bounds),pad=hi>lo?(hi-lo)*.1:Math.max(1,Math.abs(hi)*.05);min=lo>=0?Math.max(0,lo-pad):lo-pad,max=hi+pad}return min=specMin??min,max=specMax??max,max<=min&&(max=min+1),{min,max}}function hasData(block){switch(block.kind){case"text":return block.text.length>0;case"bars":return block.items.length>0;case"grid":return block.cells.length>0;case"spark":return block.values.length>0;case"meter":case"stat":return!0}}function keyLabels(keys){if(keys.length===0||!keys.every(key=>key.includes("/")))return keys.slice();let short=keys.map(key=>key.slice(key.lastIndexOf("/")+1));return short.every(label=>label.length>0)&&new Set(short).size===short.length?short:keys.slice()}function gridTone(tones,text){let lower=text.toLowerCase();for(let[status,tone]of Object.entries(tones))if(lower.includes(status.toLowerCase()))return tone;return"neutral"}var MAX_MATCH_LINES=2e3,JobWidgetRuntime=class{#matcher;#startTime;#now;#redactSource;#readers=new Map;#stats=new Map;#matchers=new Map;#store;#lastMatchAt;#lastLineAt;#unmatchedLines=0;#lastUnmatchedLine;#progress;constructor(options){this.spec=options.spec,this.#matcher=options.matcher,this.#startTime=options.startTime,this.#now=options.now??Date.now,this.#redactSource=options.redactSource,this.#store=new FieldStore(keyedFields(options.spec),pinnedKeys(options.spec))}get unmatchedLines(){return this.#unmatchedLines}get lastMatchAt(){return this.#lastMatchAt}get totalLines(){let total=0;for(let stats of this.#stats.values())total+=stats.lines;return total}get linesPerSecond(){let recent=[...this.#stats.values()].flatMap(stats=>stats.recent);return windowRate(recent,this.#now(),this.#startTime)}ingest(sources,flush){let t=this.#now(),changed=!1;for(let source of sources){let reader=this.#readers.get(source.id);(!reader||reader.source!==source)&&(reader=new SourceLineReader(source,this.#redactSource?.()),this.#readers.set(source.id,reader));let{lines,end}=reader.read(flush),progress=reader.progress;if(progress!==void 0){let once=this.#redactSource?.(),text=once?[...once.push(progress),...once.finish()].join(" "):progress;this.#progress=truncateText(text.trim(),MAX_STAGE_CHARS)}else lines.length>0&&(this.#progress=void 0);let stats=this.#stats.get(source.id);stats||(stats=newSourceStats(source.id,source.label),this.#stats.set(source.id,stats)),stats.size=end,lines.length!==0&&(changed=!0,recordLines(stats,lines,t)&&(this.#lastLineAt=t),this.#matchLines(source.id,lines,t))}return changed}#sourceMatcher(id){let known=this.#matchers.get(id);if(known!==void 0)return known??void 0;let entry=this.spec?compileSourceMatcher(this.spec,this.#matcher,id):void 0;return this.#matchers.set(id,entry??null),entry}#matchLines(sourceId,lines,t){let entry=this.#sourceMatcher(sourceId);if(!entry)return;let window=lines.length>MAX_MATCH_LINES?lines.slice(-MAX_MATCH_LINES):lines,matched=applyMatches(entry,window,t,this.#store),lastMatched=matched.size>0?Math.max(...matched):-1;lastMatched>=0&&(this.#lastMatchAt=t);let unmatched=0;for(let index=lastMatched+1;index<window.length;index++)window[index].trim().length>0&&(unmatched+=1);this.#unmatchedLines=lastMatched>=0?unmatched:this.#unmatchedLines+unmatched;for(let index=window.length-1;index>=0;index--){let line=window[index].trim();if(!(matched.has(index)||line.length===0)){this.#lastUnmatchedLine=truncateText(line,MAX_STAGE_CHARS);break}}}samples(){return[...this.#stats.values()].filter(stats=>stats.lines>0).sort((a,b)=>b.lines-a.lines).map(sourceSample)}derive(context){let now=this.#now(),updatedAtMs=this.#lastMatchAt??this.#lastLineAt??this.#startTime,lineStage=context.lineStage===!0,spec=this.spec;if(!spec){let stage2=context.stage??(lineStage?this.#progress??latestLine(this.#stats.values()):void 0),title=truncateText(context.label.replace(/\s+/g," ").trim(),48);return{state:context.authoring?"pending":"fallback",view:{title,...stage2?{stage:stage2}:{},blocks:[],lines:this.totalLines},updatedAtMs}}let ctx={store:this.#store,now,startTime:this.#startTime},headline=spec.headline?buildHeadline(spec.headline,ctx):void 0,stage=(spec.stage?this.#specStage(spec.stage):void 0)??context.stage??(lineStage?this.#progress??this.#lastUnmatchedLine:void 0);return{state:context.settled?"done":"live",view:{title:spec.title,...headline?{headline}:{},...stage?{stage}:{},blocks:spec.blocks.map(block=>buildBlock(block,ctx)).filter(hasData)},updatedAtMs}}#specStage(field){let series=this.#store.series(field),text=(series.text??series.line)?.trim();return text?truncateText(text,MAX_STAGE_CHARS):void 0}};var JobWidgetJob=class{#matcher;#redact;#asked;#authoring;#skippedAtMs;constructor(input,matcher,redact){this.settled=!1,this.#asked=!1,this.#authoring=!1,this.id=input.id,this.kind=input.kind,this.startTime=input.startedAtMs??Date.now(),this.sources=input.sources,this.brief={...input.brief,kind:input.kind},this.#matcher=matcher,this.#redact=redact,this.runtime=this.#newRuntime(void 0)}#newRuntime(spec){return new JobWidgetRuntime({spec,matcher:this.#matcher,startTime:this.startTime,redactSource:()=>this.#redact.source()})}ingest(){this.runtime.ingest(this.sources,this.settled)}requestStarted(){this.#asked=!0,this.#authoring=!0}requestSettled(outcome){this.#authoring=!1,outcome.kind==="installed"?(this.runtime=this.#newRuntime(outcome.spec),this.ingest()):outcome.kind==="skipped"&&!this.runtime.spec&&(this.#skippedAtMs=Date.now())}entry(){if(this.#skippedAtMs!==void 0)return{id:this.id,kind:this.kind,state:"skipped",updatedAtMs:this.#skippedAtMs};if(!this.#asked)return;let brief=this.brief,derived=this.runtime.derive({label:this.#redact.text(brief.intent??brief.task??brief.command??this.id),...brief.stage===void 0?{}:{stage:this.#redact.text(brief.stage)},lineStage:this.kind==="bash",authoring:this.#authoring,settled:this.settled});return{id:this.id,kind:this.kind,state:derived.state,view:derived.view,updatedAtMs:derived.updatedAtMs}}};var JOB_WIDGET_REQUEST_LIMITS={authorAfterMs:15e3,minLines:3,maxRequestsPerJob:3,maxInFlight:2,maxPerHour:30,driftLines:200,driftStaleMs:9e4,noModelRetryMs:3e4},REQUEST_WINDOW_MS=3600*1e3;function newAuthoringState(){return{requests:0,inFlight:!1,stopped:!1,specHadWatch:!1}}function reauthorReason(job,state,now,limits){let{brief,runtime}=job;if(brief.watch&&!state.specHadWatch)return`the subagent now says what to watch: ${brief.watch}`;if(runtime.unmatchedLines<limits.driftLines)return;let newest=runtime.lastMatchAt;if(!(newest!==void 0&&now-newest<=limits.driftStaleMs))return`no rule matched the last ${runtime.unmatchedLines} lines`}function planRequest(job,state,now,limits){if(state.inFlight||state.stopped||state.requests>=limits.maxRequestsPerJob||now-job.startTime<limits.authorAfterMs)return;let{brief,runtime}=job;if(brief.kind==="task"&&!brief.watch)return;let skipped=state.skippedWatch;if(!(skipped!==void 0&&(brief.kind==="bash"||skipped===brief.watch))){if(runtime.spec){let reason=reauthorReason(job,state,now,limits);return reason?{previous:{spec:runtime.spec,reason}}:void 0}return runtime.samples().some(sample=>sample.lines>=limits.minLines)?{}:void 0}}var TOOLS_SOURCE_ID="tools";function dryRun(spec,compiled,samples,numeric,errors){let seen=!1,matches=0,marked=new Set,numbers=new Set,words=new Map;for(let sample of samples)if(sample.lines.some(line=>line.trim().length>0)){seen=!0;for(let hit of compiled.matchLines(sample.lines)){let rule=spec.rules[hit.pattern];if(!ruleReadsSource(rule.from,sample.id))continue;matches+=1;let line=sample.lines[hit.line];sample.id===TOOLS_SOURCE_ID&&line.startsWith("\xBB ")&&marked.add(hit.pattern),compiled.groupNames[hit.pattern].forEach((field,position)=>{let span=hit.spans[position];if(field===rule.key||field===rule.text||span===void 0)return;let captured=line.slice(span.start,span.end);Number.isFinite(parseWidgetValue(captured))?numbers.add(field):words.has(field)||words.set(field,captured)})}}seen&&matches===0&&errors.push("no rule matches any sample line; copy the exact text of lines that carry the numbers");for(let index of marked)errors.push(`rules[${index}]: matches \`${"\xBB "}<tool> <intent>\` lines, which mark the subagent's tool calls, not its output; read the result lines below them, or skip if none show progress`);for(let[field,where]of numeric){let word=words.get(field);word===void 0||numbers.has(field)||errors.push(`${where}: field "${field}" needs numbers, but its group captured "${truncateText(word,40)}" in the samples; capture only the digits`)}}function checkStatedNumbers(spec,samples,brief,errors){let stated=statedNumbers([brief,...samples.flatMap(sample=>sample.lines)]);spec.blocks.forEach((block,index)=>{let where=`blocks[${index}] (${block.kind})`;block.kind==="meter"&&typeof block.total=="number"&&!stated.has(block.total)?errors.push(`${where}.total: ${block.total} appears nowhere in the job or its output; read the total from a line (a value ref) or show the value as a stat`):block.kind==="spark"&&block.target!==void 0&&!stated.has(block.target)&&errors.push(`${where}.target: ${block.target} appears nowhere in the job or its output; set a target only when the job states one`)})}var JOB_WIDGET_TONES=["success","error","warning","pending","info","muted","neutral"];function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function readList(value,where,errors,min,max){if(!Array.isArray(value)){errors.push(`${where}: expected an array`);return}if(value.length<min||value.length>max){errors.push(`${where}: expected ${min}\u2013${max} entries, got ${value.length}`);return}return value}function readString(value,where,errors,options={}){if(value==null){options.required&&errors.push(`${where}: required`);return}if(typeof value!="string"){errors.push(`${where}: expected a string`);return}let trimmed=value.trim();if(trimmed.length===0){options.required&&errors.push(`${where}: must not be empty`);return}if(options.max!==void 0&&trimmed.length>options.max){errors.push(`${where}: at most ${options.max} characters`);return}return options.cut===void 0?trimmed:truncateText(trimmed,options.cut)}function readNumber(value,where,errors){if(value!=null){if(typeof value!="number"||!Number.isFinite(value)){errors.push(`${where}: expected a finite number`);return}return value}}function readFieldName(value,where,errors){let name=readString(value,where,errors,{required:!0});if(name!==void 0&&!FIELD_NAME.test(name)){errors.push(`${where}: "${name}" must match ${FIELD_NAME.source}`);return}return name}function readAgg(value,where,errors,fallback){if(value==null&&fallback!==void 0)return fallback;let agg=JOB_WIDGET_AGGS.find(candidate=>candidate===value);return agg===void 0&&errors.push(`${where}: expected one of ${JOB_WIDGET_AGGS.join(", ")}`),agg}function readBetter(value,where,errors){if(value!=null){if(value==="higher"||value==="lower")return value;errors.push(`${where}: expected "higher" or "lower"`)}}function readTone(value,where,errors){let tone=JOB_WIDGET_TONES.find(candidate=>candidate===value);return tone===void 0&&errors.push(`${where}: expected one of ${JOB_WIDGET_TONES.join(", ")}`),tone}function optional(value,name){return value===void 0?{}:{[name]:value}}function parseValueRef(value,where,errors,defaultAgg){if(!isRecord(value)){errors.push(`${where}: expected an object`);return}let field=readFieldName(value.field,`${where}.field`,errors),key=readString(value.key,`${where}.key`,errors,{max:120}),agg=readAgg(value.agg,`${where}.agg`,errors,defaultAgg),unit=readString(value.unit,`${where}.unit`,errors,{cut:12}),digits=readNumber(value.digits,`${where}.digits`,errors);digits!==void 0&&(!Number.isInteger(digits)||digits<0||digits>4)&&errors.push(`${where}.digits: expected an integer 0\u20134`);let better=readBetter(value.better,`${where}.better`,errors);if(!(field===void 0||agg===void 0))return{field,agg,...key!==void 0?{key}:{},...unit!==void 0?{unit}:{},...digits!==void 0?{digits}:{},...better!==void 0?{better}:{}}}function repairRuleGroups(match,key,text){let groups=new Set(patternGroupNames(match)),wrap=text!==void 0&&FIELD_NAME.test(text)&&groups.size===0,keyGroup=key!==void 0&&groups.has(key)?key:void 0,textGroup=text!==void 0&&(wrap||groups.has(text))?text:void 0;return{match:wrap?`(?P<${text}>${match})`:match,...keyGroup!==void 0?{key:keyGroup}:{},...textGroup!==void 0?{text:textGroup}:{}}}function readMeterTotal(raw){let whole=typeof raw=="string"?Number(raw):raw;return isRecord(whole)?{kind:"ref",value:whole}:typeof whole=="number"&&!Number.isNaN(whole)?{kind:"number",value:whole}:{kind:"unknown"}}var DEFAULT_BLOCK_AGG="last";function parseBlock(value,where,errors){if(!isRecord(value)){errors.push(`${where}: expected an object`);return}let before=errors.length,block=parseBlockKind(value,where,errors);return errors.length===before?block:void 0}function parseBlockKind(value,where,errors){let label=()=>readString(value.label,`${where}.label`,errors,{cut:48,required:!0})??"",unit=()=>optional(readString(value.unit,`${where}.unit`,errors,{cut:12}),"unit"),field=()=>readFieldName(value.field,`${where}.field`,errors)??"",key=()=>optional(readString(value.key,`${where}.key`,errors,{max:120}),"key"),better=()=>optional(readBetter(value.better,`${where}.better`,errors),"better"),agg=()=>readAgg(value.agg,`${where}.agg`,errors,DEFAULT_BLOCK_AGG)??DEFAULT_BLOCK_AGG;switch(value.kind){case"spark":return{kind:"spark",field:field(),label:label(),...key(),...unit(),...better(),...optional(readNumber(value.target,`${where}.target`,errors),"target"),...optional(readString(value.targetLabel,`${where}.targetLabel`,errors,{cut:48}),"targetLabel"),...optional(readNumber(value.min,`${where}.min`,errors),"min"),...optional(readNumber(value.max,`${where}.max`,errors),"max")};case"bars":return{kind:"bars",field:field(),agg:agg(),label:label(),...unit(),...optional(readNumber(value.max,`${where}.max`,errors),"max"),...better()};case"meter":return parseMeter(value,where,errors,{field,agg,label,key,unit});case"stat":return{kind:"stat",items:parseStatItems(value.items,`${where}.items`,errors)};case"grid":return{kind:"grid",field:field(),label:label(),tones:parseTones(value.tones,where,errors)};case"text":return{kind:"text",field:field()};default:errors.push(`${where}.kind: expected spark, bars, meter, stat, grid or text`);return}}function parseMeter(value,where,errors,read){let whole=readMeterTotal(value.total);if(whole.kind==="unknown"){let ref=parseValueRef(value,where,errors,DEFAULT_BLOCK_AGG);return ref&&{kind:"stat",items:[{...ref,label:read.label()}]}}let total;return whole.kind==="number"?!Number.isFinite(whole.value)||whole.value<=0?errors.push(`${where}.total: expected a positive number`):total=whole.value:total=parseValueRef(whole.value,`${where}.total`,errors),{kind:"meter",field:read.field(),agg:read.agg(),total:total??1,label:read.label(),...read.key(),...read.unit()}}function parseStatItems(value,where,errors){let items=[];return readList(value,where,errors,1,4)?.forEach((item,index)=>{let itemWhere=`${where}[${index}]`,ref=parseValueRef(item,itemWhere,errors),label=isRecord(item)?readString(item.label,`${itemWhere}.label`,errors,{cut:48,required:!0}):void 0;ref&&label!==void 0&&items.push({...ref,label})}),items}function parseTones(value,where,errors){let tones={};if(!isRecord(value))return errors.push(`${where}.tones: expected an object of status substring \u2192 tone`),tones;let entries=Object.entries(value);entries.length>12&&errors.push(`${where}.tones: at most ${12} entries`);for(let[status,raw]of entries.slice(0,12)){let tone=readTone(raw,`${where}.tones.${status}`,errors);tone!==void 0&&(tones[status]=tone)}return tones}function parseSpec(value,errors){if(!isRecord(value)){errors.push("spec: expected an object");return}let title=readString(value.title,"title",errors,{cut:48,required:!0}),rules=readList(value.rules,"rules",errors,1,12)?.map((rule,index)=>parseRule(rule,`rules[${index}]`,errors)),blocks=readList(value.blocks,"blocks",errors,1,4)?.map((block,index)=>parseBlock(block,`blocks[${index}]`,errors)),headline=value.headline===void 0?void 0:parseHeadline(value.headline,errors),stage=value.stage===void 0?void 0:readFieldName(value.stage,"stage",errors);if(errors.length>0||title===void 0||!rules||!blocks)return;let presentRules=rules.filter(rule=>rule!==void 0),presentBlocks=blocks.filter(block=>block!==void 0);if(!(presentRules.length!==rules.length||presentBlocks.length!==blocks.length))return{title,rules:presentRules,blocks:presentBlocks,...headline?{headline}:{},...stage?{stage}:{}}}function parseHeadline(value,errors){let ref=parseValueRef(value,"headline",errors),label=isRecord(value)?readString(value.label,"headline.label",errors,{cut:48}):void 0;if(ref)return label?{...ref,label}:ref}function parseRule(value,where,errors){if(!isRecord(value)){errors.push(`${where}: expected an object`);return}let from=readString(value.from,`${where}.from`,errors,{required:!0});from!==void 0&&!SOURCE_ID.test(from)&&errors.push(`${where}.from: invalid source id "${from}"`);let match=readString(value.match,`${where}.match`,errors,{required:!0,max:400}),group=name=>{let raw=readString(value[name],`${where}.${name}`,errors);return raw!==void 0&&!GROUP_NAME.test(raw)&&errors.push(`${where}.${name}: invalid group name "${raw}"`),raw},key=group("key"),text=group("text"),count=value.count===void 0?void 0:readFieldName(value.count,`${where}.count`,errors),scale=readNumber(value.scale,`${where}.scale`,errors);if(!(from===void 0||match===void 0))return{from,...repairRuleGroups(match,key,text),...count!==void 0?{count}:{},...scale!==void 0?{scale}:{}}}function jobWidgetSkip(value){if(!isRecord(value)||typeof value.skip!="string")return;let reason=value.skip.trim();return reason.length>0?reason:void 0}function validateJobWidgetSpec(value,options){let errors=[],spec=parseSpec(value,errors);if(!spec)return{ok:!1,errors};let numeric=checkReferences(spec,errors),compiled;try{compiled=compilePatterns(options.matcher,spec.rules.map(rule=>rule.match))}catch(error){if(!(error instanceof MatcherCompileError))throw error;errors.push(`rules[${error.pattern}].match: ${error.reason}`)}return compiled&&options.samples&&errors.length===0&&(dryRun(spec,compiled,options.samples,numeric,errors),options.brief!==void 0&&checkStatedNumbers(spec,options.samples,options.brief,errors)),errors.length>0?{ok:!1,errors}:{ok:!0,spec}}function checkReferences(spec,errors){let feeds=fieldFeeds(spec),numeric=new Map,checkField=(where,field,agg,key)=>{let feed=feeds.get(field);if(!feed){errors.push(`${where}: unknown field "${field}"; no rule has a group (?P<${field}>\u2026) or count "${field}"`);return}key!==void 0&&feed.keyGroups.has(key)&&errors.push(`${where}.key: "${key}" is the name of the key group; set one of its values (one model, one job) or omit \`key\``),!(agg===void 0||!aggNeedsValue(agg))&&(feed.value?numeric.has(field)||numeric.set(field,where):errors.push(`${where}: agg "${agg}" needs numbers, but field "${field}" only counts matches or keeps text`))},checkRef=(where,ref)=>checkField(where,ref.field,ref.agg,ref.key),needsKey=(where,field,kind)=>{feeds.get(field)?.keyGroups.size===0&&errors.push(`${where}: ${kind} need a rule with \`key\``)};return spec.rules.forEach((rule,index)=>{let where=`rules[${index}]`;rule.text!==void 0&&rule.text===rule.key&&errors.push(`${where}.text: the key group is not a field`);for(let group of patternGroupNames(rule.match))group!==rule.key&&!FIELD_NAME.test(group)&&errors.push(`${where}.match: group "${group}" names a field, so it must match ${FIELD_NAME.source}`);ruleFields(rule).length===0&&errors.push(`${where}: feeds no field; name a group (?P<field>\u2026) besides the key, or set \`count\``)}),spec.headline&&checkRef("headline",spec.headline),spec.stage&&checkField("stage",spec.stage,void 0),spec.blocks.forEach((block,index)=>{let where=`blocks[${index}] (${block.kind})`;switch(block.kind){case"spark":checkField(where,block.field,"last",block.key);break;case"bars":checkField(where,block.field,block.agg),needsKey(where,block.field,"bars");break;case"meter":checkField(where,block.field,block.agg,block.key),typeof block.total!="number"&&checkRef(`${where}.total`,block.total);break;case"stat":block.items.forEach((item,itemIndex)=>checkRef(`${where}.items[${itemIndex}]`,item));break;case"grid":checkField(where,block.field,void 0),needsKey(where,block.field,"grids");break;case"text":checkField(where,block.field,void 0);break}}),numeric}var ROUNDS=2;function statedText(brief){return[brief.command,brief.task,brief.intent,brief.watch,brief.stage].filter(Boolean).join(`
34
- `)}var JobWidgetRequestController=class{#author;#matcher;#now;#limits;#redact;#states=new Map;#aborts=new Map;#sent=[];#inFlight=0;#noModelUntil=Number.NEGATIVE_INFINITY;constructor(options){this.#author=options.author,this.#matcher=options.matcher,this.#now=options.now??Date.now,this.#limits={...JOB_WIDGET_REQUEST_LIMITS,...options.limits},this.#redact=createWidgetRedactor(options.obfuscate)}configure(options){this.#limits={...JOB_WIDGET_REQUEST_LIMITS,...options.limits},this.#redact=createWidgetRedactor(options.obfuscate)}get inFlight(){return this.#inFlight}maybeRequest(job){let now=this.#now();if(now<this.#noModelUntil||this.#inFlight>=this.#limits.maxInFlight||!this.#windowHasRoom(now))return;let state=this.#states.get(job.id);state||(state=newAuthoringState(),this.#states.set(job.id,state));let plan=planRequest(job,state,now,this.#limits);return plan?this.#run(job,state,plan):void 0}forget(jobId){this.#aborts.get(jobId)?.abort(),this.#aborts.delete(jobId),this.#states.delete(jobId)}dispose(){for(let controller of this.#aborts.values())controller.abort();this.#aborts.clear(),this.#states.clear()}#windowHasRoom(now){for(;this.#sent.length>0&&now-(this.#sent[0]??now)>=REQUEST_WINDOW_MS;)this.#sent.shift();return this.#sent.length<this.#limits.maxPerHour}#canSend(state){return state.requests<this.#limits.maxRequestsPerJob&&this.#windowHasRoom(this.#now())}async#run(job,state,plan){let controller=new AbortController;this.#aborts.set(job.id,controller),state.inFlight=!0,this.#inFlight+=1;try{return await this.#rounds(job,state,plan,controller.signal)}catch(error){return controller.signal.aborted?{kind:"aborted"}:{kind:"failed",error}}finally{this.#inFlight-=1,state.inFlight=!1,this.#aborts.get(job.id)===controller&&this.#aborts.delete(job.id)}}async#rounds(job,state,plan,signal){let raw={jobId:job.id,brief:job.brief,sources:job.runtime.samples(),previous:plan.previous},base=redactAuthorRequest(raw,this.#redact),validation={matcher:this.#matcher,samples:sampleLines(base.sources),brief:statedText(base.brief)},rejected,errors=[];for(let round=0;round<ROUNDS&&this.#canSend(state);round++){state.requests+=1;let sentAt=this.#now();this.#sent.push(sentAt);let request=rejected?redactAuthorRequest({...raw,rejected},this.#redact):base,answer=await this.#author(request,signal);if(signal.aborted)return{kind:"aborted"};if(answer===void 0){state.requests-=1;let slot=this.#sent.indexOf(sentAt);return slot!==-1&&this.#sent.splice(slot,1),this.#noModelUntil=this.#now()+this.#limits.noModelRetryMs,{kind:"unavailable"}}let skip=jobWidgetSkip(answer);if(skip!==void 0)return state.skippedWatch=job.brief.watch??"",{kind:"skipped",reason:skip};let checked=validateJobWidgetSpec(answer,validation);if(checked.ok)return state.specHadWatch=!!job.brief.watch,{kind:"installed",spec:checked.spec};errors=checked.errors,rejected={answer:JSON.stringify(answer),errors}}return job.runtime.spec||(state.stopped=!0),{kind:"rejected",errors}}};var VOCABULARY_KEYS=new Set(["kind","tone"]);function redactStrings(value,redact){return typeof value=="string"?redact(value):Array.isArray(value)?value.map(item=>redactStrings(item,redact)):typeof value!="object"||value===null?value:Object.fromEntries(Object.entries(value).map(([key,field])=>[key,VOCABULARY_KEYS.has(key)?field:redactStrings(field,redact)]))}function redactEntry(entry,redact){return entry.view===void 0?entry:{...entry,view:redactStrings(entry.view,redact)}}function redactJobWidgetState(state,redact){return{...state,jobs:state.jobs.map(entry=>redactEntry(entry,redact))}}var PUBLISH_INTERVAL_MS=1e3;function displayKey(state){return JSON.stringify(state.jobs.map(({updatedAtMs:_updatedAtMs,...shown})=>shown))}var EMPTY_KEY="[]",JobWidgetStatePublisher=class{#send;#redact;#sentKey=EMPTY_KEY;#sentAt;#latest;#timer;#disposed=!1;constructor(send,redact){this.#send=send,this.#redact=redact}redacted(state){return redactJobWidgetState(state,this.#redact)}offer(state){if(this.#disposed||(this.#latest=state,this.#timer!==void 0))return;let wait=this.#sentAt===void 0?0:this.#sentAt+PUBLISH_INTERVAL_MS-Date.now();if(wait<=0){this.#flush();return}this.#timer=setTimeout(()=>{this.#timer=void 0,this.#flush()},wait),this.#timer.unref?.()}reset(){this.#sentKey=""}dispose(){this.#disposed=!0,clearTimeout(this.#timer),this.#timer=void 0}#flush(){if(!this.#latest)return;let state=this.redacted(this.#latest),key=displayKey(state);key!==this.#sentKey&&(this.#sentKey=key,this.#sentAt=Date.now(),this.#send(state))}};var INGEST_MIN_INTERVAL_MS=250,REFRESH_INTERVAL_MS=1e3,INERT_HANDLE={notify:()=>{},update:()=>{},settle:()=>{},dispose:()=>{}},JobWidgetRegistry=class{#matcher;#redact={text:text=>this.#currentRedact.text(text),source:()=>this.#currentRedact.source()};#currentRedact;#controller;#publisher;#jobs=new Map;#ticker;#ingestTimer;#lastRefreshAt=Number.NEGATIVE_INFINITY;#disposed=!1;constructor(options){this.sessionId=options.sessionId,this.#matcher=options.matcher??defaultLineMatcher,this.#currentRedact=createWidgetRedactor(options.obfuscate),this.#controller=new JobWidgetRequestController({author:options.author,matcher:this.#matcher,...options.limits===void 0?{}:{limits:options.limits},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}}),this.#publisher=new JobWidgetStatePublisher(options.publish,this.#redact.text)}add(input){if(this.#disposed)return INERT_HANDLE;let previous=this.#jobs.get(input.id);previous&&this.#forget(previous);let job=new JobWidgetJob(input,this.#matcher,this.#redact);this.#jobs.set(job.id,job),this.#refresh(job),this.#ensureTicker();let live=()=>this.#jobs.get(job.id)===job;return{notify:()=>{live()&&!job.settled&&this.#scheduleRefresh()},update:brief=>{live()&&(job.brief={...brief,kind:job.kind},this.#scheduleRefresh())},settle:()=>{live()&&this.#settle(job)},dispose:()=>{live()&&this.#forget(job)}}}state(){return this.#publisher.redacted(this.snapshot())}snapshot(){let jobs=[];for(let job of this.#jobs.values()){let entry=job.entry();entry&&jobs.push(entry)}return{v:1,sessionId:this.sessionId,jobs}}configure(options){this.#currentRedact=createWidgetRedactor(options.obfuscate),this.#controller.configure(options)}republish(){this.#publisher.reset(),this.#publish()}dispose(){this.#disposed=!0,this.#stopTicker(),clearTimeout(this.#ingestTimer),this.#ingestTimer=void 0,this.#controller.dispose(),this.#publisher.dispose(),this.#jobs.clear()}#scheduleRefresh(){if(this.#disposed||this.#ingestTimer!==void 0)return;let wait=Math.max(0,this.#lastRefreshAt+INGEST_MIN_INTERVAL_MS-Date.now());this.#ingestTimer=setTimeout(()=>{this.#ingestTimer=void 0,this.#refreshAll()},wait),this.#ingestTimer.unref?.()}#refreshAll(){if(!this.#disposed){this.#lastRefreshAt=Date.now();for(let job of this.#jobs.values())job.settled||this.#refresh(job);this.#publish()}}#refresh(job){if(job.ingest(),job.settled)return;let pending=this.#controller.maybeRequest(job);pending&&(job.requestStarted(),pending.then(outcome=>{this.#disposed||this.#jobs.get(job.id)!==job||(job.requestSettled(outcome),this.#publish())}))}#settle(job){job.settled=!0,job.ingest(),this.#publish(),this.#stopTickerWhenIdle()}#forget(job){this.#jobs.delete(job.id),this.#controller.forget(job.id),this.#publish(),this.#stopTickerWhenIdle()}#publish(){this.#disposed||this.#publisher.offer(this.snapshot())}#ensureTicker(){this.#ticker===void 0&&(this.#ticker=setInterval(()=>this.#refreshAll(),REFRESH_INTERVAL_MS),this.#ticker.unref?.())}#stopTickerWhenIdle(){for(let job of this.#jobs.values())if(!job.settled)return;this.#stopTicker()}#stopTicker(){clearInterval(this.#ticker),this.#ticker=void 0}};var sessions=new Map,sessionListeners=new Set,hostResolver;function onJobWidgetSessionChange(listener){return sessionListeners.add(listener),()=>{sessionListeners.delete(listener)}}function notifySessionChange(sessionId,open2){for(let listener of[...sessionListeners])listener(sessionId,open2)}function openJobWidgetSession(sessionId,options){let existing=sessions.get(sessionId);if(existing){existing.author=options.author,existing.publish=options.publish,existing.registry.configure({limits:{authorAfterMs:options.authorAfterMs},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}}),existing.registry.republish();return}let slot={author:options.author,publish:options.publish,registry:new JobWidgetRegistry({sessionId,author:(request,signal)=>slot.author(request,signal),publish:state=>slot.publish?.(state),limits:{authorAfterMs:options.authorAfterMs},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}})};sessions.set(sessionId,slot),notifySessionChange(sessionId,!0)}function resendJobWidgetState(sessionId){let registry=sessions.get(sessionId)?.registry;registry&&registry.snapshot().jobs.length>0&&registry.republish()}function parkJobWidgetSession(sessionId){let slot=sessions.get(sessionId);slot&&(slot.publish=void 0)}function closeJobWidgetSession(sessionId){let slot=sessions.get(sessionId);slot&&(slot.registry.dispose(),sessions.delete(sessionId),notifySessionChange(sessionId,!1))}function registerJobWidgetSource(registration){let{sessionId,...input}=registration;return sessions.get(sessionId)?.registry.add(input)}function getJobWidgetState(sessionId){return sessions.get(sessionId)?.registry.state()}function setJobWidgetAuthorResolver(resolver){return hostResolver=resolver,()=>{hostResolver===resolver&&(hostResolver=void 0)}}function jobWidgetHostResolver(){return hostResolver}function truncateToVisualLines(text,maxVisualLines,width,paddingX=0,keep="end"){if(!text)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var TerminalManager=class{constructor(options={}){this.runtimes=new Map,this.monitorIds=new Map,this.exited=new Set,this.reservations=0,this.maxSessions=options.maxSessions??DEFAULT_MAX_SESSIONS,this.scrollback=options.scrollback,options.idScope!==void 0&&(this.idScope=options.idScope)}get size(){return this.runtimes.size}get activeSize(){return this.reconcileRuntimes(),this.runtimes.size-this.exited.size+this.reservations}reserve(){if(this.reconcileRuntimes(),this.runtimes.size-this.exited.size+this.reservations>=this.maxSessions)return null;this.reservations+=1;let released=!1;return()=>{released||(released=!0,this.reservations-=1)}}async create(command,options){let pty=await loadPty(),release=this.reserve();if(!release)throw new pty.SessionRegistryCapacityError(this.maxSessions);this.registry??=new pty.SessionRegistry({maxSessions:this.maxSessions,...this.idScope===void 0?{}:{idScope:this.idScope}});let registry=this.registry,runtimeOptions={...options,scrollback:this.scrollback},{TerminalRuntimeSession}=await import("./runtime-session-OBXYK4PI.js"),runtime=new TerminalRuntimeSession(command,runtimeOptions),entry;try{entry=await registry.create({command,session:runtime.session})}catch(error){throw release(),runtime.dispose(),runtime.session.kill(),error}return this.runtimes.set(entry.id,runtime),runtime.session.onExit(()=>{this.exited.add(entry.id)}),release(),this.reconcileRuntimes(),{id:entry.id,runtime}}get(id){let registry=this.registry;return!registry||!registry.get(id)?null:this.runtimes.get(id)??null}bindMonitorId(monitorId,sessionId){this.monitorIds.set(monitorId,sessionId)}monitorIdOf(runtimeId){for(let[monitorId,sessionId]of this.monitorIds)if(sessionId===runtimeId)return monitorId}resolveId(idOrMonitorId){if(idOrMonitorId.startsWith("mon_"))return this.monitorIds.get(idOrMonitorId);let registry=this.registry;if(registry)return registry.get(idOrMonitorId)?idOrMonitorId:void 0}list(){let registry=this.registry;if(!registry)return[];let result=[];for(let entry of registry.list()){let runtime=this.runtimes.get(entry.id);runtime&&result.push({id:entry.id,runtime})}return result}async stop(id){let registry=this.registry;if(!registry)return!1;let stopped=await registry.stop(id);return this.reconcileRuntimes(),stopped}async teardown(){let registry=this.registry;registry&&await registry.teardown(),this.registry=void 0;for(let runtime of this.runtimes.values())runtime.dispose();this.runtimes.clear(),this.exited.clear(),this.monitorIds.clear()}reconcileRuntimes(){let registry=this.registry;if(!registry)return;let liveIds=new Set(registry.list().map(entry=>entry.id));for(let[id,runtime]of this.runtimes)if(!liveIds.has(id)){runtime.dispose(),this.runtimes.delete(id),this.exited.delete(id);for(let[monitorId,sessionId]of this.monitorIds)sessionId===id&&this.monitorIds.delete(monitorId)}}};function modelOnlyText(text){return{type:"text",text,audience:"model"}}function isModelOnlyText(part){return typeof part=="object"&&part!==null&&"type"in part&&part.type==="text"&&"audience"in part&&part.audience==="model"}var TERMINAL_TOOL_MAX_LINES=2e3,TERMINAL_TOOL_MAX_BYTES=50*1024,OSC_PATTERN=/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,CSI_PATTERN=/\x1b\[[0-?]*[ -/]*[@-~]/g,DESIGNATE_AND_SINGLE_PATTERN=/\x1b(?:[()#%*+][0-9A-Za-z]|[0-9<=>@-Z\\-_])/g,C0_CONTROL_PATTERN=/[\x00-\x07\x0b\x0c\x0e-\x1f\x7f]/g;function stripEscapeSequences(text){return text.replace(OSC_PATTERN,"").replace(CSI_PATTERN,"").replace(DESIGNATE_AND_SINGLE_PATTERN,"").replace(C0_CONTROL_PATTERN,"")}function collapseRedraws(line){let cells=[],cursor=0;for(let ch of line)ch==="\r"?cursor=0:ch==="\b"?cursor>0&&(cursor-=1):(cells[cursor]=ch,cursor+=1);return cells.join("")}function sanitizeTerminalOutput(raw){return stripEscapeSequences(raw).replace(/\r\n/g,`
34
+ `)}var JobWidgetRequestController=class{#author;#matcher;#now;#limits;#redact;#states=new Map;#aborts=new Map;#sent=[];#inFlight=0;#noModelUntil=Number.NEGATIVE_INFINITY;constructor(options){this.#author=options.author,this.#matcher=options.matcher,this.#now=options.now??Date.now,this.#limits={...JOB_WIDGET_REQUEST_LIMITS,...options.limits},this.#redact=createWidgetRedactor(options.obfuscate)}configure(options){this.#limits={...JOB_WIDGET_REQUEST_LIMITS,...options.limits},this.#redact=createWidgetRedactor(options.obfuscate)}get inFlight(){return this.#inFlight}maybeRequest(job){let now=this.#now();if(now<this.#noModelUntil||this.#inFlight>=this.#limits.maxInFlight||!this.#windowHasRoom(now))return;let state=this.#states.get(job.id);state||(state=newAuthoringState(),this.#states.set(job.id,state));let plan=planRequest(job,state,now,this.#limits);return plan?this.#run(job,state,plan):void 0}forget(jobId){this.#aborts.get(jobId)?.abort(),this.#aborts.delete(jobId),this.#states.delete(jobId)}dispose(){for(let controller of this.#aborts.values())controller.abort();this.#aborts.clear(),this.#states.clear()}#windowHasRoom(now){for(;this.#sent.length>0&&now-(this.#sent[0]??now)>=REQUEST_WINDOW_MS;)this.#sent.shift();return this.#sent.length<this.#limits.maxPerHour}#canSend(state){return state.requests<this.#limits.maxRequestsPerJob&&this.#windowHasRoom(this.#now())}async#run(job,state,plan){let controller=new AbortController;this.#aborts.set(job.id,controller),state.inFlight=!0,this.#inFlight+=1;try{return await this.#rounds(job,state,plan,controller.signal)}catch(error){return controller.signal.aborted?{kind:"aborted"}:{kind:"failed",error}}finally{this.#inFlight-=1,state.inFlight=!1,this.#aborts.get(job.id)===controller&&this.#aborts.delete(job.id)}}async#rounds(job,state,plan,signal){let raw={jobId:job.id,brief:job.brief,sources:job.runtime.samples(),previous:plan.previous},base=redactAuthorRequest(raw,this.#redact),validation={matcher:this.#matcher,samples:sampleLines(base.sources),brief:statedText(base.brief)},rejected,errors=[];for(let round=0;round<ROUNDS&&this.#canSend(state);round++){state.requests+=1;let sentAt=this.#now();this.#sent.push(sentAt);let request=rejected?redactAuthorRequest({...raw,rejected},this.#redact):base,answer=await this.#author(request,signal);if(signal.aborted)return{kind:"aborted"};if(answer===void 0){state.requests-=1;let slot=this.#sent.indexOf(sentAt);return slot!==-1&&this.#sent.splice(slot,1),this.#noModelUntil=this.#now()+this.#limits.noModelRetryMs,{kind:"unavailable"}}let skip=jobWidgetSkip(answer);if(skip!==void 0)return state.skippedWatch=job.brief.watch??"",{kind:"skipped",reason:skip};let checked=validateJobWidgetSpec(answer,validation);if(checked.ok)return state.specHadWatch=!!job.brief.watch,{kind:"installed",spec:checked.spec};errors=checked.errors,rejected={answer:JSON.stringify(answer),errors}}return job.runtime.spec||(state.stopped=!0),{kind:"rejected",errors}}};var VOCABULARY_KEYS=new Set(["kind","tone"]);function redactStrings(value,redact){return typeof value=="string"?redact(value):Array.isArray(value)?value.map(item=>redactStrings(item,redact)):typeof value!="object"||value===null?value:Object.fromEntries(Object.entries(value).map(([key,field])=>[key,VOCABULARY_KEYS.has(key)?field:redactStrings(field,redact)]))}function redactEntry(entry,redact){return entry.view===void 0?entry:{...entry,view:redactStrings(entry.view,redact)}}function redactJobWidgetState(state,redact){return{...state,jobs:state.jobs.map(entry=>redactEntry(entry,redact))}}var PUBLISH_INTERVAL_MS=1e3;function displayKey(state){return JSON.stringify(state.jobs.map(({updatedAtMs:_updatedAtMs,...shown})=>shown))}var EMPTY_KEY="[]",JobWidgetStatePublisher=class{#send;#redact;#sentKey=EMPTY_KEY;#sentAt;#latest;#timer;#disposed=!1;constructor(send,redact){this.#send=send,this.#redact=redact}redacted(state){return redactJobWidgetState(state,this.#redact)}offer(state){if(this.#disposed||(this.#latest=state,this.#timer!==void 0))return;let wait=this.#sentAt===void 0?0:this.#sentAt+PUBLISH_INTERVAL_MS-Date.now();if(wait<=0){this.#flush();return}this.#timer=setTimeout(()=>{this.#timer=void 0,this.#flush()},wait),this.#timer.unref?.()}reset(){this.#sentKey=""}dispose(){this.#disposed=!0,clearTimeout(this.#timer),this.#timer=void 0}#flush(){if(!this.#latest)return;let state=this.redacted(this.#latest),key=displayKey(state);key!==this.#sentKey&&(this.#sentKey=key,this.#sentAt=Date.now(),this.#send(state))}};var INGEST_MIN_INTERVAL_MS=250,REFRESH_INTERVAL_MS=1e3,INERT_HANDLE={notify:()=>{},update:()=>{},settle:()=>{},dispose:()=>{}},JobWidgetRegistry=class{#matcher;#redact={text:text=>this.#currentRedact.text(text),source:()=>this.#currentRedact.source()};#currentRedact;#controller;#publisher;#jobs=new Map;#ticker;#ingestTimer;#lastRefreshAt=Number.NEGATIVE_INFINITY;#disposed=!1;constructor(options){this.sessionId=options.sessionId,this.#matcher=options.matcher??defaultLineMatcher,this.#currentRedact=createWidgetRedactor(options.obfuscate),this.#controller=new JobWidgetRequestController({author:options.author,matcher:this.#matcher,...options.limits===void 0?{}:{limits:options.limits},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}}),this.#publisher=new JobWidgetStatePublisher(options.publish,this.#redact.text)}add(input){if(this.#disposed)return INERT_HANDLE;let previous=this.#jobs.get(input.id);previous&&this.#forget(previous);let job=new JobWidgetJob(input,this.#matcher,this.#redact);this.#jobs.set(job.id,job),this.#refresh(job),this.#ensureTicker();let live=()=>this.#jobs.get(job.id)===job;return{notify:()=>{live()&&!job.settled&&this.#scheduleRefresh()},update:brief=>{live()&&(job.brief={...brief,kind:job.kind},this.#scheduleRefresh())},settle:()=>{live()&&this.#settle(job)},dispose:()=>{live()&&this.#forget(job)}}}state(){return this.#publisher.redacted(this.snapshot())}snapshot(){let jobs=[];for(let job of this.#jobs.values()){let entry=job.entry();entry&&jobs.push(entry)}return{v:1,sessionId:this.sessionId,jobs}}configure(options){this.#currentRedact=createWidgetRedactor(options.obfuscate),this.#controller.configure(options)}republish(){this.#publisher.reset(),this.#publish()}dispose(){this.#disposed=!0,this.#stopTicker(),clearTimeout(this.#ingestTimer),this.#ingestTimer=void 0,this.#controller.dispose(),this.#publisher.dispose(),this.#jobs.clear()}#scheduleRefresh(){if(this.#disposed||this.#ingestTimer!==void 0)return;let wait=Math.max(0,this.#lastRefreshAt+INGEST_MIN_INTERVAL_MS-Date.now());this.#ingestTimer=setTimeout(()=>{this.#ingestTimer=void 0,this.#refreshAll()},wait),this.#ingestTimer.unref?.()}#refreshAll(){if(!this.#disposed){this.#lastRefreshAt=Date.now();for(let job of this.#jobs.values())job.settled||this.#refresh(job);this.#publish()}}#refresh(job){if(job.ingest(),job.settled)return;let pending=this.#controller.maybeRequest(job);pending&&(job.requestStarted(),pending.then(outcome=>{this.#disposed||this.#jobs.get(job.id)!==job||(job.requestSettled(outcome),this.#publish())}))}#settle(job){job.settled=!0,job.ingest(),this.#publish(),this.#stopTickerWhenIdle()}#forget(job){this.#jobs.delete(job.id),this.#controller.forget(job.id),this.#publish(),this.#stopTickerWhenIdle()}#publish(){this.#disposed||this.#publisher.offer(this.snapshot())}#ensureTicker(){this.#ticker===void 0&&(this.#ticker=setInterval(()=>this.#refreshAll(),REFRESH_INTERVAL_MS),this.#ticker.unref?.())}#stopTickerWhenIdle(){for(let job of this.#jobs.values())if(!job.settled)return;this.#stopTicker()}#stopTicker(){clearInterval(this.#ticker),this.#ticker=void 0}};var sessions=new Map,sessionListeners=new Set,hostResolver;function onJobWidgetSessionChange(listener){return sessionListeners.add(listener),()=>{sessionListeners.delete(listener)}}function notifySessionChange(sessionId,open2){for(let listener of[...sessionListeners])listener(sessionId,open2)}function openJobWidgetSession(sessionId,options){let existing=sessions.get(sessionId);if(existing){existing.author=options.author,existing.publish=options.publish,existing.registry.configure({limits:{authorAfterMs:options.authorAfterMs},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}}),existing.registry.republish();return}let slot={author:options.author,publish:options.publish,registry:new JobWidgetRegistry({sessionId,author:(request,signal)=>slot.author(request,signal),publish:state=>slot.publish?.(state),limits:{authorAfterMs:options.authorAfterMs},...options.obfuscate===void 0?{}:{obfuscate:options.obfuscate}})};sessions.set(sessionId,slot),notifySessionChange(sessionId,!0)}function resendJobWidgetState(sessionId){let registry=sessions.get(sessionId)?.registry;registry&&registry.snapshot().jobs.length>0&&registry.republish()}function parkJobWidgetSession(sessionId){let slot=sessions.get(sessionId);slot&&(slot.publish=void 0)}function closeJobWidgetSession(sessionId){let slot=sessions.get(sessionId);slot&&(slot.registry.dispose(),sessions.delete(sessionId),notifySessionChange(sessionId,!1))}function registerJobWidgetSource(registration){let{sessionId,...input}=registration;return sessions.get(sessionId)?.registry.add(input)}function getJobWidgetState(sessionId){return sessions.get(sessionId)?.registry.state()}function setJobWidgetAuthorResolver(resolver){return hostResolver=resolver,()=>{hostResolver===resolver&&(hostResolver=void 0)}}function jobWidgetHostResolver(){return hostResolver}function truncateToVisualLines(text,maxVisualLines,width,paddingX=0,keep="end"){if(!text)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var TerminalManager=class{constructor(options={}){this.runtimes=new Map,this.monitorIds=new Map,this.exited=new Set,this.reservations=0,this.maxSessions=options.maxSessions??DEFAULT_MAX_SESSIONS,this.scrollback=options.scrollback,options.idScope!==void 0&&(this.idScope=options.idScope)}get size(){return this.runtimes.size}get activeSize(){return this.reconcileRuntimes(),this.runtimes.size-this.exited.size+this.reservations}reserve(){if(this.reconcileRuntimes(),this.runtimes.size-this.exited.size+this.reservations>=this.maxSessions)return null;this.reservations+=1;let released=!1;return()=>{released||(released=!0,this.reservations-=1)}}async create(command,options){let pty=await loadPty(),release=this.reserve();if(!release)throw new pty.SessionRegistryCapacityError(this.maxSessions);this.registry??=new pty.SessionRegistry({maxSessions:this.maxSessions,...this.idScope===void 0?{}:{idScope:this.idScope}});let registry=this.registry,runtimeOptions={...options,scrollback:this.scrollback},{TerminalRuntimeSession}=await import("./runtime-session-OBXYK4PI.js"),runtime=new TerminalRuntimeSession(command,runtimeOptions),entry;try{entry=await registry.create({command,session:runtime.session})}catch(error){throw release(),runtime.dispose(),runtime.session.kill(),error}return this.runtimes.set(entry.id,runtime),runtime.session.onExit(()=>{this.exited.add(entry.id)}),release(),this.reconcileRuntimes(),{id:entry.id,runtime}}get(id){let registry=this.registry;return!registry||!registry.get(id)?null:this.runtimes.get(id)??null}bindMonitorId(monitorId,sessionId){this.monitorIds.set(monitorId,sessionId)}monitorIdOf(runtimeId){for(let[monitorId,sessionId]of this.monitorIds)if(sessionId===runtimeId)return monitorId}resolveId(idOrMonitorId){if(idOrMonitorId.startsWith("mon_"))return this.monitorIds.get(idOrMonitorId);let registry=this.registry;if(registry)return registry.get(idOrMonitorId)?idOrMonitorId:void 0}list(){let registry=this.registry;if(!registry)return[];let result=[];for(let entry of registry.list()){let runtime=this.runtimes.get(entry.id);runtime&&result.push({id:entry.id,runtime})}return result}async stop(id){let registry=this.registry;if(!registry)return!1;let stopped=await registry.stop(id);return this.reconcileRuntimes(),stopped}async teardown(){let registry=this.registry;registry&&await registry.teardown(),this.registry=void 0;for(let runtime of this.runtimes.values())runtime.dispose();this.runtimes.clear(),this.exited.clear(),this.monitorIds.clear()}reconcileRuntimes(){let registry=this.registry;if(!registry)return;let liveIds=new Set(registry.list().map(entry=>entry.id));for(let[id,runtime]of this.runtimes)if(!liveIds.has(id)){runtime.dispose(),this.runtimes.delete(id),this.exited.delete(id);for(let[monitorId,sessionId]of this.monitorIds)sessionId===id&&this.monitorIds.delete(monitorId)}}};var token=code=>new RegExp(`(?<![A-Za-z0-9_])${code}(?![A-Za-z0-9_])`,"u"),SHELL_TRUST_PATTERNS=[["UNABLE_TO_GET_ISSUER_CERT_LOCALLY",token("UNABLE_TO_GET_ISSUER_CERT_LOCALLY")],["UNABLE_TO_GET_ISSUER_CERT",token("UNABLE_TO_GET_ISSUER_CERT")],["UNABLE_TO_VERIFY_LEAF_SIGNATURE",token("UNABLE_TO_VERIFY_LEAF_SIGNATURE")],["SELF_SIGNED_CERT_IN_CHAIN",token("SELF_SIGNED_CERT_IN_CHAIN")],["DEPTH_ZERO_SELF_SIGNED_CERT",token("DEPTH_ZERO_SELF_SIGNED_CERT")],["CERT_UNTRUSTED",token("CERT_UNTRUSTED")],["unable-to-verify-the-first-certificate",/unable to verify the first certificate/iu],["unable-to-get-local-issuer-certificate",/unable to get local issuer certificate/iu],["unable-to-get-issuer-certificate",/unable to get issuer certificate/iu],["self-signed-certificate-in-certificate-chain",/self[- ]signed certificate in certificate chain/iu],["self-signed-certificate",/self[- ]signed certificate/iu],["certificate-not-trusted",/certificate not trusted/iu]];function annotateShellTrust({exitCode,output}){let marker=adoptedEngineTrust();if(marker?.automatic!=="fallback"||marker.fallbackReason===null||exitCode===null||exitCode===0)return;let reason=marker.fallbackReason,action=engineTrustAction(reason),status={code:"trust-import-degraded",reason,action:action.id},pattern=SHELL_TRUST_PATTERNS.find(([,matcher])=>matcher.test(output))?.[0];return pattern===void 0?{trust:{status},text:void 0}:{trust:{status,hint:{code:"tls-verify-text-in-output",heuristic:!0,pattern}},text:`omo: certificate import is degraded (${reason}), so some TLS connections may fail. This command's output contains text that looks like a certificate verification error; omo has not confirmed the cause. To diagnose: ${action.text}`}}function modelOnlyText(text){return{type:"text",text,audience:"model"}}function isModelOnlyText(part){return typeof part=="object"&&part!==null&&"type"in part&&part.type==="text"&&"audience"in part&&part.audience==="model"}var TERMINAL_TOOL_MAX_LINES=2e3,TERMINAL_TOOL_MAX_BYTES=50*1024,OSC_PATTERN=/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,CSI_PATTERN=/\x1b\[[0-?]*[ -/]*[@-~]/g,DESIGNATE_AND_SINGLE_PATTERN=/\x1b(?:[()#%*+][0-9A-Za-z]|[0-9<=>@-Z\\-_])/g,C0_CONTROL_PATTERN=/[\x00-\x07\x0b\x0c\x0e-\x1f\x7f]/g;function stripEscapeSequences(text){return text.replace(OSC_PATTERN,"").replace(CSI_PATTERN,"").replace(DESIGNATE_AND_SINGLE_PATTERN,"").replace(C0_CONTROL_PATTERN,"")}function collapseRedraws(line){let cells=[],cursor=0;for(let ch of line)ch==="\r"?cursor=0:ch==="\b"?cursor>0&&(cursor-=1):(cells[cursor]=ch,cursor+=1);return cells.join("")}function sanitizeTerminalOutput(raw){return stripEscapeSequences(raw).replace(/\r\n/g,`
35
35
  `).split(`
36
36
  `).map(collapseRedraws).join(`
37
37
  `)}function formatTerminalToolOutput(raw){let sanitized=sanitizeTerminalOutput(raw).trimEnd(),truncation=truncateTail(sanitized,{maxLines:TERMINAL_TOOL_MAX_LINES,maxBytes:TERMINAL_TOOL_MAX_BYTES});if(!truncation.truncated)return{text:sanitized,body:sanitized,truncated:!1,truncation};let marker=truncation.lastLinePartial?`[Showing last ${formatSize(truncation.outputBytes)} of a single line; earlier output dropped]`:`[Showing lines ${truncation.totalLines-truncation.outputLines+1}-${truncation.totalLines} of ${truncation.totalLines}; earlier output dropped]`;return{text:`${truncation.content}
@@ -40,10 +40,11 @@ ${marker}`,body:truncation.content,marker,truncated:!0,truncation}}function spli
40
40
  `)){if(afterNotice&&index===cursor)parts.push(modelOnlyText(notice));else if(index>cursor&&text[index-1]===`
41
41
  `)parts.push({type:"text",text:text.slice(cursor,index-1)},modelOnlyText(notice));else continue;cursor=end<text.length?end+1:end,afterNotice=end<text.length}}return parts.length===0?[{type:"text",text}]:((cursor<text.length||text[text.length-1]===`
42
42
  `)&&parts.push({type:"text",text:text.slice(cursor)}),parts)}function withTerminalContext(callback,retire){try{return callback()}catch(error){if(!isStaleExtensionContextError(error))throw error;retire();return}}async function spawnCommandSession(ctx,request){let shell=getShellConfig(ctx.shellPath),useStdin=shell.commandTransport==="stdin",args=useStdin?[...shell.args]:[...shell.args,request.command],launch=ctx.launchBarrier?.wrap(shell.shell,args)??{command:shell.shell,args},created=await ctx.manager.create(shell.shell,{command:launch.command,args:[...launch.args],cwd:request.cwd??ctx.cwd,env:{...ctx.getEnv(),...request.envOverrides},cols:request.cols,rows:request.rows,timeoutMs:request.timeoutMs,redactSecretsInOutput:ctx.redactSecretsInOutput});if(ctx.launchBarrier!==void 0){let session=created.runtime.session;try{await ctx.launchBarrier.release({pid:session.pid,write:data=>session.write(data),onExit:listener=>session.onExit(()=>listener(session.exitResult?.exitCode??null))})}catch(error){throw await ctx.manager.stop(created.id),error}}return useStdin&&created.runtime.session.write(`${request.command}
43
- `),created}function describeExit(runtime){let exit=runtime.exitResult;return exit?exit.timedOut?"timed_out":exit.cancelled?"killed":exit.exitCode===0?"completed":exit.exitCode!==null?`exited_${exit.exitCode}`:exit.signal?`signal_${exit.signal}`:"exited":null}var NON_INTERACTIVE_MODES=new Set(["print","json"]),TERMINAL_NOTIFICATION_CUSTOM_TYPE="senpi-terminal:notification",NOTICE_TAIL_MAX_CHARS=2e3;function getTerminalNotificationDelivery(deps,customType=TERMINAL_NOTIFICATION_CUSTOM_TYPE){let mode=deps.getMode();if(mode==="off")return;let ctx=deps.getContext();if(!(!ctx||NON_INTERACTIVE_MODES.has(ctx.mode)||!ctx.model))return{send:(content,options)=>deps.sendMessage({customType,content,display:!1,...options?.details===void 0?{}:{details:options.details}},{triggerTurn:!0,deliverAs:mode==="wake"||options?.forceWake===!0?"steer":"followUp"})}}function buildNotice(id,runtime){let status=describeExit(runtime)??"exited",code=runtime.exitResult?.exitCode,codeText=code==null?"":` (exit code ${code})`,tail=sanitizeTerminalOutput(runtime.fullOutput()).trimEnd(),tailSection="";if(tail.length>0){let truncated=tail.length>NOTICE_TAIL_MAX_CHARS,shown=truncated?tail.slice(tail.length-NOTICE_TAIL_MAX_CHARS):tail,note=truncated?`
43
+ `),created}function describeExit(runtime){let exit=runtime.exitResult;return exit?exit.timedOut?"timed_out":exit.cancelled?"killed":exit.exitCode===0?"completed":exit.exitCode!==null?`exited_${exit.exitCode}`:exit.signal?`signal_${exit.signal}`:"exited":null}var NON_INTERACTIVE_MODES=new Set(["print","json"]),TERMINAL_NOTIFICATION_CUSTOM_TYPE="senpi-terminal:notification",NOTICE_TAIL_MAX_CHARS=2e3;function getTerminalNotificationDelivery(deps,customType=TERMINAL_NOTIFICATION_CUSTOM_TYPE){let mode=deps.getMode();if(mode==="off")return;let ctx=deps.getContext();if(!(!ctx||NON_INTERACTIVE_MODES.has(ctx.mode)||!ctx.model))return{send:(content,options)=>deps.sendMessage({customType,content,display:!1,...options?.details===void 0?{}:{details:options.details}},{triggerTurn:!0,deliverAs:mode==="wake"||options?.forceWake===!0?"steer":"followUp"})}}function buildNotice(id,runtime,trustText){let status=describeExit(runtime)??"exited",code=runtime.exitResult?.exitCode,codeText=code==null?"":` (exit code ${code})`,tail=sanitizeTerminalOutput(runtime.fullOutput()).trimEnd(),tailSection="";if(tail.length>0){let truncated=tail.length>NOTICE_TAIL_MAX_CHARS,shown=truncated?tail.slice(tail.length-NOTICE_TAIL_MAX_CHARS):tail,note=truncated?`
44
44
  [Final output truncated to the last ${NOTICE_TAIL_MAX_CHARS} chars; the full history is still peekable.]`:"";tailSection=`
45
45
  Final output:
46
- ${shown}${note}`}return`<system-reminder>Background terminal session ${id} finished: ${status}${codeText}.${tailSection}</system-reminder>`}var TerminalNotifier=class{constructor(deps){this.notified=new Set,this.retired=!1,this.deps=deps}notifyCompletion(id,runtime){this.retired||this.notified.has(id)||withTerminalContext(()=>this.deliverCompletion(id,runtime),()=>{this.retired=!0,this.notified.clear()})}deliverCompletion(id,runtime){let delivery=getTerminalNotificationDelivery(this.deps);delivery&&(this.notified.add(id),delivery.send(buildNotice(id,runtime)))}};function resolveTerminalId(manager,id){return manager.resolveId?.(id)??id}function textResult(text,extra){return{content:[{type:"text",text}],details:extra?.details,isError:extra?.isError}}function errorResult(text){return{content:[{type:"text",text}],details:void 0,isError:!0}}function noticedResult(text,notices,extra){return{content:splitModelOnlyNotices(text,notices),details:extra?.details,isError:extra?.isError}}function createForegroundDetachGate(options){let cancelled=!1,committed=!1,timer,resolveDetached,detached=new Promise(resolve=>{resolveDetached=resolve}),clearDeadline=()=>{timer!==void 0&&(clearTimeout(timer),timer=void 0)},linearize=()=>{if(cancelled||committed||options.runtime.exited||options.signal?.aborted)return;let exitedAtGate=!1,unsubscribeExit=options.runtime.session.onExit(()=>{committed||(exitedAtGate=!0)});if(cancelled||options.runtime.exited||exitedAtGate||options.signal?.aborted){unsubscribeExit();return}committed=!0,options.removeAbortListener(),unsubscribeExit(),resolveDetached()};return timer=setTimeout(()=>queueMicrotask(linearize),options.delayMs),{detached,cancel(){cancelled=!0,clearDeadline()}}}function resolveForegroundWindowSeconds(env){let parsed=Number.parseFloat(env.PI_BASH_FOREGROUND_SECONDS??"");return!Number.isFinite(parsed)||parsed<=0?60:parsed}var SHELL_WRAPPER=/^(?:env\s+(?:[\w.]+=[^\s]*\s+)*)?(?:\/(?:usr\/)?bin\/)?(?:ba|z|da|k)?sh\s+-[a-z]*c\s+/i,POWER_MANAGEMENT=/\b(?:pmset|systemsetup|caffeinate|displaysleep|disksleep)\b/,SLEEP_CALL=/(?<![\w.\-/])(?:\/(?:usr\/)?bin\/)?sleep\s+(\d+(?:\.\d+)?)/g,PURE=/^sleep\s+\d+(?:\.\d+)?$/,LEADING=/^\(?\s*(?:\/(?:usr\/)?bin\/)?sleep\s+\d+(?:\.\d+)?\s*(?:[;&|]|$)/,LOOP=/\b(?:while|until|for)\b[\s\S]*?(?<![\w.\-/])(?:\/(?:usr\/)?bin\/)?sleep\s+\d/,TRAILING=/[;&|]\s*(?:\/(?:usr\/)?bin\/)?sleep\s+\d+(?:\.\d+)?\s*\)?\s*$/;function unwrap(command){let current=command.trim();for(let depth=0;depth<3;depth+=1){let stripped=current.replace(SHELL_WRAPPER,"");if(stripped===current)break;current=stripped.trim();let quote=current[0];(quote==="'"||quote==='"')&&current.endsWith(quote)&&current.length>1&&(current=current.slice(1,-1).trim())}return current}function longestSleepSeconds(command){SLEEP_CALL.lastIndex=0;let longest;for(let match of command.matchAll(SLEEP_CALL)){let seconds=Number.parseFloat(match[1]??"");Number.isFinite(seconds)&&(longest===void 0||seconds>longest)&&(longest=seconds)}return longest}function classifySleepWait(command){if(POWER_MANAGEMENT.test(command))return;let unwrapped=unwrap(command),seconds=longestSleepSeconds(unwrapped);if(seconds!==void 0){if(LOOP.test(unwrapped))return seconds>=2?{kind:"sleep-wait",rule:"R3",seconds}:void 0;if(!(seconds<10)){if(PURE.test(unwrapped))return{kind:"sleep-wait",rule:"R1",seconds};if(LEADING.test(unwrapped))return{kind:"sleep-wait",rule:"R2",seconds};if(TRAILING.test(unwrapped))return{kind:"sleep-wait",rule:"R4",seconds}}}}var ptyBashSchema=typebox_exports.Object({command:typebox_exports.String({description:"Shell command to execute in a PTY-backed session."}),timeout:typebox_exports.Optional(typebox_exports.Number({description:"Process kill deadline in seconds (default 1800). Foreground blocking stops at the ~60s window: a command still running then auto-detaches to a live background session instead of being killed. Ignored for run_in_background sessions (they live until exit or kill_bash)."})),description:typebox_exports.Optional(typebox_exports.String({description:"Short human-readable label for this command."})),run_in_background:typebox_exports.Optional(typebox_exports.Boolean({description:"Run as a persistent background session: returns a bash_id immediately (read with bash_output, steer with bash_input, stop with kill_bash). A plain & job dies with the call's PTY hangup (native backend), and nohup at best leaves an untracked orphan (no bash_id, no log) that the call's timeout still group-kills. This flag is the only reliable way a job outlives the call."})),cols:typebox_exports.Optional(typebox_exports.Number({description:"PTY width in columns (default 120)."})),rows:typebox_exports.Optional(typebox_exports.Number({description:"PTY height in rows (default 40)."}))});function resolveDimension(value,fallback){return value===void 0||!Number.isFinite(value)||value<1?fallback:Math.trunc(value)}function delay(ms){return new Promise(resolve=>setTimeout(resolve,ms))}var MAX_TIMEOUT_MS=2147483647,BASH_UPDATE_THROTTLE_MS=100;function createThrottledEmitter(emit,throttleMs=BASH_UPDATE_THROTTLE_MS){let timer,dirty=!1,lastEmissionAt,emitIfDirty=()=>{dirty&&(dirty=!1,lastEmissionAt=Date.now(),emit())},clearTimer=()=>{timer!==void 0&&(clearTimeout(timer),timer=void 0)};return{schedule(){if(dirty=!0,timer!==void 0)return;let elapsed=lastEmissionAt===void 0?throttleMs:Date.now()-lastEmissionAt;if(elapsed>=throttleMs){emitIfDirty();return}timer=setTimeout(()=>{timer=void 0,emitIfDirty()},throttleMs-elapsed)},flush(){clearTimer(),emitIfDirty()},dispose(){clearTimer(),dirty=!1,lastEmissionAt=void 0}}}function sessionSpawnContext(ctx){return{...ctx,getEnv:()=>({...ctx.getEnv(),PI_SESSION_CWD:void 0,PI_GOAL_STORE_FILE:void 0,OMO_BROWSER_ENGINE:void 0})}}function sessionEnvOverrides(ctx,execCtx){let session=execCtx??ctx.getSessionContext?.();if(!session?.sessionManager)return{};let env={...session.sessionEnv};env.PI_SESSION_ID=session.sessionManager.getSessionId(),session.cwd&&(env.PI_SESSION_CWD=session.cwd),session.goalStoreFile&&(env.PI_GOAL_STORE_FILE=session.goalStoreFile);let sessionFile=session.sessionManager.getSessionFile();return sessionFile&&(env.PI_SESSION_FILE=sessionFile),session.model&&(env.PI_PROVIDER=session.model.provider,env.PI_MODEL=session.model.id),session.thinkingLevel&&(env.PI_REASONING_LEVEL=session.thinkingLevel),session.browserEngine&&(env.OMO_BROWSER_ENGINE=session.browserEngine),env}function raceExitWithKillGrace(runtime,signal,timeoutMs){return new Promise((resolve,reject)=>{let settled=!1,abortGraceTimer,timeoutGraceTimer,armAbortGrace,settle=finish=>{settled||(settled=!0,abortGraceTimer&&clearTimeout(abortGraceTimer),timeoutGraceTimer&&clearTimeout(timeoutGraceTimer),signal&&armAbortGrace&&signal.removeEventListener("abort",armAbortGrace),finish())};if(runtime.session.waitExit().then(()=>settle(()=>resolve("exited")),error=>settle(()=>reject(error instanceof Error?error:new Error(String(error))))),timeoutMs!==void 0){let timeoutGraceDeadlineMs=timeoutMs+KILLED_SESSION_EXIT_GRACE_MS;timeoutGraceDeadlineMs<=MAX_TIMEOUT_MS&&(timeoutGraceTimer=setTimeout(()=>settle(()=>resolve("timeout_grace")),timeoutGraceDeadlineMs))}signal&&(armAbortGrace=()=>{abortGraceTimer??=setTimeout(()=>settle(()=>resolve("abort_grace")),KILLED_SESSION_EXIT_GRACE_MS)},signal.aborted?armAbortGrace():signal.addEventListener("abort",armAbortGrace,{once:!0}))})}function resolveAutoDetachDelayMs(ctx,input,sleepWait){if(ctx.timeoutAction==="kill")return;let windowSeconds=sleepWait?Math.min(5,resolveForegroundWindowSeconds(process.env)):resolveForegroundWindowSeconds(process.env);if(!((input.timeout!==void 0&&Number.isFinite(input.timeout)?input.timeout:1/0)<=windowSeconds))return Math.max(0,Math.trunc(windowSeconds*1e3))}function scheduleDetachedSweep(ctx,id,runtime,timeoutMs,startedAt){if(timeoutMs===void 0)return;let deadlineMs=timeoutMs+KILLED_SESSION_EXIT_GRACE_MS;if(!Number.isFinite(deadlineMs)||deadlineMs>MAX_TIMEOUT_MS||runtime.exited)return;let remainingMs=Math.max(0,deadlineMs-(Date.now()-startedAt)),timer,unsubscribeExit,clearSweep=()=>{timer!==void 0&&clearTimeout(timer),timer=void 0,unsubscribeExit?.(),unsubscribeExit=void 0};if(unsubscribeExit=runtime.session.onExit(clearSweep),runtime.exited){clearSweep();return}timer=setTimeout(()=>{clearSweep(),runtime.exited||ctx.manager.stop(id).catch(()=>{})},remainingMs)}async function runForeground(ctx,input,cols,rows,signal,cwd,onUpdate,execCtx){if(signal?.aborted)return errorResult("Command aborted");let timeoutMs=input.timeout!==void 0?Math.trunc(input.timeout*1e3):void 0,{id,runtime}=await spawnCommandSession(sessionSpawnContext(ctx),{command:input.command,cols,rows,timeoutMs,cwd,envOverrides:{...sessionEnvOverrides(ctx,execCtx),...FOREGROUND_ENV_OVERRIDES}}),startedAt=Date.now(),activity=`running ${input.command.slice(0,80)}`,updateEmitter=onUpdate?createThrottledEmitter(()=>{let text=formatTerminalToolOutput(runtime.fullOutput()).body.slice(-2e3);onUpdate?.({content:[{type:"text",text}],details:{progress:{activity,startedAt}}})}):void 0;onUpdate?.({content:[],details:void 0});let unsubscribeOutput=onUpdate?runtime.onOutput(()=>updateEmitter?.schedule()):void 0,sleepWait=classifySleepWait(input.command),detachDelayMs=resolveAutoDetachDelayMs(ctx,input,sleepWait),outcome;if(detachDelayMs===void 0){let onAbort=()=>runtime.session.kill("SIGKILL");signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));try{outcome=await raceExitWithKillGrace(runtime,signal,timeoutMs)}finally{signal?.removeEventListener("abort",onAbort),unsubscribeOutput?.(),updateEmitter?.flush(),updateEmitter?.dispose()}}else{let abortGate=new AbortController,onAbort=()=>{runtime.session.kill("SIGKILL"),abortGate.abort()};signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));let detachGate=createForegroundDetachGate({runtime,signal,delayMs:detachDelayMs,removeAbortListener:()=>signal?.removeEventListener("abort",onAbort)});try{outcome=await Promise.race([raceExitWithKillGrace(runtime,abortGate.signal,timeoutMs),detachGate.detached.then(()=>"detached")])}finally{detachGate.cancel(),signal?.removeEventListener("abort",onAbort),unsubscribeOutput?.(),updateEmitter?.flush(),updateEmitter?.dispose()}}if(outcome==="detached"){scheduleDetachedSweep(ctx,id,runtime,timeoutMs,startedAt),ctx.onBackgroundStart?.(id,input.description??input.command,startedAt,input.command),ctx.onBackgroundExit&&runtime.session.onExit(()=>ctx.onBackgroundExit?.(id,runtime));let delta=runtime.readDelta(),partialOutput=formatTerminalToolOutput(delta.text).text||"(no output yet)",timeoutNote=input.timeout!==void 0&&Number.isFinite(input.timeout)?`not killed; the original ${input.timeout}s timeout still applies`:"not killed; it will run until exit or kill_bash",guidance=sleepWait?`This command is a wait (${sleepWait.seconds}s sleep), so it detached immediately; the wait continues in the background. Do nothing and end your turn: completion will be reported automatically with exit status and output tail. Do NOT poll bash_output({ bash_id: "${id}" }) for it. When you are waiting for a pattern in a command's output, launch it with monitor({ command, filter }) instead so matching lines arrive as events. Use kill_bash({ bash_id: "${id}" }) to stop this session.`:`Continue other work; completion will be reported automatically with exit status and output tail. Use bash_output({ bash_id: "${id}" }) only to peek at new output. monitor cannot attach to this session; use it for future event-driven launches. Use kill_bash({ bash_id: "${id}" }) to stop this session.`;return textResult(`Command is still running; auto-detached to background with ID: ${id} (${timeoutNote}).
46
+ ${shown}${note}`}let trustSection=trustText===void 0?"":`
47
+ ${trustText}`;return`<system-reminder>Background terminal session ${id} finished: ${status}${codeText}.${tailSection}${trustSection}</system-reminder>`}var TerminalNotifier=class{constructor(deps){this.notified=new Set,this.retired=!1,this.deps=deps}notifyCompletion(id,runtime){this.retired||this.notified.has(id)||withTerminalContext(()=>this.deliverCompletion(id,runtime),()=>{this.retired=!0,this.notified.clear()})}deliverCompletion(id,runtime){let delivery=getTerminalNotificationDelivery(this.deps);if(!delivery)return;this.notified.add(id);let annotation=annotateShellTrust({exitCode:runtime.exitResult?.exitCode??null,output:runtime.fullOutput()});delivery.send(buildNotice(id,runtime,annotation?.text),annotation===void 0?void 0:{details:{trust:annotation.trust}})}};function resolveTerminalId(manager,id){return manager.resolveId?.(id)??id}function textResult(text,extra){return{content:[{type:"text",text}],details:extra?.details,isError:extra?.isError}}function errorResult(text){return{content:[{type:"text",text}],details:void 0,isError:!0}}function noticedResult(text,notices,extra){return{content:splitModelOnlyNotices(text,notices),details:extra?.details,isError:extra?.isError}}function createForegroundDetachGate(options){let cancelled=!1,committed=!1,timer,resolveDetached,detached=new Promise(resolve=>{resolveDetached=resolve}),clearDeadline=()=>{timer!==void 0&&(clearTimeout(timer),timer=void 0)},linearize=()=>{if(cancelled||committed||options.runtime.exited||options.signal?.aborted)return;let exitedAtGate=!1,unsubscribeExit=options.runtime.session.onExit(()=>{committed||(exitedAtGate=!0)});if(cancelled||options.runtime.exited||exitedAtGate||options.signal?.aborted){unsubscribeExit();return}committed=!0,options.removeAbortListener(),unsubscribeExit(),resolveDetached()};return timer=setTimeout(()=>queueMicrotask(linearize),options.delayMs),{detached,cancel(){cancelled=!0,clearDeadline()}}}function resolveForegroundWindowSeconds(env){let parsed=Number.parseFloat(env.PI_BASH_FOREGROUND_SECONDS??"");return!Number.isFinite(parsed)||parsed<=0?60:parsed}var SHELL_WRAPPER=/^(?:env\s+(?:[\w.]+=[^\s]*\s+)*)?(?:\/(?:usr\/)?bin\/)?(?:ba|z|da|k)?sh\s+-[a-z]*c\s+/i,POWER_MANAGEMENT=/\b(?:pmset|systemsetup|caffeinate|displaysleep|disksleep)\b/,SLEEP_CALL=/(?<![\w.\-/])(?:\/(?:usr\/)?bin\/)?sleep\s+(\d+(?:\.\d+)?)/g,PURE=/^sleep\s+\d+(?:\.\d+)?$/,LEADING=/^\(?\s*(?:\/(?:usr\/)?bin\/)?sleep\s+\d+(?:\.\d+)?\s*(?:[;&|]|$)/,LOOP=/\b(?:while|until|for)\b[\s\S]*?(?<![\w.\-/])(?:\/(?:usr\/)?bin\/)?sleep\s+\d/,TRAILING=/[;&|]\s*(?:\/(?:usr\/)?bin\/)?sleep\s+\d+(?:\.\d+)?\s*\)?\s*$/;function unwrap(command){let current=command.trim();for(let depth=0;depth<3;depth+=1){let stripped=current.replace(SHELL_WRAPPER,"");if(stripped===current)break;current=stripped.trim();let quote=current[0];(quote==="'"||quote==='"')&&current.endsWith(quote)&&current.length>1&&(current=current.slice(1,-1).trim())}return current}function longestSleepSeconds(command){SLEEP_CALL.lastIndex=0;let longest;for(let match of command.matchAll(SLEEP_CALL)){let seconds=Number.parseFloat(match[1]??"");Number.isFinite(seconds)&&(longest===void 0||seconds>longest)&&(longest=seconds)}return longest}function classifySleepWait(command){if(POWER_MANAGEMENT.test(command))return;let unwrapped=unwrap(command),seconds=longestSleepSeconds(unwrapped);if(seconds!==void 0){if(LOOP.test(unwrapped))return seconds>=2?{kind:"sleep-wait",rule:"R3",seconds}:void 0;if(!(seconds<10)){if(PURE.test(unwrapped))return{kind:"sleep-wait",rule:"R1",seconds};if(LEADING.test(unwrapped))return{kind:"sleep-wait",rule:"R2",seconds};if(TRAILING.test(unwrapped))return{kind:"sleep-wait",rule:"R4",seconds}}}}var ptyBashSchema=typebox_exports.Object({command:typebox_exports.String({description:"Shell command to execute in a PTY-backed session."}),timeout:typebox_exports.Optional(typebox_exports.Number({description:"Process kill deadline in seconds (default 1800). Foreground blocking stops at the ~60s window: a command still running then auto-detaches to a live background session instead of being killed. Ignored for run_in_background sessions (they live until exit or kill_bash)."})),description:typebox_exports.Optional(typebox_exports.String({description:"Short human-readable label for this command."})),run_in_background:typebox_exports.Optional(typebox_exports.Boolean({description:"Run as a persistent background session: returns a bash_id immediately (read with bash_output, steer with bash_input, stop with kill_bash). A plain & job dies with the call's PTY hangup (native backend), and nohup at best leaves an untracked orphan (no bash_id, no log) that the call's timeout still group-kills. This flag is the only reliable way a job outlives the call."})),cols:typebox_exports.Optional(typebox_exports.Number({description:"PTY width in columns (default 120)."})),rows:typebox_exports.Optional(typebox_exports.Number({description:"PTY height in rows (default 40)."}))});function resolveDimension(value,fallback){return value===void 0||!Number.isFinite(value)||value<1?fallback:Math.trunc(value)}function delay(ms){return new Promise(resolve=>setTimeout(resolve,ms))}var MAX_TIMEOUT_MS=2147483647,BASH_UPDATE_THROTTLE_MS=100;function createThrottledEmitter(emit,throttleMs=BASH_UPDATE_THROTTLE_MS){let timer,dirty=!1,lastEmissionAt,emitIfDirty=()=>{dirty&&(dirty=!1,lastEmissionAt=Date.now(),emit())},clearTimer=()=>{timer!==void 0&&(clearTimeout(timer),timer=void 0)};return{schedule(){if(dirty=!0,timer!==void 0)return;let elapsed=lastEmissionAt===void 0?throttleMs:Date.now()-lastEmissionAt;if(elapsed>=throttleMs){emitIfDirty();return}timer=setTimeout(()=>{timer=void 0,emitIfDirty()},throttleMs-elapsed)},flush(){clearTimer(),emitIfDirty()},dispose(){clearTimer(),dirty=!1,lastEmissionAt=void 0}}}function sessionSpawnContext(ctx){return{...ctx,getEnv:()=>({...ctx.getEnv(),PI_SESSION_CWD:void 0,PI_GOAL_STORE_FILE:void 0,OMO_BROWSER_ENGINE:void 0})}}function sessionEnvOverrides(ctx,execCtx){let session=execCtx??ctx.getSessionContext?.();if(!session?.sessionManager)return{};let env={...session.sessionEnv};env.PI_SESSION_ID=session.sessionManager.getSessionId(),session.cwd&&(env.PI_SESSION_CWD=session.cwd),session.goalStoreFile&&(env.PI_GOAL_STORE_FILE=session.goalStoreFile);let sessionFile=session.sessionManager.getSessionFile();return sessionFile&&(env.PI_SESSION_FILE=sessionFile),session.model&&(env.PI_PROVIDER=session.model.provider,env.PI_MODEL=session.model.id),session.thinkingLevel&&(env.PI_REASONING_LEVEL=session.thinkingLevel),session.browserEngine&&(env.OMO_BROWSER_ENGINE=session.browserEngine),env}function raceExitWithKillGrace(runtime,signal,timeoutMs){return new Promise((resolve,reject)=>{let settled=!1,abortGraceTimer,timeoutGraceTimer,armAbortGrace,settle=finish=>{settled||(settled=!0,abortGraceTimer&&clearTimeout(abortGraceTimer),timeoutGraceTimer&&clearTimeout(timeoutGraceTimer),signal&&armAbortGrace&&signal.removeEventListener("abort",armAbortGrace),finish())};if(runtime.session.waitExit().then(()=>settle(()=>resolve("exited")),error=>settle(()=>reject(error instanceof Error?error:new Error(String(error))))),timeoutMs!==void 0){let timeoutGraceDeadlineMs=timeoutMs+KILLED_SESSION_EXIT_GRACE_MS;timeoutGraceDeadlineMs<=MAX_TIMEOUT_MS&&(timeoutGraceTimer=setTimeout(()=>settle(()=>resolve("timeout_grace")),timeoutGraceDeadlineMs))}signal&&(armAbortGrace=()=>{abortGraceTimer??=setTimeout(()=>settle(()=>resolve("abort_grace")),KILLED_SESSION_EXIT_GRACE_MS)},signal.aborted?armAbortGrace():signal.addEventListener("abort",armAbortGrace,{once:!0}))})}function resolveAutoDetachDelayMs(ctx,input,sleepWait){if(ctx.timeoutAction==="kill")return;let windowSeconds=sleepWait?Math.min(5,resolveForegroundWindowSeconds(process.env)):resolveForegroundWindowSeconds(process.env);if(!((input.timeout!==void 0&&Number.isFinite(input.timeout)?input.timeout:1/0)<=windowSeconds))return Math.max(0,Math.trunc(windowSeconds*1e3))}function scheduleDetachedSweep(ctx,id,runtime,timeoutMs,startedAt){if(timeoutMs===void 0)return;let deadlineMs=timeoutMs+KILLED_SESSION_EXIT_GRACE_MS;if(!Number.isFinite(deadlineMs)||deadlineMs>MAX_TIMEOUT_MS||runtime.exited)return;let remainingMs=Math.max(0,deadlineMs-(Date.now()-startedAt)),timer,unsubscribeExit,clearSweep=()=>{timer!==void 0&&clearTimeout(timer),timer=void 0,unsubscribeExit?.(),unsubscribeExit=void 0};if(unsubscribeExit=runtime.session.onExit(clearSweep),runtime.exited){clearSweep();return}timer=setTimeout(()=>{clearSweep(),runtime.exited||ctx.manager.stop(id).catch(()=>{})},remainingMs)}async function runForeground(ctx,input,cols,rows,signal,cwd,onUpdate,execCtx){if(signal?.aborted)return errorResult("Command aborted");let timeoutMs=input.timeout!==void 0?Math.trunc(input.timeout*1e3):void 0,{id,runtime}=await spawnCommandSession(sessionSpawnContext(ctx),{command:input.command,cols,rows,timeoutMs,cwd,envOverrides:{...sessionEnvOverrides(ctx,execCtx),...FOREGROUND_ENV_OVERRIDES}}),startedAt=Date.now(),activity=`running ${input.command.slice(0,80)}`,updateEmitter=onUpdate?createThrottledEmitter(()=>{let text=formatTerminalToolOutput(runtime.fullOutput()).body.slice(-2e3);onUpdate?.({content:[{type:"text",text}],details:{progress:{activity,startedAt}}})}):void 0;onUpdate?.({content:[],details:void 0});let unsubscribeOutput=onUpdate?runtime.onOutput(()=>updateEmitter?.schedule()):void 0,sleepWait=classifySleepWait(input.command),detachDelayMs=resolveAutoDetachDelayMs(ctx,input,sleepWait),outcome;if(detachDelayMs===void 0){let onAbort=()=>runtime.session.kill("SIGKILL");signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));try{outcome=await raceExitWithKillGrace(runtime,signal,timeoutMs)}finally{signal?.removeEventListener("abort",onAbort),unsubscribeOutput?.(),updateEmitter?.flush(),updateEmitter?.dispose()}}else{let abortGate=new AbortController,onAbort=()=>{runtime.session.kill("SIGKILL"),abortGate.abort()};signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));let detachGate=createForegroundDetachGate({runtime,signal,delayMs:detachDelayMs,removeAbortListener:()=>signal?.removeEventListener("abort",onAbort)});try{outcome=await Promise.race([raceExitWithKillGrace(runtime,abortGate.signal,timeoutMs),detachGate.detached.then(()=>"detached")])}finally{detachGate.cancel(),signal?.removeEventListener("abort",onAbort),unsubscribeOutput?.(),updateEmitter?.flush(),updateEmitter?.dispose()}}if(outcome==="detached"){scheduleDetachedSweep(ctx,id,runtime,timeoutMs,startedAt),ctx.onBackgroundStart?.(id,input.description??input.command,startedAt,input.command),ctx.onBackgroundExit&&runtime.session.onExit(()=>ctx.onBackgroundExit?.(id,runtime));let delta=runtime.readDelta(),partialOutput=formatTerminalToolOutput(delta.text).text||"(no output yet)",timeoutNote=input.timeout!==void 0&&Number.isFinite(input.timeout)?`not killed; the original ${input.timeout}s timeout still applies`:"not killed; it will run until exit or kill_bash",guidance=sleepWait?`This command is a wait (${sleepWait.seconds}s sleep), so it detached immediately; the wait continues in the background. Do nothing and end your turn: completion will be reported automatically with exit status and output tail. Do NOT poll bash_output({ bash_id: "${id}" }) for it. When you are waiting for a pattern in a command's output, launch it with monitor({ command, filter }) instead so matching lines arrive as events. Use kill_bash({ bash_id: "${id}" }) to stop this session.`:`Continue other work; completion will be reported automatically with exit status and output tail. Use bash_output({ bash_id: "${id}" }) only to peek at new output. monitor cannot attach to this session; use it for future event-driven launches. Use kill_bash({ bash_id: "${id}" }) to stop this session.`;return textResult(`Command is still running; auto-detached to background with ID: ${id} (${timeoutNote}).
47
48
 
48
49
  Partial output:
49
50
  ${partialOutput}
@@ -52,12 +53,14 @@ ${guidance}`,{details:{bash_id:id,background:!0,auto_detached:!0,...sleepWait?{s
52
53
 
53
54
  `:""}Command aborted`);let exit=runtime.exitResult;if(outcome==="timeout_grace"||exit?.timedOut)return errorResult(`${output?`${output}
54
55
 
55
- `:""}Command timed out after ${input.timeout} seconds`);let status=describeExit(runtime);return exit&&exit.exitCode!==0&&exit.exitCode!==null?errorResult(`${output?`${output}
56
+ `:""}Command timed out after ${input.timeout} seconds`);let status=describeExit(runtime);if(exit&&exit.exitCode!==0&&exit.exitCode!==null){let text=`${output?`${output}
56
57
 
57
- `:""}Command exited with code ${exit.exitCode}`):noticedResult(output||"(no output)",[formatted.marker],{details:{status,...formatted.truncated?{truncation:formatted.truncation}:{}}})}async function runBackground(ctx,input,cols,rows,cwd,execCtx){let{id,runtime}=await spawnCommandSession(sessionSpawnContext(ctx),{command:input.command,cols,rows,cwd,envOverrides:sessionEnvOverrides(ctx,execCtx)});ctx.onBackgroundStart?.(id,input.description??input.command,Date.now(),input.command),ctx.onBackgroundExit&&runtime.session.onExit(()=>ctx.onBackgroundExit?.(id,runtime)),await Promise.race([delay(BACKGROUND_START_GRACE_MS),runtime.session.waitExit()]);let early=formatTerminalToolOutput(runtime.readDelta().text).text,header=`Command running in background with ID: ${id}`,backendNote=runtime.backend==="pipe-fallback"?`
58
+ `:""}Command exited with code ${exit.exitCode}`,annotation=annotateShellTrust({exitCode:exit.exitCode,output:runtime.fullOutput()});return annotation===void 0?errorResult(text):textResult(annotation.text===void 0?text:`${text}
59
+
60
+ ${annotation.text}`,{details:{trust:annotation.trust},isError:!0})}return noticedResult(output||"(no output)",[formatted.marker],{details:{status,...formatted.truncated?{truncation:formatted.truncation}:{}}})}async function runBackground(ctx,input,cols,rows,cwd,execCtx){let{id,runtime}=await spawnCommandSession(sessionSpawnContext(ctx),{command:input.command,cols,rows,cwd,envOverrides:sessionEnvOverrides(ctx,execCtx)});ctx.onBackgroundStart?.(id,input.description??input.command,Date.now(),input.command),ctx.onBackgroundExit&&runtime.session.onExit(()=>ctx.onBackgroundExit?.(id,runtime)),await Promise.race([delay(BACKGROUND_START_GRACE_MS),runtime.session.waitExit()]);let early=formatTerminalToolOutput(runtime.readDelta().text).text,header=`Command running in background with ID: ${id}`,backendNote=runtime.backend==="pipe-fallback"?`
58
61
  (native PTY unavailable: running via pipe fallback; bash_input/bash_resize are limited.)`:"",earlyBlock=early?`
59
62
 
60
- ${early}`:"";return textResult(`${header}${backendNote}${earlyBlock}`,{details:{bash_id:id,background:!0}})}function createPtyBashTool(ctx){return{name:TERMINAL_BASH_TOOL,exposure:"eval",label:"bash",description:"Execute a shell command in a persistent PTY-backed session. Set run_in_background:true for long-lived or interactive sessions; steer them with bash_input, snapshot with bash_output, tear down with kill_bash. To wait on observable state (a build finishing, a server coming up, a log line), never run sleep or poll loops: subscribe with the monitor tool instead. Foreground blocking stops at the ~60s window and a still-running command auto-detaches to a live background session; `timeout` is the process kill deadline in seconds.",promptSnippet:"Run shell commands; run_in_background:true for long-lived/interactive PTY sessions",promptGuidelines:["You can inspect PI_* environment variables for current model and session details."],parameters:ptyBashSchema,async execute(_toolCallId,input,signal,onUpdate,execCtx){let cols=resolveDimension(input.cols,ctx.defaultCols||DEFAULT_COLS),rows=resolveDimension(input.rows,ctx.defaultRows||DEFAULT_ROWS),cwd=execCtx?.cwd;return input.run_in_background?runBackground(ctx,input,cols,rows,cwd,execCtx):runForeground(ctx,input,cols,rows,signal,cwd,onUpdate,execCtx)}}}var bashInputSchema=typebox_exports.Object({bash_id:typebox_exports.String({description:"Session id returned by a run_in_background bash call."}),input:typebox_exports.Optional(typebox_exports.String({description:"Literal text to write to the session's stdin."})),keys:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String(),{description:"Named keys to send, e.g. ['ctrl+c'], ['enter'], ['up']. Sent after `input` when both are given."})),submit:typebox_exports.Optional(typebox_exports.Boolean({description:"Append Enter (\\r) after `input`. Default true when `input` is a non-empty string."}))});function createBashInputTool(ctx){return{name:TERMINAL_INPUT_TOOL,label:"bash_input",description:"Write stdin or named keys (ctrl+c, enter, up, ...) to a live background bash session: e.g. drive a REPL or send SIGINT. This executes arbitrary shell input and is permission-gated like bash.",exposure:"search",allowLazyActivation:!0,searchKeywords:["stdin","keys","ctrl+c","interrupt","repl","send input"],parameters:bashInputSchema,async execute(_toolCallId,input,_signal){let sessionId=resolveTerminalId(ctx.manager,input.bash_id),runtime=ctx.manager.get(sessionId);if(!runtime)return errorResult(`No terminal session found with id: ${input.bash_id}`);if(runtime.exited)return errorResult(`Session ${input.bash_id} is not running; cannot send input.`);let notes=[];if(typeof input.input=="string"){let submit=input.submit??input.input.length>0,result=runtime.session.write(submit?`${input.input}\r`:input.input);if(!result.ok)return errorResult(`Failed to write input: ${result.note}`);notes.push(submit?"wrote input + Enter":"wrote input")}if(input.keys&&input.keys.length>0){let{data,unknown}=encodeKeys(input.keys);if(data.length>0){let result=runtime.session.write(data);if(!result.ok)return errorResult(`Failed to send keys: ${result.note}`);notes.push(`sent ${input.keys.length-unknown.length} key(s)`)}unknown.length>0&&notes.push(`ignored unknown keys: ${unknown.join(", ")}`)}return notes.length===0?errorResult("Nothing to send: provide `input` and/or `keys`."):(ctx.onSessionInput?.(sessionId),textResult(`Sent to ${input.bash_id}: ${notes.join("; ")}.`))}}}var PLAIN_LINE_STYLE={fg:(_token,text)=>text};function jobWidgetLineStyle(theme,env=process.env){return env.NO_COLOR?PLAIN_LINE_STYLE:{fg:(token,text)=>theme.fg(token,text)}}var SPARK_LEVELS="\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588",ELLIPSIS="\u2026",SGR_RESET="\x1B[0m",MIN_TITLE_COLUMNS=8,GAP=" ";function sparkGlyphs(values,min,max,columns){let span=max-min,top=SPARK_LEVELS.length-1;return values.slice(-columns).map(value=>{let level=span>0?Math.round((value-min)/span*top):Math.ceil(top/2);return SPARK_LEVELS[Math.min(top,Math.max(0,level))]}).join("")}function sparkColumns(width){return width>=100?16:width>=60?12:8}function meterCells(width){return width>=60?10:6}function plain(segments){return segments.map(segment=>segment.text).join("")}function styled(segments,style){return segments.filter(segment=>segment.text.length>0).map(segment=>segment.token?style.fg(segment.token,segment.text):segment.text).join("")}function cutPlain(text,columns){return truncateToWidth(text,columns,ELLIPSIS).replaceAll(SGR_RESET,"")}function trendToken(tone){return tone==="success"?"success":tone==="error"?"error":"muted"}function oneLine(text){return text.replace(/\s+/g," ").trim()}function metricSegments(view,withHeadlineLabel,extra){let segments=[],headline=view.headline;return headline&&(headline.label&&withHeadlineLabel&&segments.push({text:`${oneLine(headline.label)} `,token:"muted"}),segments.push({text:oneLine(headline.text)}),headline.trend&&segments.push({text:` ${headline.trend.text}`,token:trendToken(headline.trend.tone)})),extra&&(segments.length>0&&segments.push({text:" \xB7 ",token:"muted"}),segments.push({text:extra})),segments}function viewParts(entry,view,width){if(entry.state==="pending"){let lines=view.lines??0,metrics=[{text:`reading output \xB7 ${lines} ${lines===1?"line":"lines"}`,token:"muted"}];return{chart:[],metrics:()=>metrics}}if(entry.state==="fallback"){let metrics=view.stage?[{text:oneLine(view.stage),token:"muted"}]:[];return{chart:[],metrics:()=>metrics}}let primary=view.blocks[0],chartToken=entry.state==="done"?"muted":"accent";if(primary?.kind==="spark"&&primary.values.length>0)return{label:primary.label,chart:[{text:sparkGlyphs(primary.values,primary.min,primary.max,sparkColumns(width)),token:chartToken}],metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel,primary.last)};if(primary?.kind==="meter"){let cells=meterCells(width),filled=Math.round(Math.min(1,Math.max(0,primary.value))*cells);return{label:primary.label,chart:[{text:"[",token:"muted"},{text:"\u2588".repeat(filled),token:chartToken},{text:"\u2591".repeat(cells-filled),token:"muted"},{text:"]",token:"muted"}],count:{text:oneLine(primary.text)},metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel)}}return{chart:[],metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel)}}function idToken(entry){return entry.state==="live"?"accent":entry.state==="done"?"success":"muted"}function formatJobWidgetLine(entry,width,style,options={}){let view=entry.view;if(entry.state==="skipped"||view===void 0||width<=0)return;let parts=viewParts(entry,view,width),title=oneLine(view.title),titleWidth=visibleWidth(title),compose=shape=>{let pieces=[];if(options.showId!==!1&&pieces.push([{text:entry.id,token:idToken(entry)}]),shape.title.length>0){let label=shape.blockLabel&&parts.label?` \xB7 ${oneLine(parts.label)}`:"";pieces.push([{text:shape.title},...label?[{text:label,token:"muted"}]:[]])}let bar=shape.chart?parts.chart:[],chart=[...bar,...parts.count?[...bar.length>0?[{text:" "}]:[],parts.count]:[]];chart.length>0&&pieces.push(chart);let metrics=parts.metrics(shape.headlineLabel);return metrics.length>0&&pieces.push(metrics),pieces.flatMap((piece,index)=>index===0?piece:[{text:shape.gap},...piece])},fits=segments=>visibleWidth(plain(segments))<=width,shrunk=(shape,minTitle)=>{let without=compose({...shape,title:"",blockLabel:!1}),room=width-visibleWidth(plain(without))-visibleWidth(shape.gap);if(room>=Math.min(minTitle,titleWidth)){let cut=titleWidth<=room?title:cutPlain(title,room);if(cut.length>0&&cut!==ELLIPSIS){let candidate=compose({...shape,title:cut,blockLabel:!1});if(fits(candidate))return candidate}}return minTitle===0&&fits(without)?without:void 0};for(let blockLabel of[!0,!1]){let candidate=compose({title,blockLabel,chart:!0,headlineLabel:!0,gap:GAP});if(fits(candidate))return styled(candidate,style)}for(let headlineLabel of[!0,!1])for(let chart of[!0,!1]){let candidate=shrunk({chart,headlineLabel,gap:GAP},MIN_TITLE_COLUMNS);if(candidate)return styled(candidate,style)}for(let gap of[GAP," "]){let candidate=shrunk({chart:!1,headlineLabel:!1,gap},0);if(candidate)return styled(candidate,style)}let hasNumbers=parts.count!==void 0||parts.metrics(!1).length>0,narrow=compose({title:hasNumbers?"":title,blockLabel:!1,chart:!1,headlineLabel:!1,gap:" "});return style===PLAIN_LINE_STYLE?cutPlain(plain(narrow),width):truncateToWidth(styled(narrow,style),width,ELLIPSIS)}var OUTPUT_PREVIEW_LINES=8;function jobWidgetOf(details){let entry=details?.jobWidget;return typeof entry?.view?.title=="string"&&Array.isArray(entry.view.blocks)?entry:void 0}var BashOutputResultComponent=class{#text="";#isPartial=!1;#expanded=!1;#jobWidget;#style;setResult(result,options,style){this.#jobWidget=jobWidgetOf(result.details),this.#style=style,this.#text=result.content.filter(content=>content.type==="text"&&!isModelOnlyText(content)).map(content=>content.type==="text"?content.text:"").join(`
63
+ ${early}`:"";return textResult(`${header}${backendNote}${earlyBlock}`,{details:{bash_id:id,background:!0}})}function createPtyBashTool(ctx){return{name:TERMINAL_BASH_TOOL,exposure:"eval",label:"bash",description:"Execute a shell command in a persistent PTY-backed session. Set run_in_background:true for long-lived or interactive sessions; steer them with bash_input, snapshot with bash_output, tear down with kill_bash. To wait on observable state (a build finishing, a server coming up, a log line), never run sleep or poll loops: subscribe with the monitor tool instead. Foreground blocking stops at the ~60s window and a still-running command auto-detaches to a live background session; `timeout` is the process kill deadline in seconds.",promptSnippet:"Run shell commands; run_in_background:true for long-lived/interactive PTY sessions",promptGuidelines:["PI_* env vars = current model + session details."],parameters:ptyBashSchema,async execute(_toolCallId,input,signal,onUpdate,execCtx){let cols=resolveDimension(input.cols,ctx.defaultCols||DEFAULT_COLS),rows=resolveDimension(input.rows,ctx.defaultRows||DEFAULT_ROWS),cwd=execCtx?.cwd;return input.run_in_background?runBackground(ctx,input,cols,rows,cwd,execCtx):runForeground(ctx,input,cols,rows,signal,cwd,onUpdate,execCtx)}}}var bashInputSchema=typebox_exports.Object({bash_id:typebox_exports.String({description:"Session id returned by a run_in_background bash call."}),input:typebox_exports.Optional(typebox_exports.String({description:"Literal text to write to the session's stdin."})),keys:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String(),{description:"Named keys to send, e.g. ['ctrl+c'], ['enter'], ['up']. Sent after `input` when both are given."})),submit:typebox_exports.Optional(typebox_exports.Boolean({description:"Append Enter (\\r) after `input`. Default true when `input` is a non-empty string."}))});function createBashInputTool(ctx){return{name:TERMINAL_INPUT_TOOL,label:"bash_input",description:"Write stdin or named keys (ctrl+c, enter, up, ...) to a live background bash session: e.g. drive a REPL or send SIGINT. This executes arbitrary shell input and is permission-gated like bash.",exposure:"search",allowLazyActivation:!0,searchKeywords:["stdin","keys","ctrl+c","interrupt","repl","send input"],parameters:bashInputSchema,async execute(_toolCallId,input,_signal){let sessionId=resolveTerminalId(ctx.manager,input.bash_id),runtime=ctx.manager.get(sessionId);if(!runtime)return errorResult(`No terminal session found with id: ${input.bash_id}`);if(runtime.exited)return errorResult(`Session ${input.bash_id} is not running; cannot send input.`);let notes=[];if(typeof input.input=="string"){let submit=input.submit??input.input.length>0,result=runtime.session.write(submit?`${input.input}\r`:input.input);if(!result.ok)return errorResult(`Failed to write input: ${result.note}`);notes.push(submit?"wrote input + Enter":"wrote input")}if(input.keys&&input.keys.length>0){let{data,unknown}=encodeKeys(input.keys);if(data.length>0){let result=runtime.session.write(data);if(!result.ok)return errorResult(`Failed to send keys: ${result.note}`);notes.push(`sent ${input.keys.length-unknown.length} key(s)`)}unknown.length>0&&notes.push(`ignored unknown keys: ${unknown.join(", ")}`)}return notes.length===0?errorResult("Nothing to send: provide `input` and/or `keys`."):(ctx.onSessionInput?.(sessionId),textResult(`Sent to ${input.bash_id}: ${notes.join("; ")}.`))}}}var PLAIN_LINE_STYLE={fg:(_token,text)=>text};function jobWidgetLineStyle(theme,env=process.env){return env.NO_COLOR?PLAIN_LINE_STYLE:{fg:(token2,text)=>theme.fg(token2,text)}}var SPARK_LEVELS="\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588",ELLIPSIS="\u2026",SGR_RESET="\x1B[0m",MIN_TITLE_COLUMNS=8,GAP=" ";function sparkGlyphs(values,min,max,columns){let span=max-min,top=SPARK_LEVELS.length-1;return values.slice(-columns).map(value=>{let level=span>0?Math.round((value-min)/span*top):Math.ceil(top/2);return SPARK_LEVELS[Math.min(top,Math.max(0,level))]}).join("")}function sparkColumns(width){return width>=100?16:width>=60?12:8}function meterCells(width){return width>=60?10:6}function plain(segments){return segments.map(segment=>segment.text).join("")}function styled(segments,style){return segments.filter(segment=>segment.text.length>0).map(segment=>segment.token?style.fg(segment.token,segment.text):segment.text).join("")}function cutPlain(text,columns){return truncateToWidth(text,columns,ELLIPSIS).replaceAll(SGR_RESET,"")}function trendToken(tone){return tone==="success"?"success":tone==="error"?"error":"muted"}function oneLine(text){return text.replace(/\s+/g," ").trim()}function metricSegments(view,withHeadlineLabel,extra){let segments=[],headline=view.headline;return headline&&(headline.label&&withHeadlineLabel&&segments.push({text:`${oneLine(headline.label)} `,token:"muted"}),segments.push({text:oneLine(headline.text)}),headline.trend&&segments.push({text:` ${headline.trend.text}`,token:trendToken(headline.trend.tone)})),extra&&(segments.length>0&&segments.push({text:" \xB7 ",token:"muted"}),segments.push({text:extra})),segments}function viewParts(entry,view,width){if(entry.state==="pending"){let lines=view.lines??0,metrics=[{text:`reading output \xB7 ${lines} ${lines===1?"line":"lines"}`,token:"muted"}];return{chart:[],metrics:()=>metrics}}if(entry.state==="fallback"){let metrics=view.stage?[{text:oneLine(view.stage),token:"muted"}]:[];return{chart:[],metrics:()=>metrics}}let primary=view.blocks[0],chartToken=entry.state==="done"?"muted":"accent";if(primary?.kind==="spark"&&primary.values.length>0)return{label:primary.label,chart:[{text:sparkGlyphs(primary.values,primary.min,primary.max,sparkColumns(width)),token:chartToken}],metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel,primary.last)};if(primary?.kind==="meter"){let cells=meterCells(width),filled=Math.round(Math.min(1,Math.max(0,primary.value))*cells);return{label:primary.label,chart:[{text:"[",token:"muted"},{text:"\u2588".repeat(filled),token:chartToken},{text:"\u2591".repeat(cells-filled),token:"muted"},{text:"]",token:"muted"}],count:{text:oneLine(primary.text)},metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel)}}return{chart:[],metrics:withHeadlineLabel=>metricSegments(view,withHeadlineLabel)}}function idToken(entry){return entry.state==="live"?"accent":entry.state==="done"?"success":"muted"}function formatJobWidgetLine(entry,width,style,options={}){let view=entry.view;if(entry.state==="skipped"||view===void 0||width<=0)return;let parts=viewParts(entry,view,width),title=oneLine(view.title),titleWidth=visibleWidth(title),compose=shape=>{let pieces=[];if(options.showId!==!1&&pieces.push([{text:entry.id,token:idToken(entry)}]),shape.title.length>0){let label=shape.blockLabel&&parts.label?` \xB7 ${oneLine(parts.label)}`:"";pieces.push([{text:shape.title},...label?[{text:label,token:"muted"}]:[]])}let bar=shape.chart?parts.chart:[],chart=[...bar,...parts.count?[...bar.length>0?[{text:" "}]:[],parts.count]:[]];chart.length>0&&pieces.push(chart);let metrics=parts.metrics(shape.headlineLabel);return metrics.length>0&&pieces.push(metrics),pieces.flatMap((piece,index)=>index===0?piece:[{text:shape.gap},...piece])},fits=segments=>visibleWidth(plain(segments))<=width,shrunk=(shape,minTitle)=>{let without=compose({...shape,title:"",blockLabel:!1}),room=width-visibleWidth(plain(without))-visibleWidth(shape.gap);if(room>=Math.min(minTitle,titleWidth)){let cut=titleWidth<=room?title:cutPlain(title,room);if(cut.length>0&&cut!==ELLIPSIS){let candidate=compose({...shape,title:cut,blockLabel:!1});if(fits(candidate))return candidate}}return minTitle===0&&fits(without)?without:void 0};for(let blockLabel of[!0,!1]){let candidate=compose({title,blockLabel,chart:!0,headlineLabel:!0,gap:GAP});if(fits(candidate))return styled(candidate,style)}for(let headlineLabel of[!0,!1])for(let chart of[!0,!1]){let candidate=shrunk({chart,headlineLabel,gap:GAP},MIN_TITLE_COLUMNS);if(candidate)return styled(candidate,style)}for(let gap of[GAP," "]){let candidate=shrunk({chart:!1,headlineLabel:!1,gap},0);if(candidate)return styled(candidate,style)}let hasNumbers=parts.count!==void 0||parts.metrics(!1).length>0,narrow=compose({title:hasNumbers?"":title,blockLabel:!1,chart:!1,headlineLabel:!1,gap:" "});return style===PLAIN_LINE_STYLE?cutPlain(plain(narrow),width):truncateToWidth(styled(narrow,style),width,ELLIPSIS)}var OUTPUT_PREVIEW_LINES=8;function jobWidgetOf(details){let entry=details?.jobWidget;return typeof entry?.view?.title=="string"&&Array.isArray(entry.view.blocks)?entry:void 0}var BashOutputResultComponent=class{#text="";#isPartial=!1;#expanded=!1;#jobWidget;#style;setResult(result,options,style){this.#jobWidget=jobWidgetOf(result.details),this.#style=style,this.#text=result.content.filter(content=>content.type==="text"&&!isModelOnlyText(content)).map(content=>content.type==="text"?content.text:"").join(`
61
64
  `),this.#isPartial=options.isPartial,this.#expanded=options.expanded}render(width){let summary=this.#jobWidget&&this.#style?formatJobWidgetLine(this.#jobWidget,width,this.#style,{showId:!1}):void 0,output=!this.#isPartial||this.#expanded?this.#text.split(`
62
65
  `):truncateToVisualLines(this.#text,OUTPUT_PREVIEW_LINES,Math.max(1,width)).visualLines.map(line=>line.trimEnd());return summary===void 0?output:[summary,...output]}invalidate(){}};function renderBashOutputCall(args,theme){return new Text(theme.fg("toolTitle",theme.bold(`bash_output ${args.bash_id}`)),0,0)}function renderMonitorCall(args,theme){let label=args.action==="rearm"?`monitor rearm ${args.bash_id??""}`.trimEnd():`monitor ${args.description??args.command??""}`.trimEnd();return new Text(theme.fg("toolTitle",theme.bold(label)),0,0)}function renderBashOutputResult(result,options,theme,context){let component=context.lastComponent??new BashOutputResultComponent;return component.setResult(result,options,jobWidgetLineStyle(theme)),component}var bashOutputSchema=typebox_exports.Object({bash_id:typebox_exports.String({description:"Session id returned by a run_in_background bash call."}),filter:typebox_exports.Optional(typebox_exports.String({description:"Only return output lines matching this regex."})),view:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("log"),typebox_exports.Literal("screen")],{description:"'log' returns new raw output (default); 'screen' returns the rendered xterm grid."}))});function statusLine(runtime){if(!runtime.exited)return"status: running";let status=describeExit(runtime)??"exited",code=runtime.exitResult?.exitCode;return code==null?`status: ${status}`:`status: ${status} exit_code: ${code}`}function applyFilter(text,filter){if(!filter)return text;let regex=safeRegExp(filter);return regex===null?text:text.split(`
63
66
  `).filter(line=>regex.test(line)).join(`
@@ -66,4 +69,4 @@ ${early}`:"";return textResult(`${header}${backendNote}${earlyBlock}`,{details:{
66
69
  `:"";if(input.view==="screen")return textResult(`${prefix}${statusLine(runtime)}
67
70
  ${screenView(runtime)}`,extra);let delta=runtime.readDelta(),formatted=formatTerminalToolOutput(applyFilter(delta.text,input.filter)),droppedNotice=delta.droppedChars>0?`[${delta.droppedChars} earlier chars dropped]`:void 0,dropped=droppedNotice===void 0?"":`${droppedNotice}
68
71
  `;return noticedResult(`${prefix}${statusLine(runtime)}
69
- ${dropped}${formatted.text||"(no new output)"}`,[droppedNotice,formatted.marker],extra)},renderCall:renderBashOutputCall,renderResult:renderBashOutputResult}}var bashResizeSchema=typebox_exports.Object({bash_id:typebox_exports.String({description:"Session id returned by a run_in_background bash call."}),cols:typebox_exports.Number({description:"New PTY width in columns."}),rows:typebox_exports.Number({description:"New PTY height in rows."})});function valid(value){return Number.isFinite(value)&&value>=1}function createBashResizeTool(ctx){return{name:TERMINAL_RESIZE_TOOL,label:"bash_resize",description:"Resize a live background bash session's PTY (cols x rows) so full-screen TUIs reflow. No-ops with a note under the pipe fallback.",exposure:"search",allowLazyActivation:!0,searchKeywords:["resize","pty size","cols","rows","terminal size"],parameters:bashResizeSchema,async execute(_toolCallId,input,_signal){let sessionId=resolveTerminalId(ctx.manager,input.bash_id),runtime=ctx.manager.get(sessionId);if(!runtime)return errorResult(`No terminal session found with id: ${input.bash_id}`);if(runtime.exited)return errorResult(`Session ${input.bash_id} is not running; cannot resize.`);if(!valid(input.cols)||!valid(input.rows))return errorResult("cols and rows must be finite integers >= 1.");let cols=Math.trunc(input.cols),rows=Math.trunc(input.rows),result=runtime.session.resize(cols,rows);return runtime.resizeScreen(cols,rows),result.ok?textResult(`Resized ${input.bash_id} to ${cols}x${rows}.`):textResult(`Resize note for ${input.bash_id}: ${result.note}`)}}}import{mkdir as mkdir4,rm as rm5}from"node:fs/promises";import{isAbsolute as isAbsolute2,join as join5}from"node:path";function terminalStateDir(ctx){if(ctx!==void 0&&NON_INTERACTIVE_MODES.has(ctx.mode))return;let sessionDir=ctx?.sessionManager?.getSessionDir?.();if(!(sessionDir===void 0||sessionDir.length===0||!isAbsolute2(sessionDir)))return join5(sessionDir,"extensions","terminal")}function monitorStateDir(terminalDir,monitorId){return join5(terminalDir,"state",monitorId)}async function ensureMonitorStateDir(terminalDir,monitorId){let dir=monitorStateDir(terminalDir,monitorId);return await mkdir4(dir,{recursive:!0,mode:448}),dir}async function removeMonitorStateDir(terminalDir,monitorId){await rm5(monitorStateDir(terminalDir,monitorId),{recursive:!0,force:!0})}var killBashSchema=typebox_exports.Object({bash_id:typebox_exports.Optional(typebox_exports.String({description:"Session id to tree-kill."})),all:typebox_exports.Optional(typebox_exports.Boolean({description:"Tree-kill every live background session."}))});function createKillBashTool(ctx){return{name:TERMINAL_KILL_TOOL,label:"kill_bash",description:"Terminate a background bash session (or all of them) and its process tree cleanly.",promptSnippet:"Tree-kill a background bash session (or all) with no orphans",parameters:killBashSchema,async execute(_toolCallId,input,_signal){let terminalDir=terminalStateDir(ctx.getSessionContext?.()),dropStateDir=async monitorId2=>{terminalDir!==void 0&&monitorId2!==void 0&&await removeMonitorStateDir(terminalDir,monitorId2)};if(input.all){let terminalCount=ctx.manager.size,monitorIds=(ctx.monitorRegistry?.snapshot()??[]).map(entry=>entry.monitorId),fileCount=await ctx.monitorRegistry?.stopAllFiles()??0,rpcCount=ctx.monitorRegistry?.stopAllRpc()??0;await ctx.manager.teardown();for(let monitorId2 of monitorIds)await dropStateDir(monitorId2);return textResult(`Killed ${terminalCount+fileCount+rpcCount} session(s).`)}if(!input.bash_id)return errorResult("Provide `bash_id` or set `all:true`.");let sessionId=resolveTerminalId(ctx.manager,input.bash_id),monitorId=input.bash_id.startsWith("mon_")?input.bash_id:ctx.manager.monitorIdOf?.(sessionId);return await ctx.monitorRegistry?.stopFile(sessionId)||ctx.monitorRegistry?.stopRpc(sessionId)?(await dropStateDir(monitorId),textResult(`Killed ${input.bash_id}.`)):ctx.manager.get(sessionId)?(await ctx.manager.stop(sessionId),await dropStateDir(monitorId),textResult(`Killed ${input.bash_id}.`)):errorResult(`No terminal session found with id: ${input.bash_id}`)}}}var TERMINAL_CHILD_JOB_KINDS={bash:"terminal.bash",output:"terminal.output",input:"terminal.input",resize:"terminal.resize",kill:"terminal.kill"};function childTerminalIdScope(generation){return`c${generation}`}var CHILD_SESSION_ID=/_c(\d+)_\d+$/;function isChildSessionId(id){return CHILD_SESSION_ID.test(id)}function childGenerationOf(id){let generation=CHILD_SESSION_ID.exec(id)?.[1];return generation===void 0?void 0:Number(generation)}function parseBackgroundWake(value){if(typeof value!="object"||value===null)return;let event=Reflect.get(value,"event"),id=Reflect.get(value,"id");if(!(typeof id!="string"||!isChildSessionId(id))){if(event==="background_start"){let description=Reflect.get(value,"description"),startedAtMs=Reflect.get(value,"startedAtMs");return typeof description!="string"||typeof startedAtMs!="number"?void 0:{event,id,description,startedAtMs}}if(event==="background_exit"){let output=Reflect.get(value,"output"),exit=Reflect.get(value,"exit");return typeof output!="string"||exit!==null&&typeof exit!="object"?void 0:{event,id,exit,output}}}}function exitView(exit,output){return{exitResult:exit,fullOutput:()=>output}}function bashIdOf(value){if(typeof value!="object"||value===null)return;let id=value.bash_id;return typeof id=="string"?id:void 0}function lostSessionResult(id,generation){return{content:[{type:"text",text:`bash_id ${id} is lost: the session's tool child (generation ${generation}) exited, which ended this session and every process it started. Start a new session with bash.`}],details:{bash_id:id,lost:!0,generation}}}function terminalChildJob(ctx,kind){return{kind,...kind===TERMINAL_CHILD_JOB_KINDS.bash?backgroundRelay(ctx):{},...kind===TERMINAL_CHILD_JOB_KINDS.bash?{}:{placement:params=>{let id=bashIdOf(params);return id===void 0?kind===TERMINAL_CHILD_JOB_KINDS.kill?"both":"child":isChildSessionId(id)?"child":"server"}},result:(params,value,generation)=>{if(kind===TERMINAL_CHILD_JOB_KINDS.bash)return value;let id=bashIdOf(params),startedOn=id===void 0?void 0:childGenerationOf(id);return id===void 0||startedOn===void 0||startedOn===generation?value:lostSessionResult(id,startedOn)},args:(params,toolCallId,execCtx)=>{let env={};for(let[name,value]of Object.entries(ctx.getEnv()))typeof value=="string"&&(env[name]=value);return{params,toolCallId,cwd:execCtx.cwd??ctx.cwd,env:{...env,...sessionEnvOverrides(ctx,execCtx)},...ctx.shellPath===void 0?{}:{shellPath:ctx.shellPath},defaultCols:ctx.defaultCols,defaultRows:ctx.defaultRows,redactSecretsInOutput:ctx.redactSecretsInOutput===!0,...ctx.timeoutAction===void 0?{}:{timeoutAction:ctx.timeoutAction}}}}}function backgroundRelay(ctx){let running=new Map;return{wake:(value,generation)=>{let wake=parseBackgroundWake(value);if(wake!==void 0){if(wake.event==="background_start"){running.set(wake.id,generation),ctx.onBackgroundStart?.(wake.id,wake.description,wake.startedAtMs);return}running.delete(wake.id),ctx.onBackgroundExit?.(wake.id,exitView(wake.exit,wake.output))}},childExited:generation=>{for(let[id,startedOn]of running)startedOn===generation&&(running.delete(id),ctx.onBackgroundExit?.(id,exitView({exitCode:null,signal:null,timedOut:!1,cancelled:!0},`The session's tool child (generation ${generation}) exited, which ended this session and every process it started.`)))}}}export{ToolChildJobError,HostCallAdmission,PayloadRefWriter,PayloadRefReader,packPayload,unpackPayload,proofIsOrdered,TEST_CONTROL_DIR_ENV,readTestControls,WindowsJobError,WindowsJob,loadKernel32Job,generationLedgerPath,DescendantsLedger,LaunchLog,sweepGroups,defaultGroupProbes,recordGenerationChild,sweepStaleGenerations,TOOL_CHILD_GENERATION_ENV,TOOL_CHILD_PROTOCOL_VERSION,runToolChild,goShimScript,controlFd,withControlPipe,MODULE_JOB_KIND,TOOL_CHILD_MODULE_ROOTS_ENV,createModuleJobHandler,TerminalManager,withTerminalContext,modelOnlyText,isModelOnlyText,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,sanitizeTerminalOutput,spawnCommandSession,describeExit,NOTICE_TAIL_MAX_CHARS,getTerminalNotificationDelivery,TerminalNotifier,resolveTerminalId,textResult,errorResult,resolveForegroundWindowSeconds,createPtyBashTool,createBashInputTool,secretOutputObfuscator,truncateText,JOB_WIDGET_AGGS,JOB_WIDGET_TONES,onJobWidgetSessionChange,openJobWidgetSession,resendJobWidgetState,parkJobWidgetSession,closeJobWidgetSession,registerJobWidgetSource,getJobWidgetState,setJobWidgetAuthorResolver,jobWidgetHostResolver,truncateToVisualLines,jobWidgetLineStyle,cutPlain,formatJobWidgetLine,renderMonitorCall,createBashOutputTool,createBashResizeTool,terminalStateDir,ensureMonitorStateDir,removeMonitorStateDir,createKillBashTool,TERMINAL_CHILD_JOB_KINDS,childTerminalIdScope,terminalChildJob};
72
+ ${dropped}${formatted.text||"(no new output)"}`,[droppedNotice,formatted.marker],extra)},renderCall:renderBashOutputCall,renderResult:renderBashOutputResult}}var bashResizeSchema=typebox_exports.Object({bash_id:typebox_exports.String({description:"Session id returned by a run_in_background bash call."}),cols:typebox_exports.Number({description:"New PTY width in columns."}),rows:typebox_exports.Number({description:"New PTY height in rows."})});function valid(value){return Number.isFinite(value)&&value>=1}function createBashResizeTool(ctx){return{name:TERMINAL_RESIZE_TOOL,label:"bash_resize",description:"Resize a live background bash session's PTY (cols x rows) so full-screen TUIs reflow. No-ops with a note under the pipe fallback.",exposure:"search",allowLazyActivation:!0,searchKeywords:["resize","pty size","cols","rows","terminal size"],parameters:bashResizeSchema,async execute(_toolCallId,input,_signal){let sessionId=resolveTerminalId(ctx.manager,input.bash_id),runtime=ctx.manager.get(sessionId);if(!runtime)return errorResult(`No terminal session found with id: ${input.bash_id}`);if(runtime.exited)return errorResult(`Session ${input.bash_id} is not running; cannot resize.`);if(!valid(input.cols)||!valid(input.rows))return errorResult("cols and rows must be finite integers >= 1.");let cols=Math.trunc(input.cols),rows=Math.trunc(input.rows),result=runtime.session.resize(cols,rows);return runtime.resizeScreen(cols,rows),result.ok?textResult(`Resized ${input.bash_id} to ${cols}x${rows}.`):textResult(`Resize note for ${input.bash_id}: ${result.note}`)}}}import{mkdir as mkdir4,rm as rm5}from"node:fs/promises";import{isAbsolute as isAbsolute2,join as join5}from"node:path";function terminalStateDir(ctx){if(ctx!==void 0&&NON_INTERACTIVE_MODES.has(ctx.mode))return;let sessionDir=ctx?.sessionManager?.getSessionDir?.();if(!(sessionDir===void 0||sessionDir.length===0||!isAbsolute2(sessionDir)))return join5(sessionDir,"extensions","terminal")}function monitorStateDir(terminalDir,monitorId){return join5(terminalDir,"state",monitorId)}async function ensureMonitorStateDir(terminalDir,monitorId){let dir=monitorStateDir(terminalDir,monitorId);return await mkdir4(dir,{recursive:!0,mode:448}),dir}async function removeMonitorStateDir(terminalDir,monitorId){await rm5(monitorStateDir(terminalDir,monitorId),{recursive:!0,force:!0})}var killBashSchema=typebox_exports.Object({bash_id:typebox_exports.Optional(typebox_exports.String({description:"Session id to tree-kill."})),all:typebox_exports.Optional(typebox_exports.Boolean({description:"Tree-kill every live background session."}))});function createKillBashTool(ctx){return{name:TERMINAL_KILL_TOOL,label:"kill_bash",description:"Terminate a background bash session (or all of them) and its process tree cleanly.",promptSnippet:"Tree-kill a background bash session (or all) with no orphans",parameters:killBashSchema,async execute(_toolCallId,input,_signal){let terminalDir=terminalStateDir(ctx.getSessionContext?.()),dropStateDir=async monitorId2=>{terminalDir!==void 0&&monitorId2!==void 0&&await removeMonitorStateDir(terminalDir,monitorId2)};if(input.all){let terminalCount=ctx.manager.size,monitorIds=(ctx.monitorRegistry?.snapshot()??[]).map(entry=>entry.monitorId),fileCount=await ctx.monitorRegistry?.stopAllFiles()??0,rpcCount=ctx.monitorRegistry?.stopAllRpc()??0;await ctx.manager.teardown();for(let monitorId2 of monitorIds)await dropStateDir(monitorId2);return textResult(`Killed ${terminalCount+fileCount+rpcCount} session(s).`)}if(!input.bash_id)return errorResult("Provide `bash_id` or set `all:true`.");let sessionId=resolveTerminalId(ctx.manager,input.bash_id),monitorId=input.bash_id.startsWith("mon_")?input.bash_id:ctx.manager.monitorIdOf?.(sessionId);return await ctx.monitorRegistry?.stopFile(sessionId)||ctx.monitorRegistry?.stopRpc(sessionId)?(await dropStateDir(monitorId),textResult(`Killed ${input.bash_id}.`)):ctx.manager.get(sessionId)?(await ctx.manager.stop(sessionId),await dropStateDir(monitorId),textResult(`Killed ${input.bash_id}.`)):errorResult(`No terminal session found with id: ${input.bash_id}`)}}}var TERMINAL_CHILD_JOB_KINDS={bash:"terminal.bash",output:"terminal.output",input:"terminal.input",resize:"terminal.resize",kill:"terminal.kill"};function childTerminalIdScope(generation){return`c${generation}`}var CHILD_SESSION_ID=/_c(\d+)_\d+$/;function isChildSessionId(id){return CHILD_SESSION_ID.test(id)}function childGenerationOf(id){let generation=CHILD_SESSION_ID.exec(id)?.[1];return generation===void 0?void 0:Number(generation)}function parseBackgroundWake(value){if(typeof value!="object"||value===null)return;let event=Reflect.get(value,"event"),id=Reflect.get(value,"id");if(!(typeof id!="string"||!isChildSessionId(id))){if(event==="background_start"){let description=Reflect.get(value,"description"),startedAtMs=Reflect.get(value,"startedAtMs");return typeof description!="string"||typeof startedAtMs!="number"?void 0:{event,id,description,startedAtMs}}if(event==="background_exit"){let output=Reflect.get(value,"output"),exit=Reflect.get(value,"exit");return typeof output!="string"||exit!==null&&typeof exit!="object"?void 0:{event,id,exit,output}}}}function exitView(exit,output){return{exitResult:exit,fullOutput:()=>output}}function bashIdOf(value){if(typeof value!="object"||value===null)return;let id=value.bash_id;return typeof id=="string"?id:void 0}function lostSessionResult(id,generation){return{content:[{type:"text",text:`bash_id ${id} is lost: the session's tool child (generation ${generation}) exited, which ended this session and every process it started. Start a new session with bash.`}],details:{bash_id:id,lost:!0,generation}}}function terminalChildJob(ctx,kind){return{kind,...kind===TERMINAL_CHILD_JOB_KINDS.bash?backgroundRelay(ctx):{},...kind===TERMINAL_CHILD_JOB_KINDS.bash?{}:{placement:params=>{let id=bashIdOf(params);return id===void 0?kind===TERMINAL_CHILD_JOB_KINDS.kill?"both":"child":isChildSessionId(id)?"child":"server"}},result:(params,value,generation)=>{if(kind===TERMINAL_CHILD_JOB_KINDS.bash)return value;let id=bashIdOf(params),startedOn=id===void 0?void 0:childGenerationOf(id);return id===void 0||startedOn===void 0||startedOn===generation?value:lostSessionResult(id,startedOn)},args:(params,toolCallId,execCtx)=>{let env={};for(let[name,value]of Object.entries(ctx.getEnv()))typeof value=="string"&&(env[name]=value);return{params,toolCallId,cwd:execCtx.cwd??ctx.cwd,env:{...env,...sessionEnvOverrides(ctx,execCtx)},...ctx.shellPath===void 0?{}:{shellPath:ctx.shellPath},defaultCols:ctx.defaultCols,defaultRows:ctx.defaultRows,redactSecretsInOutput:ctx.redactSecretsInOutput===!0,...ctx.timeoutAction===void 0?{}:{timeoutAction:ctx.timeoutAction}}}}}function backgroundRelay(ctx){let running=new Map;return{wake:(value,generation)=>{let wake=parseBackgroundWake(value);if(wake!==void 0){if(wake.event==="background_start"){running.set(wake.id,generation),ctx.onBackgroundStart?.(wake.id,wake.description,wake.startedAtMs);return}running.delete(wake.id),ctx.onBackgroundExit?.(wake.id,exitView(wake.exit,wake.output))}},childExited:generation=>{for(let[id,startedOn]of running)startedOn===generation&&(running.delete(id),ctx.onBackgroundExit?.(id,exitView({exitCode:null,signal:null,timedOut:!1,cancelled:!0},`The session's tool child (generation ${generation}) exited, which ended this session and every process it started.`)))}}}export{ToolChildJobError,HostCallAdmission,PayloadRefWriter,PayloadRefReader,packPayload,unpackPayload,proofIsOrdered,TEST_CONTROL_DIR_ENV,readTestControls,WindowsJobError,WindowsJob,loadKernel32Job,generationLedgerPath,DescendantsLedger,LaunchLog,sweepGroups,defaultGroupProbes,recordGenerationChild,sweepStaleGenerations,TOOL_CHILD_GENERATION_ENV,TOOL_CHILD_PROTOCOL_VERSION,runToolChild,goShimScript,controlFd,withControlPipe,MODULE_JOB_KIND,TOOL_CHILD_MODULE_ROOTS_ENV,createModuleJobHandler,TerminalManager,annotateShellTrust,withTerminalContext,modelOnlyText,isModelOnlyText,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,sanitizeTerminalOutput,spawnCommandSession,describeExit,NOTICE_TAIL_MAX_CHARS,getTerminalNotificationDelivery,TerminalNotifier,resolveTerminalId,textResult,errorResult,resolveForegroundWindowSeconds,createPtyBashTool,createBashInputTool,secretOutputObfuscator,truncateText,JOB_WIDGET_AGGS,JOB_WIDGET_TONES,onJobWidgetSessionChange,openJobWidgetSession,resendJobWidgetState,parkJobWidgetSession,closeJobWidgetSession,registerJobWidgetSource,getJobWidgetState,setJobWidgetAuthorResolver,jobWidgetHostResolver,truncateToVisualLines,jobWidgetLineStyle,cutPlain,formatJobWidgetLine,renderMonitorCall,createBashOutputTool,createBashResizeTool,terminalStateDir,ensureMonitorStateDir,removeMonitorStateDir,createKillBashTool,TERMINAL_CHILD_JOB_KINDS,childTerminalIdScope,terminalChildJob};