@ashx-j/lunr 0.2.19 → 0.2.20

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 (170) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +2 -2
  3. package/dist/builtin-extensions/index.d.ts.map +1 -1
  4. package/dist/builtin-extensions/index.js +0 -2
  5. package/dist/builtin-extensions/index.js.map +1 -1
  6. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts +6 -4
  7. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
  8. package/dist/builtin-extensions/pi-intercom/broker/spawn.js +93 -49
  9. package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
  10. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  11. package/dist/builtin-extensions/pi-intercom/index.js +351 -351
  12. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  13. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -1
  14. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +80 -43
  16. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +18 -8
  18. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +36 -11
  20. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  22. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  23. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +21 -12
  24. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +7 -1
  26. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +225 -15
  28. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts +29 -0
  30. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -0
  31. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +179 -0
  32. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -0
  33. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +89 -0
  34. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -0
  35. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +541 -0
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -0
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +9 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +34 -9
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +1 -2
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +2 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +35 -8
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +3 -3
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts +1 -0
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +54 -38
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -6
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +64 -5
  59. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +1 -0
  62. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +21 -8
  65. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +62 -16
  68. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -0
  70. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +75 -18
  72. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +13 -1
  74. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +67 -11
  76. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  77. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +5 -2
  79. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  81. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -3
  82. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +3 -0
  84. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  85. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +68 -11
  86. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +12 -1
  88. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +21 -2
  90. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +16 -4
  92. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  93. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  95. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +2 -0
  96. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  97. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +24 -6
  98. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  99. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +44 -4
  100. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  101. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +227 -133
  102. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  103. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.d.ts.map +1 -1
  104. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js +1 -1
  105. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js.map +1 -1
  106. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts +2 -13
  107. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts.map +1 -1
  108. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js +5 -91
  109. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js.map +1 -1
  110. package/dist/core/permissions.d.ts +1 -0
  111. package/dist/core/permissions.d.ts.map +1 -1
  112. package/dist/core/permissions.js +8 -4
  113. package/dist/core/permissions.js.map +1 -1
  114. package/dist/core/plan-mode.d.ts.map +1 -1
  115. package/dist/core/plan-mode.js +0 -5
  116. package/dist/core/plan-mode.js.map +1 -1
  117. package/dist/core/runtime-bridges.d.ts.map +1 -1
  118. package/dist/core/runtime-bridges.js +0 -2
  119. package/dist/core/runtime-bridges.js.map +1 -1
  120. package/dist/core/subagent-cancellation.d.ts +21 -0
  121. package/dist/core/subagent-cancellation.d.ts.map +1 -0
  122. package/dist/core/subagent-cancellation.js +53 -0
  123. package/dist/core/subagent-cancellation.js.map +1 -0
  124. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/assistant-message.js +12 -18
  126. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  127. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  128. package/dist/modes/interactive/components/tool-execution.js +12 -0
  129. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  130. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  131. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  132. package/dist/modes/interactive/interactive-mode.js +29 -0
  133. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  134. package/dist/node-runtime/{agent-session-services-35WNVGMR.js → agent-session-services-75JKASCW.js} +3 -3
  135. package/dist/node-runtime/{builtin-extensions-322XDDEM.js → builtin-extensions-X4JMM4ZS.js} +2 -2
  136. package/dist/node-runtime/{chunk-XATUM2HK.js → chunk-25I2BHAA.js} +1 -1
  137. package/dist/node-runtime/{chunk-MCUNIRD5.js → chunk-46ECNOLF.js} +477 -246
  138. package/dist/node-runtime/{chunk-J26TSGDL.js → chunk-6N22HULO.js} +8 -5
  139. package/dist/node-runtime/{chunk-TFBIJTM3.js → chunk-AL2FMKKM.js} +7 -7
  140. package/dist/node-runtime/chunk-AOFXZQKA.js +24 -0
  141. package/dist/node-runtime/chunk-BBUVIEZB.js +51 -0
  142. package/dist/node-runtime/{chunk-ZRCBN365.js → chunk-ELWEXVO5.js} +7 -7
  143. package/dist/node-runtime/{chunk-ATGA2WLC.js → chunk-JYNNB7DU.js} +397 -34
  144. package/dist/node-runtime/{chunk-4FX25LWP.js → chunk-K3646JTM.js} +16 -117
  145. package/dist/node-runtime/{chunk-PNJSG3IZ.js → chunk-LTYWTR3V.js} +1 -369
  146. package/dist/node-runtime/{chunk-TXHKBRHZ.js → chunk-QKFMBRAL.js} +45 -31
  147. package/dist/node-runtime/{command-DWUM5X3U.js → command-RBTRL55A.js} +1 -1
  148. package/dist/node-runtime/{gateway-UZXMFGWY.js → gateway-L4ANRTVE.js} +2 -2
  149. package/dist/node-runtime/index.js +9 -8
  150. package/dist/node-runtime/{interactive-mode-QT5IKGQ5.js → interactive-mode-HPUNH7SV.js} +5 -4
  151. package/dist/node-runtime/{lunr-cron-QPBTKBGI.js → lunr-cron-NNYTWTGF.js} +2 -2
  152. package/dist/node-runtime/main.js +7 -7
  153. package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-DDQMRNPJ.js} +96 -76
  154. package/dist/node-runtime/{pi-subagents-7YJ3I4VE.js → pi-subagents-T5WMMLBB.js} +1040 -318
  155. package/dist/node-runtime/rpc-entry.js +7 -7
  156. package/dist/node-runtime/{runtime-bridges-3RKBDLNA.js → runtime-bridges-NJQERQ72.js} +2 -4
  157. package/dist/node-runtime/{subagent-executor-5Q5A4HJ2.js → subagent-executor-SRFC26SJ.js} +168 -249
  158. package/docs/features.md +17 -3
  159. package/docs/keybindings.md +3 -1
  160. package/docs/settings.md +1 -1
  161. package/package.json +4 -4
  162. package/dist/builtin-extensions/lunr-settings-tools.d.ts +0 -4
  163. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +0 -1
  164. package/dist/builtin-extensions/lunr-settings-tools.js +0 -120
  165. package/dist/builtin-extensions/lunr-settings-tools.js.map +0 -1
  166. package/dist/core/settings-tools-bridge.d.ts +0 -35
  167. package/dist/core/settings-tools-bridge.d.ts.map +0 -1
  168. package/dist/core/settings-tools-bridge.js +0 -56
  169. package/dist/core/settings-tools-bridge.js.map +0 -1
  170. package/dist/node-runtime/chunk-3NMWLTPV.js +0 -64
package/CHANGELOG.md CHANGED
@@ -4,6 +4,29 @@ lunR is derived from pi. The published npm package is **`@ashx-j/lunr@0.2.19`**.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.20] - 2026-09-12
8
+
9
+ ### Added
10
+
11
+ - Parent agents can ask a running async child a decision-specific question without stopping its assignment. Answers can wake the parent or return through `subagent_wait`.
12
+
13
+ ### Changed
14
+
15
+ - **Child model selection.** Executable children choose exactly one of `tier: light|standard|heavy` (default) or an explicit `model: provider/id` when the user names a model. Optional `thinking` is only valid with an explicit model. Direct model launches do not require tier mode. Resume keeps user selection separate from the resolved runtime model.
16
+ - **Settings stay user-managed.** Removed `settings_load` and the four agent-managed settings tools. `/settings` still edits configuration. Direct `edit`/`write`/`code_rewrite` of lunR `settings.json` is blocked.
17
+ - **Watchdog configure removed.** Read-only watchdog status/check/recommend-model remain; agent `watchdog.configure` is gone.
18
+ - **Subagent compact rows.** Foreground and async children share one collapsed line: spinner, description, selected tier or model, tokens, and elapsed time. The hang line, tool-use count, thinking, and permission suffix are gone. Completed collapsed cards keep frozen stats. Async tool headers say `subagent async`. Completed notify cards show title and status only.
19
+
20
+ - Tier guidance recommends the lowest tier that can reliably finish the task, with examples for each tier.
21
+
22
+ ### Fixed
23
+
24
+ - Smooth streaming reveals thinking text incrementally instead of showing the full incoming chunk.
25
+ - Resuming async children restores their saved acceptance and model selection. Compiled installs use the JavaScript intercom broker, while native child channels skip it.
26
+ - Escape stops the parent. A second press within 500ms also stops its async children without clearing drafts or restarting the parent on stopped results.
27
+ - Async result delivery retries preserve undelivered files and avoid duplicate messages or errors printed over the TUI.
28
+ - **Async widget animation.** The 80ms timer now invalidates a stable widget component. It no longer rebuilds the widget from the 250ms status poller, so the spinner actually advances.
29
+
7
30
  ## [0.2.19] - 2026-09-12
8
31
 
9
32
  ### Changed
package/README.md CHANGED
@@ -205,7 +205,7 @@ See `/hotkeys` for the full list. Customize via `~/.lunr/agent/keybindings.json`
205
205
  | Ctrl+C | Clear editor |
206
206
  | Ctrl+C twice | Quit |
207
207
  | Escape | Cancel/abort |
208
- | Escape twice | Open `/tree` |
208
+ | Escape twice within 500ms | Stop this session's active async subagents; otherwise open `/tree` when idle |
209
209
  | Ctrl+L | Open model selector |
210
210
  | Ctrl+P / Shift+Ctrl+P | Cycle scoped models forward/backward |
211
211
  | Shift+Tab | Cycle permission mode (`manual` → `yolo` → `plan` → `auto`) |
