@junctionpanel/server 0.1.16

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 (400) hide show
  1. package/.env.example +10 -0
  2. package/LICENSE +671 -0
  3. package/README.md +118 -0
  4. package/agent-prompt.md +339 -0
  5. package/dist/scripts/daemon-runner.js +141 -0
  6. package/dist/scripts/daemon-runner.js.map +1 -0
  7. package/dist/scripts/dev-runner.js +17 -0
  8. package/dist/scripts/dev-runner.js.map +1 -0
  9. package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
  10. package/dist/scripts/supervisor.js +122 -0
  11. package/dist/scripts/supervisor.js.map +1 -0
  12. package/dist/server/client/daemon-client-relay-e2ee-transport.d.ts +8 -0
  13. package/dist/server/client/daemon-client-relay-e2ee-transport.d.ts.map +1 -0
  14. package/dist/server/client/daemon-client-relay-e2ee-transport.js +161 -0
  15. package/dist/server/client/daemon-client-relay-e2ee-transport.js.map +1 -0
  16. package/dist/server/client/daemon-client-terminal-stream-manager.d.ts +43 -0
  17. package/dist/server/client/daemon-client-terminal-stream-manager.d.ts.map +1 -0
  18. package/dist/server/client/daemon-client-terminal-stream-manager.js +134 -0
  19. package/dist/server/client/daemon-client-terminal-stream-manager.js.map +1 -0
  20. package/dist/server/client/daemon-client-transport-types.d.ts +34 -0
  21. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -0
  22. package/dist/server/client/daemon-client-transport-types.js +2 -0
  23. package/dist/server/client/daemon-client-transport-types.js.map +1 -0
  24. package/dist/server/client/daemon-client-transport-utils.d.ts +9 -0
  25. package/dist/server/client/daemon-client-transport-utils.d.ts.map +1 -0
  26. package/dist/server/client/daemon-client-transport-utils.js +121 -0
  27. package/dist/server/client/daemon-client-transport-utils.js.map +1 -0
  28. package/dist/server/client/daemon-client-transport.d.ts +5 -0
  29. package/dist/server/client/daemon-client-transport.d.ts.map +1 -0
  30. package/dist/server/client/daemon-client-transport.js +4 -0
  31. package/dist/server/client/daemon-client-transport.js.map +1 -0
  32. package/dist/server/client/daemon-client-websocket-transport.d.ts +7 -0
  33. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -0
  34. package/dist/server/client/daemon-client-websocket-transport.js +64 -0
  35. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -0
  36. package/dist/server/client/daemon-client.d.ts +443 -0
  37. package/dist/server/client/daemon-client.d.ts.map +1 -0
  38. package/dist/server/client/daemon-client.js +2223 -0
  39. package/dist/server/client/daemon-client.js.map +1 -0
  40. package/dist/server/server/agent/activity-curator.d.ts +8 -0
  41. package/dist/server/server/agent/activity-curator.d.ts.map +1 -0
  42. package/dist/server/server/agent/activity-curator.js +228 -0
  43. package/dist/server/server/agent/activity-curator.js.map +1 -0
  44. package/dist/server/server/agent/agent-management-mcp.d.ts +36 -0
  45. package/dist/server/server/agent/agent-management-mcp.d.ts.map +1 -0
  46. package/dist/server/server/agent/agent-management-mcp.js +644 -0
  47. package/dist/server/server/agent/agent-management-mcp.js.map +1 -0
  48. package/dist/server/server/agent/agent-manager.d.ts +252 -0
  49. package/dist/server/server/agent/agent-manager.d.ts.map +1 -0
  50. package/dist/server/server/agent/agent-manager.js +1651 -0
  51. package/dist/server/server/agent/agent-manager.js.map +1 -0
  52. package/dist/server/server/agent/agent-metadata-generator.d.ts +29 -0
  53. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -0
  54. package/dist/server/server/agent/agent-metadata-generator.js +163 -0
  55. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -0
  56. package/dist/server/server/agent/agent-projections.d.ts +17 -0
  57. package/dist/server/server/agent/agent-projections.d.ts.map +1 -0
  58. package/dist/server/server/agent/agent-projections.js +270 -0
  59. package/dist/server/server/agent/agent-projections.js.map +1 -0
  60. package/dist/server/server/agent/agent-response-loop.d.ts +60 -0
  61. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -0
  62. package/dist/server/server/agent/agent-response-loop.js +304 -0
  63. package/dist/server/server/agent/agent-response-loop.js.map +1 -0
  64. package/dist/server/server/agent/agent-sdk-types.d.ts +377 -0
  65. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -0
  66. package/dist/server/server/agent/agent-sdk-types.js +12 -0
  67. package/dist/server/server/agent/agent-sdk-types.js.map +1 -0
  68. package/dist/server/server/agent/agent-storage.d.ts +230 -0
  69. package/dist/server/server/agent/agent-storage.d.ts.map +1 -0
  70. package/dist/server/server/agent/agent-storage.js +346 -0
  71. package/dist/server/server/agent/agent-storage.js.map +1 -0
  72. package/dist/server/server/agent/agent-title-limits.d.ts +3 -0
  73. package/dist/server/server/agent/agent-title-limits.d.ts.map +1 -0
  74. package/dist/server/server/agent/agent-title-limits.js +3 -0
  75. package/dist/server/server/agent/agent-title-limits.js.map +1 -0
  76. package/dist/server/server/agent/mcp-server.d.ts +19 -0
  77. package/dist/server/server/agent/mcp-server.d.ts.map +1 -0
  78. package/dist/server/server/agent/mcp-server.js +742 -0
  79. package/dist/server/server/agent/mcp-server.js.map +1 -0
  80. package/dist/server/server/agent/model-resolver.d.ts +11 -0
  81. package/dist/server/server/agent/model-resolver.d.ts.map +1 -0
  82. package/dist/server/server/agent/model-resolver.js +21 -0
  83. package/dist/server/server/agent/model-resolver.js.map +1 -0
  84. package/dist/server/server/agent/orchestrator-instructions.d.ts +7 -0
  85. package/dist/server/server/agent/orchestrator-instructions.d.ts.map +1 -0
  86. package/dist/server/server/agent/orchestrator-instructions.js +51 -0
  87. package/dist/server/server/agent/orchestrator-instructions.js.map +1 -0
  88. package/dist/server/server/agent/orchestrator.d.ts +12 -0
  89. package/dist/server/server/agent/orchestrator.d.ts.map +1 -0
  90. package/dist/server/server/agent/orchestrator.js +12 -0
  91. package/dist/server/server/agent/orchestrator.js.map +1 -0
  92. package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
  93. package/dist/server/server/agent/pcm16-resampler.d.ts.map +1 -0
  94. package/dist/server/server/agent/pcm16-resampler.js +63 -0
  95. package/dist/server/server/agent/pcm16-resampler.js.map +1 -0
  96. package/dist/server/server/agent/provider-launch-config.d.ts +139 -0
  97. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -0
  98. package/dist/server/server/agent/provider-launch-config.js +83 -0
  99. package/dist/server/server/agent/provider-launch-config.js.map +1 -0
  100. package/dist/server/server/agent/provider-manifest.d.ts +15 -0
  101. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -0
  102. package/dist/server/server/agent/provider-manifest.js +83 -0
  103. package/dist/server/server/agent/provider-manifest.js.map +1 -0
  104. package/dist/server/server/agent/provider-registry.d.ts +18 -0
  105. package/dist/server/server/agent/provider-registry.d.ts.map +1 -0
  106. package/dist/server/server/agent/provider-registry.js +45 -0
  107. package/dist/server/server/agent/provider-registry.js.map +1 -0
  108. package/dist/server/server/agent/providers/claude/model-catalog.d.ts +29 -0
  109. package/dist/server/server/agent/providers/claude/model-catalog.d.ts.map +1 -0
  110. package/dist/server/server/agent/providers/claude/model-catalog.js +64 -0
  111. package/dist/server/server/agent/providers/claude/model-catalog.js.map +1 -0
  112. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +44 -0
  113. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -0
  114. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +250 -0
  115. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -0
  116. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
  117. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -0
  118. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +109 -0
  119. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -0
  120. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
  121. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -0
  122. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +238 -0
  123. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -0
  124. package/dist/server/server/agent/providers/claude-agent.d.ts +49 -0
  125. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -0
  126. package/dist/server/server/agent/providers/claude-agent.js +3701 -0
  127. package/dist/server/server/agent/providers/claude-agent.js.map +1 -0
  128. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
  129. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -0
  130. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
  131. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -0
  132. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +15 -0
  133. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -0
  134. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +720 -0
  135. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -0
  136. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +34 -0
  137. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -0
  138. package/dist/server/server/agent/providers/codex-app-server-agent.js +2660 -0
  139. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -0
  140. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +9 -0
  141. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -0
  142. package/dist/server/server/agent/providers/codex-rollout-timeline.js +487 -0
  143. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -0
  144. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
  145. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -0
  146. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +39 -0
  147. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -0
  148. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
  149. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -0
  150. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +151 -0
  151. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -0
  152. package/dist/server/server/agent/providers/opencode-agent.d.ts +37 -0
  153. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -0
  154. package/dist/server/server/agent/providers/opencode-agent.js +874 -0
  155. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -0
  156. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +1460 -0
  157. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -0
  158. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +552 -0
  159. package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -0
  160. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +17 -0
  161. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -0
  162. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +109 -0
  163. package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -0
  164. package/dist/server/server/agent/system-prompt.d.ts +3 -0
  165. package/dist/server/server/agent/system-prompt.d.ts.map +1 -0
  166. package/dist/server/server/agent/system-prompt.js +19 -0
  167. package/dist/server/server/agent/system-prompt.js.map +1 -0
  168. package/dist/server/server/agent/timeline-append.d.ts +10 -0
  169. package/dist/server/server/agent/timeline-append.d.ts.map +1 -0
  170. package/dist/server/server/agent/timeline-append.js +27 -0
  171. package/dist/server/server/agent/timeline-append.js.map +1 -0
  172. package/dist/server/server/agent/timeline-projection.d.ts +39 -0
  173. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -0
  174. package/dist/server/server/agent/timeline-projection.js +215 -0
  175. package/dist/server/server/agent/timeline-projection.js.map +1 -0
  176. package/dist/server/server/agent/tool-name-normalization.d.ts +7 -0
  177. package/dist/server/server/agent/tool-name-normalization.d.ts.map +1 -0
  178. package/dist/server/server/agent/tool-name-normalization.js +45 -0
  179. package/dist/server/server/agent/tool-name-normalization.js.map +1 -0
  180. package/dist/server/server/agent/wait-for-agent-tracker.d.ts +15 -0
  181. package/dist/server/server/agent/wait-for-agent-tracker.d.ts.map +1 -0
  182. package/dist/server/server/agent/wait-for-agent-tracker.js +53 -0
  183. package/dist/server/server/agent/wait-for-agent-tracker.js.map +1 -0
  184. package/dist/server/server/agent-attention-policy.d.ts +20 -0
  185. package/dist/server/server/agent-attention-policy.d.ts.map +1 -0
  186. package/dist/server/server/agent-attention-policy.js +40 -0
  187. package/dist/server/server/agent-attention-policy.js.map +1 -0
  188. package/dist/server/server/allowed-hosts.d.ts +13 -0
  189. package/dist/server/server/allowed-hosts.d.ts.map +1 -0
  190. package/dist/server/server/allowed-hosts.js +94 -0
  191. package/dist/server/server/allowed-hosts.js.map +1 -0
  192. package/dist/server/server/bootstrap.d.ts +49 -0
  193. package/dist/server/server/bootstrap.d.ts.map +1 -0
  194. package/dist/server/server/bootstrap.js +422 -0
  195. package/dist/server/server/bootstrap.js.map +1 -0
  196. package/dist/server/server/client-message-id.d.ts +3 -0
  197. package/dist/server/server/client-message-id.d.ts.map +1 -0
  198. package/dist/server/server/client-message-id.js +12 -0
  199. package/dist/server/server/client-message-id.js.map +1 -0
  200. package/dist/server/server/config.d.ts +13 -0
  201. package/dist/server/server/config.d.ts.map +1 -0
  202. package/dist/server/server/config.js +58 -0
  203. package/dist/server/server/config.js.map +1 -0
  204. package/dist/server/server/connection-offer.d.ts +19 -0
  205. package/dist/server/server/connection-offer.d.ts.map +1 -0
  206. package/dist/server/server/connection-offer.js +60 -0
  207. package/dist/server/server/connection-offer.js.map +1 -0
  208. package/dist/server/server/daemon-keypair.d.ts +8 -0
  209. package/dist/server/server/daemon-keypair.d.ts.map +1 -0
  210. package/dist/server/server/daemon-keypair.js +40 -0
  211. package/dist/server/server/daemon-keypair.js.map +1 -0
  212. package/dist/server/server/daemon-version.d.ts +5 -0
  213. package/dist/server/server/daemon-version.d.ts.map +1 -0
  214. package/dist/server/server/daemon-version.js +22 -0
  215. package/dist/server/server/daemon-version.js.map +1 -0
  216. package/dist/server/server/exports.d.ts +16 -0
  217. package/dist/server/server/exports.d.ts.map +1 -0
  218. package/dist/server/server/exports.js +16 -0
  219. package/dist/server/server/exports.js.map +1 -0
  220. package/dist/server/server/file-download/token-store.d.ts +25 -0
  221. package/dist/server/server/file-download/token-store.d.ts.map +1 -0
  222. package/dist/server/server/file-download/token-store.js +40 -0
  223. package/dist/server/server/file-download/token-store.js.map +1 -0
  224. package/dist/server/server/file-explorer/service.d.ts +41 -0
  225. package/dist/server/server/file-explorer/service.d.ts.map +1 -0
  226. package/dist/server/server/file-explorer/service.js +226 -0
  227. package/dist/server/server/file-explorer/service.js.map +1 -0
  228. package/dist/server/server/index.d.ts +2 -0
  229. package/dist/server/server/index.d.ts.map +1 -0
  230. package/dist/server/server/index.js +141 -0
  231. package/dist/server/server/index.js.map +1 -0
  232. package/dist/server/server/json-utils.d.ts +11 -0
  233. package/dist/server/server/json-utils.d.ts.map +1 -0
  234. package/dist/server/server/json-utils.js +45 -0
  235. package/dist/server/server/json-utils.js.map +1 -0
  236. package/dist/server/server/junction-home.d.ts +2 -0
  237. package/dist/server/server/junction-home.d.ts.map +1 -0
  238. package/dist/server/server/junction-home.js +19 -0
  239. package/dist/server/server/junction-home.js.map +1 -0
  240. package/dist/server/server/logger.d.ts +12 -0
  241. package/dist/server/server/logger.d.ts.map +1 -0
  242. package/dist/server/server/logger.js +29 -0
  243. package/dist/server/server/logger.js.map +1 -0
  244. package/dist/server/server/messages.d.ts +9 -0
  245. package/dist/server/server/messages.d.ts.map +1 -0
  246. package/dist/server/server/messages.js +29 -0
  247. package/dist/server/server/messages.js.map +1 -0
  248. package/dist/server/server/package-version.d.ts +13 -0
  249. package/dist/server/server/package-version.d.ts.map +1 -0
  250. package/dist/server/server/package-version.js +47 -0
  251. package/dist/server/server/package-version.js.map +1 -0
  252. package/dist/server/server/path-utils.d.ts +3 -0
  253. package/dist/server/server/path-utils.d.ts.map +1 -0
  254. package/dist/server/server/path-utils.js +20 -0
  255. package/dist/server/server/path-utils.js.map +1 -0
  256. package/dist/server/server/persisted-config.d.ts +270 -0
  257. package/dist/server/server/persisted-config.d.ts.map +1 -0
  258. package/dist/server/server/persisted-config.js +152 -0
  259. package/dist/server/server/persisted-config.js.map +1 -0
  260. package/dist/server/server/persistence-hooks.d.ts +30 -0
  261. package/dist/server/server/persistence-hooks.d.ts.map +1 -0
  262. package/dist/server/server/persistence-hooks.js +68 -0
  263. package/dist/server/server/persistence-hooks.js.map +1 -0
  264. package/dist/server/server/pid-lock.d.ts +26 -0
  265. package/dist/server/server/pid-lock.d.ts.map +1 -0
  266. package/dist/server/server/pid-lock.js +280 -0
  267. package/dist/server/server/pid-lock.js.map +1 -0
  268. package/dist/server/server/relay-transport.d.ts +23 -0
  269. package/dist/server/server/relay-transport.d.ts.map +1 -0
  270. package/dist/server/server/relay-transport.js +457 -0
  271. package/dist/server/server/relay-transport.js.map +1 -0
  272. package/dist/server/server/server-id.d.ts +17 -0
  273. package/dist/server/server/server-id.d.ts.map +1 -0
  274. package/dist/server/server/server-id.js +63 -0
  275. package/dist/server/server/server-id.js.map +1 -0
  276. package/dist/server/server/session.d.ts +280 -0
  277. package/dist/server/server/session.d.ts.map +1 -0
  278. package/dist/server/server/session.js +4395 -0
  279. package/dist/server/server/session.js.map +1 -0
  280. package/dist/server/server/terminal-mcp/index.d.ts +4 -0
  281. package/dist/server/server/terminal-mcp/index.d.ts.map +1 -0
  282. package/dist/server/server/terminal-mcp/index.js +3 -0
  283. package/dist/server/server/terminal-mcp/index.js.map +1 -0
  284. package/dist/server/server/terminal-mcp/server.d.ts +10 -0
  285. package/dist/server/server/terminal-mcp/server.d.ts.map +1 -0
  286. package/dist/server/server/terminal-mcp/server.js +217 -0
  287. package/dist/server/server/terminal-mcp/server.js.map +1 -0
  288. package/dist/server/server/terminal-mcp/terminal-manager.d.ts +123 -0
  289. package/dist/server/server/terminal-mcp/terminal-manager.d.ts.map +1 -0
  290. package/dist/server/server/terminal-mcp/terminal-manager.js +351 -0
  291. package/dist/server/server/terminal-mcp/terminal-manager.js.map +1 -0
  292. package/dist/server/server/terminal-mcp/tmux.d.ts +207 -0
  293. package/dist/server/server/terminal-mcp/tmux.d.ts.map +1 -0
  294. package/dist/server/server/terminal-mcp/tmux.js +924 -0
  295. package/dist/server/server/terminal-mcp/tmux.js.map +1 -0
  296. package/dist/server/server/types.d.ts +5 -0
  297. package/dist/server/server/types.d.ts.map +1 -0
  298. package/dist/server/server/types.js +3 -0
  299. package/dist/server/server/types.js.map +1 -0
  300. package/dist/server/server/utils/diff-highlighter.d.ts +52 -0
  301. package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -0
  302. package/dist/server/server/utils/diff-highlighter.js +244 -0
  303. package/dist/server/server/utils/diff-highlighter.js.map +1 -0
  304. package/dist/server/server/utils/syntax-highlighter.d.ts +10 -0
  305. package/dist/server/server/utils/syntax-highlighter.d.ts.map +1 -0
  306. package/dist/server/server/utils/syntax-highlighter.js +145 -0
  307. package/dist/server/server/utils/syntax-highlighter.js.map +1 -0
  308. package/dist/server/server/websocket-server.d.ts +79 -0
  309. package/dist/server/server/websocket-server.d.ts.map +1 -0
  310. package/dist/server/server/websocket-server.js +742 -0
  311. package/dist/server/server/websocket-server.js.map +1 -0
  312. package/dist/server/server/worktree-bootstrap.d.ts +29 -0
  313. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -0
  314. package/dist/server/server/worktree-bootstrap.js +454 -0
  315. package/dist/server/server/worktree-bootstrap.js.map +1 -0
  316. package/dist/server/shared/agent-attention-notification.d.ts +40 -0
  317. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -0
  318. package/dist/server/shared/agent-attention-notification.js +130 -0
  319. package/dist/server/shared/agent-attention-notification.js.map +1 -0
  320. package/dist/server/shared/agent-lifecycle.d.ts +3 -0
  321. package/dist/server/shared/agent-lifecycle.d.ts.map +1 -0
  322. package/dist/server/shared/agent-lifecycle.js +8 -0
  323. package/dist/server/shared/agent-lifecycle.js.map +1 -0
  324. package/dist/server/shared/binary-mux.d.ts +31 -0
  325. package/dist/server/shared/binary-mux.d.ts.map +1 -0
  326. package/dist/server/shared/binary-mux.js +114 -0
  327. package/dist/server/shared/binary-mux.js.map +1 -0
  328. package/dist/server/shared/connection-offer.d.ts +62 -0
  329. package/dist/server/shared/connection-offer.d.ts.map +1 -0
  330. package/dist/server/shared/connection-offer.js +17 -0
  331. package/dist/server/shared/connection-offer.js.map +1 -0
  332. package/dist/server/shared/daemon-endpoints.d.ts +27 -0
  333. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -0
  334. package/dist/server/shared/daemon-endpoints.js +113 -0
  335. package/dist/server/shared/daemon-endpoints.js.map +1 -0
  336. package/dist/server/shared/messages.d.ts +36982 -0
  337. package/dist/server/shared/messages.d.ts.map +1 -0
  338. package/dist/server/shared/messages.js +1793 -0
  339. package/dist/server/shared/messages.js.map +1 -0
  340. package/dist/server/shared/path-utils.d.ts +2 -0
  341. package/dist/server/shared/path-utils.d.ts.map +1 -0
  342. package/dist/server/shared/path-utils.js +16 -0
  343. package/dist/server/shared/path-utils.js.map +1 -0
  344. package/dist/server/shared/terminal-key-input.d.ts +9 -0
  345. package/dist/server/shared/terminal-key-input.d.ts.map +1 -0
  346. package/dist/server/shared/terminal-key-input.js +132 -0
  347. package/dist/server/shared/terminal-key-input.js.map +1 -0
  348. package/dist/server/shared/tool-call-display.d.ts +11 -0
  349. package/dist/server/shared/tool-call-display.d.ts.map +1 -0
  350. package/dist/server/shared/tool-call-display.js +102 -0
  351. package/dist/server/shared/tool-call-display.js.map +1 -0
  352. package/dist/server/shared/tool-call-interpretation.d.ts +14 -0
  353. package/dist/server/shared/tool-call-interpretation.d.ts.map +1 -0
  354. package/dist/server/shared/tool-call-interpretation.js +76 -0
  355. package/dist/server/shared/tool-call-interpretation.js.map +1 -0
  356. package/dist/server/terminal/terminal-manager.d.ts +30 -0
  357. package/dist/server/terminal/terminal-manager.d.ts.map +1 -0
  358. package/dist/server/terminal/terminal-manager.js +148 -0
  359. package/dist/server/terminal/terminal-manager.js.map +1 -0
  360. package/dist/server/terminal/terminal.d.ts +93 -0
  361. package/dist/server/terminal/terminal.d.ts.map +1 -0
  362. package/dist/server/terminal/terminal.js +386 -0
  363. package/dist/server/terminal/terminal.js.map +1 -0
  364. package/dist/server/utils/checkout-git.d.ts +150 -0
  365. package/dist/server/utils/checkout-git.d.ts.map +1 -0
  366. package/dist/server/utils/checkout-git.js +1427 -0
  367. package/dist/server/utils/checkout-git.js.map +1 -0
  368. package/dist/server/utils/city-names.d.ts +17 -0
  369. package/dist/server/utils/city-names.d.ts.map +1 -0
  370. package/dist/server/utils/city-names.js +122 -0
  371. package/dist/server/utils/city-names.js.map +1 -0
  372. package/dist/server/utils/directory-suggestions.d.ts +31 -0
  373. package/dist/server/utils/directory-suggestions.d.ts.map +1 -0
  374. package/dist/server/utils/directory-suggestions.js +678 -0
  375. package/dist/server/utils/directory-suggestions.js.map +1 -0
  376. package/dist/server/utils/git-clone.d.ts +10 -0
  377. package/dist/server/utils/git-clone.d.ts.map +1 -0
  378. package/dist/server/utils/git-clone.js +45 -0
  379. package/dist/server/utils/git-clone.js.map +1 -0
  380. package/dist/server/utils/git-init.d.ts +9 -0
  381. package/dist/server/utils/git-init.d.ts.map +1 -0
  382. package/dist/server/utils/git-init.js +91 -0
  383. package/dist/server/utils/git-init.js.map +1 -0
  384. package/dist/server/utils/path.d.ts +5 -0
  385. package/dist/server/utils/path.d.ts.map +1 -0
  386. package/dist/server/utils/path.js +15 -0
  387. package/dist/server/utils/path.js.map +1 -0
  388. package/dist/server/utils/project-icon.d.ts +39 -0
  389. package/dist/server/utils/project-icon.d.ts.map +1 -0
  390. package/dist/server/utils/project-icon.js +391 -0
  391. package/dist/server/utils/project-icon.js.map +1 -0
  392. package/dist/server/utils/worktree-metadata.d.ts +47 -0
  393. package/dist/server/utils/worktree-metadata.d.ts.map +1 -0
  394. package/dist/server/utils/worktree-metadata.js +116 -0
  395. package/dist/server/utils/worktree-metadata.js.map +1 -0
  396. package/dist/server/utils/worktree.d.ts +175 -0
  397. package/dist/server/utils/worktree.d.ts.map +1 -0
  398. package/dist/server/utils/worktree.js +858 -0
  399. package/dist/server/utils/worktree.js.map +1 -0
  400. package/package.json +107 -0
