@clinebot/core 0.0.37 → 0.0.38

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 (617) hide show
  1. package/README.md +11 -1
  2. package/dist/ClineCore.d.ts +18 -214
  3. package/dist/account/cline-account-service.d.ts +0 -1
  4. package/dist/account/index.d.ts +0 -1
  5. package/dist/account/rpc.d.ts +0 -1
  6. package/dist/account/types.d.ts +0 -1
  7. package/dist/auth/bounded-ttl-cache.d.ts +0 -1
  8. package/dist/auth/client.d.ts +0 -1
  9. package/dist/auth/cline.d.ts +0 -5
  10. package/dist/auth/codex.d.ts +0 -1
  11. package/dist/auth/oca.d.ts +0 -1
  12. package/dist/auth/server.d.ts +0 -1
  13. package/dist/auth/types.d.ts +0 -1
  14. package/dist/auth/utils.d.ts +0 -1
  15. package/dist/cline-core/automation.d.ts +34 -0
  16. package/dist/cline-core/runtime-services.d.ts +5 -0
  17. package/dist/cline-core/start-input.d.ts +10 -0
  18. package/dist/cline-core/telemetry.d.ts +10 -0
  19. package/dist/cline-core/types.d.ts +221 -0
  20. package/dist/cron/{cron-event-ingress.d.ts → events/cron-event-ingress.d.ts} +1 -2
  21. package/dist/cron/{cron-report-writer.d.ts → reports/cron-report-writer.d.ts} +1 -2
  22. package/dist/cron/{cron-materializer.d.ts → runner/cron-materializer.d.ts} +1 -2
  23. package/dist/cron/{cron-runner.d.ts → runner/cron-runner.d.ts} +6 -4
  24. package/dist/cron/{resource-limiter.d.ts → runner/resource-limiter.d.ts} +0 -1
  25. package/dist/cron/schedule/scheduler.d.ts +12 -0
  26. package/dist/cron/{cron-service.d.ts → service/cron-service.d.ts} +4 -5
  27. package/dist/cron/{schedule-command-service.d.ts → service/schedule-command-service.d.ts} +0 -1
  28. package/dist/cron/{schedule-service.d.ts → service/schedule-service.d.ts} +20 -22
  29. package/dist/cron/{cron-reconciler.d.ts → specs/cron-reconciler.d.ts} +1 -2
  30. package/dist/cron/{cron-spec-parser.d.ts → specs/cron-spec-parser.d.ts} +0 -1
  31. package/dist/cron/{cron-watcher.d.ts → specs/cron-watcher.d.ts} +0 -1
  32. package/dist/cron/{cron-schema.d.ts → store/cron-schema.d.ts} +0 -1
  33. package/dist/cron/{sqlite-cron-store.d.ts → store/sqlite-cron-store.d.ts} +12 -2
  34. package/dist/extensions/config/index.d.ts +4 -7
  35. package/dist/extensions/config/runtime-commands.d.ts +0 -1
  36. package/dist/extensions/config/skill-frontmatter-toggle.d.ts +11 -0
  37. package/dist/extensions/config/unified-config-file-watcher.d.ts +0 -1
  38. package/dist/extensions/config/user-instruction-config-loader.d.ts +0 -1
  39. package/dist/extensions/config/user-instruction-plugin.d.ts +25 -0
  40. package/dist/extensions/config/user-instruction-service.d.ts +23 -0
  41. package/dist/extensions/context/agentic-compaction.d.ts +0 -1
  42. package/dist/extensions/context/basic-compaction.d.ts +0 -1
  43. package/dist/extensions/context/compaction-shared.d.ts +0 -1
  44. package/dist/extensions/context/compaction.d.ts +0 -1
  45. package/dist/extensions/index.d.ts +0 -1
  46. package/dist/extensions/mcp/client.d.ts +0 -1
  47. package/dist/extensions/mcp/config-loader.d.ts +0 -1
  48. package/dist/extensions/mcp/index.d.ts +0 -1
  49. package/dist/extensions/mcp/manager.d.ts +0 -1
  50. package/dist/extensions/mcp/name-transform.d.ts +0 -1
  51. package/dist/extensions/mcp/policies.d.ts +0 -1
  52. package/dist/extensions/mcp/tools.d.ts +2 -3
  53. package/dist/extensions/mcp/types.d.ts +3 -4
  54. package/dist/extensions/plugin/plugin-config-loader.d.ts +0 -1
  55. package/dist/extensions/plugin/plugin-load-report.d.ts +0 -1
  56. package/dist/extensions/plugin/plugin-loader.d.ts +0 -1
  57. package/dist/extensions/plugin/plugin-module-import.d.ts +0 -1
  58. package/dist/extensions/plugin/plugin-sandbox.d.ts +0 -1
  59. package/dist/extensions/plugin/plugin-targeting.d.ts +0 -1
  60. package/dist/extensions/plugin-sandbox-bootstrap.js +1 -446
  61. package/dist/extensions/tools/constants.d.ts +0 -1
  62. package/dist/extensions/tools/definitions.d.ts +13 -14
  63. package/dist/extensions/tools/executors/apply-patch-parser.d.ts +0 -1
  64. package/dist/extensions/tools/executors/apply-patch.d.ts +0 -1
  65. package/dist/extensions/tools/executors/bash.d.ts +0 -1
  66. package/dist/extensions/tools/executors/editor.d.ts +0 -1
  67. package/dist/extensions/tools/executors/file-read.d.ts +0 -1
  68. package/dist/extensions/tools/executors/index.d.ts +0 -1
  69. package/dist/extensions/tools/executors/search.d.ts +0 -1
  70. package/dist/extensions/tools/executors/web-fetch.d.ts +0 -1
  71. package/dist/extensions/tools/helpers.d.ts +0 -1
  72. package/dist/extensions/tools/index.d.ts +2 -3
  73. package/dist/extensions/tools/model-tool-routing.d.ts +0 -1
  74. package/dist/extensions/tools/presets.d.ts +4 -5
  75. package/dist/extensions/tools/runtime.d.ts +0 -1
  76. package/dist/extensions/tools/schemas.d.ts +0 -1
  77. package/dist/extensions/tools/team/delegated-agent.d.ts +3 -4
  78. package/dist/extensions/tools/team/index.d.ts +0 -1
  79. package/dist/extensions/tools/team/multi-agent.d.ts +1 -2
  80. package/dist/extensions/tools/team/projections.d.ts +0 -1
  81. package/dist/extensions/tools/team/runtime.d.ts +0 -1
  82. package/dist/extensions/tools/team/spawn-agent-tool.d.ts +4 -5
  83. package/dist/extensions/tools/team/subagent-prompts.d.ts +0 -1
  84. package/dist/extensions/tools/team/team-tools.d.ts +7 -8
  85. package/dist/extensions/tools/types.d.ts +11 -12
  86. package/dist/hooks/checkpoint-hooks.d.ts +9 -2
  87. package/dist/hooks/hook-extension.d.ts +2 -0
  88. package/dist/{extensions/config/hooks-config-loader.d.ts → hooks/hook-file-config.d.ts} +1 -2
  89. package/dist/hooks/hook-file-hooks.d.ts +2 -2
  90. package/dist/hooks/index.d.ts +3 -1
  91. package/dist/hooks/subprocess-runner.d.ts +0 -1
  92. package/dist/hooks/subprocess.d.ts +0 -1
  93. package/dist/hub/{connect.d.ts → client/connect.d.ts} +1 -2
  94. package/dist/hub/{client.d.ts → client/index.d.ts} +41 -4
  95. package/dist/hub/{session-client.d.ts → client/session-client.d.ts} +41 -13
  96. package/dist/hub/{ui-client.d.ts → client/ui-client.d.ts} +1 -1
  97. package/dist/hub/daemon/entry.d.ts +1 -0
  98. package/dist/hub/daemon/entry.js +720 -0
  99. package/dist/hub/{daemon.d.ts → daemon/index.d.ts} +6 -3
  100. package/dist/hub/{runtime-handlers.d.ts → daemon/runtime-handlers.d.ts} +3 -2
  101. package/dist/hub/{start-shared-server.d.ts → daemon/start-shared-server.d.ts} +1 -2
  102. package/dist/hub/{defaults.d.ts → discovery/defaults.d.ts} +0 -1
  103. package/dist/hub/{discovery.d.ts → discovery/index.d.ts} +2 -1
  104. package/dist/hub/{workspace.d.ts → discovery/workspace.d.ts} +1 -2
  105. package/dist/hub/index.d.ts +28 -11
  106. package/dist/hub/index.js +484 -1061
  107. package/dist/hub/runtime-host/hub-runtime-host.d.ts +73 -0
  108. package/dist/{transports/remote.d.ts → hub/runtime-host/remote-runtime-host.d.ts} +1 -2
  109. package/dist/hub/{browser-websocket.d.ts → server/browser-websocket.d.ts} +1 -2
  110. package/dist/hub/{transport.d.ts → server/command-transport.d.ts} +0 -1
  111. package/dist/hub/server/handlers/approval-handlers.d.ts +17 -0
  112. package/dist/hub/server/handlers/capability-handlers.d.ts +12 -0
  113. package/dist/hub/server/handlers/client-handlers.d.ts +6 -0
  114. package/dist/hub/server/handlers/context.d.ts +56 -0
  115. package/dist/hub/server/handlers/run-handlers.d.ts +5 -0
  116. package/dist/hub/server/handlers/session-event-projector.d.ts +7 -0
  117. package/dist/hub/server/handlers/session-handlers.d.ts +20 -0
  118. package/dist/hub/server/hub-client-contributions.d.ts +19 -0
  119. package/dist/hub/server/hub-notifications.d.ts +7 -0
  120. package/dist/hub/server/hub-schedule-events.d.ts +2 -0
  121. package/dist/hub/server/hub-server-logging.d.ts +2 -0
  122. package/dist/hub/server/hub-server-options.d.ts +55 -0
  123. package/dist/hub/server/hub-server-transport.d.ts +34 -0
  124. package/dist/hub/server/hub-session-records.d.ts +8 -0
  125. package/dist/hub/server/hub-websocket-server.d.ts +6 -0
  126. package/dist/hub/server/index.d.ts +4 -0
  127. package/dist/hub/{native-transport.d.ts → server/native-transport.d.ts} +1 -2
  128. package/dist/index.d.ts +51 -41
  129. package/dist/index.js +214 -872
  130. package/dist/runtime/capabilities/index.d.ts +2 -0
  131. package/dist/runtime/capabilities/normalize-runtime-capabilities.d.ts +2 -0
  132. package/dist/runtime/capabilities/runtime-capabilities.d.ts +6 -0
  133. package/dist/runtime/config/agent-message-codec.d.ts +6 -0
  134. package/dist/runtime/{agent-runtime-config-builder.d.ts → config/agent-runtime-config-builder.d.ts} +12 -21
  135. package/dist/runtime/host/history.d.ts +18 -0
  136. package/dist/runtime/{host.d.ts → host/host.d.ts} +3 -4
  137. package/dist/runtime/host/local/agent-event-bridge.d.ts +29 -0
  138. package/dist/runtime/host/local/session-record.d.ts +6 -0
  139. package/dist/runtime/host/local/session-service-invoker.d.ts +4 -0
  140. package/dist/runtime/host/local/spawn-tool.d.ts +15 -0
  141. package/dist/runtime/host/local/user-files.d.ts +1 -0
  142. package/dist/runtime/host/local-runtime-host.d.ts +118 -0
  143. package/dist/{transports → runtime/host}/runtime-host-support.d.ts +3 -5
  144. package/dist/runtime/{runtime-host.d.ts → host/runtime-host.d.ts} +66 -31
  145. package/dist/runtime/{runtime-builder.d.ts → orchestration/runtime-builder.d.ts} +0 -1
  146. package/dist/runtime/{runtime-event-adapter.d.ts → orchestration/runtime-event-adapter.d.ts} +0 -1
  147. package/dist/runtime/{runtime-oauth-token-manager.d.ts → orchestration/runtime-oauth-token-manager.d.ts} +1 -2
  148. package/dist/runtime/{session-runtime-orchestrator.d.ts → orchestration/session-runtime-orchestrator.d.ts} +20 -63
  149. package/dist/runtime/{session-runtime.d.ts → orchestration/session-runtime.d.ts} +14 -12
  150. package/dist/runtime/{user-input-builder.d.ts → orchestration/user-input-builder.d.ts} +2 -11
  151. package/dist/runtime/{loop-detection.d.ts → safety/loop-detection.d.ts} +0 -1
  152. package/dist/runtime/{mistake-tracker.d.ts → safety/mistake-tracker.d.ts} +0 -1
  153. package/dist/runtime/{rules.d.ts → safety/rules.d.ts} +1 -2
  154. package/dist/runtime/{subprocess-sandbox.d.ts → tools/subprocess-sandbox.d.ts} +15 -1
  155. package/dist/runtime/{tool-approval.d.ts → tools/tool-approval.d.ts} +0 -1
  156. package/dist/runtime/turn-queue/pending-prompt-service.d.ts +64 -0
  157. package/dist/services/agent-events.d.ts +1 -2
  158. package/dist/services/config.d.ts +0 -1
  159. package/dist/services/global-settings.d.ts +27 -5
  160. package/dist/{llms → services/llms}/cline-recommended-models.d.ts +1 -2
  161. package/dist/{llms → services/llms}/configured-provider-registry.d.ts +0 -1
  162. package/dist/services/llms/handler-factory.d.ts +3 -0
  163. package/dist/{llms → services/llms}/provider-defaults.d.ts +2 -1
  164. package/dist/{llms → services/llms}/provider-settings.d.ts +5 -3
  165. package/dist/{llms → services/llms}/runtime-config.d.ts +0 -1
  166. package/dist/{llms → services/llms}/runtime-registry.d.ts +0 -1
  167. package/dist/{llms → services/llms}/runtime-types.d.ts +0 -1
  168. package/dist/services/local-runtime-bootstrap.d.ts +7 -9
  169. package/dist/services/plugin-tools.d.ts +0 -1
  170. package/dist/services/providers/local-provider-registry.d.ts +9 -10
  171. package/dist/services/providers/local-provider-service.d.ts +36 -3
  172. package/dist/services/providers/model-source.d.ts +3 -0
  173. package/dist/services/session-artifacts.d.ts +0 -1
  174. package/dist/services/session-data.d.ts +2 -3
  175. package/dist/services/session-telemetry.d.ts +0 -1
  176. package/dist/services/storage/file-team-store.d.ts +0 -1
  177. package/dist/services/storage/provider-settings-legacy-migration.d.ts +0 -1
  178. package/dist/services/storage/provider-settings-manager.d.ts +3 -4
  179. package/dist/services/storage/sqlite-session-store.d.ts +0 -1
  180. package/dist/services/storage/sqlite-team-store.d.ts +0 -1
  181. package/dist/services/storage/team-store.d.ts +0 -1
  182. package/dist/services/telemetry/ITelemetryAdapter.d.ts +0 -1
  183. package/dist/services/telemetry/OpenTelemetryAdapter.d.ts +0 -1
  184. package/dist/services/telemetry/OpenTelemetryProvider.d.ts +32 -1
  185. package/dist/services/telemetry/TelemetryLoggerSink.d.ts +0 -1
  186. package/dist/services/telemetry/TelemetryService.d.ts +0 -1
  187. package/dist/services/telemetry/core-events.d.ts +46 -3
  188. package/dist/services/telemetry/distinct-id.d.ts +0 -1
  189. package/dist/services/telemetry/index.d.ts +1 -2
  190. package/dist/services/telemetry/index.js +1 -0
  191. package/dist/services/usage.d.ts +10 -2
  192. package/dist/services/workspace/file-indexer.d.ts +0 -1
  193. package/dist/services/workspace/index.d.ts +0 -1
  194. package/dist/services/workspace/mention-enricher.d.ts +0 -1
  195. package/dist/{session → services/workspace}/workspace-manager.d.ts +0 -1
  196. package/dist/services/{workspace-manifest.d.ts → workspace/workspace-manifest.d.ts} +20 -5
  197. package/dist/services/workspace/workspace-telemetry.d.ts +18 -0
  198. package/dist/session/checkpoint-restore.d.ts +20 -0
  199. package/dist/session/{session-graph.d.ts → models/session-graph.d.ts} +2 -3
  200. package/dist/session/{session-manifest.d.ts → models/session-manifest.d.ts} +0 -1
  201. package/dist/session/{session-row.d.ts → models/session-row.d.ts} +2 -3
  202. package/dist/session/{file-session-service.d.ts → services/file-session-service.d.ts} +1 -2
  203. package/dist/session/{message-builder.d.ts → services/message-builder.d.ts} +7 -16
  204. package/dist/session/{persistence-service.d.ts → services/persistence-service.d.ts} +10 -11
  205. package/dist/session/{session-service.d.ts → services/session-service.d.ts} +4 -5
  206. package/dist/session/session-snapshot.d.ts +57 -0
  207. package/dist/session/session-versioning-service.d.ts +48 -0
  208. package/dist/session/{conversation-store.d.ts → stores/conversation-store.d.ts} +0 -1
  209. package/dist/session/{session-manifest-store.d.ts → stores/session-manifest-store.d.ts} +3 -4
  210. package/dist/session/{team-persistence-store.d.ts → stores/team-persistence-store.d.ts} +2 -3
  211. package/dist/session/team/index.d.ts +2 -0
  212. package/dist/session/{subagent-session-manager.d.ts → team/team-child-session-manager.d.ts} +7 -8
  213. package/dist/session/{session-team-coordination.d.ts → team/team-session-coordinator.d.ts} +3 -4
  214. package/dist/settings/index.d.ts +2 -0
  215. package/dist/settings/settings-service.d.ts +6 -0
  216. package/dist/settings/types.d.ts +42 -0
  217. package/dist/types/chat-schema.d.ts +24 -7
  218. package/dist/types/common.d.ts +0 -1
  219. package/dist/types/config.d.ts +2 -3
  220. package/dist/types/events.d.ts +8 -1
  221. package/dist/types/provider-settings.d.ts +2 -3
  222. package/dist/types/session.d.ts +22 -6
  223. package/dist/types/sessions.d.ts +0 -1
  224. package/dist/types/storage.d.ts +0 -1
  225. package/dist/types.d.ts +17 -14
  226. package/dist/version.d.ts +0 -1
  227. package/package.json +16 -12
  228. package/dist/ClineCore.d.ts.map +0 -1
  229. package/dist/account/cline-account-service.d.ts.map +0 -1
  230. package/dist/account/index.d.ts.map +0 -1
  231. package/dist/account/rpc.d.ts.map +0 -1
  232. package/dist/account/types.d.ts.map +0 -1
  233. package/dist/auth/bounded-ttl-cache.d.ts.map +0 -1
  234. package/dist/auth/client.d.ts.map +0 -1
  235. package/dist/auth/cline.d.ts.map +0 -1
  236. package/dist/auth/codex.d.ts.map +0 -1
  237. package/dist/auth/oca.d.ts.map +0 -1
  238. package/dist/auth/server.d.ts.map +0 -1
  239. package/dist/auth/types.d.ts.map +0 -1
  240. package/dist/auth/utils.d.ts.map +0 -1
  241. package/dist/cron/cron-event-ingress.d.ts.map +0 -1
  242. package/dist/cron/cron-materializer.d.ts.map +0 -1
  243. package/dist/cron/cron-reconciler.d.ts.map +0 -1
  244. package/dist/cron/cron-report-writer.d.ts.map +0 -1
  245. package/dist/cron/cron-runner.d.ts.map +0 -1
  246. package/dist/cron/cron-schema.d.ts.map +0 -1
  247. package/dist/cron/cron-service.d.ts.map +0 -1
  248. package/dist/cron/cron-spec-parser.d.ts.map +0 -1
  249. package/dist/cron/cron-watcher.d.ts.map +0 -1
  250. package/dist/cron/resource-limiter.d.ts.map +0 -1
  251. package/dist/cron/schedule-command-service.d.ts.map +0 -1
  252. package/dist/cron/schedule-service.d.ts.map +0 -1
  253. package/dist/cron/scheduler.d.ts +0 -68
  254. package/dist/cron/scheduler.d.ts.map +0 -1
  255. package/dist/cron/sqlite-cron-store.d.ts.map +0 -1
  256. package/dist/cron/sqlite-schedule-store.d.ts +0 -52
  257. package/dist/cron/sqlite-schedule-store.d.ts.map +0 -1
  258. package/dist/extensions/config/agent-config-loader.d.ts +0 -20
  259. package/dist/extensions/config/agent-config-loader.d.ts.map +0 -1
  260. package/dist/extensions/config/agent-config-parser.d.ts +0 -29
  261. package/dist/extensions/config/agent-config-parser.d.ts.map +0 -1
  262. package/dist/extensions/config/hooks-config-loader.d.ts.map +0 -1
  263. package/dist/extensions/config/index.d.ts.map +0 -1
  264. package/dist/extensions/config/runtime-commands.d.ts.map +0 -1
  265. package/dist/extensions/config/unified-config-file-watcher.d.ts.map +0 -1
  266. package/dist/extensions/config/user-instruction-config-loader.d.ts.map +0 -1
  267. package/dist/extensions/context/agentic-compaction.d.ts.map +0 -1
  268. package/dist/extensions/context/basic-compaction.d.ts.map +0 -1
  269. package/dist/extensions/context/compaction-shared.d.ts.map +0 -1
  270. package/dist/extensions/context/compaction.d.ts.map +0 -1
  271. package/dist/extensions/index.d.ts.map +0 -1
  272. package/dist/extensions/mcp/client.d.ts.map +0 -1
  273. package/dist/extensions/mcp/config-loader.d.ts.map +0 -1
  274. package/dist/extensions/mcp/index.d.ts.map +0 -1
  275. package/dist/extensions/mcp/manager.d.ts.map +0 -1
  276. package/dist/extensions/mcp/name-transform.d.ts.map +0 -1
  277. package/dist/extensions/mcp/policies.d.ts.map +0 -1
  278. package/dist/extensions/mcp/tools.d.ts.map +0 -1
  279. package/dist/extensions/mcp/types.d.ts.map +0 -1
  280. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +0 -1
  281. package/dist/extensions/plugin/plugin-load-report.d.ts.map +0 -1
  282. package/dist/extensions/plugin/plugin-loader.d.ts.map +0 -1
  283. package/dist/extensions/plugin/plugin-module-import.d.ts.map +0 -1
  284. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +0 -1
  285. package/dist/extensions/plugin/plugin-targeting.d.ts.map +0 -1
  286. package/dist/extensions/tools/constants.d.ts.map +0 -1
  287. package/dist/extensions/tools/definitions.d.ts.map +0 -1
  288. package/dist/extensions/tools/executors/apply-patch-parser.d.ts.map +0 -1
  289. package/dist/extensions/tools/executors/apply-patch.d.ts.map +0 -1
  290. package/dist/extensions/tools/executors/bash.d.ts.map +0 -1
  291. package/dist/extensions/tools/executors/editor.d.ts.map +0 -1
  292. package/dist/extensions/tools/executors/file-read.d.ts.map +0 -1
  293. package/dist/extensions/tools/executors/index.d.ts.map +0 -1
  294. package/dist/extensions/tools/executors/search.d.ts.map +0 -1
  295. package/dist/extensions/tools/executors/web-fetch.d.ts.map +0 -1
  296. package/dist/extensions/tools/helpers.d.ts.map +0 -1
  297. package/dist/extensions/tools/index.d.ts.map +0 -1
  298. package/dist/extensions/tools/model-tool-routing.d.ts.map +0 -1
  299. package/dist/extensions/tools/presets.d.ts.map +0 -1
  300. package/dist/extensions/tools/runtime.d.ts.map +0 -1
  301. package/dist/extensions/tools/schemas.d.ts.map +0 -1
  302. package/dist/extensions/tools/team/delegated-agent.d.ts.map +0 -1
  303. package/dist/extensions/tools/team/index.d.ts.map +0 -1
  304. package/dist/extensions/tools/team/multi-agent.d.ts.map +0 -1
  305. package/dist/extensions/tools/team/projections.d.ts.map +0 -1
  306. package/dist/extensions/tools/team/runtime.d.ts.map +0 -1
  307. package/dist/extensions/tools/team/spawn-agent-tool.d.ts.map +0 -1
  308. package/dist/extensions/tools/team/subagent-prompts.d.ts.map +0 -1
  309. package/dist/extensions/tools/team/team-tools.d.ts.map +0 -1
  310. package/dist/extensions/tools/types.d.ts.map +0 -1
  311. package/dist/hooks/checkpoint-hooks.d.ts.map +0 -1
  312. package/dist/hooks/hook-bridge.d.ts +0 -118
  313. package/dist/hooks/hook-bridge.d.ts.map +0 -1
  314. package/dist/hooks/hook-file-hooks.d.ts.map +0 -1
  315. package/dist/hooks/hook-registry.d.ts +0 -16
  316. package/dist/hooks/hook-registry.d.ts.map +0 -1
  317. package/dist/hooks/index.d.ts.map +0 -1
  318. package/dist/hooks/subprocess-runner.d.ts.map +0 -1
  319. package/dist/hooks/subprocess.d.ts.map +0 -1
  320. package/dist/hub/browser-websocket.d.ts.map +0 -1
  321. package/dist/hub/client.d.ts.map +0 -1
  322. package/dist/hub/connect.d.ts.map +0 -1
  323. package/dist/hub/daemon-entry.d.ts +0 -2
  324. package/dist/hub/daemon-entry.d.ts.map +0 -1
  325. package/dist/hub/daemon-entry.js +0 -1305
  326. package/dist/hub/daemon.d.ts.map +0 -1
  327. package/dist/hub/defaults.d.ts.map +0 -1
  328. package/dist/hub/discovery.d.ts.map +0 -1
  329. package/dist/hub/index.d.ts.map +0 -1
  330. package/dist/hub/native-transport.d.ts.map +0 -1
  331. package/dist/hub/runtime-handlers.d.ts.map +0 -1
  332. package/dist/hub/server.d.ts +0 -104
  333. package/dist/hub/server.d.ts.map +0 -1
  334. package/dist/hub/session-client.d.ts.map +0 -1
  335. package/dist/hub/start-shared-server.d.ts.map +0 -1
  336. package/dist/hub/transport.d.ts.map +0 -1
  337. package/dist/hub/ui-client.d.ts.map +0 -1
  338. package/dist/hub/workspace.d.ts.map +0 -1
  339. package/dist/index.d.ts.map +0 -1
  340. package/dist/llms/cline-recommended-models.d.ts.map +0 -1
  341. package/dist/llms/configured-provider-registry.d.ts.map +0 -1
  342. package/dist/llms/handler-factory.d.ts +0 -16
  343. package/dist/llms/handler-factory.d.ts.map +0 -1
  344. package/dist/llms/provider-defaults.d.ts.map +0 -1
  345. package/dist/llms/provider-settings.d.ts.map +0 -1
  346. package/dist/llms/runtime-config.d.ts.map +0 -1
  347. package/dist/llms/runtime-registry.d.ts.map +0 -1
  348. package/dist/llms/runtime-types.d.ts.map +0 -1
  349. package/dist/runtime/agent-config-adapter.d.ts +0 -148
  350. package/dist/runtime/agent-config-adapter.d.ts.map +0 -1
  351. package/dist/runtime/agent-runtime-config-builder.d.ts.map +0 -1
  352. package/dist/runtime/history.d.ts +0 -10
  353. package/dist/runtime/history.d.ts.map +0 -1
  354. package/dist/runtime/host.d.ts.map +0 -1
  355. package/dist/runtime/loop-detection.d.ts.map +0 -1
  356. package/dist/runtime/mistake-tracker.d.ts.map +0 -1
  357. package/dist/runtime/rules.d.ts.map +0 -1
  358. package/dist/runtime/runtime-builder.d.ts.map +0 -1
  359. package/dist/runtime/runtime-event-adapter.d.ts.map +0 -1
  360. package/dist/runtime/runtime-host.d.ts.map +0 -1
  361. package/dist/runtime/runtime-oauth-token-manager.d.ts.map +0 -1
  362. package/dist/runtime/session-runtime-orchestrator.d.ts.map +0 -1
  363. package/dist/runtime/session-runtime.d.ts.map +0 -1
  364. package/dist/runtime/subprocess-sandbox.d.ts.map +0 -1
  365. package/dist/runtime/tool-approval.d.ts.map +0 -1
  366. package/dist/runtime/user-input-builder.d.ts.map +0 -1
  367. package/dist/services/agent-events.d.ts.map +0 -1
  368. package/dist/services/config.d.ts.map +0 -1
  369. package/dist/services/global-settings.d.ts.map +0 -1
  370. package/dist/services/index.js +0 -28
  371. package/dist/services/local-runtime-bootstrap.d.ts.map +0 -1
  372. package/dist/services/plugin-tools.d.ts.map +0 -1
  373. package/dist/services/providers/local-provider-registry.d.ts.map +0 -1
  374. package/dist/services/providers/local-provider-service.d.ts.map +0 -1
  375. package/dist/services/session-artifacts.d.ts.map +0 -1
  376. package/dist/services/session-data.d.ts.map +0 -1
  377. package/dist/services/session-telemetry.d.ts.map +0 -1
  378. package/dist/services/storage/file-team-store.d.ts.map +0 -1
  379. package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +0 -1
  380. package/dist/services/storage/provider-settings-manager.d.ts.map +0 -1
  381. package/dist/services/storage/sqlite-session-store.d.ts.map +0 -1
  382. package/dist/services/storage/sqlite-team-store.d.ts.map +0 -1
  383. package/dist/services/storage/team-store.d.ts.map +0 -1
  384. package/dist/services/telemetry/ITelemetryAdapter.d.ts.map +0 -1
  385. package/dist/services/telemetry/OpenTelemetryAdapter.d.ts.map +0 -1
  386. package/dist/services/telemetry/OpenTelemetryProvider.d.ts.map +0 -1
  387. package/dist/services/telemetry/TelemetryLoggerSink.d.ts.map +0 -1
  388. package/dist/services/telemetry/TelemetryService.d.ts.map +0 -1
  389. package/dist/services/telemetry/core-events.d.ts.map +0 -1
  390. package/dist/services/telemetry/distinct-id.d.ts.map +0 -1
  391. package/dist/services/telemetry/index.d.ts.map +0 -1
  392. package/dist/services/usage.d.ts.map +0 -1
  393. package/dist/services/workspace/file-indexer.d.ts.map +0 -1
  394. package/dist/services/workspace/index.d.ts.map +0 -1
  395. package/dist/services/workspace/mention-enricher.d.ts.map +0 -1
  396. package/dist/services/workspace-manifest.d.ts.map +0 -1
  397. package/dist/session/conversation-store.d.ts.map +0 -1
  398. package/dist/session/file-session-service.d.ts.map +0 -1
  399. package/dist/session/message-builder.d.ts.map +0 -1
  400. package/dist/session/persistence-service.d.ts.map +0 -1
  401. package/dist/session/session-graph.d.ts.map +0 -1
  402. package/dist/session/session-manifest-store.d.ts.map +0 -1
  403. package/dist/session/session-manifest.d.ts.map +0 -1
  404. package/dist/session/session-row.d.ts.map +0 -1
  405. package/dist/session/session-service.d.ts.map +0 -1
  406. package/dist/session/session-team-coordination.d.ts.map +0 -1
  407. package/dist/session/subagent-session-manager.d.ts.map +0 -1
  408. package/dist/session/team-persistence-store.d.ts.map +0 -1
  409. package/dist/session/workspace-manager.d.ts.map +0 -1
  410. package/dist/transports/hub.d.ts +0 -58
  411. package/dist/transports/hub.d.ts.map +0 -1
  412. package/dist/transports/local.d.ts +0 -119
  413. package/dist/transports/local.d.ts.map +0 -1
  414. package/dist/transports/remote.d.ts.map +0 -1
  415. package/dist/transports/runtime-host-support.d.ts.map +0 -1
  416. package/dist/types/chat-schema.d.ts.map +0 -1
  417. package/dist/types/common.d.ts.map +0 -1
  418. package/dist/types/config.d.ts.map +0 -1
  419. package/dist/types/events.d.ts.map +0 -1
  420. package/dist/types/provider-settings.d.ts.map +0 -1
  421. package/dist/types/session.d.ts.map +0 -1
  422. package/dist/types/sessions.d.ts.map +0 -1
  423. package/dist/types/storage.d.ts.map +0 -1
  424. package/dist/types.d.ts.map +0 -1
  425. package/dist/version.d.ts.map +0 -1
  426. package/src/ClineCore.ts +0 -1026
  427. package/src/account/cline-account-service.ts +0 -338
  428. package/src/account/index.ts +0 -24
  429. package/src/account/rpc.ts +0 -185
  430. package/src/account/types.ts +0 -108
  431. package/src/auth/bounded-ttl-cache.ts +0 -53
  432. package/src/auth/client.ts +0 -46
  433. package/src/auth/cline.ts +0 -724
  434. package/src/auth/codex.ts +0 -491
  435. package/src/auth/oca.ts +0 -588
  436. package/src/auth/server.ts +0 -265
  437. package/src/auth/types.ts +0 -110
  438. package/src/auth/utils.ts +0 -247
  439. package/src/cron/cron-event-ingress.ts +0 -357
  440. package/src/cron/cron-materializer.ts +0 -97
  441. package/src/cron/cron-reconciler.ts +0 -241
  442. package/src/cron/cron-report-writer.ts +0 -153
  443. package/src/cron/cron-runner.ts +0 -495
  444. package/src/cron/cron-schema.ts +0 -127
  445. package/src/cron/cron-service.ts +0 -163
  446. package/src/cron/cron-spec-parser.ts +0 -489
  447. package/src/cron/cron-watcher.ts +0 -102
  448. package/src/cron/index.ts +0 -15
  449. package/src/cron/resource-limiter.ts +0 -46
  450. package/src/cron/schedule-command-service.ts +0 -193
  451. package/src/cron/schedule-service.ts +0 -703
  452. package/src/cron/scheduler.ts +0 -772
  453. package/src/cron/sqlite-cron-store.ts +0 -1286
  454. package/src/cron/sqlite-schedule-store.ts +0 -708
  455. package/src/extensions/config/agent-config-loader.ts +0 -114
  456. package/src/extensions/config/agent-config-parser.ts +0 -198
  457. package/src/extensions/config/hooks-config-loader.ts +0 -117
  458. package/src/extensions/config/index.ts +0 -77
  459. package/src/extensions/config/runtime-commands.ts +0 -82
  460. package/src/extensions/config/unified-config-file-watcher.ts +0 -496
  461. package/src/extensions/config/user-instruction-config-loader.ts +0 -549
  462. package/src/extensions/context/agentic-compaction.ts +0 -131
  463. package/src/extensions/context/basic-compaction.ts +0 -300
  464. package/src/extensions/context/compaction-shared.ts +0 -459
  465. package/src/extensions/context/compaction.ts +0 -226
  466. package/src/extensions/index.ts +0 -18
  467. package/src/extensions/mcp/client.ts +0 -420
  468. package/src/extensions/mcp/config-loader.ts +0 -219
  469. package/src/extensions/mcp/index.ts +0 -42
  470. package/src/extensions/mcp/manager.ts +0 -260
  471. package/src/extensions/mcp/name-transform.ts +0 -33
  472. package/src/extensions/mcp/policies.ts +0 -47
  473. package/src/extensions/mcp/tools.ts +0 -47
  474. package/src/extensions/mcp/types.ts +0 -116
  475. package/src/extensions/plugin/plugin-config-loader.ts +0 -140
  476. package/src/extensions/plugin/plugin-load-report.ts +0 -20
  477. package/src/extensions/plugin/plugin-loader.ts +0 -220
  478. package/src/extensions/plugin/plugin-module-import.ts +0 -276
  479. package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +0 -662
  480. package/src/extensions/plugin/plugin-sandbox.ts +0 -586
  481. package/src/extensions/plugin/plugin-targeting.ts +0 -32
  482. package/src/extensions/tools/constants.ts +0 -37
  483. package/src/extensions/tools/definitions.ts +0 -738
  484. package/src/extensions/tools/executors/apply-patch-parser.ts +0 -520
  485. package/src/extensions/tools/executors/apply-patch.ts +0 -348
  486. package/src/extensions/tools/executors/bash.ts +0 -207
  487. package/src/extensions/tools/executors/editor.ts +0 -220
  488. package/src/extensions/tools/executors/file-read.ts +0 -135
  489. package/src/extensions/tools/executors/index.ts +0 -87
  490. package/src/extensions/tools/executors/search.ts +0 -470
  491. package/src/extensions/tools/executors/web-fetch.ts +0 -259
  492. package/src/extensions/tools/helpers.ts +0 -154
  493. package/src/extensions/tools/index.ts +0 -183
  494. package/src/extensions/tools/model-tool-routing.ts +0 -134
  495. package/src/extensions/tools/presets.ts +0 -190
  496. package/src/extensions/tools/runtime.ts +0 -261
  497. package/src/extensions/tools/schemas.ts +0 -343
  498. package/src/extensions/tools/team/delegated-agent.ts +0 -136
  499. package/src/extensions/tools/team/index.ts +0 -5
  500. package/src/extensions/tools/team/multi-agent.ts +0 -1845
  501. package/src/extensions/tools/team/projections.ts +0 -283
  502. package/src/extensions/tools/team/runtime.ts +0 -54
  503. package/src/extensions/tools/team/spawn-agent-tool.ts +0 -201
  504. package/src/extensions/tools/team/subagent-prompts.ts +0 -41
  505. package/src/extensions/tools/team/team-tools.ts +0 -902
  506. package/src/extensions/tools/types.ts +0 -354
  507. package/src/hooks/checkpoint-hooks.ts +0 -238
  508. package/src/hooks/hook-bridge.ts +0 -489
  509. package/src/hooks/hook-file-hooks.ts +0 -934
  510. package/src/hooks/hook-registry.ts +0 -257
  511. package/src/hooks/index.ts +0 -18
  512. package/src/hooks/subprocess-runner.ts +0 -196
  513. package/src/hooks/subprocess.ts +0 -469
  514. package/src/hub/browser-websocket.ts +0 -159
  515. package/src/hub/client.ts +0 -633
  516. package/src/hub/connect.ts +0 -156
  517. package/src/hub/daemon-entry.ts +0 -122
  518. package/src/hub/daemon.ts +0 -284
  519. package/src/hub/defaults.ts +0 -70
  520. package/src/hub/discovery.ts +0 -247
  521. package/src/hub/index.ts +0 -14
  522. package/src/hub/native-transport.ts +0 -31
  523. package/src/hub/runtime-handlers.ts +0 -141
  524. package/src/hub/server.ts +0 -2317
  525. package/src/hub/session-client.ts +0 -502
  526. package/src/hub/start-shared-server.ts +0 -61
  527. package/src/hub/transport.ts +0 -14
  528. package/src/hub/ui-client.ts +0 -126
  529. package/src/hub/workspace.ts +0 -19
  530. package/src/index.ts +0 -688
  531. package/src/llms/cline-recommended-models.ts +0 -167
  532. package/src/llms/configured-provider-registry.ts +0 -193
  533. package/src/llms/handler-factory.ts +0 -56
  534. package/src/llms/provider-defaults.ts +0 -653
  535. package/src/llms/provider-settings.ts +0 -310
  536. package/src/llms/runtime-config.ts +0 -43
  537. package/src/llms/runtime-registry.ts +0 -172
  538. package/src/llms/runtime-types.ts +0 -121
  539. package/src/runtime/agent-config-adapter.ts +0 -636
  540. package/src/runtime/agent-runtime-config-builder.ts +0 -205
  541. package/src/runtime/error-feedback.ts +0 -142
  542. package/src/runtime/history.ts +0 -374
  543. package/src/runtime/host.ts +0 -222
  544. package/src/runtime/index.ts +0 -23
  545. package/src/runtime/loop-detection.ts +0 -162
  546. package/src/runtime/mistake-tracker.ts +0 -221
  547. package/src/runtime/rules.ts +0 -49
  548. package/src/runtime/runtime-builder.ts +0 -814
  549. package/src/runtime/runtime-event-adapter.ts +0 -412
  550. package/src/runtime/runtime-host.ts +0 -250
  551. package/src/runtime/runtime-oauth-token-manager.ts +0 -268
  552. package/src/runtime/session-runtime-orchestrator.ts +0 -1253
  553. package/src/runtime/session-runtime.ts +0 -69
  554. package/src/runtime/subprocess-sandbox.ts +0 -255
  555. package/src/runtime/tool-approval.ts +0 -102
  556. package/src/runtime/user-input-builder.ts +0 -167
  557. package/src/services/agent-events.ts +0 -256
  558. package/src/services/config.ts +0 -5
  559. package/src/services/global-settings.ts +0 -122
  560. package/src/services/local-runtime-bootstrap.ts +0 -424
  561. package/src/services/plugin-tools.ts +0 -86
  562. package/src/services/providers/local-provider-registry.ts +0 -456
  563. package/src/services/providers/local-provider-service.ts +0 -772
  564. package/src/services/session-artifacts.ts +0 -138
  565. package/src/services/session-data.ts +0 -398
  566. package/src/services/session-telemetry.ts +0 -89
  567. package/src/services/storage/artifact-store.ts +0 -1
  568. package/src/services/storage/file-team-store.ts +0 -250
  569. package/src/services/storage/index.ts +0 -11
  570. package/src/services/storage/provider-settings-legacy-migration.ts +0 -789
  571. package/src/services/storage/provider-settings-manager.ts +0 -167
  572. package/src/services/storage/session-store.ts +0 -1
  573. package/src/services/storage/sqlite-session-store.ts +0 -270
  574. package/src/services/storage/sqlite-team-store.ts +0 -537
  575. package/src/services/storage/team-store.ts +0 -36
  576. package/src/services/telemetry/ITelemetryAdapter.ts +0 -94
  577. package/src/services/telemetry/OpenTelemetryAdapter.ts +0 -348
  578. package/src/services/telemetry/OpenTelemetryProvider.ts +0 -415
  579. package/src/services/telemetry/TelemetryLoggerSink.ts +0 -121
  580. package/src/services/telemetry/TelemetryService.ts +0 -139
  581. package/src/services/telemetry/core-events.ts +0 -400
  582. package/src/services/telemetry/distinct-id.ts +0 -58
  583. package/src/services/telemetry/index.ts +0 -20
  584. package/src/services/usage.ts +0 -32
  585. package/src/services/workspace/file-indexer.ts +0 -351
  586. package/src/services/workspace/index.ts +0 -7
  587. package/src/services/workspace/mention-enricher.ts +0 -122
  588. package/src/services/workspace-manifest.ts +0 -72
  589. package/src/session/conversation-store.ts +0 -77
  590. package/src/session/file-session-service.ts +0 -282
  591. package/src/session/index.ts +0 -32
  592. package/src/session/message-builder.ts +0 -941
  593. package/src/session/persistence-service.ts +0 -559
  594. package/src/session/session-graph.ts +0 -92
  595. package/src/session/session-manifest-store.ts +0 -158
  596. package/src/session/session-manifest.ts +0 -29
  597. package/src/session/session-row.ts +0 -199
  598. package/src/session/session-service.ts +0 -324
  599. package/src/session/session-team-coordination.ts +0 -240
  600. package/src/session/subagent-session-manager.ts +0 -397
  601. package/src/session/team-persistence-store.ts +0 -176
  602. package/src/session/workspace-manager.ts +0 -100
  603. package/src/transports/hub.ts +0 -1081
  604. package/src/transports/local.ts +0 -1826
  605. package/src/transports/remote.ts +0 -27
  606. package/src/transports/runtime-host-support.ts +0 -140
  607. package/src/types/chat-schema.ts +0 -81
  608. package/src/types/common.ts +0 -26
  609. package/src/types/config.ts +0 -220
  610. package/src/types/events.ts +0 -80
  611. package/src/types/index.ts +0 -26
  612. package/src/types/provider-settings.ts +0 -54
  613. package/src/types/session.ts +0 -111
  614. package/src/types/sessions.ts +0 -37
  615. package/src/types/storage.ts +0 -56
  616. package/src/types.ts +0 -167
  617. package/src/version.ts +0 -3