@@ -468,7 +468,7 @@ See [docs/rpc.md](docs/rpc.md) for the protocol.
468
468
  lunR keeps a small core and still lets you shape the product with [extensions](#extensions), [skills](#skills), and [packages](#packages). Unlike upstream pi, lunR **does** ship the workflows most coding agents expect:
469
469
 
470
470
  - **MCP** — `/mcp`, `/mcp-auth`
471
- - **Subagents** — always fresh; every child selects a configured model tier; 3+ children receive one large-launch confirmation in manual and yolo; default parallel concurrency is unlimited
471
+ - **Subagents** — always fresh; children use a configured tier by default, or an explicit model when the user names one; 3+ children receive one large-launch confirmation in manual and yolo; default parallel concurrency is unlimited
472
472
  - **Permission modes** — `manual | yolo | plan | auto`; Shift+Tab cycles that order
473
473
  - **Plan mode** — `/plan` plus the `present_plan` tool
474
474
  - **Todos** — lunr-todos (full-replace)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builtin-extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAwBrF,yFAAyF;AACzF,eAAO,MAAM,sBAAsB,EAAE,eAAe,EAWnD,CAAC;AAiBF,eAAO,MAAM,gCAAgC,UAAsD,CAAC;AAEpG,6FAA6F;AAC7F,eAAO,MAAM,sBAAsB,yBAA0B,CAAC;AAE9D,6EAA6E;AAC7E,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAQhF;AAED,yFAAyF;AACzF,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAE3E;AAED,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAA2B,CAAC","sourcesContent":["/**\n * Built-in extensions for lunR.\n *\n * Light factories stay on the first-paint graph. Heavy factories are imported\n * only when attachDeferredBuiltinExtensions() runs after the TUI is up, or\n * immediately for print/RPC/gateway where there is no first-paint window.\n */\n\nimport type { ExtensionFactory, InlineExtension } from \"../core/extensions/types.ts\";\nimport { measureStartup } from \"../core/timings.ts\";\n\nimport simplePiMemory from \"./simple-pi-memory.ts\";\nimport piTps from \"./pi-tps.ts\";\nimport ashxjTui from \"./ashxj-tui.ts\";\nimport ashxjSpinners from \"./ashxj-spinners.ts\";\nimport ashxjThinking from \"./ashxj-thinking.ts\";\nimport lunrLocalProviders from \"./lunr-local-providers/index.ts\";\nimport lunrTodos from \"./lunr-todos.ts\";\nimport lunrPlanTools from \"./lunr-plan-tools.ts\";\nimport lunrSkillCreator from \"./lunr-skill-creator/index.ts\";\nimport lunrSettingsTools from \"./lunr-settings-tools.ts\";\n\n/**\n * Wrap a raw factory function as a named InlineExtension.\n * The cast bridges the gap between the source-level ExtensionFactory type\n * (used here) and the dist-level type that extensions import via the package\n * name. The underlying function signatures are structurally identical.\n */\nfunction ext(name: string, factory: unknown): InlineExtension {\n\treturn { name, factory: factory as ExtensionFactory };\n}\n\n/** UI, local providers, and small lunR-native factories. Safe to import at CLI start. */\nexport const lightBuiltinExtensions: InlineExtension[] = [\n\text(\"simple-pi-memory\", simplePiMemory),\n\text(\"pi-tps\", piTps),\n\text(\"ashxj-tui\", ashxjTui),\n\text(\"ashxj-spinners\", ashxjSpinners),\n\text(\"ashxj-thinking\", ashxjThinking),\n\text(\"lunr-local-providers\", lunrLocalProviders),\n\text(\"lunr-todos\", lunrTodos),\n\text(\"lunr-plan-tools\", lunrPlanTools),\n\text(\"lunr-skill-creator\", lunrSkillCreator),\n\text(\"lunr-settings-tools\", lunrSettingsTools),\n];\n\nconst DEFERRED_BUILTIN_LOADERS: Array<{\n\tname: string;\n\tload: () => Promise<{ default: unknown }>;\n}> = [\n\t{ name: \"pi-ollama-cloud\", load: () => import(\"./pi-ollama-cloud/index.ts\") },\n\t{ name: \"narumiruna-pi-goal\", load: () => import(\"./narumiruna-pi-goal/src/goal.ts\") },\n\t{ name: \"lunr-cron\", load: () => import(\"./lunr-cron.ts\") },\n\t{ name: \"pi-intercom\", load: () => import(\"./pi-intercom/index.ts\") },\n\t{ name: \"pi-prompt-template-model\", load: () => import(\"./pi-prompt-template-model/index.ts\") },\n\t{ name: \"pi-subagents\", load: () => import(\"./pi-subagents/index.ts\") },\n\t{ name: \"pi-web-access\", load: () => import(\"./pi-web-access/index.ts\") },\n\t{ name: \"pi-lsp-extension\", load: () => import(\"./pi-lsp-extension/src/index.ts\") },\n\t{ name: \"pi-mcp-adapter\", load: () => import(\"./pi-mcp-adapter/index.ts\") },\n];\n\nexport const DEFERRED_BUILTIN_EXTENSION_NAMES = DEFERRED_BUILTIN_LOADERS.map((entry) => entry.name);\n\n/** Flags registered only after deferred builtins attach. Do not fail CLI parse for these. */\nexport const DEFERRED_BUILTIN_FLAGS = [\"mcp-config\"] as const;\n\n/** Import MCP / LSP / web-access / intercom / subagents only when needed. */\nexport async function loadDeferredBuiltinExtensions(): Promise<InlineExtension[]> {\n\tconst loaded = await Promise.all(\n\t\tDEFERRED_BUILTIN_LOADERS.map(async ({ name, load }) => {\n\t\t\tconst module = await measureStartup(name, load, \"imports\");\n\t\t\treturn ext(name, module.default);\n\t\t}),\n\t);\n\treturn loaded;\n}\n\n/** Full roster. Print / RPC / gateway still need every factory before the first turn. */\nexport async function loadAllBuiltinExtensions(): Promise<InlineExtension[]> {\n\treturn [...lightBuiltinExtensions, ...(await loadDeferredBuiltinExtensions())];\n}\n\n/** Eager full roster. Prefer loadAllBuiltinExtensions() so CLI start stays light. */\nexport const builtinExtensions: InlineExtension[] = lightBuiltinExtensions;\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builtin-extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAuBrF,yFAAyF;AACzF,eAAO,MAAM,sBAAsB,EAAE,eAAe,EAUnD,CAAC;AAiBF,eAAO,MAAM,gCAAgC,UAAsD,CAAC;AAEpG,6FAA6F;AAC7F,eAAO,MAAM,sBAAsB,yBAA0B,CAAC;AAE9D,6EAA6E;AAC7E,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAQhF;AAED,yFAAyF;AACzF,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAE3E;AAED,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAA2B,CAAC","sourcesContent":["/**\n * Built-in extensions for lunR.\n *\n * Light factories stay on the first-paint graph. Heavy factories are imported\n * only when attachDeferredBuiltinExtensions() runs after the TUI is up, or\n * immediately for print/RPC/gateway where there is no first-paint window.\n */\n\nimport type { ExtensionFactory, InlineExtension } from \"../core/extensions/types.ts\";\nimport { measureStartup } from \"../core/timings.ts\";\n\nimport simplePiMemory from \"./simple-pi-memory.ts\";\nimport piTps from \"./pi-tps.ts\";\nimport ashxjTui from \"./ashxj-tui.ts\";\nimport ashxjSpinners from \"./ashxj-spinners.ts\";\nimport ashxjThinking from \"./ashxj-thinking.ts\";\nimport lunrLocalProviders from \"./lunr-local-providers/index.ts\";\nimport lunrTodos from \"./lunr-todos.ts\";\nimport lunrPlanTools from \"./lunr-plan-tools.ts\";\nimport lunrSkillCreator from \"./lunr-skill-creator/index.ts\";\n\n/**\n * Wrap a raw factory function as a named InlineExtension.\n * The cast bridges the gap between the source-level ExtensionFactory type\n * (used here) and the dist-level type that extensions import via the package\n * name. The underlying function signatures are structurally identical.\n */\nfunction ext(name: string, factory: unknown): InlineExtension {\n\treturn { name, factory: factory as ExtensionFactory };\n}\n\n/** UI, local providers, and small lunR-native factories. Safe to import at CLI start. */\nexport const lightBuiltinExtensions: InlineExtension[] = [\n\text(\"simple-pi-memory\", simplePiMemory),\n\text(\"pi-tps\", piTps),\n\text(\"ashxj-tui\", ashxjTui),\n\text(\"ashxj-spinners\", ashxjSpinners),\n\text(\"ashxj-thinking\", ashxjThinking),\n\text(\"lunr-local-providers\", lunrLocalProviders),\n\text(\"lunr-todos\", lunrTodos),\n\text(\"lunr-plan-tools\", lunrPlanTools),\n\text(\"lunr-skill-creator\", lunrSkillCreator),\n];\n\nconst DEFERRED_BUILTIN_LOADERS: Array<{\n\tname: string;\n\tload: () => Promise<{ default: unknown }>;\n}> = [\n\t{ name: \"pi-ollama-cloud\", load: () => import(\"./pi-ollama-cloud/index.ts\") },\n\t{ name: \"narumiruna-pi-goal\", load: () => import(\"./narumiruna-pi-goal/src/goal.ts\") },\n\t{ name: \"lunr-cron\", load: () => import(\"./lunr-cron.ts\") },\n\t{ name: \"pi-intercom\", load: () => import(\"./pi-intercom/index.ts\") },\n\t{ name: \"pi-prompt-template-model\", load: () => import(\"./pi-prompt-template-model/index.ts\") },\n\t{ name: \"pi-subagents\", load: () => import(\"./pi-subagents/index.ts\") },\n\t{ name: \"pi-web-access\", load: () => import(\"./pi-web-access/index.ts\") },\n\t{ name: \"pi-lsp-extension\", load: () => import(\"./pi-lsp-extension/src/index.ts\") },\n\t{ name: \"pi-mcp-adapter\", load: () => import(\"./pi-mcp-adapter/index.ts\") },\n];\n\nexport const DEFERRED_BUILTIN_EXTENSION_NAMES = DEFERRED_BUILTIN_LOADERS.map((entry) => entry.name);\n\n/** Flags registered only after deferred builtins attach. Do not fail CLI parse for these. */\nexport const DEFERRED_BUILTIN_FLAGS = [\"mcp-config\"] as const;\n\n/** Import MCP / LSP / web-access / intercom / subagents only when needed. */\nexport async function loadDeferredBuiltinExtensions(): Promise<InlineExtension[]> {\n\tconst loaded = await Promise.all(\n\t\tDEFERRED_BUILTIN_LOADERS.map(async ({ name, load }) => {\n\t\t\tconst module = await measureStartup(name, load, \"imports\");\n\t\t\treturn ext(name, module.default);\n\t\t}),\n\t);\n\treturn loaded;\n}\n\n/** Full roster. Print / RPC / gateway still need every factory before the first turn. */\nexport async function loadAllBuiltinExtensions(): Promise<InlineExtension[]> {\n\treturn [...lightBuiltinExtensions, ...(await loadDeferredBuiltinExtensions())];\n}\n\n/** Eager full roster. Prefer loadAllBuiltinExtensions() so CLI start stays light. */\nexport const builtinExtensions: InlineExtension[] = lightBuiltinExtensions;\n"]}
@@ -15,7 +15,6 @@ import lunrLocalProviders from "./lunr-local-providers/index.js";
15
15
  import lunrTodos from "./lunr-todos.js";
16
16
  import lunrPlanTools from "./lunr-plan-tools.js";
17
17
  import lunrSkillCreator from "./lunr-skill-creator/index.js";