@@ -0,0 +1,742 @@
1
+ import { WebSocketServer as WebSocketServer_WS } from "ws";
2
+ import { hostname as getHostname } from "node:os";
3
+ import { WSInboundMessageSchema, wrapSessionMessage, } from "./messages.js";
4
+ import { asUint8Array, decodeBinaryMuxFrame, encodeBinaryMuxFrame, } from "../shared/binary-mux.js";
5
+ import { isHostAllowed } from "./allowed-hosts.js";
6
+ import { Session } from "./session.js";
7
+ import { computeShouldNotifyClient, } from "./agent-attention-policy.js";
8
+ import { buildAgentAttentionNotificationPayload, findLatestAssistantMessageFromTimeline, findLatestPermissionRequest, } from "../shared/agent-attention-notification.js";
9
+ function bufferFromWsData(data) {
10
+ if (typeof data === "string")
11
+ return Buffer.from(data, "utf8");
12
+ if (Array.isArray(data)) {
13
+ return Buffer.concat(data.map((item) => Buffer.isBuffer(item) ? item : Buffer.from(item)));
14
+ }
15
+ if (Buffer.isBuffer(data))
16
+ return data;
17
+ return Buffer.from(data);
18
+ }
19
+ const EXTERNAL_SESSION_DISCONNECT_GRACE_MS = 90000;
20
+ const HELLO_TIMEOUT_MS = 15000;
21
+ const WS_CLOSE_HELLO_TIMEOUT = 4001;
22
+ const WS_CLOSE_INVALID_HELLO = 4002;
23
+ const WS_CLOSE_INCOMPATIBLE_PROTOCOL = 4003;
24
+ const WS_CLOSE_AUTH_REQUIRED = 4004;
25
+ const WS_PROTOCOL_VERSION = 1;
26
+ export class MissingDaemonVersionError extends Error {
27
+ constructor() {
28
+ super("WebSocketServer requires a non-empty daemonVersion.");
29
+ this.name = "MissingDaemonVersionError";
30
+ }
31
+ }
32
+ /**
33
+ * WebSocket server that only accepts sockets + parses/forwards messages to the session layer.
34
+ */
35
+ export class WebSocketServer {
36
+ constructor(server, logger, serverId, agentManager, agentStorage, downloadTokenStore, junctionHome, createAgentMcpTransport, wsConfig, terminalManager, agentProviderRuntimeSettings, daemonVersion, onLifecycleIntent, jwtValidator) {
37
+ this.pendingConnections = new Map();
38
+ this.sessions = new Map();
39
+ this.externalSessionsByKey = new Map();
40
+ this.ACTIVITY_THRESHOLD_MS = 120000;
41
+ this.logger = logger.child({ module: "websocket-server" });
42
+ this.serverId = serverId;
43
+ if (typeof daemonVersion !== "string" || daemonVersion.trim().length === 0) {
44
+ throw new MissingDaemonVersionError();
45
+ }
46
+ this.daemonVersion = daemonVersion.trim();
47
+ this.agentManager = agentManager;
48
+ this.agentStorage = agentStorage;
49
+ this.downloadTokenStore = downloadTokenStore;
50
+ this.junctionHome = junctionHome;
51
+ this.createAgentMcpTransport = createAgentMcpTransport;
52
+ this.terminalManager = terminalManager ?? null;
53
+ this.agentProviderRuntimeSettings = agentProviderRuntimeSettings;
54
+ this.onLifecycleIntent = onLifecycleIntent ?? null;
55
+ this.jwtValidator = jwtValidator ?? null;
56
+ this.agentManager.setAgentAttentionCallback((params) => {
57
+ this.broadcastAgentAttention(params);
58
+ });
59
+ const { allowedOrigins, allowedHosts } = wsConfig;
60
+ this.wss = new WebSocketServer_WS({
61
+ server,
62
+ path: "/ws",
63
+ verifyClient: ({ req }, callback) => {
64
+ const requestMetadata = extractSocketRequestMetadata(req);
65
+ const origin = requestMetadata.origin;
66
+ const requestHost = requestMetadata.host ?? null;
67
+ if (requestHost && !isHostAllowed(requestHost, allowedHosts)) {
68
+ this.logger.warn({ ...requestMetadata, host: requestHost }, "Rejected connection from disallowed host");
69
+ callback(false, 403, "Host not allowed");
70
+ return;
71
+ }
72
+ const sameOrigin = !!origin &&
73
+ !!requestHost &&
74
+ (origin === `http://${requestHost}` || origin === `https://${requestHost}`);
75
+ if (!origin || allowedOrigins.has(origin) || sameOrigin) {
76
+ callback(true);
77
+ }
78
+ else {
79
+ this.logger.warn({ ...requestMetadata, origin }, "Rejected connection from origin");
80
+ callback(false, 403, "Origin not allowed");
81
+ }
82
+ },
83
+ });
84
+ this.wss.on("connection", (ws, request) => {
85
+ void this.attachSocket(ws, request);
86
+ });
87
+ this.logger.info("WebSocket server initialized on /ws");
88
+ }
89
+ broadcast(message) {
90
+ const payload = JSON.stringify(message);
91
+ for (const ws of this.sessions.keys()) {
92
+ // WebSocket.OPEN = 1
93
+ if (ws.readyState === 1) {
94
+ ws.send(payload);
95
+ }
96
+ }
97
+ }
98
+ async attachExternalSocket(ws, metadata) {
99
+ await this.attachSocket(ws, undefined, metadata);
100
+ }
101
+ async close() {
102
+ const uniqueConnections = new Set([
103
+ ...this.sessions.values(),
104
+ ...this.externalSessionsByKey.values(),
105
+ ]);
106
+ const pendingSockets = new Set(this.pendingConnections.keys());
107
+ for (const pending of this.pendingConnections.values()) {
108
+ if (pending.helloTimeout) {
109
+ clearTimeout(pending.helloTimeout);
110
+ pending.helloTimeout = null;
111
+ }
112
+ }
113
+ const cleanupPromises = [];
114
+ for (const connection of uniqueConnections) {
115
+ if (connection.externalDisconnectCleanupTimeout) {
116
+ clearTimeout(connection.externalDisconnectCleanupTimeout);
117
+ connection.externalDisconnectCleanupTimeout = null;
118
+ }
119
+ cleanupPromises.push(connection.session.cleanup());
120
+ for (const ws of connection.sockets) {
121
+ cleanupPromises.push(new Promise((resolve) => {
122
+ // WebSocket.CLOSED = 3
123
+ if (ws.readyState === 3) {
124
+ resolve();
125
+ return;
126
+ }
127
+ ws.once("close", () => resolve());
128
+ ws.close();
129
+ }));
130
+ }
131
+ }
132
+ for (const ws of pendingSockets) {
133
+ cleanupPromises.push(new Promise((resolve) => {
134
+ if (ws.readyState === 3) {
135
+ resolve();
136
+ return;
137
+ }
138
+ ws.once("close", () => resolve());
139
+ ws.close();
140
+ }));
141
+ }
142
+ await Promise.all(cleanupPromises);
143
+ this.pendingConnections.clear();
144
+ this.sessions.clear();
145
+ this.externalSessionsByKey.clear();
146
+ this.wss.close();
147
+ }
148
+ sendToClient(ws, message) {
149
+ // WebSocket.OPEN = 1
150
+ if (ws.readyState === 1) {
151
+ ws.send(JSON.stringify(message));
152
+ }
153
+ }
154
+ sendBinaryToClient(ws, frame) {
155
+ if (ws.readyState !== 1) {
156
+ return;
157
+ }
158
+ ws.send(encodeBinaryMuxFrame(frame));
159
+ }
160
+ sendToConnection(connection, message) {
161
+ for (const ws of connection.sockets) {
162
+ this.sendToClient(ws, message);
163
+ }
164
+ }
165
+ sendBinaryToConnection(connection, frame) {
166
+ for (const ws of connection.sockets) {
167
+ this.sendBinaryToClient(ws, frame);
168
+ }
169
+ }
170
+ async attachSocket(ws, request, metadata) {
171
+ const requestMetadata = extractSocketRequestMetadata(request);
172
+ const connectionLoggerFields = {
173
+ transport: metadata?.transport === "relay" ? "relay" : "direct",
174
+ };
175
+ if (requestMetadata.host) {
176
+ connectionLoggerFields.host = requestMetadata.host;
177
+ }
178
+ if (requestMetadata.origin) {
179
+ connectionLoggerFields.origin = requestMetadata.origin;
180
+ }
181
+ if (requestMetadata.userAgent) {
182
+ connectionLoggerFields.userAgent = requestMetadata.userAgent;
183
+ }
184
+ if (requestMetadata.remoteAddress) {
185
+ connectionLoggerFields.remoteAddress = requestMetadata.remoteAddress;
186
+ }
187
+ const connectionLogger = this.logger.child(connectionLoggerFields);
188
+ const pending = {
189
+ connectionLogger,
190
+ helloTimeout: null,
191
+ };
192
+ const timeout = setTimeout(() => {
193
+ if (this.pendingConnections.get(ws) !== pending) {
194
+ return;
195
+ }
196
+ pending.helloTimeout = null;
197
+ this.pendingConnections.delete(ws);
198
+ pending.connectionLogger.warn({ timeoutMs: HELLO_TIMEOUT_MS }, "Closing connection due to missing hello");
199
+ try {
200
+ ws.close(WS_CLOSE_HELLO_TIMEOUT, "Hello timeout");
201
+ }
202
+ catch {
203
+ // ignore close errors
204
+ }
205
+ }, HELLO_TIMEOUT_MS);
206
+ pending.helloTimeout = timeout;
207
+ timeout.unref?.();
208
+ this.pendingConnections.set(ws, pending);
209
+ this.bindSocketHandlers(ws);
210
+ pending.connectionLogger.trace({
211
+ totalPendingConnections: this.pendingConnections.size,
212
+ }, "Client connected; awaiting hello");
213
+ }
214
+ createSessionConnection(params) {
215
+ const { ws, clientId, userId, connectionLogger } = params;
216
+ let connection = null;
217
+ const session = new Session({
218
+ clientId,
219
+ userId,
220
+ onMessage: (msg) => {
221
+ if (!connection) {
222
+ return;
223
+ }
224
+ this.sendToConnection(connection, wrapSessionMessage(msg));
225
+ },
226
+ onBinaryMessage: (frame) => {
227
+ if (!connection) {
228
+ return;
229
+ }
230
+ this.sendBinaryToConnection(connection, frame);
231
+ },
232
+ onLifecycleIntent: (intent) => {
233
+ this.onLifecycleIntent?.(intent);
234
+ },
235
+ logger: connectionLogger.child({ module: "session" }),
236
+ downloadTokenStore: this.downloadTokenStore,
237
+ junctionHome: this.junctionHome,
238
+ agentManager: this.agentManager,
239
+ agentStorage: this.agentStorage,
240
+ createAgentMcpTransport: this.createAgentMcpTransport,
241
+ terminalManager: this.terminalManager,
242
+ agentProviderRuntimeSettings: this.agentProviderRuntimeSettings,
243
+ });
244
+ connection = {
245
+ session,
246
+ clientId,
247
+ connectionLogger,
248
+ sockets: new Set([ws]),
249
+ externalDisconnectCleanupTimeout: null,
250
+ };
251
+ return connection;
252
+ }
253
+ clearPendingConnection(ws) {
254
+ const pending = this.pendingConnections.get(ws);
255
+ if (!pending) {
256
+ return null;
257
+ }
258
+ if (pending.helloTimeout) {
259
+ clearTimeout(pending.helloTimeout);
260
+ pending.helloTimeout = null;
261
+ }
262
+ this.pendingConnections.delete(ws);
263
+ return pending;
264
+ }
265
+ buildWelcomeMessage(params) {
266
+ return {
267
+ type: "welcome",
268
+ serverId: this.serverId,
269
+ hostname: getHostname(),
270
+ version: this.daemonVersion,
271
+ resumed: params.resumed,
272
+ };
273
+ }
274
+ handleHello(params) {
275
+ const { ws, message, pending } = params;
276
+ if (message.protocolVersion !== WS_PROTOCOL_VERSION) {
277
+ this.clearPendingConnection(ws);
278
+ pending.connectionLogger.warn({
279
+ receivedProtocolVersion: message.protocolVersion,
280
+ expectedProtocolVersion: WS_PROTOCOL_VERSION,
281
+ }, "Rejected hello due to protocol version mismatch");
282
+ try {
283
+ ws.close(WS_CLOSE_INCOMPATIBLE_PROTOCOL, "Incompatible protocol version");
284
+ }
285
+ catch {
286
+ // ignore close errors
287
+ }
288
+ return;
289
+ }
290
+ const clientId = message.clientId.trim();
291
+ if (clientId.length === 0) {
292
+ this.clearPendingConnection(ws);
293
+ pending.connectionLogger.warn("Rejected hello with empty clientId");
294
+ try {
295
+ ws.close(WS_CLOSE_INVALID_HELLO, "Invalid hello");
296
+ }
297
+ catch {
298
+ // ignore close errors
299
+ }
300
+ return;
301
+ }
302
+ // Validate JWT if auth is enabled
303
+ let userId;
304
+ if (this.jwtValidator) {
305
+ if (!message.token) {
306
+ pending.connectionLogger.warn("Rejected hello: authentication required but no token provided");
307
+ try {
308
+ ws.close(WS_CLOSE_AUTH_REQUIRED, "Authentication required");
309
+ }
310
+ catch {
311
+ // ignore close errors
312
+ }
313
+ return;
314
+ }
315
+ const payload = this.jwtValidator(message.token);
316
+ if (!payload) {
317
+ pending.connectionLogger.warn("Rejected hello: invalid or expired token");
318
+ try {
319
+ ws.close(WS_CLOSE_AUTH_REQUIRED, "Invalid token");
320
+ }
321
+ catch {
322
+ // ignore close errors
323
+ }
324
+ return;
325
+ }
326
+ userId = payload.sub;
327
+ }
328
+ this.clearPendingConnection(ws);
329
+ const existing = this.externalSessionsByKey.get(clientId);
330
+ if (existing) {
331
+ if (existing.externalDisconnectCleanupTimeout) {
332
+ clearTimeout(existing.externalDisconnectCleanupTimeout);
333
+ existing.externalDisconnectCleanupTimeout = null;
334
+ }
335
+ existing.sockets.add(ws);
336
+ this.sessions.set(ws, existing);
337
+ this.sendToClient(ws, this.buildWelcomeMessage({ resumed: true }));
338
+ existing.connectionLogger.trace({
339
+ clientId,
340
+ resumed: true,
341
+ totalSessions: this.sessions.size,
342
+ }, "Client connected via hello");
343
+ return;
344
+ }
345
+ const connectionLogger = pending.connectionLogger.child({ clientId });
346
+ const connection = this.createSessionConnection({
347
+ ws,
348
+ clientId,
349
+ userId,
350
+ connectionLogger,
351
+ });
352
+ this.sessions.set(ws, connection);
353
+ this.externalSessionsByKey.set(clientId, connection);
354
+ this.sendToClient(ws, this.buildWelcomeMessage({ resumed: false }));
355
+ connection.connectionLogger.trace({
356
+ clientId,
357
+ resumed: false,
358
+ totalSessions: this.sessions.size,
359
+ }, "Client connected via hello");
360
+ }
361
+ bindSocketHandlers(ws) {
362
+ ws.on("message", (data) => {
363
+ void this.handleRawMessage(ws, data);
364
+ });
365
+ ws.on("close", async (code, reason) => {
366
+ await this.detachSocket(ws, {
367
+ code: typeof code === "number" ? code : undefined,
368
+ reason,
369
+ });
370
+ });
371
+ ws.on("error", async (error) => {
372
+ const err = error instanceof Error ? error : new Error(String(error));
373
+ const active = this.sessions.get(ws);
374
+ const pending = this.pendingConnections.get(ws);
375
+ const log = active?.connectionLogger ?? pending?.connectionLogger ?? this.logger;
376
+ log.error({ err }, "Client error");
377
+ await this.detachSocket(ws, { error: err });
378
+ });
379
+ }
380
+ async detachSocket(ws, details) {
381
+ const pending = this.clearPendingConnection(ws);
382
+ if (pending) {
383
+ pending.connectionLogger.trace({
384
+ code: details.code,
385
+ reason: stringifyCloseReason(details.reason),
386
+ }, "Pending client disconnected");
387
+ return;
388
+ }
389
+ const connection = this.sessions.get(ws);
390
+ if (!connection) {
391
+ return;
392
+ }
393
+ this.sessions.delete(ws);
394
+ connection.sockets.delete(ws);
395
+ if (connection.sockets.size === 0) {
396
+ if (connection.externalDisconnectCleanupTimeout) {
397
+ clearTimeout(connection.externalDisconnectCleanupTimeout);
398
+ }
399
+ const timeout = setTimeout(() => {
400
+ if (connection.externalDisconnectCleanupTimeout !== timeout) {
401
+ return;
402
+ }
403
+ connection.externalDisconnectCleanupTimeout = null;
404
+ void this.cleanupConnection(connection, "Client disconnected (grace timeout)");
405
+ }, EXTERNAL_SESSION_DISCONNECT_GRACE_MS);
406
+ connection.externalDisconnectCleanupTimeout = timeout;
407
+ connection.connectionLogger.trace({
408
+ clientId: connection.clientId,
409
+ code: details.code,
410
+ reason: stringifyCloseReason(details.reason),
411
+ reconnectGraceMs: EXTERNAL_SESSION_DISCONNECT_GRACE_MS,
412
+ }, "Client disconnected; waiting for reconnect");
413
+ return;
414
+ }
415
+ if (connection.sockets.size > 0) {
416
+ connection.connectionLogger.trace({
417
+ clientId: connection.clientId,
418
+ remainingSockets: connection.sockets.size,
419
+ code: details.code,
420
+ reason: stringifyCloseReason(details.reason),
421
+ }, "Client socket disconnected; session remains attached");
422
+ return;
423
+ }
424
+ await this.cleanupConnection(connection, "Client disconnected");
425
+ }
426
+ async cleanupConnection(connection, logMessage) {
427
+ if (connection.externalDisconnectCleanupTimeout) {
428
+ clearTimeout(connection.externalDisconnectCleanupTimeout);
429
+ connection.externalDisconnectCleanupTimeout = null;
430
+ }
431
+ for (const socket of connection.sockets) {
432
+ this.sessions.delete(socket);
433
+ }
434
+ connection.sockets.clear();
435
+ const existing = this.externalSessionsByKey.get(connection.clientId);
436
+ if (existing === connection) {
437
+ this.externalSessionsByKey.delete(connection.clientId);
438
+ }
439
+ connection.connectionLogger.trace({ clientId: connection.clientId, totalSessions: this.sessions.size }, logMessage);
440
+ await connection.session.cleanup();
441
+ }
442
+ async handleRawMessage(ws, data) {
443
+ const activeConnection = this.sessions.get(ws);
444
+ const pendingConnection = this.pendingConnections.get(ws);
445
+ const log = activeConnection?.connectionLogger ?? pendingConnection?.connectionLogger ?? this.logger;
446
+ try {
447
+ const buffer = bufferFromWsData(data);
448
+ const asBytes = asUint8Array(buffer);
449
+ if (asBytes) {
450
+ const frame = decodeBinaryMuxFrame(asBytes);
451
+ if (frame) {
452
+ if (!activeConnection) {
453
+ log.warn("Rejected binary frame before hello");
454
+ this.clearPendingConnection(ws);
455
+ try {
456
+ ws.close(WS_CLOSE_INVALID_HELLO, "Session message before hello");
457
+ }
458
+ catch {
459
+ // ignore close errors
460
+ }
461
+ return;
462
+ }
463
+ activeConnection.session.handleBinaryFrame(frame);
464
+ return;
465
+ }
466
+ }
467
+ const parsed = JSON.parse(buffer.toString());
468
+ const parsedMessage = WSInboundMessageSchema.safeParse(parsed);
469
+ if (!parsedMessage.success) {
470
+ if (pendingConnection) {
471
+ pendingConnection.connectionLogger.warn({
472
+ error: parsedMessage.error.message,
473
+ }, "Rejected pending message before hello");
474
+ this.clearPendingConnection(ws);
475
+ try {
476
+ ws.close(WS_CLOSE_INVALID_HELLO, "Invalid hello");
477
+ }
478
+ catch {
479
+ // ignore close errors
480
+ }
481
+ return;
482
+ }
483
+ const requestInfo = extractRequestInfoFromUnknownWsInbound(parsed);
484
+ const isUnknownSchema = requestInfo?.requestId != null &&
485
+ typeof parsed === "object" &&
486
+ parsed != null &&
487
+ "type" in parsed &&
488
+ parsed.type === "session";
489
+ log.warn({
490
+ clientId: activeConnection?.clientId,
491
+ requestId: requestInfo?.requestId,
492
+ requestType: requestInfo?.requestType,
493
+ error: parsedMessage.error.message,
494
+ }, "WS inbound message validation failed");
495
+ if (requestInfo) {
496
+ this.sendToClient(ws, wrapSessionMessage({
497
+ type: "rpc_error",
498
+ payload: {
499
+ requestId: requestInfo.requestId,
500
+ requestType: requestInfo.requestType,
501
+ error: isUnknownSchema ? "Unknown request schema" : "Invalid message",
502
+ code: isUnknownSchema ? "unknown_schema" : "invalid_message",
503
+ },
504
+ }));
505
+ return;
506
+ }
507
+ const errorMessage = `Invalid message: ${parsedMessage.error.message}`;
508
+ this.sendToClient(ws, wrapSessionMessage({
509
+ type: "status",
510
+ payload: {
511
+ status: "error",
512
+ message: errorMessage,
513
+ },
514
+ }));
515
+ return;
516
+ }
517
+ const message = parsedMessage.data;
518
+ if (message.type === "ping") {
519
+ this.sendToClient(ws, { type: "pong" });
520
+ return;
521
+ }
522
+ if (pendingConnection) {
523
+ if (message.type === "hello") {
524
+ this.handleHello({
525
+ ws,
526
+ message,
527
+ pending: pendingConnection,
528
+ });
529
+ return;
530
+ }
531
+ pendingConnection.connectionLogger.warn({
532
+ messageType: message.type,
533
+ }, "Rejected pending message before hello");
534
+ this.clearPendingConnection(ws);
535
+ try {
536
+ ws.close(WS_CLOSE_INVALID_HELLO, "Session message before hello");
537
+ }
538
+ catch {
539
+ // ignore close errors
540
+ }
541
+ return;
542
+ }
543
+ if (!activeConnection) {
544
+ this.logger.error("No connection found for websocket");
545
+ return;
546
+ }
547
+ if (message.type === "hello") {
548
+ activeConnection.connectionLogger.warn("Received hello on active connection");
549
+ try {
550
+ ws.close(WS_CLOSE_INVALID_HELLO, "Unexpected hello");
551
+ }
552
+ catch {
553
+ // ignore close errors
554
+ }
555
+ return;
556
+ }
557
+ if (message.type === "session") {
558
+ await activeConnection.session.handleMessage(message.message);
559
+ }
560
+ }
561
+ catch (error) {
562
+ const err = error instanceof Error ? error : new Error(String(error));
563
+ let rawPayload = null;
564
+ let parsedPayload = null;
565
+ try {
566
+ const buffer = bufferFromWsData(data);
567
+ rawPayload = buffer.toString();
568
+ parsedPayload = JSON.parse(rawPayload);
569
+ }
570
+ catch (payloadError) {
571
+ rawPayload = rawPayload ?? "<unreadable>";
572
+ parsedPayload = parsedPayload ?? rawPayload;
573
+ const payloadErr = payloadError instanceof Error ? payloadError : new Error(String(payloadError));
574
+ this.logger.error({ err: payloadErr }, "Failed to decode raw payload");
575
+ }
576
+ const trimmedRawPayload = typeof rawPayload === "string" && rawPayload.length > 2000
577
+ ? `${rawPayload.slice(0, 2000)}... (truncated)`
578
+ : rawPayload;
579
+ log.error({
580
+ err,
581
+ rawPayload: trimmedRawPayload,
582
+ parsedPayload,
583
+ }, "Failed to parse/handle message");
584
+ if (this.pendingConnections.has(ws)) {
585
+ this.clearPendingConnection(ws);
586
+ try {
587
+ ws.close(WS_CLOSE_INVALID_HELLO, "Invalid hello");
588
+ }
589
+ catch {
590
+ // ignore close errors
591
+ }
592
+ return;
593
+ }
594
+ const requestInfo = extractRequestInfoFromUnknownWsInbound(parsedPayload);
595
+ if (requestInfo) {
596
+ this.sendToClient(ws, wrapSessionMessage({
597
+ type: "rpc_error",
598
+ payload: {
599
+ requestId: requestInfo.requestId,
600
+ requestType: requestInfo.requestType,
601
+ error: "Invalid message",
602
+ code: "invalid_message",
603
+ },
604
+ }));
605
+ return;
606
+ }
607
+ this.sendToClient(ws, wrapSessionMessage({
608
+ type: "status",
609
+ payload: {
610
+ status: "error",
611
+ message: `Invalid message: ${err.message}`,
612
+ },
613
+ }));
614
+ }
615
+ }
616
+ getClientActivityState(session) {
617
+ const activity = session.getClientActivity();
618
+ if (!activity) {
619
+ return { deviceType: null, focusedAgentId: null, isStale: true, appVisible: false };
620
+ }
621
+ const now = Date.now();
622
+ const ageMs = now - activity.lastActivityAt.getTime();
623
+ const isStale = ageMs >= this.ACTIVITY_THRESHOLD_MS;
624
+ return {
625
+ deviceType: activity.deviceType,
626
+ focusedAgentId: activity.focusedAgentId,
627
+ isStale,
628
+ appVisible: activity.appVisible,
629
+ };
630
+ }
631
+ broadcastAgentAttention(params) {
632
+ const clientEntries = [];
633
+ for (const [ws, connection] of this.sessions) {
634
+ clientEntries.push({
635
+ ws,
636
+ state: this.getClientActivityState(connection.session),
637
+ });
638
+ }
639
+ const allStates = clientEntries.map((e) => e.state);
640
+ const agent = this.agentManager.getAgent(params.agentId);
641
+ if (agent?.labels?.ui !== "true") {
642
+ this.logger.debug({
643
+ agentId: params.agentId,
644
+ labels: agent?.labels ?? null,
645
+ }, "Skipping attention notification for non-UI agent");
646
+ return;
647
+ }
648
+ const notification = buildAgentAttentionNotificationPayload({
649
+ reason: params.reason,
650
+ serverId: this.serverId,
651
+ agentId: params.agentId,
652
+ assistantMessage: agent
653
+ ? findLatestAssistantMessageFromTimeline(agent.timeline)
654
+ : null,
655
+ permissionRequest: agent
656
+ ? findLatestPermissionRequest(agent.pendingPermissions)
657
+ : null,
658
+ });
659
+ for (const { ws, state } of clientEntries) {
660
+ const shouldNotify = computeShouldNotifyClient({
661
+ clientState: state,
662
+ allClientStates: allStates,
663
+ agentId: params.agentId,
664
+ });
665
+ const message = wrapSessionMessage({
666
+ type: "agent_stream",
667
+ payload: {
668
+ agentId: params.agentId,
669
+ event: {
670
+ type: "attention_required",
671
+ provider: params.provider,
672
+ reason: params.reason,
673
+ timestamp: new Date().toISOString(),
674
+ shouldNotify,
675
+ notification,
676
+ },
677
+ timestamp: new Date().toISOString(),
678
+ },
679
+ });
680
+ this.sendToClient(ws, message);
681
+ }
682
+ }
683
+ }
684
+ function extractSocketRequestMetadata(request) {
685
+ if (!request || typeof request !== "object") {
686
+ return {};
687
+ }
688
+ const record = request;
689
+ const host = typeof record.headers?.host === "string" ? record.headers.host : undefined;
690
+ const origin = typeof record.headers?.origin === "string" ? record.headers.origin : undefined;
691
+ const userAgent = typeof record.headers?.["user-agent"] === "string"
692
+ ? record.headers["user-agent"]
693
+ : undefined;
694
+ const remoteAddress = typeof record.socket?.remoteAddress === "string"
695
+ ? record.socket.remoteAddress
696
+ : undefined;
697
+ return {
698
+ ...(host ? { host } : {}),
699
+ ...(origin ? { origin } : {}),
700
+ ...(userAgent ? { userAgent } : {}),
701
+ ...(remoteAddress ? { remoteAddress } : {}),
702
+ };
703
+ }
704
+ function stringifyCloseReason(reason) {
705
+ if (typeof reason === "string") {
706
+ return reason.length > 0 ? reason : null;
707
+ }
708
+ if (Buffer.isBuffer(reason)) {
709
+ const text = reason.toString();
710
+ return text.length > 0 ? text : null;
711
+ }
712
+ if (reason == null) {
713
+ return null;
714
+ }
715
+ const text = String(reason);
716
+ return text.length > 0 ? text : null;
717
+ }
718
+ function extractRequestInfoFromUnknownWsInbound(payload) {
719
+ if (!payload || typeof payload !== "object") {
720
+ return null;
721
+ }
722
+ const record = payload;
723
+ // Session-wrapped messages
724
+ if (record.type === "session" && record.message && typeof record.message === "object") {
725
+ const msg = record.message;
726
+ if (typeof msg.requestId === "string") {
727
+ return {
728
+ requestId: msg.requestId,
729
+ ...(typeof msg.type === "string" ? { requestType: msg.type } : {}),
730
+ };
731
+ }
732
+ }
733
+ // Non-session messages (future-proof)
734
+ if (typeof record.requestId === "string") {
735
+ return {
736
+ requestId: record.requestId,
737
+ ...(typeof record.type === "string" ? { requestType: record.type } : {}),
738
+ };
739
+ }
740
+ return null;
741
+ }
742
+ //# sourceMappingURL=websocket-server.js.map