package/src/hub/server.ts DELETED
@@ -1,2317 +0,0 @@
1
- import http from "node:http";
2
- import { URL } from "node:url";
3
- import type {
4
- HubClientRecord,
5
- HubClientRegistration,
6
- HubCommandEnvelope,
7
- HubEventEnvelope,
8
- HubReplyEnvelope,
9
- SessionRecord as HubSessionRecord,
10
- HubToolExecutorName,
11
- JsonValue,
12
- RuntimeConfigExtensionKind,
13
- SessionParticipant,
14
- TeamProgressProjectionEvent,
15
- ToolApprovalRequest,
16
- ToolContext,
17
- } from "@clinebot/shared";
18
- import { createSessionId } from "@clinebot/shared";
19
- import { WebSocketServer } from "ws";
20
- import { CronService, type CronServiceOptions } from "../cron/cron-service";
21
- import { HubScheduleCommandService } from "../cron/schedule-command-service";
22
- import {
23
- type HubScheduleRuntimeHandlers,
24
- HubScheduleService,
25
- type HubScheduleServiceOptions,
26
- } from "../cron/schedule-service";
27
- import type { ToolExecutors } from "../extensions/tools";
28
- import { parseHookEventPayload } from "../hooks";
29
- import type {
30
- RuntimeHost,
31
- RuntimeSessionConfig,
32
- } from "../runtime/runtime-host";
33
- import { SqliteSessionStore } from "../services/storage/sqlite-session-store";
34
- import { CoreSessionService } from "../session/session-service";
35
- import { LocalRuntimeHost } from "../transports/local";
36
- import { readPersistedMessagesFile } from "../transports/runtime-host-support";
37
- import type { CoreSessionEvent, SessionPendingPrompt } from "../types/events";
38
- import type { SessionRecord as LocalSessionRecord } from "../types/sessions";
39
- import { BrowserWebSocketHubAdapter } from "./browser-websocket";
40
- import { verifyHubConnection } from "./client";
41
- import { resolveDefaultHubPort } from "./defaults";
42
- import {
43
- clearHubDiscovery,
44
- createHubServerUrl,
45
- type HubOwnerContext,
46
- type HubServerDiscoveryRecord,
47
- probeHubServer,
48
- readHubDiscovery,
49
- resolveHubBuildId,
50
- resolveHubOwnerContext,
51
- withHubStartupLock,
52
- writeHubDiscovery,
53
- } from "./discovery";
54
- import {
55
- type NativeHubTransport,
56
- NativeHubTransportAdapter,
57
- } from "./native-transport";
58
-
59
- type NodeWebSocketLike = {
60
- send(data: string): void;
61
- on(event: "message", listener: (data: unknown) => void): void;
62
- on(event: "close", listener: () => void): void;
63
- once(event: "close", listener: () => void): void;
64
- };
65
-
66
- type NodeUpgradeSocketLike = {
67
- destroy(error?: Error): void;
68
- write(chunk: string): boolean;
69
- end(): void;
70
- };
71
-
72
- type HubSessionState = {
73
- createdByClientId: string;
74
- interactive: boolean;
75
- participants: Map<string, SessionParticipant>;
76
- };
77
-
78
- function decodeSocketData(data: unknown): string {
79
- if (typeof data === "string") {
80
- return data;
81
- }
82
- if (data instanceof Uint8Array) {
83
- return Buffer.from(data).toString();
84
- }
85
- if (data instanceof ArrayBuffer) {
86
- return Buffer.from(data).toString();
87
- }
88
- if (Array.isArray(data)) {
89
- return Buffer.concat(data.map((chunk) => Buffer.from(chunk))).toString();
90
- }
91
- return String(data);
92
- }
93
-
94
- function wrapWsSocket(socket: NodeWebSocketLike) {
95
- return {
96
- send(data: string): void {
97
- socket.send(data);
98
- },
99
- addEventListener(
100
- type: "message" | "close",
101
- listener: (...args: never[]) => void,
102
- ): void {
103
- if (type === "message") {
104
- socket.on("message", (data: unknown) => {
105
- (listener as (event: { data: string }) => void)({
106
- data: decodeSocketData(data),
107
- });
108
- });
109
- return;
110
- }
111
- socket.on("close", listener as () => void);
112
- },
113
- removeEventListener(): void {},
114
- };
115
- }
116
-
117
- const RUNTIME_CONFIG_EXTENSION_KINDS = new Set<RuntimeConfigExtensionKind>([
118
- "rules",
119
- "skills",
120
- "plugins",
121
- ]);
122
-
123
- function parseRuntimeConfigExtensions(
124
- value: unknown,
125
- ): RuntimeConfigExtensionKind[] | undefined {
126
- if (!Array.isArray(value)) {
127
- return undefined;
128
- }
129
- const extensions = value
130
- .map((item) => (typeof item === "string" ? item.trim() : ""))
131
- .filter((item): item is RuntimeConfigExtensionKind =>
132
- RUNTIME_CONFIG_EXTENSION_KINDS.has(item as RuntimeConfigExtensionKind),
133
- );
134
- return [...new Set(extensions)];
135
- }
136
-
137
- function rejectUpgradeSocket(socket: NodeUpgradeSocketLike): void {
138
- try {
139
- socket.write(
140
- "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
141
- );
142
- socket.end();
143
- } catch {
144
- socket.destroy();
145
- }
146
- }
147
-
148
- function formatHubUptime(ms: number): string {
149
- const totalSeconds = Math.max(0, Math.floor(ms / 1000));
150
- const days = Math.floor(totalSeconds / 86_400);
151
- const hours = Math.floor((totalSeconds % 86_400) / 3_600);
152
- const minutes = Math.floor((totalSeconds % 3_600) / 60);
153
- const seconds = totalSeconds % 60;
154
- if (days > 0) {
155
- return `${days}d ${hours}h`;
156
- }
157
- if (hours > 0) {
158
- return `${hours}h ${minutes}m`;
159
- }
160
- if (minutes > 0) {
161
- return `${minutes}m ${seconds}s`;
162
- }
163
- return `${seconds}s`;
164
- }
165
-
166
- function mapLocalStatusToHubStatus(
167
- status: LocalSessionRecord["status"],
168
- ): HubSessionRecord["status"] {
169
- switch (status) {
170
- case "completed":
171
- return "completed";
172
- case "failed":
173
- return "failed";
174
- case "cancelled":
175
- return "aborted";
176
- default:
177
- return "running";
178
- }
179
- }
180
-
181
- function cloneSessionMetadata(
182
- session: LocalSessionRecord,
183
- ): Record<string, JsonValue | undefined> | undefined {
184
- const metadata =
185
- session.metadata && typeof session.metadata === "object"
186
- ? (JSON.parse(JSON.stringify(session.metadata)) as Record<
187
- string,
188
- JsonValue | undefined
189
- >)
190
- : ({} as Record<string, JsonValue | undefined>);
191
- if (session.parentSessionId?.trim())
192
- metadata.parentSessionId = session.parentSessionId;
193
- if (session.parentAgentId?.trim())
194
- metadata.parentAgentId = session.parentAgentId;
195
- if (session.agentId?.trim()) metadata.agentId = session.agentId;
196
- if (session.conversationId?.trim())
197
- metadata.conversationId = session.conversationId;
198
- if (session.messagesPath?.trim())
199
- metadata.messagesPath = session.messagesPath;
200
- if (session.prompt?.trim()) metadata.prompt = session.prompt;
201
- if (session.provider?.trim()) metadata.provider = session.provider;
202
- if (session.model?.trim()) metadata.model = session.model;
203
- if (session.source?.trim()) metadata.source = session.source;
204
- if (typeof session.pid === "number") metadata.pid = session.pid;
205
- return Object.keys(metadata).length > 0 ? metadata : undefined;
206
- }
207
-
208
- function toHubSessionRecord(
209
- session: LocalSessionRecord,
210
- state?: HubSessionState,
211
- ): HubSessionRecord {
212
- return {
213
- sessionId: session.sessionId,
214
- workspaceRoot: session.workspaceRoot,
215
- cwd: session.cwd,
216
- createdAt: Date.parse(session.startedAt),
217
- updatedAt: Date.parse(session.updatedAt),
218
- createdByClientId: state?.createdByClientId ?? "hub",
219
- status: mapLocalStatusToHubStatus(session.status),
220
- participants: state ? [...state.participants.values()] : [],
221
- metadata: cloneSessionMetadata(session),
222
- runtimeOptions: {
223
- enableTools: session.enableTools,
224
- enableSpawn: session.enableSpawn,
225
- enableTeams: session.enableTeams,
226
- mode:
227
- typeof session.metadata?.mode === "string"
228
- ? (session.metadata.mode as "act" | "plan" | "yolo")
229
- : undefined,
230
- systemPrompt:
231
- typeof session.metadata?.systemPrompt === "string"
232
- ? session.metadata.systemPrompt
233
- : undefined,
234
- },
235
- runtimeSession: session.agentId
236
- ? {
237
- agentId: session.agentId,
238
- team: session.teamName ? { teamId: session.teamName } : undefined,
239
- }
240
- : undefined,
241
- };
242
- }
243
-
244
- function eventNameForScheduleCommand(
245
- command: HubCommandEnvelope["command"],
246
- ): HubEventEnvelope["event"] | undefined {
247
- switch (command) {
248
- case "schedule.create":
249
- return "schedule.created";
250
- case "schedule.update":
251
- case "schedule.enable":
252
- case "schedule.disable":
253
- return "schedule.updated";
254
- case "schedule.delete":
255
- return "schedule.deleted";
256
- case "schedule.trigger":
257
- return "schedule.triggered";
258
- default:
259
- return undefined;
260
- }
261
- }
262
-
263
- function extractAssistantText(content: unknown): string | undefined {
264
- if (typeof content === "string") {
265
- const trimmed = content.trim();
266
- return trimmed || undefined;
267
- }
268
- if (!Array.isArray(content)) {
269
- return undefined;
270
- }
271
- const text = content
272
- .map((part) => {
273
- if (
274
- part &&
275
- typeof part === "object" &&
276
- "type" in part &&
277
- (part as { type?: unknown }).type === "text" &&
278
- "text" in part &&
279
- typeof (part as { text?: unknown }).text === "string"
280
- ) {
281
- return (part as { text: string }).text.trim();
282
- }
283
- return "";
284
- })
285
- .filter(Boolean)
286
- .join("\n")
287
- .trim();
288
- return text || undefined;
289
- }
290
-
291
- const MAX_NOTIFICATION_BODY_BYTES = 120;
292
- const NOTIFICATION_BODY_ELLIPSIS = "...";
293
-
294
- export function truncateNotificationBody(value: string): string {
295
- const trimmed = value.trim();
296
- if (!trimmed) {
297
- return "";
298
- }
299
- if (Buffer.byteLength(trimmed, "utf8") <= MAX_NOTIFICATION_BODY_BYTES) {
300
- return trimmed;
301
- }
302
- const budget =
303
- MAX_NOTIFICATION_BODY_BYTES -
304
- Buffer.byteLength(NOTIFICATION_BODY_ELLIPSIS, "utf8");
305
- if (budget <= 0) {
306
- return NOTIFICATION_BODY_ELLIPSIS;
307
- }
308
- let truncated = "";
309
- for (const char of trimmed) {
310
- if (Buffer.byteLength(truncated + char, "utf8") > budget) {
311
- break;
312
- }
313
- truncated += char;
314
- }
315
- return `${truncated}${NOTIFICATION_BODY_ELLIPSIS}`;
316
- }
317
-
318
- async function buildCompletionNotification(
319
- session: HubSessionRecord | undefined,
320
- ): Promise<{
321
- title: string;
322
- body: string;
323
- severity: "info";
324
- }> {
325
- const sessionId = session?.sessionId?.trim() || "unknown";
326
- const messagesPath =
327
- typeof session?.metadata?.messagesPath === "string"
328
- ? session.metadata.messagesPath
329
- : undefined;
330
- const messages = await readPersistedMessagesFile(messagesPath);
331
- const latestAssistantText = [...messages]
332
- .reverse()
333
- .find((message) => message.role === "assistant");
334
- const assistantReply = latestAssistantText
335
- ? extractAssistantText(latestAssistantText.content)
336
- : undefined;
337
- const workspaceRoot = session?.workspaceRoot?.trim() || "workspace";
338
- const fallback =
339
- typeof session?.metadata?.prompt === "string"
340
- ? session.metadata.prompt.trim()
341
- : workspaceRoot;
342
- return {
343
- title: `Task completed (${sessionId})`,
344
- body: truncateNotificationBody(
345
- assistantReply && assistantReply.length > 0
346
- ? assistantReply
347
- : fallback.length > 0
348
- ? fallback
349
- : workspaceRoot,
350
- ),
351
- severity: "info",
352
- };
353
- }
354
-
355
- function isHubToolExecutorName(value: unknown): value is HubToolExecutorName {
356
- return (
357
- value === "readFile" ||
358
- value === "search" ||
359
- value === "bash" ||
360
- value === "webFetch" ||
361
- value === "editor" ||
362
- value === "applyPatch" ||
363
- value === "skills" ||
364
- value === "askQuestion" ||
365
- value === "submit"
366
- );
367
- }
368
-
369
- function formatHubStartupError(
370
- error: unknown,
371
- context: {
372
- host: string;
373
- port: number;
374
- pathname: string;
375
- },
376
- ): Error {
377
- const code =
378
- error &&
379
- typeof error === "object" &&
380
- "code" in error &&
381
- typeof (error as { code?: unknown }).code === "string"
382
- ? (error as { code: string }).code
383
- : undefined;
384
- const message =
385
- error instanceof Error
386
- ? error.message
387
- : typeof error === "string"
388
- ? error
389
- : "Unknown startup error";
390
- const details = `Failed to start hub server on ${context.host}:${context.port}${context.pathname}: ${message}`;
391
- const wrapped = new Error(code ? `${details} (${code})` : details);
392
- if (code) {
393
- (error as Error & { code?: string }).code = code;
394
- (wrapped as Error & { code?: string }).code = code;
395
- }
396
- if (error instanceof Error && error.stack) {
397
- wrapped.stack = `${wrapped.name}: ${wrapped.message}\nCaused by: ${error.stack}`;
398
- }
399
- return wrapped;
400
- }
401
-
402
- function isAddressInUseError(error: unknown): boolean {
403
- return (
404
- error instanceof Error &&
405
- "code" in error &&
406
- (error as Error & { code?: string }).code === "EADDRINUSE"
407
- );
408
- }
409
-
410
- function serializeToolContext(context: ToolContext): Record<string, unknown> {
411
- return {
412
- agentId: context.agentId,
413
- conversationId: context.conversationId,
414
- iteration: context.iteration,
415
- metadata: context.metadata,
416
- };
417
- }
418
-
419
- function createCapabilityBackedToolExecutors(
420
- targetClientId: string,
421
- executors: HubToolExecutorName[],
422
- requestCapability: (
423
- sessionId: string,
424
- capabilityName: string,
425
- payload: Record<string, unknown>,
426
- targetClientId: string,
427
- ) => Promise<Record<string, unknown> | undefined>,
428
- ): Partial<ToolExecutors> {
429
- const available = new Set(executors);
430
- const invoke = async (
431
- executor: HubToolExecutorName,
432
- args: unknown[],
433
- context: ToolContext,
434
- ): Promise<unknown> => {
435
- const response = await requestCapability(
436
- context.conversationId,
437
- `tool_executor.${executor}`,
438
- {
439
- executor,
440
- args,
441
- context: serializeToolContext(context),
442
- },
443
- targetClientId,
444
- );
445
- return response?.result;
446
- };
447
-
448
- return {
449
- ...(available.has("readFile")
450
- ? {
451
- readFile: async (request, context) =>
452
- (await invoke("readFile", [request], context)) as Awaited<
453
- ReturnType<NonNullable<ToolExecutors["readFile"]>>
454
- >,
455
- }
456
- : {}),
457
- ...(available.has("search")
458
- ? {
459
- search: async (query, cwd, context) =>
460
- String((await invoke("search", [query, cwd], context)) ?? ""),
461
- }
462
- : {}),
463
- ...(available.has("bash")
464
- ? {
465
- bash: async (command, cwd, context) =>
466
- String((await invoke("bash", [command, cwd], context)) ?? ""),
467
- }
468
- : {}),
469
- ...(available.has("webFetch")
470
- ? {
471
- webFetch: async (url, prompt, context) =>
472
- String((await invoke("webFetch", [url, prompt], context)) ?? ""),
473
- }
474
- : {}),
475
- ...(available.has("editor")
476
- ? {
477
- editor: async (input, cwd, context) =>
478
- String((await invoke("editor", [input, cwd], context)) ?? ""),
479
- }
480
- : {}),
481
- ...(available.has("applyPatch")
482
- ? {
483
- applyPatch: async (input, cwd, context) =>
484
- String((await invoke("applyPatch", [input, cwd], context)) ?? ""),
485
- }
486
- : {}),
487
- ...(available.has("skills")
488
- ? {
489
- skills: async (skill, args, context) =>
490
- String((await invoke("skills", [skill, args], context)) ?? ""),
491
- }
492
- : {}),
493
- ...(available.has("askQuestion")
494
- ? {
495
- askQuestion: async (question, options, context) =>
496
- String(
497
- (await invoke("askQuestion", [question, options], context)) ?? "",
498
- ),
499
- }
500
- : {}),
501
- ...(available.has("submit")
502
- ? {
503
- submit: async (summary, verified, context) =>
504
- String(
505
- (await invoke("submit", [summary, verified], context)) ?? "",
506
- ),
507
- }
508
- : {}),
509
- };
510
- }
511
-
512
- /** @internal Exported for unit testing fetch/runtime wiring. */
513
- export class HubServerTransport implements NativeHubTransport {
514
- private readonly clients = new Map<string, HubClientRecord>();
515
- private readonly listeners = new Map<
516
- string,
517
- Set<{ sessionId?: string; listener: (event: HubEventEnvelope) => void }>
518
- >();
519
- private readonly sessionState = new Map<string, HubSessionState>();
520
- private readonly pendingApprovals = new Map<
521
- string,
522
- {
523
- sessionId: string;
524
- resolve: (result: { approved: boolean; reason?: string }) => void;
525
- }
526
- >();
527
- private readonly pendingCapabilityRequests = new Map<
528
- string,
529
- {
530
- sessionId: string;
531
- capabilityName: string;
532
- resolve: (result: {
533
- ok: boolean;
534
- payload?: Record<string, unknown>;
535
- error?: string;
536
- }) => void;
537
- }
538
- >();
539
- private readonly suppressNextTerminalEventBySession = new Map<
540
- string,
541
- string
542
- >();
543
- private readonly schedules: HubScheduleService;
544
- private readonly scheduleCommands: HubScheduleCommandService;
545
- private readonly cronService?: CronService;
546
- private readonly sessionHost: RuntimeHost;
547
- private readonly hubId = createSessionId("hub_");
548
- private readonly startedAtMs = Date.now();
549
-
550
- constructor(readonly options: HubWebSocketServerOptions) {
551
- this.sessionHost =
552
- options.sessionHost ??
553
- new LocalRuntimeHost({
554
- sessionService: new CoreSessionService(new SqliteSessionStore()),
555
- fetch: options.fetch,
556
- });
557
- this.schedules = new HubScheduleService({
558
- ...options.scheduleOptions,
559
- runtimeHandlers: options.runtimeHandlers,
560
- eventPublisher: (eventType, payload) => {
561
- const mapped =
562
- eventType === "schedule.execution.completed"
563
- ? "schedule.execution_completed"
564
- : eventType === "schedule.execution.failed"
565
- ? "schedule.execution_failed"
566
- : undefined;
567
- if (!mapped) {
568
- return;
569
- }
570
- this.publish({
571
- version: "v1",
572
- event: mapped,
573
- eventId: createSessionId("hevt_"),
574
- timestamp: Date.now(),
575
- payload:
576
- payload && typeof payload === "object"
577
- ? (payload as Record<string, unknown>)
578
- : undefined,
579
- });
580
- },
581
- });
582
- this.scheduleCommands = new HubScheduleCommandService(this.schedules);
583
- if (options.cronOptions) {
584
- this.cronService = new CronService({
585
- runtimeHandlers: options.runtimeHandlers,
586
- ...options.cronOptions,
587
- });
588
- }
589
- this.sessionHost.subscribe((event) => {
590
- void this.handleSessionEvent(event).catch((error) => {
591
- logHubBoundaryError("session event handling failed", error);
592
- });
593
- });
594
- }
595
-
596
- getCronService(): CronService | undefined {
597
- return this.cronService;
598
- }
599
-
600
- getHubId(): string {
601
- return this.hubId;
602
- }
603
-
604
- async start(): Promise<void> {
605
- await this.schedules.start();
606
- if (this.cronService) {
607
- try {
608
- await this.cronService.start();
609
- } catch (err) {
610
- console.error("[hub] cron service start failed", err);
611
- }
612
- }
613
- }
614
-
615
- async stop(): Promise<void> {
616
- for (const approvalId of this.pendingApprovals.keys()) {
617
- this.resolvePendingApproval(approvalId, {
618
- approved: false,
619
- reason: "Hub shutting down before approval was resolved.",
620
- });
621
- }
622
- for (const pending of this.pendingCapabilityRequests.values()) {
623
- pending.resolve({
624
- ok: false,
625
- error: "Hub shutting down before capability request was resolved.",
626
- });
627
- }
628
- this.pendingCapabilityRequests.clear();
629
- await this.sessionHost.dispose("hub_server_stop");
630
- await this.schedules.dispose();
631
- if (this.cronService) {
632
- try {
633
- await this.cronService.dispose();
634
- } catch (err) {
635
- console.error("[hub] cron service stop failed", err);
636
- }
637
- }
638
- }
639
-
640
- async handleCommand(envelope: HubCommandEnvelope): Promise<HubReplyEnvelope> {
641
- const uptimeMs = Date.now() - this.startedAtMs;
642
- console.error(
643
- `[hub] command=${envelope.command} uptime=${formatHubUptime(uptimeMs)} client=${envelope.clientId ?? "unknown"} session=${envelope.sessionId ?? "-"}`,
644
- );
645
- switch (envelope.command) {
646
- case "client.register":
647
- return this.handleClientRegister(envelope);
648
- case "client.update":
649
- return this.handleClientUpdate(envelope);
650
- case "client.unregister":
651
- return this.handleClientUnregister(envelope);
652
- case "client.list":
653
- return {
654
- version: envelope.version,
655
- requestId: envelope.requestId,
656
- ok: true,
657
- payload: { clients: [...this.clients.values()] },
658
- };
659
- case "session.create":
660
- return await this.handleSessionCreate(envelope);
661
- case "session.attach":
662
- return await this.handleSessionAttach(envelope);
663
- case "session.detach":
664
- return await this.handleSessionDetach(envelope);
665
- case "session.get":
666
- return await this.handleSessionGet(envelope);
667
- case "session.messages":
668
- return await this.handleSessionMessages(envelope);
669
- case "session.list":
670
- return await this.handleSessionList(envelope);
671
- case "session.update":
672
- return await this.handleSessionUpdate(envelope);
673
- case "session.pending_prompts":
674
- return await this.handleSessionPendingPrompts(envelope);
675
- case "session.update_pending_prompt":
676
- return await this.handleSessionUpdatePendingPrompt(envelope);
677
- case "session.remove_pending_prompt":
678
- return await this.handleSessionRemovePendingPrompt(envelope);
679
- case "session.delete":
680
- return await this.handleSessionDelete(envelope);
681
- case "session.hook":
682
- return await this.handleSessionHook(envelope);
683
- case "run.start":
684
- case "session.send_input":
685
- return await this.handleSessionInput(envelope);
686
- case "run.abort":
687
- return await this.handleRunAbort(envelope);
688
- case "capability.request":
689
- return await this.handleCapabilityRequest(envelope);
690
- case "approval.respond":
691
- return await this.handleApprovalRespond(envelope);
692
- case "capability.respond":
693
- return await this.handleCapabilityRespond(envelope);
694
- case "ui.notify":
695
- this.publish(this.buildEvent("ui.notify", envelope.payload ?? {}));
696
- return {
697
- version: envelope.version,
698
- requestId: envelope.requestId,
699
- ok: true,
700
- };
701
- case "ui.show_window":
702
- this.publish(this.buildEvent("ui.show_window", envelope.payload ?? {}));
703
- return {
704
- version: envelope.version,
705
- requestId: envelope.requestId,
706
- ok: true,
707
- };
708
- default: {
709
- const reply = await this.scheduleCommands.handleCommand(envelope);
710
- if (reply.ok) {
711
- const event = eventNameForScheduleCommand(envelope.command);
712
- if (event) {
713
- this.publish({
714
- version: "v1",
715
- event,
716
- eventId: createSessionId("hevt_"),
717
- timestamp: Date.now(),
718
- payload: reply.payload,
719
- });
720
- }
721
- }
722
- return reply;
723
- }
724
- }
725
- }
726
-
727
- private handleClientRegister(envelope: HubCommandEnvelope): HubReplyEnvelope {
728
- const payload = envelope.payload as HubClientRegistration | undefined;
729
- const clientId =
730
- payload?.clientId?.trim() ||
731
- envelope.clientId?.trim() ||
732
- createSessionId("client_");
733
- this.clients.set(clientId, {
734
- clientId,
735
- clientType: payload?.clientType ?? "unknown",
736
- displayName: payload?.displayName,
737
- actorKind: payload?.actorKind ?? "client",
738
- connectedAt: Date.now(),
739
- lastSeenAt: Date.now(),
740
- transport: payload?.transport ?? "native",
741
- capabilities: payload?.capabilities ?? [],
742
- metadata: payload?.metadata,
743
- workspaceContext: payload?.workspaceContext,
744
- });
745
- this.publish(
746
- this.buildEvent("hub.client.registered", {
747
- clientId,
748
- clientType: payload?.clientType ?? "unknown",
749
- displayName: payload?.displayName,
750
- connectedAt: Date.now(),
751
- }),
752
- );
753
- return {
754
- version: envelope.version,
755
- requestId: envelope.requestId,
756
- ok: true,
757
- payload: { clientId },
758
- };
759
- }
760
-
761
- private handleClientUpdate(envelope: HubCommandEnvelope): HubReplyEnvelope {
762
- const clientId = envelope.clientId?.trim();
763
- const client = clientId ? this.clients.get(clientId) : undefined;
764
- if (!clientId || !client) {
765
- return {
766
- version: envelope.version,
767
- requestId: envelope.requestId,
768
- ok: false,
769
- error: {
770
- code: "client_not_found",
771
- message: "Client is not registered with this hub.",
772
- },
773
- };
774
- }
775
- const metadata =
776
- envelope.payload?.metadata &&
777
- typeof envelope.payload.metadata === "object" &&
778
- !Array.isArray(envelope.payload.metadata)
779
- ? (envelope.payload.metadata as Record<string, JsonValue | undefined>)
780
- : undefined;
781
- client.lastSeenAt = Date.now();
782
- if (metadata) {
783
- client.metadata = JSON.parse(JSON.stringify(metadata)) as Record<
784
- string,
785
- JsonValue | undefined
786
- >;
787
- }
788
- return {
789
- version: envelope.version,
790
- requestId: envelope.requestId,
791
- ok: true,
792
- };
793
- }
794
-
795
- private handleClientUnregister(
796
- envelope: HubCommandEnvelope,
797
- ): HubReplyEnvelope {
798
- const clientId = envelope.clientId?.trim();
799
- if (clientId) {
800
- this.clients.delete(clientId);
801
- this.listeners.delete(clientId);
802
- }
803
- if (clientId) {
804
- this.publish(this.buildEvent("hub.client.disconnected", { clientId }));
805
- }
806
- return {
807
- version: envelope.version,
808
- requestId: envelope.requestId,
809
- ok: true,
810
- };
811
- }
812
-
813
- private buildEvent(
814
- event: HubEventEnvelope["event"],
815
- payload?: Record<string, unknown>,
816
- sessionId?: string,
817
- ): HubEventEnvelope {
818
- return {
819
- version: "v1",
820
- event,
821
- eventId: createSessionId("hevt_"),
822
- sessionId,
823
- timestamp: Date.now(),
824
- payload,
825
- };
826
- }
827
-
828
- private async readHubSessionRecord(
829
- sessionId: string,
830
- ): Promise<HubSessionRecord | undefined> {
831
- const session = await this.sessionHost.get(sessionId);
832
- if (!session) {
833
- return undefined;
834
- }
835
- return toHubSessionRecord(session, this.sessionState.get(sessionId));
836
- }
837
-
838
- private ensureSessionState(
839
- sessionId: string,
840
- clientId: string,
841
- role: SessionParticipant["role"],
842
- options: { interactive?: boolean } = {},
843
- ): HubSessionState {
844
- const existing = this.sessionState.get(sessionId);
845
- if (existing) {
846
- if (options.interactive !== undefined) {
847
- existing.interactive = options.interactive;
848
- }
849
- if (!existing.participants.has(clientId)) {
850
- existing.participants.set(clientId, {
851
- clientId,
852
- attachedAt: Date.now(),
853
- role,
854
- });
855
- }
856
- return existing;
857
- }
858
- const state: HubSessionState = {
859
- createdByClientId: clientId,
860
- interactive: options.interactive ?? true,
861
- participants: new Map([
862
- [
863
- clientId,
864
- {
865
- clientId,
866
- attachedAt: Date.now(),
867
- role,
868
- },
869
- ],
870
- ]),
871
- };
872
- this.sessionState.set(sessionId, state);
873
- return state;
874
- }
875
-
876
- private async requestCapability(
877
- sessionId: string,
878
- capabilityName: string,
879
- payload: Record<string, unknown>,
880
- targetClientId: string,
881
- ): Promise<Record<string, unknown> | undefined> {
882
- const requestId = createSessionId("capreq_");
883
- return await new Promise((resolve, reject) => {
884
- this.pendingCapabilityRequests.set(requestId, {
885
- sessionId,
886
- capabilityName,
887
- resolve: (result) => {
888
- if (!result.ok) {
889
- reject(
890
- new Error(
891
- result.error ||
892
- `Capability ${capabilityName} was rejected by ${targetClientId}.`,
893
- ),
894
- );
895
- return;
896
- }
897
- resolve(result.payload);
898
- },
899
- });
900
- this.publish(
901
- this.buildEvent(
902
- "capability.requested",
903
- {
904
- requestId,
905
- targetClientId,
906
- capabilityName,
907
- payload,
908
- },
909
- sessionId,
910
- ),
911
- );
912
- });
913
- }
914
-
915
- private async handleSessionCreate(
916
- envelope: HubCommandEnvelope,
917
- ): Promise<HubReplyEnvelope> {
918
- const payload =
919
- envelope.payload && typeof envelope.payload === "object"
920
- ? envelope.payload
921
- : {};
922
- const metadata =
923
- payload.metadata && typeof payload.metadata === "object"
924
- ? JSON.parse(JSON.stringify(payload.metadata))
925
- : {};
926
- const sessionConfig =
927
- payload.sessionConfig && typeof payload.sessionConfig === "object"
928
- ? (JSON.parse(
929
- JSON.stringify(payload.sessionConfig),
930
- ) as Partial<RuntimeSessionConfig>)
931
- : undefined;
932
- const runtimeOptions =
933
- payload.runtimeOptions && typeof payload.runtimeOptions === "object"
934
- ? (payload.runtimeOptions as Record<string, unknown>)
935
- : {};
936
- if (typeof sessionConfig?.mode === "string") {
937
- metadata.mode = sessionConfig.mode;
938
- } else if (typeof runtimeOptions.mode === "string") {
939
- metadata.mode = runtimeOptions.mode;
940
- }
941
- if (typeof sessionConfig?.systemPrompt === "string") {
942
- metadata.systemPrompt = sessionConfig.systemPrompt;
943
- } else if (typeof runtimeOptions.systemPrompt === "string") {
944
- metadata.systemPrompt = runtimeOptions.systemPrompt;
945
- }
946
- if (sessionConfig?.checkpoint?.enabled === true) {
947
- metadata.checkpointEnabled = true;
948
- } else if (runtimeOptions.checkpointEnabled === true) {
949
- metadata.checkpointEnabled = true;
950
- }
951
- const modelSelection =
952
- payload.modelSelection && typeof payload.modelSelection === "object"
953
- ? (payload.modelSelection as Record<string, unknown>)
954
- : {};
955
- const workspaceRoot =
956
- typeof payload.workspaceRoot === "string" && payload.workspaceRoot.trim()
957
- ? payload.workspaceRoot.trim()
958
- : typeof payload.cwd === "string" && payload.cwd.trim()
959
- ? payload.cwd.trim()
960
- : "";
961
- if (!workspaceRoot) {
962
- return {
963
- version: envelope.version,
964
- requestId: envelope.requestId,
965
- ok: false,
966
- error: {
967
- code: "invalid_session_create",
968
- message: "session.create requires workspaceRoot or cwd",
969
- },
970
- };
971
- }
972
- const clientId = envelope.clientId?.trim() || "hub-client";
973
- const advertisedToolExecutors = Array.isArray(runtimeOptions.toolExecutors)
974
- ? runtimeOptions.toolExecutors.filter(isHubToolExecutorName)
975
- : [];
976
- const configExtensions = parseRuntimeConfigExtensions(
977
- runtimeOptions.configExtensions,
978
- );
979
- const started = await this.sessionHost.start({
980
- source: typeof metadata.source === "string" ? metadata.source : undefined,
981
- interactive: metadata.interactive !== false,
982
- sessionMetadata:
983
- Object.keys(metadata as Record<string, unknown>).length > 0
984
- ? (metadata as Record<string, unknown>)
985
- : undefined,
986
- initialMessages: Array.isArray(payload.initialMessages)
987
- ? (payload.initialMessages as never[])
988
- : undefined,
989
- localRuntime: {
990
- modelCatalogDefaults: {
991
- loadLatestOnInit: true,
992
- loadPrivateOnAuth: true,
993
- },
994
- configExtensions,
995
- defaultToolExecutors: createCapabilityBackedToolExecutors(
996
- clientId,
997
- advertisedToolExecutors,
998
- async (
999
- sessionId,
1000
- capabilityName,
1001
- capabilityPayload,
1002
- targetClientId,
1003
- ) =>
1004
- await this.requestCapability(
1005
- sessionId,
1006
- capabilityName,
1007
- capabilityPayload,
1008
- targetClientId,
1009
- ),
1010
- ),
1011
- },
1012
- requestToolApproval: async (request: ToolApprovalRequest) => {
1013
- return await this.requestToolApproval(request);
1014
- },
1015
- config: {
1016
- ...(sessionConfig ?? {}),
1017
- providerId:
1018
- sessionConfig?.providerId ??
1019
- (typeof modelSelection.provider === "string"
1020
- ? modelSelection.provider
1021
- : typeof metadata.provider === "string"
1022
- ? metadata.provider
1023
- : "hub"),
1024
- modelId:
1025
- sessionConfig?.modelId ??
1026
- (typeof modelSelection.model === "string"
1027
- ? modelSelection.model
1028
- : typeof metadata.model === "string"
1029
- ? metadata.model
1030
- : "hub"),
1031
- apiKey:
1032
- sessionConfig?.apiKey ??
1033
- (typeof modelSelection.apiKey === "string"
1034
- ? modelSelection.apiKey
1035
- : undefined),
1036
- cwd:
1037
- sessionConfig?.cwd ??
1038
- (typeof payload.cwd === "string" && payload.cwd.trim()
1039
- ? payload.cwd.trim()
1040
- : workspaceRoot),
1041
- workspaceRoot: sessionConfig?.workspaceRoot ?? workspaceRoot,
1042
- systemPrompt:
1043
- sessionConfig?.systemPrompt ??
1044
- (typeof runtimeOptions.systemPrompt === "string"
1045
- ? runtimeOptions.systemPrompt
1046
- : ""),
1047
- mode:
1048
- sessionConfig?.mode ??
1049
- (runtimeOptions.mode === "plan" || runtimeOptions.mode === "yolo"
1050
- ? runtimeOptions.mode
1051
- : "act"),
1052
- maxIterations:
1053
- sessionConfig?.maxIterations ??
1054
- (typeof runtimeOptions.maxIterations === "number"
1055
- ? runtimeOptions.maxIterations
1056
- : undefined),
1057
- enableTools:
1058
- sessionConfig?.enableTools ?? runtimeOptions.enableTools !== false,
1059
- enableSpawnAgent:
1060
- sessionConfig?.enableSpawnAgent ??
1061
- runtimeOptions.enableSpawn !== false,
1062
- enableAgentTeams:
1063
- sessionConfig?.enableAgentTeams ??
1064
- runtimeOptions.enableTeams !== false,
1065
- checkpoint:
1066
- sessionConfig?.checkpoint ??
1067
- (runtimeOptions.checkpointEnabled === true
1068
- ? { enabled: true }
1069
- : undefined),
1070
- teamName:
1071
- sessionConfig?.teamName ??
1072
- (typeof metadata.teamName === "string"
1073
- ? metadata.teamName
1074
- : undefined),
1075
- },
1076
- toolPolicies:
1077
- payload.toolPolicies &&
1078
- typeof payload.toolPolicies === "object" &&
1079
- !Array.isArray(payload.toolPolicies)
1080
- ? (JSON.parse(JSON.stringify(payload.toolPolicies)) as Record<
1081
- string,
1082
- { autoApprove?: boolean; enabled?: boolean }
1083
- >)
1084
- : runtimeOptions.autoApproveTools === true
1085
- ? { "*": { autoApprove: true } }
1086
- : undefined,
1087
- });
1088
- this.ensureSessionState(started.sessionId, clientId, "creator", {
1089
- interactive: metadata.interactive !== false,
1090
- });
1091
- const session = await this.readHubSessionRecord(started.sessionId);
1092
- if (session) {
1093
- this.publish(
1094
- this.buildEvent("session.created", { session }, started.sessionId),
1095
- );
1096
- }
1097
- return {
1098
- version: envelope.version,
1099
- requestId: envelope.requestId,
1100
- ok: true,
1101
- payload: { session },
1102
- };
1103
- }
1104
-
1105
- private async handleSessionAttach(
1106
- envelope: HubCommandEnvelope,
1107
- ): Promise<HubReplyEnvelope> {
1108
- const sessionId =
1109
- typeof envelope.payload?.sessionId === "string"
1110
- ? envelope.payload.sessionId.trim()
1111
- : envelope.sessionId?.trim() || "";
1112
- if (!sessionId) {
1113
- return {
1114
- version: envelope.version,
1115
- requestId: envelope.requestId,
1116
- ok: false,
1117
- error: {
1118
- code: "invalid_session_attach",
1119
- message: "session.attach requires a session id",
1120
- },
1121
- };
1122
- }
1123
- this.ensureSessionState(
1124
- sessionId,
1125
- envelope.clientId?.trim() || "hub-client",
1126
- "participant",
1127
- );
1128
- const session = await this.readHubSessionRecord(sessionId);
1129
- if (session) {
1130
- this.publish(this.buildEvent("session.attached", { session }, sessionId));
1131
- }
1132
- return {
1133
- version: envelope.version,
1134
- requestId: envelope.requestId,
1135
- ok: Boolean(session),
1136
- ...(session
1137
- ? { payload: { session } }
1138
- : {
1139
- error: {
1140
- code: "session_not_found",
1141
- message: `Unknown session: ${sessionId}`,
1142
- },
1143
- }),
1144
- };
1145
- }
1146
-
1147
- private async handleSessionDetach(
1148
- envelope: HubCommandEnvelope,
1149
- ): Promise<HubReplyEnvelope> {
1150
- const sessionId =
1151
- typeof envelope.payload?.sessionId === "string"
1152
- ? envelope.payload.sessionId.trim()
1153
- : envelope.sessionId?.trim() || "";
1154
- if (!sessionId) {
1155
- return {
1156
- version: envelope.version,
1157
- requestId: envelope.requestId,
1158
- ok: false,
1159
- error: {
1160
- code: "invalid_session_detach",
1161
- message: "session.detach requires a session id",
1162
- },
1163
- };
1164
- }
1165
- const clientId = envelope.clientId?.trim() || "hub-client";
1166
- const state = this.sessionState.get(sessionId);
1167
- if (state) {
1168
- state.participants.delete(clientId);
1169
- if (state.participants.size === 0) {
1170
- this.sessionState.delete(sessionId);
1171
- }
1172
- }
1173
- const session = await this.readHubSessionRecord(sessionId);
1174
- this.publish(
1175
- this.buildEvent(
1176
- "session.detached",
1177
- session ? { session, clientId } : { clientId },
1178
- sessionId,
1179
- ),
1180
- );
1181
- return {
1182
- version: envelope.version,
1183
- requestId: envelope.requestId,
1184
- ok: true,
1185
- };
1186
- }
1187
-
1188
- private async handleSessionGet(
1189
- envelope: HubCommandEnvelope,
1190
- ): Promise<HubReplyEnvelope> {
1191
- const sessionId =
1192
- typeof envelope.payload?.sessionId === "string"
1193
- ? envelope.payload.sessionId.trim()
1194
- : envelope.sessionId?.trim() || "";
1195
- const session = await this.readHubSessionRecord(sessionId);
1196
- return {
1197
- version: envelope.version,
1198
- requestId: envelope.requestId,
1199
- ok: Boolean(session),
1200
- ...(session
1201
- ? { payload: { session } }
1202
- : {
1203
- error: {
1204
- code: "session_not_found",
1205
- message: `Unknown session: ${sessionId}`,
1206
- },
1207
- }),
1208
- };
1209
- }
1210
-
1211
- private async handleSessionMessages(
1212
- envelope: HubCommandEnvelope,
1213
- ): Promise<HubReplyEnvelope> {
1214
- const sessionId =
1215
- typeof envelope.payload?.sessionId === "string"
1216
- ? envelope.payload.sessionId.trim()
1217
- : envelope.sessionId?.trim() || "";
1218
- if (!sessionId) {
1219
- return {
1220
- version: envelope.version,
1221
- requestId: envelope.requestId,
1222
- ok: false,
1223
- error: {
1224
- code: "invalid_session_id",
1225
- message: "session.messages requires a session id",
1226
- },
1227
- };
1228
- }
1229
- const session = await this.readHubSessionRecord(sessionId);
1230
- if (!session) {
1231
- return {
1232
- version: envelope.version,
1233
- requestId: envelope.requestId,
1234
- ok: false,
1235
- error: {
1236
- code: "session_not_found",
1237
- message: `Unknown session: ${sessionId}`,
1238
- },
1239
- };
1240
- }
1241
- const messages = await this.sessionHost.readMessages(sessionId);
1242
- return {
1243
- version: envelope.version,
1244
- requestId: envelope.requestId,
1245
- ok: true,
1246
- payload: { sessionId, messages },
1247
- };
1248
- }
1249
-
1250
- private async handleSessionList(
1251
- envelope: HubCommandEnvelope,
1252
- ): Promise<HubReplyEnvelope> {
1253
- const limit =
1254
- typeof envelope.payload?.limit === "number"
1255
- ? envelope.payload.limit
1256
- : 200;
1257
- const sessions = (await this.sessionHost.list(limit)).map((session) =>
1258
- toHubSessionRecord(session, this.sessionState.get(session.sessionId)),
1259
- );
1260
- return {
1261
- version: envelope.version,
1262
- requestId: envelope.requestId,
1263
- ok: true,
1264
- payload: { sessions },
1265
- };
1266
- }
1267
-
1268
- private async handleSessionUpdate(
1269
- envelope: HubCommandEnvelope,
1270
- ): Promise<HubReplyEnvelope> {
1271
- const sessionId =
1272
- typeof envelope.payload?.sessionId === "string"
1273
- ? envelope.payload.sessionId.trim()
1274
- : envelope.sessionId?.trim() || "";
1275
- const metadata =
1276
- envelope.payload?.metadata &&
1277
- typeof envelope.payload.metadata === "object" &&
1278
- !Array.isArray(envelope.payload.metadata)
1279
- ? (envelope.payload.metadata as Record<string, JsonValue | undefined>)
1280
- : undefined;
1281
- const updated = await this.sessionHost.update(sessionId, { metadata });
1282
- const session = await this.readHubSessionRecord(sessionId);
1283
- if (session) {
1284
- this.publish(this.buildEvent("session.updated", { session }, sessionId));
1285
- }
1286
- return {
1287
- version: envelope.version,
1288
- requestId: envelope.requestId,
1289
- ok: updated.updated,
1290
- payload: { updated: updated.updated, session },
1291
- };
1292
- }
1293
-
1294
- private async handleSessionPendingPrompts(
1295
- envelope: HubCommandEnvelope,
1296
- ): Promise<HubReplyEnvelope> {
1297
- const sessionId =
1298
- typeof envelope.payload?.sessionId === "string"
1299
- ? envelope.payload.sessionId.trim()
1300
- : envelope.sessionId?.trim() || "";
1301
- const prompts = await this.sessionHost.pendingPrompts("list", {
1302
- sessionId,
1303
- });
1304
- return {
1305
- version: envelope.version,
1306
- requestId: envelope.requestId,
1307
- ok: true,
1308
- payload: { sessionId, prompts },
1309
- };
1310
- }
1311
-
1312
- private async handleSessionUpdatePendingPrompt(
1313
- envelope: HubCommandEnvelope,
1314
- ): Promise<HubReplyEnvelope> {
1315
- const sessionId =
1316
- typeof envelope.payload?.sessionId === "string"
1317
- ? envelope.payload.sessionId.trim()
1318
- : envelope.sessionId?.trim() || "";
1319
- const promptId =
1320
- typeof envelope.payload?.promptId === "string"
1321
- ? envelope.payload.promptId.trim()
1322
- : "";
1323
- const prompt =
1324
- typeof envelope.payload?.prompt === "string"
1325
- ? envelope.payload.prompt
1326
- : undefined;
1327
- const delivery =
1328
- envelope.payload?.delivery === "queue" ||
1329
- envelope.payload?.delivery === "steer"
1330
- ? envelope.payload.delivery
1331
- : undefined;
1332
- const result = await this.sessionHost.pendingPrompts("update", {
1333
- sessionId,
1334
- promptId,
1335
- prompt,
1336
- delivery,
1337
- });
1338
- return {
1339
- version: envelope.version,
1340
- requestId: envelope.requestId,
1341
- ok: true,
1342
- payload: result as unknown as Record<string, JsonValue | undefined>,
1343
- };
1344
- }
1345
-
1346
- private async handleSessionRemovePendingPrompt(
1347
- envelope: HubCommandEnvelope,
1348
- ): Promise<HubReplyEnvelope> {
1349
- const sessionId =
1350
- typeof envelope.payload?.sessionId === "string"
1351
- ? envelope.payload.sessionId.trim()
1352
- : envelope.sessionId?.trim() || "";
1353
- const promptId =
1354
- typeof envelope.payload?.promptId === "string"
1355
- ? envelope.payload.promptId.trim()
1356
- : "";
1357
- const result = await this.sessionHost.pendingPrompts("delete", {
1358
- sessionId,
1359
- promptId,
1360
- });
1361
- return {
1362
- version: envelope.version,
1363
- requestId: envelope.requestId,
1364
- ok: true,
1365
- payload: result as unknown as Record<string, JsonValue | undefined>,
1366
- };
1367
- }
1368
-
1369
- private async handleSessionDelete(
1370
- envelope: HubCommandEnvelope,
1371
- ): Promise<HubReplyEnvelope> {
1372
- const sessionId =
1373
- typeof envelope.payload?.sessionId === "string"
1374
- ? envelope.payload.sessionId.trim()
1375
- : envelope.sessionId?.trim() || "";
1376
- const deleted = await this.sessionHost.delete(sessionId);
1377
- this.sessionState.delete(sessionId);
1378
- return {
1379
- version: envelope.version,
1380
- requestId: envelope.requestId,
1381
- ok: true,
1382
- payload: { deleted },
1383
- };
1384
- }
1385
-
1386
- private async handleSessionInput(
1387
- envelope: HubCommandEnvelope,
1388
- ): Promise<HubReplyEnvelope> {
1389
- const sessionId =
1390
- typeof envelope.payload?.sessionId === "string"
1391
- ? envelope.payload.sessionId.trim()
1392
- : envelope.sessionId?.trim() || "";
1393
- const payload =
1394
- envelope.payload && typeof envelope.payload === "object"
1395
- ? envelope.payload
1396
- : {};
1397
- const prompt =
1398
- typeof payload.prompt === "string"
1399
- ? payload.prompt
1400
- : typeof payload.input === "string"
1401
- ? payload.input
1402
- : "";
1403
- if (!prompt.trim()) {
1404
- return {
1405
- version: envelope.version,
1406
- requestId: envelope.requestId,
1407
- ok: false,
1408
- error: {
1409
- code: "invalid_session_input",
1410
- message: "session input requires a prompt string",
1411
- },
1412
- };
1413
- }
1414
- this.publish(this.buildEvent("run.started", undefined, sessionId));
1415
- const attachments =
1416
- payload.attachments &&
1417
- typeof payload.attachments === "object" &&
1418
- !Array.isArray(payload.attachments)
1419
- ? (payload.attachments as Record<string, unknown>)
1420
- : undefined;
1421
- const userFiles = Array.isArray(attachments?.userFiles)
1422
- ? attachments.userFiles.filter((filePath) => typeof filePath === "string")
1423
- : undefined;
1424
- const result = await this.sessionHost.send({
1425
- sessionId,
1426
- prompt,
1427
- delivery:
1428
- payload.delivery === "queue" || payload.delivery === "steer"
1429
- ? payload.delivery
1430
- : undefined,
1431
- userImages: Array.isArray(attachments?.userImages)
1432
- ? (attachments.userImages as string[])
1433
- : undefined,
1434
- userFiles,
1435
- });
1436
- if (result) {
1437
- this.suppressNextTerminalEventBySession.set(
1438
- sessionId,
1439
- result.finishReason,
1440
- );
1441
- this.publish(
1442
- this.buildEvent(
1443
- "run.completed",
1444
- { reason: result.finishReason, result },
1445
- sessionId,
1446
- ),
1447
- );
1448
- }
1449
- return {
1450
- version: envelope.version,
1451
- requestId: envelope.requestId,
1452
- ok: true,
1453
- payload: result ? { result } : undefined,
1454
- };
1455
- }
1456
-
1457
- private async handleRunAbort(
1458
- envelope: HubCommandEnvelope,
1459
- ): Promise<HubReplyEnvelope> {
1460
- const sessionId =
1461
- typeof envelope.payload?.sessionId === "string"
1462
- ? envelope.payload.sessionId.trim()
1463
- : envelope.sessionId?.trim() || "";
1464
- await this.sessionHost.abort(sessionId, envelope.payload?.reason);
1465
- this.publish(
1466
- this.buildEvent(
1467
- "run.aborted",
1468
- typeof envelope.payload?.reason === "string"
1469
- ? { reason: envelope.payload.reason }
1470
- : undefined,
1471
- sessionId,
1472
- ),
1473
- );
1474
- return {
1475
- version: envelope.version,
1476
- requestId: envelope.requestId,
1477
- ok: true,
1478
- payload: { applied: true },
1479
- };
1480
- }
1481
-
1482
- private async handleSessionHook(
1483
- envelope: HubCommandEnvelope,
1484
- ): Promise<HubReplyEnvelope> {
1485
- const parsed = parseHookEventPayload(envelope.payload?.payload);
1486
- if (!parsed) {
1487
- return {
1488
- version: envelope.version,
1489
- requestId: envelope.requestId,
1490
- ok: false,
1491
- error: {
1492
- code: "invalid_hook_payload",
1493
- message: "session.hook requires a valid hook event payload",
1494
- },
1495
- };
1496
- }
1497
- await this.sessionHost.handleHookEvent(parsed);
1498
- return {
1499
- version: envelope.version,
1500
- requestId: envelope.requestId,
1501
- ok: true,
1502
- payload: { applied: true },
1503
- };
1504
- }
1505
-
1506
- private async requestToolApproval(
1507
- request: ToolApprovalRequest,
1508
- ): Promise<{ approved: boolean; reason?: string }> {
1509
- const approvalId = createSessionId("approval_");
1510
- const sessionId = request.sessionId;
1511
- const state = this.sessionState.get(sessionId);
1512
- if (state?.interactive === false) {
1513
- return {
1514
- approved: false,
1515
- reason:
1516
- "Tool approval requires an interactive session, but this session is non-interactive.",
1517
- };
1518
- }
1519
- return await new Promise((resolve) => {
1520
- this.pendingApprovals.set(approvalId, {
1521
- sessionId,
1522
- resolve,
1523
- });
1524
- this.publish(
1525
- this.buildEvent(
1526
- "approval.requested",
1527
- {
1528
- approvalId,
1529
- sessionId: request.sessionId,
1530
- agentId: request.agentId,
1531
- conversationId: request.conversationId,
1532
- iteration: request.iteration,
1533
- toolCallId: request.toolCallId,
1534
- toolName: request.toolName,
1535
- inputJson: JSON.stringify(request.input ?? null),
1536
- policy: request.policy,
1537
- },
1538
- sessionId,
1539
- ),
1540
- );
1541
- });
1542
- }
1543
-
1544
- private resolvePendingApproval(
1545
- approvalId: string,
1546
- result: { approved: boolean; reason?: string },
1547
- ): { sessionId: string } | undefined {
1548
- const pending = this.pendingApprovals.get(approvalId);
1549
- if (!pending) {
1550
- return undefined;
1551
- }
1552
- this.pendingApprovals.delete(approvalId);
1553
- pending.resolve(result);
1554
- return { sessionId: pending.sessionId };
1555
- }
1556
-
1557
- private async handleApprovalRespond(
1558
- envelope: HubCommandEnvelope,
1559
- ): Promise<HubReplyEnvelope> {
1560
- const approvalId =
1561
- typeof envelope.payload?.approvalId === "string"
1562
- ? envelope.payload.approvalId.trim()
1563
- : "";
1564
- const pending = this.pendingApprovals.get(approvalId);
1565
- if (!pending) {
1566
- return {
1567
- version: envelope.version,
1568
- requestId: envelope.requestId,
1569
- ok: false,
1570
- error: {
1571
- code: "approval_not_found",
1572
- message: `Unknown approval: ${approvalId}`,
1573
- },
1574
- };
1575
- }
1576
- const reason =
1577
- typeof envelope.payload?.reason === "string"
1578
- ? envelope.payload.reason
1579
- : envelope.payload?.payload &&
1580
- typeof envelope.payload.payload === "object" &&
1581
- !Array.isArray(envelope.payload.payload) &&
1582
- typeof (envelope.payload.payload as Record<string, unknown>)
1583
- .reason === "string"
1584
- ? ((envelope.payload.payload as Record<string, unknown>)
1585
- .reason as string)
1586
- : undefined;
1587
- const resolved = this.resolvePendingApproval(approvalId, {
1588
- approved: envelope.payload?.approved === true,
1589
- reason,
1590
- });
1591
- if (!resolved) {
1592
- return {
1593
- version: envelope.version,
1594
- requestId: envelope.requestId,
1595
- ok: false,
1596
- error: {
1597
- code: "approval_not_found",
1598
- message: `Unknown approval: ${approvalId}`,
1599
- },
1600
- };
1601
- }
1602
- this.publish(
1603
- this.buildEvent(
1604
- "approval.resolved",
1605
- { approvalId, approved: envelope.payload?.approved === true, reason },
1606
- resolved.sessionId,
1607
- ),
1608
- );
1609
- return {
1610
- version: envelope.version,
1611
- requestId: envelope.requestId,
1612
- ok: true,
1613
- payload: { approvalId, approved: envelope.payload?.approved === true },
1614
- };
1615
- }
1616
-
1617
- private async handleCapabilityRequest(
1618
- envelope: HubCommandEnvelope,
1619
- ): Promise<HubReplyEnvelope> {
1620
- const sessionId =
1621
- typeof envelope.payload?.sessionId === "string"
1622
- ? envelope.payload.sessionId.trim()
1623
- : envelope.sessionId?.trim() || "";
1624
- const capabilityName =
1625
- typeof envelope.payload?.capabilityName === "string"
1626
- ? envelope.payload.capabilityName.trim()
1627
- : "";
1628
- const targetClientId =
1629
- typeof envelope.payload?.targetClientId === "string"
1630
- ? envelope.payload.targetClientId.trim()
1631
- : "";
1632
- if (!sessionId || !capabilityName || !targetClientId) {
1633
- return {
1634
- version: envelope.version,
1635
- requestId: envelope.requestId,
1636
- ok: false,
1637
- error: {
1638
- code: "invalid_capability_request",
1639
- message:
1640
- "capability.request requires sessionId, capabilityName, and targetClientId",
1641
- },
1642
- };
1643
- }
1644
- try {
1645
- const payload =
1646
- envelope.payload?.payload &&
1647
- typeof envelope.payload.payload === "object" &&
1648
- !Array.isArray(envelope.payload.payload)
1649
- ? (envelope.payload.payload as Record<string, unknown>)
1650
- : {};
1651
- const response = await this.requestCapability(
1652
- sessionId,
1653
- capabilityName,
1654
- payload,
1655
- targetClientId,
1656
- );
1657
- return {
1658
- version: envelope.version,
1659
- requestId: envelope.requestId,
1660
- ok: true,
1661
- payload: response,
1662
- };
1663
- } catch (error) {
1664
- return {
1665
- version: envelope.version,
1666
- requestId: envelope.requestId,
1667
- ok: false,
1668
- error: {
1669
- code: "capability_request_failed",
1670
- message: error instanceof Error ? error.message : String(error),
1671
- },
1672
- };
1673
- }
1674
- }
1675
-
1676
- private async handleCapabilityRespond(
1677
- envelope: HubCommandEnvelope,
1678
- ): Promise<HubReplyEnvelope> {
1679
- const requestId =
1680
- typeof envelope.payload?.requestId === "string"
1681
- ? envelope.payload.requestId.trim()
1682
- : "";
1683
- const pending = this.pendingCapabilityRequests.get(requestId);
1684
- if (!pending) {
1685
- return {
1686
- version: envelope.version,
1687
- requestId: envelope.requestId,
1688
- ok: false,
1689
- error: {
1690
- code: "capability_not_found",
1691
- message: `Unknown capability request: ${requestId}`,
1692
- },
1693
- };
1694
- }
1695
- this.pendingCapabilityRequests.delete(requestId);
1696
- const payload =
1697
- envelope.payload?.payload &&
1698
- typeof envelope.payload.payload === "object" &&
1699
- !Array.isArray(envelope.payload.payload)
1700
- ? (envelope.payload.payload as Record<string, unknown>)
1701
- : undefined;
1702
- const error =
1703
- typeof envelope.payload?.error === "string"
1704
- ? envelope.payload.error
1705
- : undefined;
1706
- const ok = envelope.payload?.ok === true;
1707
- pending.resolve({ ok, payload, error });
1708
- this.publish(
1709
- this.buildEvent(
1710
- "capability.resolved",
1711
- {
1712
- requestId,
1713
- capabilityName: pending.capabilityName,
1714
- targetClientId: envelope.clientId?.trim(),
1715
- ok,
1716
- payload,
1717
- error,
1718
- },
1719
- pending.sessionId,
1720
- ),
1721
- );
1722
- return {
1723
- version: envelope.version,
1724
- requestId: envelope.requestId,
1725
- ok: true,
1726
- payload: { requestId, ok },
1727
- };
1728
- }
1729
-
1730
- private async handleSessionEvent(event: CoreSessionEvent): Promise<void> {
1731
- switch (event.type) {
1732
- case "chunk":
1733
- // Ignore raw agent chunks here. In this runtime they can contain
1734
- // serialized event envelopes rather than user-facing assistant text.
1735
- // Structured live content is forwarded via the "agent_event" branch.
1736
- return;
1737
- case "agent_event": {
1738
- const { sessionId, event: agentEvent } = event.payload;
1739
- if (agentEvent.type === "iteration_start") {
1740
- this.publish(
1741
- this.buildEvent(
1742
- "iteration.started",
1743
- { iteration: agentEvent.iteration },
1744
- sessionId,
1745
- ),
1746
- );
1747
- return;
1748
- }
1749
- if (agentEvent.type === "iteration_end") {
1750
- this.publish(
1751
- this.buildEvent(
1752
- "iteration.finished",
1753
- {
1754
- iteration: agentEvent.iteration,
1755
- hadToolCalls: agentEvent.hadToolCalls,
1756
- toolCallCount: agentEvent.toolCallCount,
1757
- },
1758
- sessionId,
1759
- ),
1760
- );
1761
- return;
1762
- }
1763
- if (agentEvent.type === "content_start") {
1764
- if (
1765
- agentEvent.contentType === "text" &&
1766
- typeof agentEvent.text === "string" &&
1767
- agentEvent.text.length > 0
1768
- ) {
1769
- this.publish(
1770
- this.buildEvent(
1771
- "assistant.delta",
1772
- { text: agentEvent.text },
1773
- sessionId,
1774
- ),
1775
- );
1776
- return;
1777
- }
1778
- if (agentEvent.contentType === "reasoning") {
1779
- if (agentEvent.redacted && !agentEvent.reasoning) {
1780
- this.publish(
1781
- this.buildEvent(
1782
- "reasoning.delta",
1783
- { text: "", redacted: true },
1784
- sessionId,
1785
- ),
1786
- );
1787
- return;
1788
- }
1789
- if (
1790
- typeof agentEvent.reasoning === "string" &&
1791
- agentEvent.reasoning.length > 0
1792
- ) {
1793
- this.publish(
1794
- this.buildEvent(
1795
- "reasoning.delta",
1796
- {
1797
- text: agentEvent.reasoning,
1798
- redacted: agentEvent.redacted === true,
1799
- },
1800
- sessionId,
1801
- ),
1802
- );
1803
- }
1804
- return;
1805
- }
1806
- if (agentEvent.contentType === "tool") {
1807
- this.publish(
1808
- this.buildEvent(
1809
- "tool.started",
1810
- {
1811
- toolCallId: agentEvent.toolCallId,
1812
- toolName: agentEvent.toolName,
1813
- input: agentEvent.input,
1814
- },
1815
- sessionId,
1816
- ),
1817
- );
1818
- return;
1819
- }
1820
- }
1821
- if (agentEvent.type === "content_end") {
1822
- switch (agentEvent.contentType) {
1823
- case "text":
1824
- this.publish(
1825
- this.buildEvent(
1826
- "assistant.finished",
1827
- { text: agentEvent.text },
1828
- sessionId,
1829
- ),
1830
- );
1831
- break;
1832
- case "reasoning":
1833
- this.publish(
1834
- this.buildEvent(
1835
- "reasoning.finished",
1836
- { reasoning: agentEvent.reasoning },
1837
- sessionId,
1838
- ),
1839
- );
1840
- break;
1841
- case "tool":
1842
- this.publish(
1843
- this.buildEvent(
1844
- "tool.finished",
1845
- {
1846
- toolCallId: agentEvent.toolCallId,
1847
- toolName: agentEvent.toolName,
1848
- output: agentEvent.output,
1849
- error: agentEvent.error,
1850
- },
1851
- sessionId,
1852
- ),
1853
- );
1854
- break;
1855
- }
1856
- return;
1857
- }
1858
- if (agentEvent.type === "done") {
1859
- this.publish(
1860
- this.buildEvent(
1861
- "agent.done",
1862
- {
1863
- reason: agentEvent.reason,
1864
- text: agentEvent.text,
1865
- iterations: agentEvent.iterations,
1866
- usage: agentEvent.usage,
1867
- },
1868
- sessionId,
1869
- ),
1870
- );
1871
- }
1872
- return;
1873
- }
1874
- case "hook":
1875
- if (event.payload.hookEventName === "tool_call") {
1876
- this.publish(
1877
- this.buildEvent(
1878
- "tool.started",
1879
- { toolName: event.payload.toolName },
1880
- event.payload.sessionId,
1881
- ),
1882
- );
1883
- } else if (event.payload.hookEventName === "tool_result") {
1884
- this.publish(
1885
- this.buildEvent(
1886
- "tool.finished",
1887
- { toolName: event.payload.toolName },
1888
- event.payload.sessionId,
1889
- ),
1890
- );
1891
- }
1892
- return;
1893
- case "team_progress": {
1894
- const projection: TeamProgressProjectionEvent = {
1895
- type: "team_progress_projection",
1896
- version: 1,
1897
- sessionId: event.payload.sessionId,
1898
- summary: event.payload.summary,
1899
- lastEvent: event.payload.lifecycle,
1900
- };
1901
- this.publish(
1902
- this.buildEvent(
1903
- "team.progress",
1904
- projection as unknown as Record<string, unknown>,
1905
- event.payload.sessionId,
1906
- ),
1907
- );
1908
- return;
1909
- }
1910
- case "pending_prompts": {
1911
- this.publish(
1912
- this.buildEvent(
1913
- "session.pending_prompts",
1914
- {
1915
- sessionId: event.payload.sessionId,
1916
- prompts: event.payload.prompts,
1917
- },
1918
- event.payload.sessionId,
1919
- ),
1920
- );
1921
- return;
1922
- }
1923
- case "pending_prompt_submitted": {
1924
- const prompt: SessionPendingPrompt = {
1925
- id: event.payload.id,
1926
- prompt: event.payload.prompt,
1927
- delivery: event.payload.delivery,
1928
- attachmentCount: event.payload.attachmentCount,
1929
- };
1930
- this.publish(
1931
- this.buildEvent(
1932
- "session.pending_prompt_submitted",
1933
- { sessionId: event.payload.sessionId, prompt },
1934
- event.payload.sessionId,
1935
- ),
1936
- );
1937
- return;
1938
- }
1939
- case "status": {
1940
- const session = await this.readHubSessionRecord(
1941
- event.payload.sessionId,
1942
- );
1943
- if (session) {
1944
- this.publish(
1945
- this.buildEvent(
1946
- "session.updated",
1947
- { session },
1948
- event.payload.sessionId,
1949
- ),
1950
- );
1951
- }
1952
- return;
1953
- }
1954
- case "ended": {
1955
- const suppressDuplicateTerminalEvent =
1956
- this.suppressNextTerminalEventBySession.get(
1957
- event.payload.sessionId,
1958
- ) === event.payload.reason;
1959
- if (suppressDuplicateTerminalEvent) {
1960
- this.suppressNextTerminalEventBySession.delete(
1961
- event.payload.sessionId,
1962
- );
1963
- }
1964
- if (event.payload.reason === "completed") {
1965
- const session = await this.readHubSessionRecord(
1966
- event.payload.sessionId,
1967
- );
1968
- const notification = await buildCompletionNotification(session);
1969
- this.publish(
1970
- this.buildEvent("ui.notify", notification, event.payload.sessionId),
1971
- );
1972
- }
1973
- if (suppressDuplicateTerminalEvent) {
1974
- return;
1975
- }
1976
- this.publish(
1977
- this.buildEvent(
1978
- event.payload.reason === "aborted"
1979
- ? "run.aborted"
1980
- : "run.completed",
1981
- { reason: event.payload.reason },
1982
- event.payload.sessionId,
1983
- ),
1984
- );
1985
- return;
1986
- }
1987
- default:
1988
- return;
1989
- }
1990
- }
1991
-
1992
- subscribe(
1993
- clientId: string,
1994
- listener: (event: HubEventEnvelope) => void,
1995
- options?: { sessionId?: string },
1996
- ): () => void {
1997
- const current = this.listeners.get(clientId) ?? new Set();
1998
- const entry = { sessionId: options?.sessionId, listener };
1999
- current.add(entry);
2000
- this.listeners.set(clientId, current);
2001
- return () => {
2002
- const listeners = this.listeners.get(clientId);
2003
- if (!listeners) {
2004
- return;
2005
- }
2006
- listeners.delete(entry);
2007
- if (listeners.size === 0) {
2008
- this.listeners.delete(clientId);
2009
- }
2010
- };
2011
- }
2012
-
2013
- private publish(event: HubEventEnvelope): void {
2014
- for (const entries of this.listeners.values()) {
2015
- for (const entry of entries) {
2016
- if (entry.sessionId && entry.sessionId !== event.sessionId) {
2017
- continue;
2018
- }
2019
- try {
2020
- entry.listener(event);
2021
- } catch (error) {
2022
- logHubBoundaryError(
2023
- `listener threw while publishing ${event.event}`,
2024
- error,
2025
- );
2026
- }
2027
- }
2028
- }
2029
- }
2030
- }
2031
-
2032
- function logHubBoundaryError(message: string, error: unknown): void {
2033
- const details =
2034
- error instanceof Error ? error.stack || error.message : String(error);
2035
- console.error(`[hub] ${message}: ${details}`);
2036
- }
2037
-
2038
- export interface HubWebSocketServerOptions {
2039
- host?: string;
2040
- port?: number;
2041
- pathname?: string;
2042
- owner?: HubOwnerContext;
2043
- sessionHost?: RuntimeHost;
2044
- runtimeHandlers: HubScheduleRuntimeHandlers;
2045
- scheduleOptions?: Omit<HubScheduleServiceOptions, "runtimeHandlers">;
2046
- /**
2047
- * File-based cron automation options. When provided, the hub starts a
2048
- * `CronService` that watches global `~/.cline/cron/` by default, reconciles
2049
- * specs into `cron.db`, and executes queued runs through `runtimeHandlers`.
2050
- * Pass `cronOptions.specs` to use a different source, including future
2051
- * workspace-scoped specs.
2052
- */
2053
- cronOptions?: Omit<CronServiceOptions, "runtimeHandlers">;
2054
- /**
2055
- * Custom `fetch` implementation forwarded to the internally-constructed
2056
- * `LocalRuntimeHost` that executes incoming `session.create` traffic.
2057
- * Used by the AI gateway providers for every session that runs inside
2058
- * this hub process.
2059
- *
2060
- * Ignored when `sessionHost` is supplied — in that case the caller owns
2061
- * runtime construction and is responsible for wiring its own fetch.
2062
- */
2063
- fetch?: typeof fetch;
2064
- }
2065
-
2066
- export interface HubWebSocketServer {
2067
- host: string;
2068
- port: number;
2069
- url: string;
2070
- close(): Promise<void>;
2071
- }
2072
-
2073
- export interface EnsureHubWebSocketServerOptions
2074
- extends HubWebSocketServerOptions {
2075
- allowPortFallback?: boolean;
2076
- }
2077
-
2078
- export interface EnsuredHubWebSocketServerResult {
2079
- server?: HubWebSocketServer;
2080
- url: string;
2081
- action: "reuse" | "started";
2082
- }
2083
-
2084
- const SHARED_SERVERS = new Map<string, Promise<HubWebSocketServer>>();
2085
-
2086
- export async function startHubWebSocketServer(
2087
- options: HubWebSocketServerOptions,
2088
- ): Promise<HubWebSocketServer> {
2089
- const owner = options.owner ?? resolveHubOwnerContext();
2090
- const host = options.host ?? "127.0.0.1";
2091
- const pathname = options.pathname ?? "/hub";
2092
- const requestedPort = options.port ?? resolveDefaultHubPort();
2093
- let port = requestedPort;
2094
- let url = createHubServerUrl(host, requestedPort, pathname);
2095
- const buildId = resolveHubBuildId();
2096
- const transport = new HubServerTransport(options);
2097
- await transport.start();
2098
- const adapter = new BrowserWebSocketHubAdapter(
2099
- new NativeHubTransportAdapter(transport),
2100
- );
2101
- const cleanup = new Set<() => void>();
2102
- const startedAt = new Date().toISOString();
2103
- const versionPayload = {
2104
- protocolVersion: "v1",
2105
- buildId,
2106
- pid: process.pid,
2107
- startedAt,
2108
- } as const;
2109
- let closePromise: Promise<void> | undefined;
2110
-
2111
- const closeServer = async (): Promise<void> => {
2112
- if (closePromise) {
2113
- return closePromise;
2114
- }
2115
- closePromise = (async () => {
2116
- for (const detach of cleanup) {
2117
- detach();
2118
- }
2119
- cleanup.clear();
2120
- await new Promise<void>((resolve, reject) => {
2121
- wss.close((error?: Error) => {
2122
- if (error) {
2123
- reject(error);
2124
- return;
2125
- }
2126
- resolve();
2127
- });
2128
- });
2129
- await new Promise<void>((resolve, reject) => {
2130
- server.close((error) => {
2131
- if (error) {
2132
- reject(error);
2133
- return;
2134
- }
2135
- resolve();
2136
- });
2137
- });
2138
- await transport.stop();
2139
- const current = await readHubDiscovery(owner.discoveryPath);
2140
- if (current?.url === url) {
2141
- await clearHubDiscovery(owner.discoveryPath);
2142
- }
2143
- })();
2144
- return closePromise;
2145
- };
2146
-
2147
- const server = http.createServer((req, res) => {
2148
- if ((req.url ?? "/") === "/health") {
2149
- const body = JSON.stringify({
2150
- hubId: transport.getHubId(),
2151
- ...versionPayload,
2152
- host,
2153
- port,
2154
- url,
2155
- updatedAt: new Date().toISOString(),
2156
- } satisfies HubServerDiscoveryRecord);
2157
- res.statusCode = 200;
2158
- res.setHeader("content-type", "application/json");
2159
- res.end(body);
2160
- return;
2161
- }
2162
- if ((req.url ?? "/") === "/version") {
2163
- res.statusCode = 200;
2164
- res.setHeader("content-type", "application/json");
2165
- res.end(JSON.stringify(versionPayload));
2166
- return;
2167
- }
2168
- if ((req.url ?? "/") === "/shutdown" && req.method === "POST") {
2169
- res.statusCode = 202;
2170
- res.setHeader("content-type", "application/json");
2171
- res.end(JSON.stringify({ ok: true }));
2172
- queueMicrotask(() => {
2173
- void closeServer();
2174
- });
2175
- return;
2176
- }
2177
- res.statusCode = 404;
2178
- res.end("Not found");
2179
- });
2180
- const wss = new WebSocketServer({ noServer: true });
2181
-
2182
- server.on("upgrade", (request, socket, head) => {
2183
- const requestUrl = new URL(request.url ?? "/", `http://${host}:${port}`);
2184
- if (requestUrl.pathname !== pathname) {
2185
- socket.destroy();
2186
- return;
2187
- }
2188
- try {
2189
- wss.handleUpgrade(
2190
- request,
2191
- socket,
2192
- head,
2193
- (websocket: NodeWebSocketLike) => {
2194
- const detach = adapter.attach(wrapWsSocket(websocket));
2195
- cleanup.add(detach);
2196
- websocket.once("close", () => {
2197
- detach();
2198
- cleanup.delete(detach);
2199
- });
2200
- },
2201
- );
2202
- } catch {
2203
- rejectUpgradeSocket(socket);
2204
- }
2205
- });
2206
-
2207
- await new Promise<void>((resolve, reject) => {
2208
- server.once("error", (error) => {
2209
- reject(
2210
- formatHubStartupError(error, {
2211
- host,
2212
- port: requestedPort,
2213
- pathname,
2214
- }),
2215
- );
2216
- });
2217
- server.listen(requestedPort, host, () => {
2218
- const address = server.address();
2219
- if (!address || typeof address === "string") {
2220
- reject(
2221
- formatHubStartupError(new Error("Failed to resolve hub port"), {
2222
- host,
2223
- port: requestedPort,
2224
- pathname,
2225
- }),
2226
- );
2227
- return;
2228
- }
2229
- port = address.port;
2230
- url = createHubServerUrl(host, port, pathname);
2231
- resolve();
2232
- });
2233
- });
2234
-
2235
- await writeHubDiscovery(owner.discoveryPath, {
2236
- hubId: transport.getHubId(),
2237
- protocolVersion: "v1",
2238
- buildId,
2239
- host,
2240
- port,
2241
- url,
2242
- pid: process.pid,
2243
- startedAt,
2244
- updatedAt: startedAt,
2245
- });
2246
-
2247
- return {
2248
- host,
2249
- port,
2250
- url,
2251
- close: closeServer,
2252
- };
2253
- }
2254
-
2255
- export async function ensureHubWebSocketServer(
2256
- options: EnsureHubWebSocketServerOptions,
2257
- ): Promise<EnsuredHubWebSocketServerResult> {
2258
- const owner = options.owner ?? resolveHubOwnerContext();
2259
- const host = options.host ?? "127.0.0.1";
2260
- const port = options.port ?? resolveDefaultHubPort();
2261
- const pathname = options.pathname ?? "/hub";
2262
- const expectedUrl = createHubServerUrl(host, port, pathname);
2263
- const sharedKey = owner.discoveryPath;
2264
- const existing = SHARED_SERVERS.get(sharedKey);
2265
- if (existing) {
2266
- const server = await existing;
2267
- if (server.url === expectedUrl) {
2268
- return { server, url: server.url, action: "reuse" };
2269
- }
2270
- }
2271
-
2272
- return await withHubStartupLock(owner.discoveryPath, async () => {
2273
- const discovered = await readHubDiscovery(owner.discoveryPath);
2274
- const canReuseDiscovered =
2275
- discovered?.url &&
2276
- (discovered.url === expectedUrl || options.allowPortFallback === true);
2277
- if (canReuseDiscovered) {
2278
- const healthy = await probeHubServer(discovered.url);
2279
- if (healthy?.url && (await verifyHubConnection(healthy.url))) {
2280
- return { url: healthy.url, action: "reuse" };
2281
- }
2282
- }
2283
-
2284
- const expected = await probeHubServer(expectedUrl);
2285
- if (expected?.url && (await verifyHubConnection(expected.url))) {
2286
- await writeHubDiscovery(owner.discoveryPath, expected);
2287
- return { url: expected.url, action: "reuse" };
2288
- }
2289
-
2290
- if (discovered?.url) {
2291
- await clearHubDiscovery(owner.discoveryPath);
2292
- }
2293
-
2294
- const start = async (
2295
- startOptions: HubWebSocketServerOptions,
2296
- ): Promise<EnsuredHubWebSocketServerResult> => {
2297
- const serverPromise = startHubWebSocketServer({ ...startOptions, owner });
2298
- SHARED_SERVERS.set(sharedKey, serverPromise);
2299
- try {
2300
- const server = await serverPromise;
2301
- return { server, url: server.url, action: "started" };
2302
- } catch (error) {
2303
- SHARED_SERVERS.delete(sharedKey);
2304
- throw error;
2305
- }
2306
- };
2307
-
2308
- try {
2309
- return await start(options);
2310
- } catch (error) {
2311
- if (!options.allowPortFallback || !isAddressInUseError(error)) {
2312
- throw error;
2313
- }
2314
- return await start({ ...options, port: 0 });
2315
- }
2316
- });
2317
- }