18
- import lunrSettingsTools from "./lunr-settings-tools.js";
19
18
  /**
20
19
  * Wrap a raw factory function as a named InlineExtension.
21
20
  * The cast bridges the gap between the source-level ExtensionFactory type
@@ -36,7 +35,6 @@ export const lightBuiltinExtensions = [
36
35
  ext("lunr-todos", lunrTodos),
37
36
  ext("lunr-plan-tools", lunrPlanTools),
38
37
  ext("lunr-skill-creator", lunrSkillCreator),
39
- ext("lunr-settings-tools", lunrSettingsTools),
40
38
  ];
41
39
  const DEFERRED_BUILTIN_LOADERS = [
42
40
  { name: "pi-ollama-cloud", load: () => import("./pi-ollama-cloud/index.js") },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builtin-extensions/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Built-in extensions for lunR.\n *\n * Light factories stay on the first-paint graph. Heavy factories are imported\n * only when attachDeferredBuiltinExtensions() runs after the TUI is up, or\n * immediately for print/RPC/gateway where there is no first-paint window.\n */\n\nimport type { ExtensionFactory, InlineExtension } from \"../core/extensions/types.ts\";\nimport { measureStartup } from \"../core/timings.ts\";\n\nimport simplePiMemory from \"./simple-pi-memory.ts\";\nimport piTps from \"./pi-tps.ts\";\nimport ashxjTui from \"./ashxj-tui.ts\";\nimport ashxjSpinners from \"./ashxj-spinners.ts\";\nimport ashxjThinking from \"./ashxj-thinking.ts\";\nimport lunrLocalProviders from \"./lunr-local-providers/index.ts\";\nimport lunrTodos from \"./lunr-todos.ts\";\nimport lunrPlanTools from \"./lunr-plan-tools.ts\";\nimport lunrSkillCreator from \"./lunr-skill-creator/index.ts\";\nimport lunrSettingsTools from \"./lunr-settings-tools.ts\";\n\n/**\n * Wrap a raw factory function as a named InlineExtension.\n * The cast bridges the gap between the source-level ExtensionFactory type\n * (used here) and the dist-level type that extensions import via the package\n * name. The underlying function signatures are structurally identical.\n */\nfunction ext(name: string, factory: unknown): InlineExtension {\n\treturn { name, factory: factory as ExtensionFactory };\n}\n\n/** UI, local providers, and small lunR-native factories. Safe to import at CLI start. */\nexport const lightBuiltinExtensions: InlineExtension[] = [\n\text(\"simple-pi-memory\", simplePiMemory),\n\text(\"pi-tps\", piTps),\n\text(\"ashxj-tui\", ashxjTui),\n\text(\"ashxj-spinners\", ashxjSpinners),\n\text(\"ashxj-thinking\", ashxjThinking),\n\text(\"lunr-local-providers\", lunrLocalProviders),\n\text(\"lunr-todos\", lunrTodos),\n\text(\"lunr-plan-tools\", lunrPlanTools),\n\text(\"lunr-skill-creator\", lunrSkillCreator),\n\text(\"lunr-settings-tools\", lunrSettingsTools),\n];\n\nconst DEFERRED_BUILTIN_LOADERS: Array<{\n\tname: string;\n\tload: () => Promise<{ default: unknown }>;\n}> = [\n\t{ name: \"pi-ollama-cloud\", load: () => import(\"./pi-ollama-cloud/index.ts\") },\n\t{ name: \"narumiruna-pi-goal\", load: () => import(\"./narumiruna-pi-goal/src/goal.ts\") },\n\t{ name: \"lunr-cron\", load: () => import(\"./lunr-cron.ts\") },\n\t{ name: \"pi-intercom\", load: () => import(\"./pi-intercom/index.ts\") },\n\t{ name: \"pi-prompt-template-model\", load: () => import(\"./pi-prompt-template-model/index.ts\") },\n\t{ name: \"pi-subagents\", load: () => import(\"./pi-subagents/index.ts\") },\n\t{ name: \"pi-web-access\", load: () => import(\"./pi-web-access/index.ts\") },\n\t{ name: \"pi-lsp-extension\", load: () => import(\"./pi-lsp-extension/src/index.ts\") },\n\t{ name: \"pi-mcp-adapter\", load: () => import(\"./pi-mcp-adapter/index.ts\") },\n];\n\nexport const DEFERRED_BUILTIN_EXTENSION_NAMES = DEFERRED_BUILTIN_LOADERS.map((entry) => entry.name);\n\n/** Flags registered only after deferred builtins attach. Do not fail CLI parse for these. */\nexport const DEFERRED_BUILTIN_FLAGS = [\"mcp-config\"] as const;\n\n/** Import MCP / LSP / web-access / intercom / subagents only when needed. */\nexport async function loadDeferredBuiltinExtensions(): Promise<InlineExtension[]> {\n\tconst loaded = await Promise.all(\n\t\tDEFERRED_BUILTIN_LOADERS.map(async ({ name, load }) => {\n\t\t\tconst module = await measureStartup(name, load, \"imports\");\n\t\t\treturn ext(name, module.default);\n\t\t}),\n\t);\n\treturn loaded;\n}\n\n/** Full roster. Print / RPC / gateway still need every factory before the first turn. */\nexport async function loadAllBuiltinExtensions(): Promise<InlineExtension[]> {\n\treturn [...lightBuiltinExtensions, ...(await loadDeferredBuiltinExtensions())];\n}\n\n/** Eager full roster. Prefer loadAllBuiltinExtensions() so CLI start stays light. */\nexport const builtinExtensions: InlineExtension[] = lightBuiltinExtensions;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builtin-extensions/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Built-in extensions for lunR.\n *\n * Light factories stay on the first-paint graph. Heavy factories are imported\n * only when attachDeferredBuiltinExtensions() runs after the TUI is up, or\n * immediately for print/RPC/gateway where there is no first-paint window.\n */\n\nimport type { ExtensionFactory, InlineExtension } from \"../core/extensions/types.ts\";\nimport { measureStartup } from \"../core/timings.ts\";\n\nimport simplePiMemory from \"./simple-pi-memory.ts\";\nimport piTps from \"./pi-tps.ts\";\nimport ashxjTui from \"./ashxj-tui.ts\";\nimport ashxjSpinners from \"./ashxj-spinners.ts\";\nimport ashxjThinking from \"./ashxj-thinking.ts\";\nimport lunrLocalProviders from \"./lunr-local-providers/index.ts\";\nimport lunrTodos from \"./lunr-todos.ts\";\nimport lunrPlanTools from \"./lunr-plan-tools.ts\";\nimport lunrSkillCreator from \"./lunr-skill-creator/index.ts\";\n\n/**\n * Wrap a raw factory function as a named InlineExtension.\n * The cast bridges the gap between the source-level ExtensionFactory type\n * (used here) and the dist-level type that extensions import via the package\n * name. The underlying function signatures are structurally identical.\n */\nfunction ext(name: string, factory: unknown): InlineExtension {\n\treturn { name, factory: factory as ExtensionFactory };\n}\n\n/** UI, local providers, and small lunR-native factories. Safe to import at CLI start. */\nexport const lightBuiltinExtensions: InlineExtension[] = [\n\text(\"simple-pi-memory\", simplePiMemory),\n\text(\"pi-tps\", piTps),\n\text(\"ashxj-tui\", ashxjTui),\n\text(\"ashxj-spinners\", ashxjSpinners),\n\text(\"ashxj-thinking\", ashxjThinking),\n\text(\"lunr-local-providers\", lunrLocalProviders),\n\text(\"lunr-todos\", lunrTodos),\n\text(\"lunr-plan-tools\", lunrPlanTools),\n\text(\"lunr-skill-creator\", lunrSkillCreator),\n];\n\nconst DEFERRED_BUILTIN_LOADERS: Array<{\n\tname: string;\n\tload: () => Promise<{ default: unknown }>;\n}> = [\n\t{ name: \"pi-ollama-cloud\", load: () => import(\"./pi-ollama-cloud/index.ts\") },\n\t{ name: \"narumiruna-pi-goal\", load: () => import(\"./narumiruna-pi-goal/src/goal.ts\") },\n\t{ name: \"lunr-cron\", load: () => import(\"./lunr-cron.ts\") },\n\t{ name: \"pi-intercom\", load: () => import(\"./pi-intercom/index.ts\") },\n\t{ name: \"pi-prompt-template-model\", load: () => import(\"./pi-prompt-template-model/index.ts\") },\n\t{ name: \"pi-subagents\", load: () => import(\"./pi-subagents/index.ts\") },\n\t{ name: \"pi-web-access\", load: () => import(\"./pi-web-access/index.ts\") },\n\t{ name: \"pi-lsp-extension\", load: () => import(\"./pi-lsp-extension/src/index.ts\") },\n\t{ name: \"pi-mcp-adapter\", load: () => import(\"./pi-mcp-adapter/index.ts\") },\n];\n\nexport const DEFERRED_BUILTIN_EXTENSION_NAMES = DEFERRED_BUILTIN_LOADERS.map((entry) => entry.name);\n\n/** Flags registered only after deferred builtins attach. Do not fail CLI parse for these. */\nexport const DEFERRED_BUILTIN_FLAGS = [\"mcp-config\"] as const;\n\n/** Import MCP / LSP / web-access / intercom / subagents only when needed. */\nexport async function loadDeferredBuiltinExtensions(): Promise<InlineExtension[]> {\n\tconst loaded = await Promise.all(\n\t\tDEFERRED_BUILTIN_LOADERS.map(async ({ name, load }) => {\n\t\t\tconst module = await measureStartup(name, load, \"imports\");\n\t\t\treturn ext(name, module.default);\n\t\t}),\n\t);\n\treturn loaded;\n}\n\n/** Full roster. Print / RPC / gateway still need every factory before the first turn. */\nexport async function loadAllBuiltinExtensions(): Promise<InlineExtension[]> {\n\treturn [...lightBuiltinExtensions, ...(await loadDeferredBuiltinExtensions())];\n}\n\n/** Eager full roster. Prefer loadAllBuiltinExtensions() so CLI start stays light. */\nexport const builtinExtensions: InlineExtension[] = lightBuiltinExtensions;\n"]}
@@ -10,14 +10,16 @@ type BrokerLaunchSpec = {
10
10
  launcherCommandLine: string;
11
11
  };
12
12
  export declare function getTsxCliPath(extensionDir?: string): string;
13
+ export declare function isNativeSupervisorChannelActive(env?: NodeJS.ProcessEnv): boolean;
14
+ export declare function resolveBrokerScriptPath(brokerDir?: string): string;
13
15
  export declare function getWindowsHiddenLauncherPath(intercomDir?: string): string;
14
- export declare function getWindowsBrokerCommandLine(brokerPath: string, extensionDir?: string, nodePath?: string, brokerCommand?: string, brokerArgs?: string[]): string;
16
+ export declare function getWindowsBrokerCommandLine(brokerPath: string, extensionDir?: string, nodePath?: string, brokerCommand?: string, brokerArgs?: string[], stderrLogPath?: string): string;
15
17
  export declare function getWindowsHiddenLauncherScript(commandLine: string): string;
16
18
  export declare function isBrokerHealthOkMessage(message: unknown, requestId: string): boolean;
17
- export declare function getBrokerLaunchSpec(brokerPath: string, brokerCommand: string, brokerArgs: string[], extensionDir?: string, platform?: NodeJS.Platform, intercomDir?: string, nodePath?: string): BrokerLaunchSpec;
18
- export declare function getBrokerSpawnOptions(extensionDir?: string, env?: NodeJS.ProcessEnv): {
19
+ export declare function getBrokerLaunchSpec(brokerPath: string, brokerCommand: string, brokerArgs: string[], extensionDir?: string, platform?: NodeJS.Platform, intercomDir?: string, nodePath?: string, stderrLogPath?: string): BrokerLaunchSpec;
20
+ export declare function getBrokerSpawnOptions(extensionDir?: string, env?: NodeJS.ProcessEnv, stderrFd?: number): {
19
21
  detached: true;
20
- stdio: "ignore";
22
+ stdio: "ignore" | ["ignore", "ignore", number];
21
23
  cwd: string;
22
24
  env: NodeJS.ProcessEnv;
23
25
  windowsHide: true;
@@ -1 +1 @@
1
- {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/builtin-extensions/pi-intercom/broker/spawn.ts"],"names":[],"mappings":"AA0BA,KAAK,gBAAgB,GACjB;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GACC;IACA,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAMJ,wBAAgB,aAAa,CAAC,YAAY,GAAE,MAAsB,GAAG,MAAM,CAa1E;AAMD,wBAAgB,4BAA4B,CAAC,WAAW,GAAE,MAAqB,GAAG,MAAM,CAEvF;AASD,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAsB,EACpC,QAAQ,GAAE,MAAyB,EACnC,aAAa,SAAQ,EACrB,UAAU,GAAE,MAAM,EAA4B,GAC7C,MAAM,CAMR;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAO1E;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CASpF;AAeD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAAE,EACpB,YAAY,GAAE,MAAsB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,WAAW,GAAE,MAAqB,EAClC,QAAQ,GAAE,MAAyB,GAClC,gBAAgB,CAyBlB;AAED,wBAAgB,qBAAqB,CACnC,YAAY,GAAE,MAAsB,EACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IACD,QAAQ,EAAE,IAAI,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,WAAW,EAAE,IAAI,CAAC;CACnB,CAQA;AAMD,wBAAsB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DpG","sourcesContent":["// @ts-nocheck\nimport { spawn } from \"child_process\";\nimport { existsSync, readFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createRequire } from \"module\";\nimport net from \"net\";\nimport { randomUUID } from \"crypto\";\nimport { createMessageReader, writeMessage } from \"./framing.ts\";\nimport {\n ensureIntercomRuntimeDir,\n getAgentDirPath,\n getBrokerConnectTarget,\n getIntercomDirPath,\n INTERCOM_PROTOCOL_NAME,\n INTERCOM_PROTOCOL_VERSION,\n INTERCOM_RUNTIME_FILE_MODE,\n restrictIntercomRuntimeFile,\n type BrokerConnectTarget,\n} from \"./paths.ts\";\n\nconst INTERCOM_DIR = getIntercomDirPath();\nconst EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst BROKER_PID = join(INTERCOM_DIR, \"broker.pid\");\nconst BROKER_SPAWN_LOCK = join(INTERCOM_DIR, \"broker.spawn.lock\");\n\ntype BrokerLaunchSpec =\n | {\n kind: \"direct\";\n command: string;\n args: string[];\n }\n | {\n kind: \"windows-launcher\";\n command: string;\n args: string[];\n launcherPath: string;\n launcherCommandLine: string;\n };\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function getTsxCliPath(extensionDir: string = EXTENSION_DIR): string {\n // Resolve tsx via Node's module resolution so it works regardless of whether\n // tsx is bundled under extensionDir/node_modules or hoisted to a workspace\n // root by npm. We resolve the tsx package main entry (its \"exports\" field\n // does not expose ./dist/cli.mjs as a subpath) and then locate cli.mjs next\n // to it. Falls back to the legacy relative path if resolution fails.\n try {\n const requireFromExtension = createRequire(import.meta.url);\n const tsxMain = requireFromExtension.resolve(\"tsx\");\n return join(dirname(tsxMain), \"cli.mjs\");\n } catch {\n return join(extensionDir, \"node_modules\", \"tsx\", \"dist\", \"cli.mjs\");\n }\n}\n\nfunction quoteWindowsArg(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport function getWindowsHiddenLauncherPath(intercomDir: string = INTERCOM_DIR): string {\n return join(intercomDir, \"broker-launch.vbs\");\n}\n\nfunction usesDefaultBrokerCommand(brokerCommand: string, brokerArgs: string[]): boolean {\n return brokerCommand === \"npx\"\n && brokerArgs.length === 2\n && brokerArgs[0] === \"--no-install\"\n && brokerArgs[1] === \"tsx\";\n}\n\nexport function getWindowsBrokerCommandLine(\n brokerPath: string,\n extensionDir: string = EXTENSION_DIR,\n nodePath: string = process.execPath,\n brokerCommand = \"npx\",\n brokerArgs: string[] = [\"--no-install\", \"tsx\"],\n): string {\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return [quoteWindowsArg(nodePath), quoteWindowsArg(getTsxCliPath(extensionDir)), quoteWindowsArg(brokerPath)].join(\" \");\n }\n\n return [quoteWindowsArg(brokerCommand), ...brokerArgs.map(quoteWindowsArg), quoteWindowsArg(brokerPath)].join(\" \");\n}\n\nexport function getWindowsHiddenLauncherScript(commandLine: string): string {\n return [\n 'Set WshShell = CreateObject(\"WScript.Shell\")',\n `WshShell.Run \"${commandLine.replace(/\"/g, '\"\"')}\", 0, False`,\n 'Set WshShell = Nothing',\n '',\n ].join(\"\\r\\n\");\n}\n\nexport function isBrokerHealthOkMessage(message: unknown, requestId: string): boolean {\n if (typeof message !== \"object\" || message === null || !(\"type\" in message)) {\n return false;\n }\n const response = message as Record<string, unknown>;\n return response.type === \"health_ok\"\n && response.requestId === requestId\n && response.protocol === INTERCOM_PROTOCOL_NAME\n && response.version === INTERCOM_PROTOCOL_VERSION;\n}\n\nfunction writeWindowsHiddenLauncher(\n commandLine: string,\n launcherPath: string = getWindowsHiddenLauncherPath(),\n): string {\n ensureIntercomRuntimeDir(dirname(launcherPath));\n writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine), {\n encoding: \"utf-8\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(launcherPath);\n return launcherPath;\n}\n\nexport function getBrokerLaunchSpec(\n brokerPath: string,\n brokerCommand: string,\n brokerArgs: string[],\n extensionDir: string = EXTENSION_DIR,\n platform: NodeJS.Platform = process.platform,\n intercomDir: string = INTERCOM_DIR,\n nodePath: string = process.execPath,\n): BrokerLaunchSpec {\n if (platform === \"win32\") {\n const launcherPath = getWindowsHiddenLauncherPath(intercomDir);\n return {\n kind: \"windows-launcher\",\n command: \"wscript.exe\",\n args: [launcherPath],\n launcherPath,\n launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs),\n };\n }\n\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return {\n kind: \"direct\",\n command: nodePath,\n args: [getTsxCliPath(extensionDir), brokerPath],\n };\n }\n\n return {\n kind: \"direct\",\n command: brokerCommand,\n args: [...brokerArgs, brokerPath],\n };\n}\n\nexport function getBrokerSpawnOptions(\n extensionDir: string = EXTENSION_DIR,\n env: NodeJS.ProcessEnv = process.env,\n): {\n detached: true;\n stdio: \"ignore\";\n cwd: string;\n env: NodeJS.ProcessEnv;\n windowsHide: true;\n} {\n return {\n detached: true,\n stdio: \"ignore\",\n cwd: extensionDir,\n env: { ...env, PI_CODING_AGENT_DIR: getAgentDirPath(env), NODE_NO_WARNINGS: \"1\" },\n windowsHide: true,\n };\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport async function spawnBrokerIfNeeded(brokerCommand: string, brokerArgs: string[]): Promise<void> {\n ensureIntercomRuntimeDir(INTERCOM_DIR);\n\n if (await isBrokerRunning()) {\n return;\n }\n\n const ownsLock = acquireSpawnLock();\n if (!ownsLock) {\n await waitForBroker();\n return;\n }\n\n try {\n if (await isBrokerRunning()) {\n return;\n }\n\n const brokerPath = join(dirname(fileURLToPath(import.meta.url)), \"broker.ts\");\n const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs);\n if (launch.kind === \"windows-launcher\") {\n writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);\n }\n const child = spawn(launch.command, launch.args, getBrokerSpawnOptions());\n child.unref();\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n child.off(\"error\", onError);\n child.off(\"exit\", onExit);\n };\n\n const onError = (error: Error) => {\n cleanup();\n reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));\n };\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n if (launch.kind === \"windows-launcher\" && code === 0 && signal === null) {\n return;\n }\n cleanup();\n if (signal) {\n reject(new Error(`Intercom broker exited before startup with signal ${signal}`));\n return;\n }\n reject(new Error(`Intercom broker exited before startup with code ${code ?? \"unknown\"}`));\n };\n\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n waitForBroker().then(() => {\n cleanup();\n resolve();\n }, (error) => {\n cleanup();\n reject(toError(error));\n });\n });\n } finally {\n releaseSpawnLock();\n }\n}\n\nasync function isBrokerRunning(): Promise<boolean> {\n if (await checkSocketConnectable()) {\n return true;\n }\n\n if (!existsSync(BROKER_PID)) return false;\n\n try {\n const pid = parseInt(readFileSync(BROKER_PID, \"utf-8\").trim(), 10);\n if (!Number.isFinite(pid)) return false;\n process.kill(pid, 0);\n return checkSocketConnectable();\n } catch {\n // Missing or unreadable PID state means there is no live broker to reuse.\n return false;\n }\n}\n\nfunction connectToBrokerTarget(target: BrokerConnectTarget): net.Socket {\n return typeof target === \"string\"\n ? net.connect(target)\n : net.connect({ host: target.host, port: target.port });\n}\n\nfunction checkSocketConnectable(): Promise<boolean> {\n return new Promise((resolve) => {\n let target: BrokerConnectTarget;\n try {\n target = getBrokerConnectTarget();\n } catch {\n resolve(false);\n return;\n }\n\n const socket = connectToBrokerTarget(target);\n const requestId = randomUUID();\n const expectedStateId = typeof target === \"string\" ? undefined : target.stateId;\n let settled = false;\n const finish = (isConnected: boolean) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n socket.off(\"connect\", onConnect);\n socket.off(\"error\", onError);\n socket.off(\"data\", reader);\n socket.destroy();\n resolve(isConnected);\n };\n const onConnect = () => {\n try {\n writeMessage(socket, {\n type: \"health\",\n requestId,\n ...(expectedStateId ? { stateId: expectedStateId } : {}),\n });\n } catch {\n finish(false);\n }\n };\n const onError = () => finish(false);\n const reader = createMessageReader((message) => {\n finish(isBrokerHealthOkMessage(message, requestId));\n }, () => finish(false));\n socket.on(\"connect\", onConnect);\n socket.on(\"error\", onError);\n socket.on(\"data\", reader);\n const timeout = setTimeout(() => finish(false), 1000);\n });\n}\n\nfunction acquireSpawnLock(): boolean {\n const maxRetries = 5;\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n writeFileSync(BROKER_SPAWN_LOCK, `${process.pid}\\n${Date.now()}\\n`, {\n flag: \"wx\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(BROKER_SPAWN_LOCK);\n return true;\n } catch (error) {\n if (!(error instanceof Error) || (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n if (isSpawnLockStale()) {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // If we can't delete the stale lock, retry a few times before giving up\n }\n continue;\n }\n return false;\n }\n }\n return false;\n}\n\nfunction isSpawnLockStale(): boolean {\n if (!existsSync(BROKER_SPAWN_LOCK)) {\n return false;\n }\n\n try {\n const [pidLine = \"\", createdAtLine = \"0\"] = readFileSync(BROKER_SPAWN_LOCK, \"utf-8\").trim().split(\"\\n\");\n const pid = Number.parseInt(pidLine, 10);\n const createdAt = Number.parseInt(createdAtLine, 10);\n const ageMs = Date.now() - createdAt;\n\n if (Number.isFinite(pid)) {\n try {\n process.kill(pid, 0);\n } catch {\n // The process that created the lock is gone.\n return true;\n }\n }\n\n return !Number.isFinite(createdAt) || ageMs > 10_000;\n } catch {\n // Unreadable lock contents are treated as stale so a new broker can start.\n return true;\n }\n}\n\nfunction releaseSpawnLock(): void {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // Another cleanup path may already have removed the lock.\n }\n}\n\nasync function waitForBroker(timeoutMs = 5000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await checkSocketConnectable()) {\n return;\n }\n await sleep(100);\n }\n throw new Error(\"Broker failed to start within timeout\");\n}\n"]}
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/builtin-extensions/pi-intercom/broker/spawn.ts"],"names":[],"mappings":"AA4BA,KAAK,gBAAgB,GACjB;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GACC;IACA,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAMJ,wBAAgB,aAAa,CAAC,YAAY,GAAE,MAAsB,GAAG,MAAM,CAa1E;AAED,wBAAgB,+BAA+B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE7F;AAED,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAgD,GAAG,MAAM,CAI3G;AAUD,wBAAgB,4BAA4B,CAAC,WAAW,GAAE,MAAqB,GAAG,MAAM,CAEvF;AA+BD,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAsB,EACpC,QAAQ,GAAE,MAAyB,EACnC,aAAa,SAAQ,EACrB,UAAU,GAAE,MAAM,EAA4B,EAC9C,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAIR;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAO1E;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CASpF;AAeD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAAE,EACpB,YAAY,GAAE,MAAsB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,WAAW,GAAE,MAAqB,EAClC,QAAQ,GAAE,MAAyB,EACnC,aAAa,CAAC,EAAE,MAAM,GACrB,gBAAgB,CAyBlB;AAED,wBAAgB,qBAAqB,CACnC,YAAY,GAAE,MAAsB,EACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,CAAC,EAAE,MAAM,GAChB;IACD,QAAQ,EAAE,IAAI,CAAC;IACf,KAAK,EAAE,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,WAAW,EAAE,IAAI,CAAC;CACnB,CAQA;AAMD,wBAAsB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2FpG","sourcesContent":["// @ts-nocheck\nimport { spawn } from \"child_process\";\nimport { closeSync, existsSync, openSync, readFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createRequire } from \"module\";\nimport net from \"net\";\nimport { randomUUID } from \"crypto\";\nimport { createMessageReader, writeMessage } from \"./framing.ts\";\nimport {\n ensureIntercomRuntimeDir,\n getAgentDirPath,\n getBrokerConnectTarget,\n getIntercomDirPath,\n INTERCOM_PROTOCOL_NAME,\n INTERCOM_PROTOCOL_VERSION,\n INTERCOM_RUNTIME_FILE_MODE,\n restrictIntercomRuntimeFile,\n type BrokerConnectTarget,\n} from \"./paths.ts\";\n\nconst INTERCOM_DIR = getIntercomDirPath();\nconst EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst BROKER_PID = join(INTERCOM_DIR, \"broker.pid\");\nconst BROKER_SPAWN_LOCK = join(INTERCOM_DIR, \"broker.spawn.lock\");\nconst BROKER_STDERR = join(INTERCOM_DIR, \"broker.stderr.log\");\nconst NATIVE_SUPERVISOR_CHANNEL_DIR_ENV = \"PI_SUBAGENT_SUPERVISOR_CHANNEL_DIR\";\n\ntype BrokerLaunchSpec =\n | {\n kind: \"direct\";\n command: string;\n args: string[];\n }\n | {\n kind: \"windows-launcher\";\n command: string;\n args: string[];\n launcherPath: string;\n launcherCommandLine: string;\n };\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function getTsxCliPath(extensionDir: string = EXTENSION_DIR): string {\n // Resolve tsx via Node's module resolution so it works regardless of whether\n // tsx is bundled under extensionDir/node_modules or hoisted to a workspace\n // root by npm. We resolve the tsx package main entry (its \"exports\" field\n // does not expose ./dist/cli.mjs as a subpath) and then locate cli.mjs next\n // to it. Falls back to the legacy relative path if resolution fails.\n try {\n const requireFromExtension = createRequire(import.meta.url);\n const tsxMain = requireFromExtension.resolve(\"tsx\");\n return join(dirname(tsxMain), \"cli.mjs\");\n } catch {\n return join(extensionDir, \"node_modules\", \"tsx\", \"dist\", \"cli.mjs\");\n }\n}\n\nexport function isNativeSupervisorChannelActive(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env[NATIVE_SUPERVISOR_CHANNEL_DIR_ENV]?.trim());\n}\n\nexport function resolveBrokerScriptPath(brokerDir: string = dirname(fileURLToPath(import.meta.url))): string {\n const tsPath = join(brokerDir, \"broker.ts\");\n if (existsSync(tsPath)) return tsPath;\n return join(brokerDir, \"broker.js\");\n}\n\nfunction isCompiledBrokerScript(brokerPath: string): boolean {\n return brokerPath.endsWith(\".js\");\n}\n\nfunction quoteWindowsArg(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport function getWindowsHiddenLauncherPath(intercomDir: string = INTERCOM_DIR): string {\n return join(intercomDir, \"broker-launch.vbs\");\n}\n\nfunction usesDefaultBrokerCommand(brokerCommand: string, brokerArgs: string[]): boolean {\n return brokerCommand === \"npx\"\n && brokerArgs.length === 2\n && brokerArgs[0] === \"--no-install\"\n && brokerArgs[1] === \"tsx\";\n}\n\nfunction defaultBrokerArgv(\n brokerPath: string,\n extensionDir: string,\n nodePath: string,\n brokerCommand: string,\n brokerArgs: string[],\n): { command: string; args: string[] } {\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs) && isCompiledBrokerScript(brokerPath)) {\n return { command: nodePath, args: [brokerPath] };\n }\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return { command: nodePath, args: [getTsxCliPath(extensionDir), brokerPath] };\n }\n return { command: brokerCommand, args: [...brokerArgs, brokerPath] };\n}\n\nfunction withWindowsStderr(commandLine: string, stderrLogPath?: string): string {\n if (!stderrLogPath) return commandLine;\n const redirected = `${commandLine} 1>NUL 2>>${quoteWindowsArg(stderrLogPath)}`;\n return `cmd.exe /s /c \"${redirected}\"`;\n}\n\nexport function getWindowsBrokerCommandLine(\n brokerPath: string,\n extensionDir: string = EXTENSION_DIR,\n nodePath: string = process.execPath,\n brokerCommand = \"npx\",\n brokerArgs: string[] = [\"--no-install\", \"tsx\"],\n stderrLogPath?: string,\n): string {\n const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);\n const commandLine = [quoteWindowsArg(argv.command), ...argv.args.map(quoteWindowsArg)].join(\" \");\n return withWindowsStderr(commandLine, stderrLogPath);\n}\n\nexport function getWindowsHiddenLauncherScript(commandLine: string): string {\n return [\n 'Set WshShell = CreateObject(\"WScript.Shell\")',\n `WshShell.Run \"${commandLine.replace(/\"/g, '\"\"')}\", 0, False`,\n 'Set WshShell = Nothing',\n '',\n ].join(\"\\r\\n\");\n}\n\nexport function isBrokerHealthOkMessage(message: unknown, requestId: string): boolean {\n if (typeof message !== \"object\" || message === null || !(\"type\" in message)) {\n return false;\n }\n const response = message as Record<string, unknown>;\n return response.type === \"health_ok\"\n && response.requestId === requestId\n && response.protocol === INTERCOM_PROTOCOL_NAME\n && response.version === INTERCOM_PROTOCOL_VERSION;\n}\n\nfunction writeWindowsHiddenLauncher(\n commandLine: string,\n launcherPath: string = getWindowsHiddenLauncherPath(),\n): string {\n ensureIntercomRuntimeDir(dirname(launcherPath));\n writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine), {\n encoding: \"utf-8\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(launcherPath);\n return launcherPath;\n}\n\nexport function getBrokerLaunchSpec(\n brokerPath: string,\n brokerCommand: string,\n brokerArgs: string[],\n extensionDir: string = EXTENSION_DIR,\n platform: NodeJS.Platform = process.platform,\n intercomDir: string = INTERCOM_DIR,\n nodePath: string = process.execPath,\n stderrLogPath?: string,\n): BrokerLaunchSpec {\n if (platform === \"win32\") {\n const launcherPath = getWindowsHiddenLauncherPath(intercomDir);\n return {\n kind: \"windows-launcher\",\n command: \"wscript.exe\",\n args: [launcherPath],\n launcherPath,\n launcherCommandLine: getWindowsBrokerCommandLine(\n brokerPath,\n extensionDir,\n nodePath,\n brokerCommand,\n brokerArgs,\n stderrLogPath,\n ),\n };\n }\n\n const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);\n return {\n kind: \"direct\",\n command: argv.command,\n args: argv.args,\n };\n}\n\nexport function getBrokerSpawnOptions(\n extensionDir: string = EXTENSION_DIR,\n env: NodeJS.ProcessEnv = process.env,\n stderrFd?: number,\n): {\n detached: true;\n stdio: \"ignore\" | [\"ignore\", \"ignore\", number];\n cwd: string;\n env: NodeJS.ProcessEnv;\n windowsHide: true;\n} {\n return {\n detached: true,\n stdio: stderrFd === undefined ? \"ignore\" : [\"ignore\", \"ignore\", stderrFd],\n cwd: extensionDir,\n env: { ...env, PI_CODING_AGENT_DIR: getAgentDirPath(env), NODE_NO_WARNINGS: \"1\" },\n windowsHide: true,\n };\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport async function spawnBrokerIfNeeded(brokerCommand: string, brokerArgs: string[]): Promise<void> {\n if (isNativeSupervisorChannelActive()) {\n return;\n }\n\n ensureIntercomRuntimeDir(INTERCOM_DIR);\n\n if (await isBrokerRunning()) {\n return;\n }\n\n const ownsLock = acquireSpawnLock();\n if (!ownsLock) {\n await waitForBroker();\n return;\n }\n\n try {\n if (await isBrokerRunning()) {\n return;\n }\n\n const brokerPath = resolveBrokerScriptPath();\n const launch = getBrokerLaunchSpec(\n brokerPath,\n brokerCommand,\n brokerArgs,\n EXTENSION_DIR,\n process.platform,\n INTERCOM_DIR,\n process.execPath,\n BROKER_STDERR,\n );\n if (launch.kind === \"windows-launcher\") {\n writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);\n }\n let stderrFd: number | undefined;\n try {\n stderrFd = openSync(BROKER_STDERR, \"a\");\n } catch {\n stderrFd = undefined;\n }\n try {\n const child = spawn(launch.command, launch.args, getBrokerSpawnOptions(EXTENSION_DIR, process.env, launch.kind === \"windows-launcher\" ? undefined : stderrFd));\n child.unref();\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n child.off(\"error\", onError);\n child.off(\"exit\", onExit);\n };\n\n const onError = (error: Error) => {\n cleanup();\n reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));\n };\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n if (launch.kind === \"windows-launcher\" && code === 0 && signal === null) {\n return;\n }\n cleanup();\n if (signal) {\n reject(new Error(`Intercom broker exited before startup with signal ${signal}`));\n return;\n }\n reject(new Error(`Intercom broker exited before startup with code ${code ?? \"unknown\"}`));\n };\n\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n waitForBroker().then(() => {\n cleanup();\n resolve();\n }, (error) => {\n cleanup();\n reject(toError(error));\n });\n });\n } finally {\n if (stderrFd !== undefined) {\n try {\n closeSync(stderrFd);\n } catch {\n // The child already inherited this fd; failing to close the parent copy is non-fatal.\n }\n }\n }\n } finally {\n releaseSpawnLock();\n }\n}\n\nasync function isBrokerRunning(): Promise<boolean> {\n if (await checkSocketConnectable()) {\n return true;\n }\n\n if (!existsSync(BROKER_PID)) return false;\n\n try {\n const pid = parseInt(readFileSync(BROKER_PID, \"utf-8\").trim(), 10);\n if (!Number.isFinite(pid)) return false;\n process.kill(pid, 0);\n return checkSocketConnectable();\n } catch {\n // Missing or unreadable PID state means there is no live broker to reuse.\n return false;\n }\n}\n\nfunction connectToBrokerTarget(target: BrokerConnectTarget): net.Socket {\n return typeof target === \"string\"\n ? net.connect(target)\n : net.connect({ host: target.host, port: target.port });\n}\n\nfunction checkSocketConnectable(): Promise<boolean> {\n return new Promise((resolve) => {\n let target: BrokerConnectTarget;\n try {\n target = getBrokerConnectTarget();\n } catch {\n resolve(false);\n return;\n }\n\n const socket = connectToBrokerTarget(target);\n const requestId = randomUUID();\n const expectedStateId = typeof target === \"string\" ? undefined : target.stateId;\n let settled = false;\n const finish = (isConnected: boolean) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n socket.off(\"connect\", onConnect);\n socket.off(\"error\", onError);\n socket.off(\"data\", reader);\n socket.destroy();\n resolve(isConnected);\n };\n const onConnect = () => {\n try {\n writeMessage(socket, {\n type: \"health\",\n requestId,\n ...(expectedStateId ? { stateId: expectedStateId } : {}),\n });\n } catch {\n finish(false);\n }\n };\n const onError = () => finish(false);\n const reader = createMessageReader((message) => {\n finish(isBrokerHealthOkMessage(message, requestId));\n }, () => finish(false));\n socket.on(\"connect\", onConnect);\n socket.on(\"error\", onError);\n socket.on(\"data\", reader);\n const timeout = setTimeout(() => finish(false), 1000);\n });\n}\n\nfunction acquireSpawnLock(): boolean {\n const maxRetries = 5;\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n writeFileSync(BROKER_SPAWN_LOCK, `${process.pid}\\n${Date.now()}\\n`, {\n flag: \"wx\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(BROKER_SPAWN_LOCK);\n return true;\n } catch (error) {\n if (!(error instanceof Error) || (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n if (isSpawnLockStale()) {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // If we can't delete the stale lock, retry a few times before giving up\n }\n continue;\n }\n return false;\n }\n }\n return false;\n}\n\nfunction isSpawnLockStale(): boolean {\n if (!existsSync(BROKER_SPAWN_LOCK)) {\n return false;\n }\n\n try {\n const [pidLine = \"\", createdAtLine = \"0\"] = readFileSync(BROKER_SPAWN_LOCK, \"utf-8\").trim().split(\"\\n\");\n const pid = Number.parseInt(pidLine, 10);\n const createdAt = Number.parseInt(createdAtLine, 10);\n const ageMs = Date.now() - createdAt;\n\n if (Number.isFinite(pid)) {\n try {\n process.kill(pid, 0);\n } catch {\n // The process that created the lock is gone.\n return true;\n }\n }\n\n return !Number.isFinite(createdAt) || ageMs > 10_000;\n } catch {\n // Unreadable lock contents are treated as stale so a new broker can start.\n return true;\n }\n}\n\nfunction releaseSpawnLock(): void {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // Another cleanup path may already have removed the lock.\n }\n}\n\nasync function waitForBroker(timeoutMs = 5000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await checkSocketConnectable()) {\n return;\n }\n await sleep(100);\n }\n throw new Error(\"Broker failed to start within timeout\");\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  import { spawn } from "child_process";
3
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs";
3
+ import { closeSync, existsSync, openSync, readFileSync, unlinkSync, writeFileSync } from "fs";
4
4
  import { join, dirname } from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { createRequire } from "module";
@@ -12,6 +12,8 @@ const INTERCOM_DIR = getIntercomDirPath();
12
12
  const EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), "..");
13
13
  const BROKER_PID = join(INTERCOM_DIR, "broker.pid");
14
14
  const BROKER_SPAWN_LOCK = join(INTERCOM_DIR, "broker.spawn.lock");
15
+ const BROKER_STDERR = join(INTERCOM_DIR, "broker.stderr.log");
16
+ const NATIVE_SUPERVISOR_CHANNEL_DIR_ENV = "PI_SUBAGENT_SUPERVISOR_CHANNEL_DIR";
15
17
  function sleep(ms) {
16
18
  return new Promise(resolve => setTimeout(resolve, ms));
17
19
  }
@@ -30,6 +32,18 @@ export function getTsxCliPath(extensionDir = EXTENSION_DIR) {
30
32
  return join(extensionDir, "node_modules", "tsx", "dist", "cli.mjs");
31
33
  }
32
34
  }
35
+ export function isNativeSupervisorChannelActive(env = process.env) {
36
+ return Boolean(env[NATIVE_SUPERVISOR_CHANNEL_DIR_ENV]?.trim());
37
+ }
38
+ export function resolveBrokerScriptPath(brokerDir = dirname(fileURLToPath(import.meta.url))) {
39
+ const tsPath = join(brokerDir, "broker.ts");
40
+ if (existsSync(tsPath))
41
+ return tsPath;
42
+ return join(brokerDir, "broker.js");
43
+ }
44
+ function isCompiledBrokerScript(brokerPath) {
45
+ return brokerPath.endsWith(".js");
46
+ }
33
47
  function quoteWindowsArg(value) {
34
48
  return `"${value.replace(/"/g, '""')}"`;
35
49
  }
@@ -42,11 +56,25 @@ function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
42
56
  && brokerArgs[0] === "--no-install"
43
57
  && brokerArgs[1] === "tsx";
44
58
  }
45
- export function getWindowsBrokerCommandLine(brokerPath, extensionDir = EXTENSION_DIR, nodePath = process.execPath, brokerCommand = "npx", brokerArgs = ["--no-install", "tsx"]) {
59
+ function defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs) {
60
+ if (usesDefaultBrokerCommand(brokerCommand, brokerArgs) && isCompiledBrokerScript(brokerPath)) {
61
+ return { command: nodePath, args: [brokerPath] };
62
+ }
46
63
  if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {
47
- return [quoteWindowsArg(nodePath), quoteWindowsArg(getTsxCliPath(extensionDir)), quoteWindowsArg(brokerPath)].join(" ");
64
+ return { command: nodePath, args: [getTsxCliPath(extensionDir), brokerPath] };
48
65
  }
49
- return [quoteWindowsArg(brokerCommand), ...brokerArgs.map(quoteWindowsArg), quoteWindowsArg(brokerPath)].join(" ");
66
+ return { command: brokerCommand, args: [...brokerArgs, brokerPath] };
67
+ }
68
+ function withWindowsStderr(commandLine, stderrLogPath) {
69
+ if (!stderrLogPath)
70
+ return commandLine;
71
+ const redirected = `${commandLine} 1>NUL 2>>${quoteWindowsArg(stderrLogPath)}`;
72
+ return `cmd.exe /s /c "${redirected}"`;
73
+ }
74
+ export function getWindowsBrokerCommandLine(brokerPath, extensionDir = EXTENSION_DIR, nodePath = process.execPath, brokerCommand = "npx", brokerArgs = ["--no-install", "tsx"], stderrLogPath) {
75
+ const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);
76
+ const commandLine = [quoteWindowsArg(argv.command), ...argv.args.map(quoteWindowsArg)].join(" ");
77
+ return withWindowsStderr(commandLine, stderrLogPath);
50
78
  }
51
79
  export function getWindowsHiddenLauncherScript(commandLine) {
52
80
  return [
@@ -75,7 +103,7 @@ function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHidden
75
103
  restrictIntercomRuntimeFile(launcherPath);
76
104
  return launcherPath;
77
105
  }
78
- export function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath) {
106
+ export function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, stderrLogPath) {
79
107
  if (platform === "win32") {
80
108
  const launcherPath = getWindowsHiddenLauncherPath(intercomDir);
81
109
  return {
@@ -83,26 +111,20 @@ export function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, exten
83
111
  command: "wscript.exe",
84
112
  args: [launcherPath],
85
113
  launcherPath,
86
- launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs),
87
- };
88
- }
89
- if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {
90
- return {
91
- kind: "direct",
92
- command: nodePath,
93
- args: [getTsxCliPath(extensionDir), brokerPath],
114
+ launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs, stderrLogPath),
94
115
  };
95
116
  }
117
+ const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);
96
118
  return {
97
119
  kind: "direct",
98
- command: brokerCommand,
99
- args: [...brokerArgs, brokerPath],
120
+ command: argv.command,
121
+ args: argv.args,
100
122
  };
101
123
  }
102
- export function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, env = process.env) {
124
+ export function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, env = process.env, stderrFd) {
103
125
  return {
104
126
  detached: true,
105
- stdio: "ignore",
127
+ stdio: stderrFd === undefined ? "ignore" : ["ignore", "ignore", stderrFd],
106
128
  cwd: extensionDir,
107
129
  env: { ...env, PI_CODING_AGENT_DIR: getAgentDirPath(env), NODE_NO_WARNINGS: "1" },
108
130
  windowsHide: true,
@@ -112,6 +134,9 @@ function toError(error) {
112
134
  return error instanceof Error ? error : new Error(String(error));
113
135
  }
114
136
  export async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
137
+ if (isNativeSupervisorChannelActive()) {
138
+ return;
139
+ }
115
140
  ensureIntercomRuntimeDir(INTERCOM_DIR);
116
141
  if (await isBrokerRunning()) {
117
142
  return;
@@ -125,43 +150,62 @@ export async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
125
150
  if (await isBrokerRunning()) {
126
151
  return;
127
152
  }
128
- const brokerPath = join(dirname(fileURLToPath(import.meta.url)), "broker.ts");
129
- const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs);
153
+ const brokerPath = resolveBrokerScriptPath();
154
+ const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, EXTENSION_DIR, process.platform, INTERCOM_DIR, process.execPath, BROKER_STDERR);
130
155
  if (launch.kind === "windows-launcher") {
131
156
  writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
132
157
  }
133
- const child = spawn(launch.command, launch.args, getBrokerSpawnOptions());
134
- child.unref();
135
- await new Promise((resolve, reject) => {
136
- const cleanup = () => {
137
- child.off("error", onError);
138
- child.off("exit", onExit);
139
- };
140
- const onError = (error) => {
141
- cleanup();
142
- reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));
143
- };
144
- const onExit = (code, signal) => {
145
- if (launch.kind === "windows-launcher" && code === 0 && signal === null) {
146
- return;
158
+ let stderrFd;
159
+ try {
160
+ stderrFd = openSync(BROKER_STDERR, "a");
161
+ }
162
+ catch {
163
+ stderrFd = undefined;
164
+ }
165
+ try {
166
+ const child = spawn(launch.command, launch.args, getBrokerSpawnOptions(EXTENSION_DIR, process.env, launch.kind === "windows-launcher" ? undefined : stderrFd));
167
+ child.unref();
168
+ await new Promise((resolve, reject) => {
169
+ const cleanup = () => {
170
+ child.off("error", onError);
171
+ child.off("exit", onExit);
172
+ };
173
+ const onError = (error) => {
174
+ cleanup();
175
+ reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));
176
+ };
177
+ const onExit = (code, signal) => {
178
+ if (launch.kind === "windows-launcher" && code === 0 && signal === null) {
179
+ return;
180
+ }
181
+ cleanup();
182
+ if (signal) {
183
+ reject(new Error(`Intercom broker exited before startup with signal ${signal}`));
184
+ return;
185
+ }
186
+ reject(new Error(`Intercom broker exited before startup with code ${code ?? "unknown"}`));
187
+ };
188
+ child.once("error", onError);
189
+ child.once("exit", onExit);
190
+ waitForBroker().then(() => {
191
+ cleanup();
192
+ resolve();
193
+ }, (error) => {
194
+ cleanup();
195
+ reject(toError(error));
196
+ });
197
+ });
198
+ }
199
+ finally {
200
+ if (stderrFd !== undefined) {
201
+ try {
202
+ closeSync(stderrFd);
147
203
  }
148
- cleanup();
149
- if (signal) {
150
- reject(new Error(`Intercom broker exited before startup with signal ${signal}`));
151
- return;
204
+ catch {
205
+ // The child already inherited this fd; failing to close the parent copy is non-fatal.
152
206
  }
153
- reject(new Error(`Intercom broker exited before startup with code ${code ?? "unknown"}`));
154
- };
155
- child.once("error", onError);
156
- child.once("exit", onExit);
157
- waitForBroker().then(() => {
158
- cleanup();
159
- resolve();
160
- }, (error) => {
161
- cleanup();
162
- reject(toError(error));
163
- });
164
- });
207
+ }
208
+ }
165
209
  }
166
210
  finally {
167
211
  releaseSpawnLock();
@@ -1 +1 @@
1
- {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../../src/builtin-extensions/pi-intercom/broker/spawn.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { spawn } from \"child_process\";\nimport { existsSync, readFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createRequire } from \"module\";\nimport net from \"net\";\nimport { randomUUID } from \"crypto\";\nimport { createMessageReader, writeMessage } from \"./framing.ts\";\nimport {\n ensureIntercomRuntimeDir,\n getAgentDirPath,\n getBrokerConnectTarget,\n getIntercomDirPath,\n INTERCOM_PROTOCOL_NAME,\n INTERCOM_PROTOCOL_VERSION,\n INTERCOM_RUNTIME_FILE_MODE,\n restrictIntercomRuntimeFile,\n type BrokerConnectTarget,\n} from \"./paths.ts\";\n\nconst INTERCOM_DIR = getIntercomDirPath();\nconst EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst BROKER_PID = join(INTERCOM_DIR, \"broker.pid\");\nconst BROKER_SPAWN_LOCK = join(INTERCOM_DIR, \"broker.spawn.lock\");\n\ntype BrokerLaunchSpec =\n | {\n kind: \"direct\";\n command: string;\n args: string[];\n }\n | {\n kind: \"windows-launcher\";\n command: string;\n args: string[];\n launcherPath: string;\n launcherCommandLine: string;\n };\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function getTsxCliPath(extensionDir: string = EXTENSION_DIR): string {\n // Resolve tsx via Node's module resolution so it works regardless of whether\n // tsx is bundled under extensionDir/node_modules or hoisted to a workspace\n // root by npm. We resolve the tsx package main entry (its \"exports\" field\n // does not expose ./dist/cli.mjs as a subpath) and then locate cli.mjs next\n // to it. Falls back to the legacy relative path if resolution fails.\n try {\n const requireFromExtension = createRequire(import.meta.url);\n const tsxMain = requireFromExtension.resolve(\"tsx\");\n return join(dirname(tsxMain), \"cli.mjs\");\n } catch {\n return join(extensionDir, \"node_modules\", \"tsx\", \"dist\", \"cli.mjs\");\n }\n}\n\nfunction quoteWindowsArg(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport function getWindowsHiddenLauncherPath(intercomDir: string = INTERCOM_DIR): string {\n return join(intercomDir, \"broker-launch.vbs\");\n}\n\nfunction usesDefaultBrokerCommand(brokerCommand: string, brokerArgs: string[]): boolean {\n return brokerCommand === \"npx\"\n && brokerArgs.length === 2\n && brokerArgs[0] === \"--no-install\"\n && brokerArgs[1] === \"tsx\";\n}\n\nexport function getWindowsBrokerCommandLine(\n brokerPath: string,\n extensionDir: string = EXTENSION_DIR,\n nodePath: string = process.execPath,\n brokerCommand = \"npx\",\n brokerArgs: string[] = [\"--no-install\", \"tsx\"],\n): string {\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return [quoteWindowsArg(nodePath), quoteWindowsArg(getTsxCliPath(extensionDir)), quoteWindowsArg(brokerPath)].join(\" \");\n }\n\n return [quoteWindowsArg(brokerCommand), ...brokerArgs.map(quoteWindowsArg), quoteWindowsArg(brokerPath)].join(\" \");\n}\n\nexport function getWindowsHiddenLauncherScript(commandLine: string): string {\n return [\n 'Set WshShell = CreateObject(\"WScript.Shell\")',\n `WshShell.Run \"${commandLine.replace(/\"/g, '\"\"')}\", 0, False`,\n 'Set WshShell = Nothing',\n '',\n ].join(\"\\r\\n\");\n}\n\nexport function isBrokerHealthOkMessage(message: unknown, requestId: string): boolean {\n if (typeof message !== \"object\" || message === null || !(\"type\" in message)) {\n return false;\n }\n const response = message as Record<string, unknown>;\n return response.type === \"health_ok\"\n && response.requestId === requestId\n && response.protocol === INTERCOM_PROTOCOL_NAME\n && response.version === INTERCOM_PROTOCOL_VERSION;\n}\n\nfunction writeWindowsHiddenLauncher(\n commandLine: string,\n launcherPath: string = getWindowsHiddenLauncherPath(),\n): string {\n ensureIntercomRuntimeDir(dirname(launcherPath));\n writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine), {\n encoding: \"utf-8\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(launcherPath);\n return launcherPath;\n}\n\nexport function getBrokerLaunchSpec(\n brokerPath: string,\n brokerCommand: string,\n brokerArgs: string[],\n extensionDir: string = EXTENSION_DIR,\n platform: NodeJS.Platform = process.platform,\n intercomDir: string = INTERCOM_DIR,\n nodePath: string = process.execPath,\n): BrokerLaunchSpec {\n if (platform === \"win32\") {\n const launcherPath = getWindowsHiddenLauncherPath(intercomDir);\n return {\n kind: \"windows-launcher\",\n command: \"wscript.exe\",\n args: [launcherPath],\n launcherPath,\n launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs),\n };\n }\n\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return {\n kind: \"direct\",\n command: nodePath,\n args: [getTsxCliPath(extensionDir), brokerPath],\n };\n }\n\n return {\n kind: \"direct\",\n command: brokerCommand,\n args: [...brokerArgs, brokerPath],\n };\n}\n\nexport function getBrokerSpawnOptions(\n extensionDir: string = EXTENSION_DIR,\n env: NodeJS.ProcessEnv = process.env,\n): {\n detached: true;\n stdio: \"ignore\";\n cwd: string;\n env: NodeJS.ProcessEnv;\n windowsHide: true;\n} {\n return {\n detached: true,\n stdio: \"ignore\",\n cwd: extensionDir,\n env: { ...env, PI_CODING_AGENT_DIR: getAgentDirPath(env), NODE_NO_WARNINGS: \"1\" },\n windowsHide: true,\n };\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport async function spawnBrokerIfNeeded(brokerCommand: string, brokerArgs: string[]): Promise<void> {\n ensureIntercomRuntimeDir(INTERCOM_DIR);\n\n if (await isBrokerRunning()) {\n return;\n }\n\n const ownsLock = acquireSpawnLock();\n if (!ownsLock) {\n await waitForBroker();\n return;\n }\n\n try {\n if (await isBrokerRunning()) {\n return;\n }\n\n const brokerPath = join(dirname(fileURLToPath(import.meta.url)), \"broker.ts\");\n const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs);\n if (launch.kind === \"windows-launcher\") {\n writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);\n }\n const child = spawn(launch.command, launch.args, getBrokerSpawnOptions());\n child.unref();\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n child.off(\"error\", onError);\n child.off(\"exit\", onExit);\n };\n\n const onError = (error: Error) => {\n cleanup();\n reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));\n };\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n if (launch.kind === \"windows-launcher\" && code === 0 && signal === null) {\n return;\n }\n cleanup();\n if (signal) {\n reject(new Error(`Intercom broker exited before startup with signal ${signal}`));\n return;\n }\n reject(new Error(`Intercom broker exited before startup with code ${code ?? \"unknown\"}`));\n };\n\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n waitForBroker().then(() => {\n cleanup();\n resolve();\n }, (error) => {\n cleanup();\n reject(toError(error));\n });\n });\n } finally {\n releaseSpawnLock();\n }\n}\n\nasync function isBrokerRunning(): Promise<boolean> {\n if (await checkSocketConnectable()) {\n return true;\n }\n\n if (!existsSync(BROKER_PID)) return false;\n\n try {\n const pid = parseInt(readFileSync(BROKER_PID, \"utf-8\").trim(), 10);\n if (!Number.isFinite(pid)) return false;\n process.kill(pid, 0);\n return checkSocketConnectable();\n } catch {\n // Missing or unreadable PID state means there is no live broker to reuse.\n return false;\n }\n}\n\nfunction connectToBrokerTarget(target: BrokerConnectTarget): net.Socket {\n return typeof target === \"string\"\n ? net.connect(target)\n : net.connect({ host: target.host, port: target.port });\n}\n\nfunction checkSocketConnectable(): Promise<boolean> {\n return new Promise((resolve) => {\n let target: BrokerConnectTarget;\n try {\n target = getBrokerConnectTarget();\n } catch {\n resolve(false);\n return;\n }\n\n const socket = connectToBrokerTarget(target);\n const requestId = randomUUID();\n const expectedStateId = typeof target === \"string\" ? undefined : target.stateId;\n let settled = false;\n const finish = (isConnected: boolean) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n socket.off(\"connect\", onConnect);\n socket.off(\"error\", onError);\n socket.off(\"data\", reader);\n socket.destroy();\n resolve(isConnected);\n };\n const onConnect = () => {\n try {\n writeMessage(socket, {\n type: \"health\",\n requestId,\n ...(expectedStateId ? { stateId: expectedStateId } : {}),\n });\n } catch {\n finish(false);\n }\n };\n const onError = () => finish(false);\n const reader = createMessageReader((message) => {\n finish(isBrokerHealthOkMessage(message, requestId));\n }, () => finish(false));\n socket.on(\"connect\", onConnect);\n socket.on(\"error\", onError);\n socket.on(\"data\", reader);\n const timeout = setTimeout(() => finish(false), 1000);\n });\n}\n\nfunction acquireSpawnLock(): boolean {\n const maxRetries = 5;\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n writeFileSync(BROKER_SPAWN_LOCK, `${process.pid}\\n${Date.now()}\\n`, {\n flag: \"wx\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(BROKER_SPAWN_LOCK);\n return true;\n } catch (error) {\n if (!(error instanceof Error) || (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n if (isSpawnLockStale()) {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // If we can't delete the stale lock, retry a few times before giving up\n }\n continue;\n }\n return false;\n }\n }\n return false;\n}\n\nfunction isSpawnLockStale(): boolean {\n if (!existsSync(BROKER_SPAWN_LOCK)) {\n return false;\n }\n\n try {\n const [pidLine = \"\", createdAtLine = \"0\"] = readFileSync(BROKER_SPAWN_LOCK, \"utf-8\").trim().split(\"\\n\");\n const pid = Number.parseInt(pidLine, 10);\n const createdAt = Number.parseInt(createdAtLine, 10);\n const ageMs = Date.now() - createdAt;\n\n if (Number.isFinite(pid)) {\n try {\n process.kill(pid, 0);\n } catch {\n // The process that created the lock is gone.\n return true;\n }\n }\n\n return !Number.isFinite(createdAt) || ageMs > 10_000;\n } catch {\n // Unreadable lock contents are treated as stale so a new broker can start.\n return true;\n }\n}\n\nfunction releaseSpawnLock(): void {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // Another cleanup path may already have removed the lock.\n }\n}\n\nasync function waitForBroker(timeoutMs = 5000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await checkSocketConnectable()) {\n return;\n }\n await sleep(100);\n }\n throw new Error(\"Broker failed to start within timeout\");\n}\n"]}
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../../src/builtin-extensions/pi-intercom/broker/spawn.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { spawn } from \"child_process\";\nimport { closeSync, existsSync, openSync, readFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createRequire } from \"module\";\nimport net from \"net\";\nimport { randomUUID } from \"crypto\";\nimport { createMessageReader, writeMessage } from \"./framing.ts\";\nimport {\n ensureIntercomRuntimeDir,\n getAgentDirPath,\n getBrokerConnectTarget,\n getIntercomDirPath,\n INTERCOM_PROTOCOL_NAME,\n INTERCOM_PROTOCOL_VERSION,\n INTERCOM_RUNTIME_FILE_MODE,\n restrictIntercomRuntimeFile,\n type BrokerConnectTarget,\n} from \"./paths.ts\";\n\nconst INTERCOM_DIR = getIntercomDirPath();\nconst EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst BROKER_PID = join(INTERCOM_DIR, \"broker.pid\");\nconst BROKER_SPAWN_LOCK = join(INTERCOM_DIR, \"broker.spawn.lock\");\nconst BROKER_STDERR = join(INTERCOM_DIR, \"broker.stderr.log\");\nconst NATIVE_SUPERVISOR_CHANNEL_DIR_ENV = \"PI_SUBAGENT_SUPERVISOR_CHANNEL_DIR\";\n\ntype BrokerLaunchSpec =\n | {\n kind: \"direct\";\n command: string;\n args: string[];\n }\n | {\n kind: \"windows-launcher\";\n command: string;\n args: string[];\n launcherPath: string;\n launcherCommandLine: string;\n };\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function getTsxCliPath(extensionDir: string = EXTENSION_DIR): string {\n // Resolve tsx via Node's module resolution so it works regardless of whether\n // tsx is bundled under extensionDir/node_modules or hoisted to a workspace\n // root by npm. We resolve the tsx package main entry (its \"exports\" field\n // does not expose ./dist/cli.mjs as a subpath) and then locate cli.mjs next\n // to it. Falls back to the legacy relative path if resolution fails.\n try {\n const requireFromExtension = createRequire(import.meta.url);\n const tsxMain = requireFromExtension.resolve(\"tsx\");\n return join(dirname(tsxMain), \"cli.mjs\");\n } catch {\n return join(extensionDir, \"node_modules\", \"tsx\", \"dist\", \"cli.mjs\");\n }\n}\n\nexport function isNativeSupervisorChannelActive(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env[NATIVE_SUPERVISOR_CHANNEL_DIR_ENV]?.trim());\n}\n\nexport function resolveBrokerScriptPath(brokerDir: string = dirname(fileURLToPath(import.meta.url))): string {\n const tsPath = join(brokerDir, \"broker.ts\");\n if (existsSync(tsPath)) return tsPath;\n return join(brokerDir, \"broker.js\");\n}\n\nfunction isCompiledBrokerScript(brokerPath: string): boolean {\n return brokerPath.endsWith(\".js\");\n}\n\nfunction quoteWindowsArg(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport function getWindowsHiddenLauncherPath(intercomDir: string = INTERCOM_DIR): string {\n return join(intercomDir, \"broker-launch.vbs\");\n}\n\nfunction usesDefaultBrokerCommand(brokerCommand: string, brokerArgs: string[]): boolean {\n return brokerCommand === \"npx\"\n && brokerArgs.length === 2\n && brokerArgs[0] === \"--no-install\"\n && brokerArgs[1] === \"tsx\";\n}\n\nfunction defaultBrokerArgv(\n brokerPath: string,\n extensionDir: string,\n nodePath: string,\n brokerCommand: string,\n brokerArgs: string[],\n): { command: string; args: string[] } {\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs) && isCompiledBrokerScript(brokerPath)) {\n return { command: nodePath, args: [brokerPath] };\n }\n if (usesDefaultBrokerCommand(brokerCommand, brokerArgs)) {\n return { command: nodePath, args: [getTsxCliPath(extensionDir), brokerPath] };\n }\n return { command: brokerCommand, args: [...brokerArgs, brokerPath] };\n}\n\nfunction withWindowsStderr(commandLine: string, stderrLogPath?: string): string {\n if (!stderrLogPath) return commandLine;\n const redirected = `${commandLine} 1>NUL 2>>${quoteWindowsArg(stderrLogPath)}`;\n return `cmd.exe /s /c \"${redirected}\"`;\n}\n\nexport function getWindowsBrokerCommandLine(\n brokerPath: string,\n extensionDir: string = EXTENSION_DIR,\n nodePath: string = process.execPath,\n brokerCommand = \"npx\",\n brokerArgs: string[] = [\"--no-install\", \"tsx\"],\n stderrLogPath?: string,\n): string {\n const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);\n const commandLine = [quoteWindowsArg(argv.command), ...argv.args.map(quoteWindowsArg)].join(\" \");\n return withWindowsStderr(commandLine, stderrLogPath);\n}\n\nexport function getWindowsHiddenLauncherScript(commandLine: string): string {\n return [\n 'Set WshShell = CreateObject(\"WScript.Shell\")',\n `WshShell.Run \"${commandLine.replace(/\"/g, '\"\"')}\", 0, False`,\n 'Set WshShell = Nothing',\n '',\n ].join(\"\\r\\n\");\n}\n\nexport function isBrokerHealthOkMessage(message: unknown, requestId: string): boolean {\n if (typeof message !== \"object\" || message === null || !(\"type\" in message)) {\n return false;\n }\n const response = message as Record<string, unknown>;\n return response.type === \"health_ok\"\n && response.requestId === requestId\n && response.protocol === INTERCOM_PROTOCOL_NAME\n && response.version === INTERCOM_PROTOCOL_VERSION;\n}\n\nfunction writeWindowsHiddenLauncher(\n commandLine: string,\n launcherPath: string = getWindowsHiddenLauncherPath(),\n): string {\n ensureIntercomRuntimeDir(dirname(launcherPath));\n writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine), {\n encoding: \"utf-8\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(launcherPath);\n return launcherPath;\n}\n\nexport function getBrokerLaunchSpec(\n brokerPath: string,\n brokerCommand: string,\n brokerArgs: string[],\n extensionDir: string = EXTENSION_DIR,\n platform: NodeJS.Platform = process.platform,\n intercomDir: string = INTERCOM_DIR,\n nodePath: string = process.execPath,\n stderrLogPath?: string,\n): BrokerLaunchSpec {\n if (platform === \"win32\") {\n const launcherPath = getWindowsHiddenLauncherPath(intercomDir);\n return {\n kind: \"windows-launcher\",\n command: \"wscript.exe\",\n args: [launcherPath],\n launcherPath,\n launcherCommandLine: getWindowsBrokerCommandLine(\n brokerPath,\n extensionDir,\n nodePath,\n brokerCommand,\n brokerArgs,\n stderrLogPath,\n ),\n };\n }\n\n const argv = defaultBrokerArgv(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs);\n return {\n kind: \"direct\",\n command: argv.command,\n args: argv.args,\n };\n}\n\nexport function getBrokerSpawnOptions(\n extensionDir: string = EXTENSION_DIR,\n env: NodeJS.ProcessEnv = process.env,\n stderrFd?: number,\n): {\n detached: true;\n stdio: \"ignore\" | [\"ignore\", \"ignore\", number];\n cwd: string;\n env: NodeJS.ProcessEnv;\n windowsHide: true;\n} {\n return {\n detached: true,\n stdio: stderrFd === undefined ? \"ignore\" : [\"ignore\", \"ignore\", stderrFd],\n cwd: extensionDir,\n env: { ...env, PI_CODING_AGENT_DIR: getAgentDirPath(env), NODE_NO_WARNINGS: \"1\" },\n windowsHide: true,\n };\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport async function spawnBrokerIfNeeded(brokerCommand: string, brokerArgs: string[]): Promise<void> {\n if (isNativeSupervisorChannelActive()) {\n return;\n }\n\n ensureIntercomRuntimeDir(INTERCOM_DIR);\n\n if (await isBrokerRunning()) {\n return;\n }\n\n const ownsLock = acquireSpawnLock();\n if (!ownsLock) {\n await waitForBroker();\n return;\n }\n\n try {\n if (await isBrokerRunning()) {\n return;\n }\n\n const brokerPath = resolveBrokerScriptPath();\n const launch = getBrokerLaunchSpec(\n brokerPath,\n brokerCommand,\n brokerArgs,\n EXTENSION_DIR,\n process.platform,\n INTERCOM_DIR,\n process.execPath,\n BROKER_STDERR,\n );\n if (launch.kind === \"windows-launcher\") {\n writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);\n }\n let stderrFd: number | undefined;\n try {\n stderrFd = openSync(BROKER_STDERR, \"a\");\n } catch {\n stderrFd = undefined;\n }\n try {\n const child = spawn(launch.command, launch.args, getBrokerSpawnOptions(EXTENSION_DIR, process.env, launch.kind === \"windows-launcher\" ? undefined : stderrFd));\n child.unref();\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n child.off(\"error\", onError);\n child.off(\"exit\", onExit);\n };\n\n const onError = (error: Error) => {\n cleanup();\n reject(new Error(`Failed to spawn intercom broker: ${error.message}`, { cause: error }));\n };\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n if (launch.kind === \"windows-launcher\" && code === 0 && signal === null) {\n return;\n }\n cleanup();\n if (signal) {\n reject(new Error(`Intercom broker exited before startup with signal ${signal}`));\n return;\n }\n reject(new Error(`Intercom broker exited before startup with code ${code ?? \"unknown\"}`));\n };\n\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n waitForBroker().then(() => {\n cleanup();\n resolve();\n }, (error) => {\n cleanup();\n reject(toError(error));\n });\n });\n } finally {\n if (stderrFd !== undefined) {\n try {\n closeSync(stderrFd);\n } catch {\n // The child already inherited this fd; failing to close the parent copy is non-fatal.\n }\n }\n }\n } finally {\n releaseSpawnLock();\n }\n}\n\nasync function isBrokerRunning(): Promise<boolean> {\n if (await checkSocketConnectable()) {\n return true;\n }\n\n if (!existsSync(BROKER_PID)) return false;\n\n try {\n const pid = parseInt(readFileSync(BROKER_PID, \"utf-8\").trim(), 10);\n if (!Number.isFinite(pid)) return false;\n process.kill(pid, 0);\n return checkSocketConnectable();\n } catch {\n // Missing or unreadable PID state means there is no live broker to reuse.\n return false;\n }\n}\n\nfunction connectToBrokerTarget(target: BrokerConnectTarget): net.Socket {\n return typeof target === \"string\"\n ? net.connect(target)\n : net.connect({ host: target.host, port: target.port });\n}\n\nfunction checkSocketConnectable(): Promise<boolean> {\n return new Promise((resolve) => {\n let target: BrokerConnectTarget;\n try {\n target = getBrokerConnectTarget();\n } catch {\n resolve(false);\n return;\n }\n\n const socket = connectToBrokerTarget(target);\n const requestId = randomUUID();\n const expectedStateId = typeof target === \"string\" ? undefined : target.stateId;\n let settled = false;\n const finish = (isConnected: boolean) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n socket.off(\"connect\", onConnect);\n socket.off(\"error\", onError);\n socket.off(\"data\", reader);\n socket.destroy();\n resolve(isConnected);\n };\n const onConnect = () => {\n try {\n writeMessage(socket, {\n type: \"health\",\n requestId,\n ...(expectedStateId ? { stateId: expectedStateId } : {}),\n });\n } catch {\n finish(false);\n }\n };\n const onError = () => finish(false);\n const reader = createMessageReader((message) => {\n finish(isBrokerHealthOkMessage(message, requestId));\n }, () => finish(false));\n socket.on(\"connect\", onConnect);\n socket.on(\"error\", onError);\n socket.on(\"data\", reader);\n const timeout = setTimeout(() => finish(false), 1000);\n });\n}\n\nfunction acquireSpawnLock(): boolean {\n const maxRetries = 5;\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n writeFileSync(BROKER_SPAWN_LOCK, `${process.pid}\\n${Date.now()}\\n`, {\n flag: \"wx\",\n mode: INTERCOM_RUNTIME_FILE_MODE,\n });\n restrictIntercomRuntimeFile(BROKER_SPAWN_LOCK);\n return true;\n } catch (error) {\n if (!(error instanceof Error) || (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n if (isSpawnLockStale()) {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // If we can't delete the stale lock, retry a few times before giving up\n }\n continue;\n }\n return false;\n }\n }\n return false;\n}\n\nfunction isSpawnLockStale(): boolean {\n if (!existsSync(BROKER_SPAWN_LOCK)) {\n return false;\n }\n\n try {\n const [pidLine = \"\", createdAtLine = \"0\"] = readFileSync(BROKER_SPAWN_LOCK, \"utf-8\").trim().split(\"\\n\");\n const pid = Number.parseInt(pidLine, 10);\n const createdAt = Number.parseInt(createdAtLine, 10);\n const ageMs = Date.now() - createdAt;\n\n if (Number.isFinite(pid)) {\n try {\n process.kill(pid, 0);\n } catch {\n // The process that created the lock is gone.\n return true;\n }\n }\n\n return !Number.isFinite(createdAt) || ageMs > 10_000;\n } catch {\n // Unreadable lock contents are treated as stale so a new broker can start.\n return true;\n }\n}\n\nfunction releaseSpawnLock(): void {\n try {\n unlinkSync(BROKER_SPAWN_LOCK);\n } catch {\n // Another cleanup path may already have removed the lock.\n }\n}\n\nasync function waitForBroker(timeoutMs = 5000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await checkSocketConnectable()) {\n return;\n }\n await sleep(100);\n }\n throw new Error(\"Broker failed to start within timeout\");\n}\n"]}