@pellux/goodvibes-tui 1.27.0 → 2.0.1

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 (404) hide show
  1. package/CHANGELOG.md +125 -2
  2. package/README.md +7 -9
  3. package/bin/goodvibes +2 -2
  4. package/bin/launcher-support.js +8 -4
  5. package/docs/README.md +11 -2
  6. package/docs/foundation-artifacts/operator-contract.json +6403 -2347
  7. package/package.json +14 -25
  8. package/scripts/postinstall.js +35 -35
  9. package/src/audio/spoken-turn-model-routing.ts +1 -1
  10. package/src/cli/bundle-command.ts +5 -5
  11. package/src/cli/completions/generate.ts +1 -1
  12. package/src/cli/doctor.ts +3 -3
  13. package/src/cli/entrypoint.ts +12 -7
  14. package/src/cli/help.ts +4 -5
  15. package/src/cli/hooks-command.ts +1 -1
  16. package/src/cli/index.ts +1 -4
  17. package/src/cli/launch-auto-update.ts +59 -7
  18. package/src/cli/management-commands.ts +6 -6
  19. package/src/cli/management-utils.ts +5 -5
  20. package/src/cli/management.ts +7 -7
  21. package/src/cli/network-posture.ts +1 -1
  22. package/src/cli/package-verification.ts +7 -6
  23. package/src/cli/plugin-bundles-command.ts +1 -1
  24. package/src/cli/plugin-command.ts +2 -2
  25. package/src/cli/service-command.ts +2 -2
  26. package/src/cli/service-posture.ts +4 -4
  27. package/src/cli/status.ts +9 -8
  28. package/src/cli/surface-command.ts +4 -4
  29. package/src/cli/tui-startup.ts +12 -3
  30. package/src/cli-flags.ts +3 -3
  31. package/src/config/goodvibes-home-audit.ts +0 -2
  32. package/src/config/secret-config.ts +37 -5
  33. package/src/config/tui-extension-settings.ts +1 -1
  34. package/src/core/approval-alert.ts +2 -2
  35. package/src/core/budget-breach-notifier.ts +3 -3
  36. package/src/core/conversation-compaction-render.ts +1 -1
  37. package/src/core/conversation-line-cache.ts +1 -1
  38. package/src/core/conversation-render-context.ts +1 -1
  39. package/src/core/conversation-rendering.ts +2 -2
  40. package/src/core/conversation.ts +10 -10
  41. package/src/core/long-task-notifier.ts +2 -2
  42. package/src/core/memory-diagnostics-gateway.ts +1 -1
  43. package/src/core/scriptable-statusline.ts +1 -1
  44. package/src/core/session-auto-titler.ts +1 -1
  45. package/src/core/session-resume-core.ts +2 -2
  46. package/src/core/stream-event-wiring.ts +24 -44
  47. package/src/core/terminal-notifier.ts +3 -3
  48. package/src/core/turn-cancellation.ts +1 -1
  49. package/src/core/turn-event-wiring.ts +5 -5
  50. package/src/input/command-registry.ts +6 -6
  51. package/src/input/commands/channel-pairing.ts +1 -1
  52. package/src/input/commands/cluster-runtime.ts +1 -1
  53. package/src/input/commands/codebase-runtime.ts +1 -1
  54. package/src/input/commands/devices-runtime.ts +1 -1
  55. package/src/input/commands/hosted-runtime.ts +330 -0
  56. package/src/input/commands/local-setup-review.ts +1 -1
  57. package/src/input/commands/local-setup-transfer.ts +2 -2
  58. package/src/input/commands/local-setup.ts +3 -3
  59. package/src/input/commands/managed-runtime.ts +2 -2
  60. package/src/input/commands/operator-rpc.ts +24 -110
  61. package/src/input/commands/payment-card-intake.ts +1 -1
  62. package/src/input/commands/permissions-provenance.ts +2 -2
  63. package/src/input/commands/plugin-runtime.ts +1 -1
  64. package/src/input/commands/provider.ts +1 -1
  65. package/src/input/commands/relay-runtime.ts +18 -9
  66. package/src/input/commands/rewind-runtime.ts +1 -1
  67. package/src/input/commands/runtime-services.ts +1 -1
  68. package/src/input/commands/services-runtime.ts +1 -1
  69. package/src/input/commands/session-workflow.ts +1 -1
  70. package/src/input/commands/settings-sync-runtime.ts +2 -2
  71. package/src/input/commands/share-runtime.ts +1 -1
  72. package/src/input/commands/tasks-runtime.ts +145 -55
  73. package/src/input/commands/update-runtime.ts +31 -28
  74. package/src/input/commands/work-plan-runtime.ts +2 -2
  75. package/src/input/commands/workstream-attempts.ts +1 -1
  76. package/src/input/commands/workstream-runtime.ts +2 -2
  77. package/src/input/commands.ts +2 -0
  78. package/src/input/feature-unit-layout.ts +1 -1
  79. package/src/input/feed-context-factory.ts +3 -3
  80. package/src/input/handler-content-actions.ts +2 -2
  81. package/src/input/handler-feed-routes.ts +1 -1
  82. package/src/input/handler-feed.ts +3 -3
  83. package/src/input/handler-modal-token-routes.ts +1 -1
  84. package/src/input/handler-onboarding-daemon-adopt.ts +3 -2
  85. package/src/input/handler-onboarding.ts +1 -1
  86. package/src/input/handler-types.ts +2 -2
  87. package/src/input/handler-ui-state.ts +1 -1
  88. package/src/input/handler.ts +4 -4
  89. package/src/input/input-history.ts +1 -1
  90. package/src/input/onboarding/onboarding-feature-units.ts +2 -2
  91. package/src/input/onboarding/onboarding-runtime-status.ts +15 -1
  92. package/src/input/onboarding/onboarding-wizard-apply.ts +17 -8
  93. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +5 -3
  94. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +1 -1
  95. package/src/input/onboarding/onboarding-wizard-types.ts +1 -1
  96. package/src/input/payments-config.ts +6 -6
  97. package/src/input/search.ts +1 -1
  98. package/src/input/session-picker-modal.ts +46 -0
  99. package/src/input/settings-modal-activation.ts +1 -1
  100. package/src/input/settings-modal-behavior.ts +4 -4
  101. package/src/input/settings-modal-commit.ts +11 -0
  102. package/src/input/settings-modal-data.ts +13 -80
  103. package/src/input/settings-modal-mutations.ts +33 -0
  104. package/src/input/settings-modal-secrets.ts +34 -0
  105. package/src/input/settings-modal-subscriptions.ts +1 -1
  106. package/src/input/settings-modal-types.ts +15 -1
  107. package/src/input/settings-modal.ts +28 -3
  108. package/src/input/worktree-setup-config.ts +1 -1
  109. package/src/main.ts +11 -9
  110. package/src/panels/agent-inspector-shared.ts +2 -2
  111. package/src/panels/base-panel.ts +2 -2
  112. package/src/panels/builtin/operations.ts +6 -8
  113. package/src/panels/builtin/session.ts +17 -0
  114. package/src/panels/builtin/shared.ts +5 -5
  115. package/src/panels/builtin-modals.ts +3 -3
  116. package/src/panels/confirm-state.ts +1 -1
  117. package/src/panels/cost-tracker-panel.ts +4 -4
  118. package/src/panels/diff-panel.ts +2 -2
  119. package/src/panels/diff-review-panel.ts +2 -2
  120. package/src/panels/expandable-list-panel.ts +2 -2
  121. package/src/panels/fleet-acts.ts +1 -1
  122. package/src/panels/fleet-observed-render.ts +1 -1
  123. package/src/panels/fleet-panel-format.ts +1 -1
  124. package/src/panels/fleet-panel.ts +1 -1
  125. package/src/panels/fleet-spawn.ts +1 -1
  126. package/src/panels/fleet-steer.ts +1 -1
  127. package/src/panels/fleet-transcript.ts +1 -1
  128. package/src/panels/git-panel.ts +1 -1
  129. package/src/panels/hosted-session-feed.ts +352 -0
  130. package/src/panels/hosted-session-panel.ts +221 -0
  131. package/src/panels/local-auth-panel.ts +3 -3
  132. package/src/panels/modals/devices-modal.ts +1 -1
  133. package/src/panels/modals/local-auth-modal.ts +1 -1
  134. package/src/panels/modals/pairing-modal.ts +1 -1
  135. package/src/panels/modals/services-modal.ts +1 -1
  136. package/src/panels/modals/settings-sync-modal.ts +1 -1
  137. package/src/panels/modals/subscription-modal.ts +1 -1
  138. package/src/panels/modals/work-plan-modal.ts +1 -1
  139. package/src/panels/notifications-panel.ts +1 -1
  140. package/src/panels/panel-confirm-overlay.ts +1 -1
  141. package/src/panels/plugins-panel.ts +2 -2
  142. package/src/panels/polish-core.ts +2 -2
  143. package/src/panels/polish-tables.ts +1 -1
  144. package/src/panels/polish.ts +2 -2
  145. package/src/panels/scrollable-list-panel.ts +3 -3
  146. package/src/panels/skills-panel.ts +3 -3
  147. package/src/panels/token-budget-panel.ts +5 -5
  148. package/src/panels/types.ts +1 -2
  149. package/src/permissions/prompt.ts +1 -1
  150. package/src/renderer/autocomplete-overlay.ts +1 -1
  151. package/src/renderer/block-actions-overlay.ts +1 -1
  152. package/src/renderer/bookmark-modal.ts +1 -1
  153. package/src/renderer/buffer.ts +1 -1
  154. package/src/renderer/code-block.ts +1 -1
  155. package/src/renderer/composer-fragments.ts +1 -1
  156. package/src/renderer/compositor.ts +2 -2
  157. package/src/renderer/config-modal.ts +1 -1
  158. package/src/renderer/context-inspector.ts +1 -1
  159. package/src/renderer/conversation-layout.ts +2 -2
  160. package/src/renderer/conversation-overlays.ts +1 -1
  161. package/src/renderer/conversation-surface.ts +2 -2
  162. package/src/renderer/diff-view.ts +1 -1
  163. package/src/renderer/diff.ts +1 -1
  164. package/src/renderer/file-picker-overlay.ts +1 -1
  165. package/src/renderer/fleet-tab-strip.ts +1 -1
  166. package/src/renderer/fullscreen-primitives.ts +2 -2
  167. package/src/renderer/fullscreen-workspace.ts +1 -1
  168. package/src/renderer/header-line.ts +1 -1
  169. package/src/renderer/help-overlay.ts +1 -1
  170. package/src/renderer/history-search-overlay.ts +2 -2
  171. package/src/renderer/layout.ts +5 -8
  172. package/src/renderer/markdown-inline.ts +1 -1
  173. package/src/renderer/markdown-table.ts +1 -1
  174. package/src/renderer/markdown.ts +1 -1
  175. package/src/renderer/mcp-workspace.ts +1 -1
  176. package/src/renderer/modal-factory.ts +2 -2
  177. package/src/renderer/model-workspace.ts +2 -2
  178. package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
  179. package/src/renderer/overlay-box.ts +1 -1
  180. package/src/renderer/panel-composite.ts +1 -1
  181. package/src/renderer/panel-workspace-bar.ts +1 -1
  182. package/src/renderer/process-indicator.ts +1 -1
  183. package/src/renderer/profile-picker-modal.ts +1 -1
  184. package/src/renderer/search-overlay.ts +2 -2
  185. package/src/renderer/selection-modal-overlay.ts +1 -1
  186. package/src/renderer/session-picker-modal.ts +124 -3
  187. package/src/renderer/settings-modal-helpers.ts +2 -0
  188. package/src/renderer/settings-modal.ts +2 -2
  189. package/src/renderer/shell-surface.ts +2 -2
  190. package/src/renderer/system-message.ts +1 -1
  191. package/src/renderer/tab-strip.ts +1 -1
  192. package/src/renderer/theme-mode-config.ts +1 -1
  193. package/src/renderer/theme.ts +11 -12
  194. package/src/renderer/thinking.ts +1 -1
  195. package/src/renderer/tool-call.ts +2 -2
  196. package/src/renderer/tool-result-expanded-lines.ts +1 -1
  197. package/src/renderer/turn-injection.ts +7 -8
  198. package/src/renderer/ui-factory.ts +3 -3
  199. package/src/runtime/bootstrap-command-context.ts +4 -4
  200. package/src/runtime/bootstrap-command-parts.ts +5 -5
  201. package/src/runtime/bootstrap-core.ts +30 -30
  202. package/src/runtime/bootstrap-shell.ts +4 -4
  203. package/src/runtime/bootstrap.ts +128 -157
  204. package/src/runtime/client/approval-updates.ts +82 -0
  205. package/src/runtime/client/build-floors.ts +167 -0
  206. package/src/runtime/client/daemon-attach-handshake.ts +115 -0
  207. package/src/runtime/client/fleet-union.ts +147 -0
  208. package/src/runtime/client/host-service-status.ts +71 -0
  209. package/src/runtime/client/hosted-exit.ts +86 -0
  210. package/src/runtime/client/hosted-roster.ts +110 -0
  211. package/src/runtime/client/hosted-session-stream.ts +178 -0
  212. package/src/runtime/client/hosted-sessions.ts +187 -0
  213. package/src/runtime/client/operator-endpoint.ts +213 -0
  214. package/src/runtime/client/spine-adoption.ts +99 -0
  215. package/src/runtime/cloudflare-control-plane.ts +1 -1
  216. package/src/runtime/context-accounting-source.ts +1 -1
  217. package/src/runtime/context.ts +2 -2
  218. package/src/runtime/conversation-rewind-port.ts +42 -14
  219. package/src/runtime/daemon-attach-notices.ts +55 -19
  220. package/src/runtime/diagnostics/panels/ops.ts +1 -1
  221. package/src/runtime/disposal-wiring.ts +4 -24
  222. package/src/runtime/index.ts +119 -105
  223. package/src/runtime/install-self-check-startup.ts +2 -2
  224. package/src/runtime/interaction-seams.ts +1 -1
  225. package/src/runtime/knowledge-services.ts +8 -2
  226. package/src/runtime/legacy-daemon-migration.ts +15 -3
  227. package/src/runtime/legacy-daemon-reconcile.ts +3 -2
  228. package/src/runtime/memory-spine-transport.ts +37 -267
  229. package/src/runtime/notification-dispatch.ts +2 -2
  230. package/src/runtime/onboarding/apply.ts +2 -2
  231. package/src/runtime/onboarding/derivation.ts +2 -2
  232. package/src/runtime/onboarding/markers.ts +2 -2
  233. package/src/runtime/onboarding/progress.ts +2 -2
  234. package/src/runtime/onboarding/snapshot.ts +1 -1
  235. package/src/runtime/onboarding/state.ts +2 -2
  236. package/src/runtime/onboarding/types.ts +2 -2
  237. package/src/runtime/orchestrator-core-services.ts +1 -1
  238. package/src/runtime/path-shadow-startup.ts +28 -221
  239. package/src/runtime/power-keepawake-remote.ts +3 -2
  240. package/src/runtime/process-lifecycle.ts +2 -2
  241. package/src/runtime/provider-fallback.ts +10 -66
  242. package/src/runtime/recovery-autosave.ts +1 -1
  243. package/src/runtime/recovery-offer-wiring.ts +39 -23
  244. package/src/runtime/recovery-prompt.ts +31 -17
  245. package/src/runtime/relay-reachability-bridge.ts +53 -42
  246. package/src/runtime/release-artifacts.ts +2 -1
  247. package/src/runtime/runtime-services-types.ts +82 -35
  248. package/src/runtime/services.ts +305 -300
  249. package/src/runtime/session-resume-liveness-confirm.ts +1 -1
  250. package/src/runtime/ui-services.ts +7 -6
  251. package/src/runtime/update-check.ts +23 -43
  252. package/src/runtime/workspace-checkpointing.ts +1 -1
  253. package/src/runtime/wrfc-persistence.ts +2 -2
  254. package/src/shell/ui-openers.ts +30 -7
  255. package/src/utils/clipboard.ts +1 -1
  256. package/src/verification/verification-ledger.ts +10 -8
  257. package/src/version.ts +1 -1
  258. package/bin/goodvibes-daemon +0 -90
  259. package/src/cli/config-overrides.ts +0 -267
  260. package/src/cli/endpoints.ts +0 -109
  261. package/src/cli/parser.ts +0 -395
  262. package/src/cli/redaction.ts +0 -170
  263. package/src/cli/types.ts +0 -84
  264. package/src/cluster/commands.ts +0 -382
  265. package/src/cluster/remote-daemon-target.ts +0 -225
  266. package/src/cluster/render.ts +0 -268
  267. package/src/config/atomic-write.ts +0 -70
  268. package/src/config/credential-availability.ts +0 -122
  269. package/src/config/goodvibes-home.ts +0 -149
  270. package/src/config/index.ts +0 -88
  271. package/src/config/provider-model.ts +0 -23
  272. package/src/config/read-versioned.ts +0 -228
  273. package/src/core/alert-gating.ts +0 -67
  274. package/src/core/consolidation-receipt.ts +0 -41
  275. package/src/core/focus-tracker.ts +0 -41
  276. package/src/core/history.ts +0 -45
  277. package/src/core/memory-status.ts +0 -118
  278. package/src/core/orchestrator.ts +0 -7
  279. package/src/core/pairing-devices.ts +0 -49
  280. package/src/core/pairing-handoff.ts +0 -101
  281. package/src/core/pairing-offers.ts +0 -83
  282. package/src/core/pairing-origin.ts +0 -78
  283. package/src/core/rewind-turn-anchors.ts +0 -311
  284. package/src/core/session-recovery.ts +0 -210
  285. package/src/core/stable-host.ts +0 -171
  286. package/src/core/transcript-journal.ts +0 -503
  287. package/src/daemon/cli.ts +0 -641
  288. package/src/daemon/handlers/context.ts +0 -29
  289. package/src/daemon/handlers/contracts.ts +0 -77
  290. package/src/daemon/handlers/credentials.ts +0 -139
  291. package/src/daemon/handlers/drafts/draft-store.ts +0 -427
  292. package/src/daemon/handlers/drafts/index.ts +0 -17
  293. package/src/daemon/handlers/drafts/register.ts +0 -331
  294. package/src/daemon/handlers/errors.ts +0 -18
  295. package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
  296. package/src/daemon/handlers/inbox/index.ts +0 -284
  297. package/src/daemon/handlers/inbox/mapping.ts +0 -192
  298. package/src/daemon/handlers/inbox/poller.ts +0 -212
  299. package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
  300. package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
  301. package/src/daemon/handlers/inbox/providers/email.ts +0 -152
  302. package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
  303. package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
  304. package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
  305. package/src/daemon/handlers/index.ts +0 -117
  306. package/src/daemon/handlers/register.ts +0 -168
  307. package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
  308. package/src/daemon/handlers/remote/backends/docker.ts +0 -79
  309. package/src/daemon/handlers/remote/backends/index.ts +0 -40
  310. package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
  311. package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
  312. package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
  313. package/src/daemon/handlers/remote/backends/types.ts +0 -97
  314. package/src/daemon/handlers/remote/dispatcher.ts +0 -181
  315. package/src/daemon/handlers/remote/index.ts +0 -119
  316. package/src/daemon/handlers/remote/peer-registry.ts +0 -357
  317. package/src/daemon/handlers/remote/service.ts +0 -191
  318. package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
  319. package/src/daemon/handlers/routing/index.ts +0 -261
  320. package/src/daemon/handlers/routing/route-store.ts +0 -319
  321. package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
  322. package/src/daemon/handlers/sqlite-store.ts +0 -278
  323. package/src/daemon/handlers/triage/index.ts +0 -57
  324. package/src/daemon/handlers/triage/integration.ts +0 -213
  325. package/src/daemon/handlers/triage/pipeline.ts +0 -274
  326. package/src/daemon/handlers/triage/scorer.ts +0 -287
  327. package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
  328. package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
  329. package/src/daemon/handlers/triage/tagger/index.ts +0 -184
  330. package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
  331. package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
  332. package/src/daemon/handlers/triage/types.ts +0 -50
  333. package/src/daemon/lifecycle.ts +0 -41
  334. package/src/daemon/provision-wake-model.ts +0 -81
  335. package/src/daemon/safe-serve.ts +0 -61
  336. package/src/daemon/send/channels.ts +0 -200
  337. package/src/daemon/send/command.ts +0 -332
  338. package/src/daemon/send/composition.ts +0 -99
  339. package/src/daemon/send/failure-text.ts +0 -93
  340. package/src/daemon/send/inert-text.ts +0 -225
  341. package/src/daemon/send/stdin.ts +0 -24
  342. package/src/daemon/service-commands.ts +0 -329
  343. package/src/export/cost-utils.ts +0 -319
  344. package/src/input/selection.ts +0 -135
  345. package/src/plugins/loader.ts +0 -15
  346. package/src/renderer/bottom-bar.ts +0 -58
  347. package/src/renderer/conversation-tree.ts +0 -228
  348. package/src/runtime/agent-graph-composition.ts +0 -78
  349. package/src/runtime/channel-composition.ts +0 -46
  350. package/src/runtime/cluster-composition.ts +0 -124
  351. package/src/runtime/cluster-group-composition.ts +0 -284
  352. package/src/runtime/code-index-services.ts +0 -167
  353. package/src/runtime/daemon-handler-composition.ts +0 -76
  354. package/src/runtime/device-posture-composition.ts +0 -110
  355. package/src/runtime/durability-housekeeping.ts +0 -183
  356. package/src/runtime/durability-services.ts +0 -155
  357. package/src/runtime/embedded-service-factories.ts +0 -58
  358. package/src/runtime/feature-settings.ts +0 -154
  359. package/src/runtime/fleet-needs-input-push.ts +0 -70
  360. package/src/runtime/fleet-services.ts +0 -41
  361. package/src/runtime/idle-power-services.ts +0 -85
  362. package/src/runtime/mail-composition.ts +0 -65
  363. package/src/runtime/memory-fold.ts +0 -55
  364. package/src/runtime/operator-token-cleanup.ts +0 -109
  365. package/src/runtime/path-shadow.ts +0 -418
  366. package/src/runtime/perf/panel-health-monitor.ts +0 -18
  367. package/src/runtime/provider-optimizer-wiring.ts +0 -55
  368. package/src/runtime/reachability-notice.ts +0 -100
  369. package/src/runtime/remote-execution-composition.ts +0 -62
  370. package/src/runtime/session-liveness-marker.ts +0 -257
  371. package/src/runtime/session-pointer-surface.ts +0 -22
  372. package/src/runtime/session-storage-services.ts +0 -41
  373. package/src/runtime/surface-feature-flags.ts +0 -96
  374. package/src/runtime/terminal-output-guard.ts +0 -235
  375. package/src/runtime/trust/workspace-registration.ts +0 -192
  376. package/src/runtime/trust/workspace-trust.ts +0 -229
  377. package/src/runtime/ui/index.ts +0 -39
  378. package/src/runtime/ui/model-picker/data-provider.ts +0 -182
  379. package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
  380. package/src/runtime/ui/model-picker/index.ts +0 -59
  381. package/src/runtime/ui/model-picker/types.ts +0 -153
  382. package/src/runtime/ui/provider-health/data-provider.ts +0 -244
  383. package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
  384. package/src/runtime/ui/provider-health/index.ts +0 -46
  385. package/src/runtime/ui/provider-health/types.ts +0 -146
  386. package/src/runtime/ui-events.ts +0 -1
  387. package/src/runtime/ui-read-model-helpers.ts +0 -1
  388. package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
  389. package/src/runtime/ui-read-models-observability-options.ts +0 -1
  390. package/src/runtime/ui-read-models-observability-remote.ts +0 -1
  391. package/src/runtime/ui-read-models-observability-security.ts +0 -1
  392. package/src/runtime/ui-read-models-observability-system.ts +0 -1
  393. package/src/runtime/ui-read-models-observability.ts +0 -1
  394. package/src/runtime/ui-service-queries.ts +0 -1
  395. package/src/runtime/voice-setup-services.ts +0 -98
  396. package/src/runtime/workstream-attempts-validation.ts +0 -77
  397. package/src/runtime/workstream-draft-edits.ts +0 -95
  398. package/src/runtime/workstream-draft-store.ts +0 -274
  399. package/src/runtime/workstream-draft-types.ts +0 -42
  400. package/src/runtime/workstream-services.ts +0 -373
  401. package/src/tools/index.ts +0 -1
  402. package/src/types/grid.ts +0 -48
  403. package/src/types/sql-js.d.ts +0 -15
  404. package/src/work-plans/work-plan-store.ts +0 -702
@@ -1,117 +0,0 @@
1
- /**
2
- * Composition root for the daemon handler layer — the only module that
3
- * `src/runtime/services.ts` imports. It assembles every surface (routing,
4
- * inbox+triage, drafts, calendar, email, remote) onto the SDK gateway catalog
5
- * and returns a single teardown plus the cross-surface handles the runtime
6
- * needs (routing resolver, the remote `DistributedRuntimeRouteService` the SDK
7
- * facade injects, and the `remote.peers.invoke` dispatch adapter).
8
- *
9
- * Surfaces are provided by the caller as `SurfaceRegister` functions so this
10
- * foundation module stays free of import cycles and does not author any SDK
11
- * descriptor or schema. Registration order is fixed; teardown runs in reverse.
12
- */
13
- import type { DistributedRuntimeRouteService } from './contracts.ts';
14
- import type { HandlerContext, SurfaceRegister } from './context.ts';
15
- import type { Unregister } from './register.ts';
16
-
17
- /** Routing surface handle: teardown plus the resolver other surfaces consume. */
18
- export interface RoutingRegistration {
19
- readonly unregister: Unregister;
20
- /** Resolve an inbound channel target to a profile id (exact → wildcard → null). */
21
- readonly resolveProfileId: (surfaceKind: string, routeId?: string) => string | null;
22
- }
23
-
24
- /** Adapter the runtime wires into the published `remote.peers.invoke` route. */
25
- export interface RemoteInvokeAdapter {
26
- invoke(input: Record<string, unknown>): Promise<unknown>;
27
- }
28
-
29
- /** Remote surface handle: the host service the SDK facade injects + its teardown. */
30
- export interface RemoteSurfaceRegistration {
31
- readonly unregister: Unregister;
32
- readonly service: DistributedRuntimeRouteService;
33
- readonly dispatch: RemoteInvokeAdapter;
34
- }
35
-
36
- /** Aggregate result returned to the runtime for teardown and cross-surface wiring. */
37
- export interface DaemonHandlerSurfaces {
38
- readonly unregister: Unregister;
39
- readonly routing: RoutingRegistration;
40
- readonly remoteSurface: { readonly service: DistributedRuntimeRouteService };
41
- readonly remoteDispatch: RemoteInvokeAdapter;
42
- }
43
-
44
- /**
45
- * The surface implementations the runtime supplies. Each builds its stores and
46
- * attaches handlers to the SDK catalog via `registerCatalogHandler(s)`.
47
- *
48
- * Order of composition (and reverse teardown) is enforced by
49
- * `registerDaemonHandlers`: routing → inbox(+triage) → drafts → calendar →
50
- * email → remote.
51
- */
52
- export interface DaemonHandlerSurfaceProviders {
53
- /** channels.routing.* — returns the resolver consumed by the inbox surface. */
54
- readonly registerRouting: (ctx: HandlerContext) => RoutingRegistration;
55
- /** channels.inbox.list (triage-decorated) + inbox.triage.* (daemon-internal). */
56
- readonly registerInbox: (ctx: HandlerContext, routing: RoutingRegistration) => Unregister;
57
- /** channels.drafts.* */
58
- readonly registerDrafts: SurfaceRegister;
59
- /** remote.peers.* — supplies the host DistributedRuntimeRouteService + dispatch adapter. */
60
- readonly registerRemote: (ctx: HandlerContext) => RemoteSurfaceRegistration;
61
- }
62
-
63
- /**
64
- * Compose all daemon handler surfaces onto the gateway catalog held by `ctx`.
65
- * Returns a single teardown (reverse order, best-effort) and the handles the
66
- * runtime must expose: the routing registration, the remote service the SDK
67
- * facade injects into `DaemonRemoteRouteContext.distributedRuntime`, and the
68
- * remote invoke dispatch adapter.
69
- */
70
- export function registerDaemonHandlers(
71
- ctx: HandlerContext,
72
- providers: DaemonHandlerSurfaceProviders,
73
- ): DaemonHandlerSurfaces {
74
- const teardowns: Unregister[] = [];
75
-
76
- const routing = providers.registerRouting(ctx);
77
- teardowns.push(routing.unregister);
78
-
79
- teardowns.push(providers.registerInbox(ctx, routing));
80
- teardowns.push(providers.registerDrafts(ctx));
81
- // calendar.* and email.* are NOT registered here any more. Both are served
82
- // by the SDK (control-plane/routes/{calendar,email}.ts over the platform
83
- // CalDAV/Google and IMAP/SMTP implementations), registered through
84
- // registerGatewayVerbGroups in runtime/services.ts. This product used to
85
- // carry its own handlers for the same descriptor ids and, registering later,
86
- // won — two implementations behind one path, which is the drift the hoist
87
- // exists to end.
88
-
89
- const remote = providers.registerRemote(ctx);
90
- teardowns.push(remote.unregister);
91
-
92
- // Idempotent: teardown is reachable from more than one shutdown path now that
93
- // the runtime disposal scope owns it, and the surfaces underneath are not all
94
- // safe to unwind twice — the inbox surface closes a SQLite handle, which a
95
- // second pass would close again inside a floating promise (an unhandled
96
- // rejection, not a caught one). Running once is also simply the honest
97
- // meaning of "release these surfaces".
98
- let torn = false;
99
- const unregister: Unregister = () => {
100
- if (torn) return;
101
- torn = true;
102
- for (let i = teardowns.length - 1; i >= 0; i -= 1) {
103
- try {
104
- teardowns[i]!();
105
- } catch (error) {
106
- ctx.logger.warn('daemon handler surface teardown failed', { error });
107
- }
108
- }
109
- };
110
-
111
- return {
112
- unregister,
113
- routing,
114
- remoteSurface: { service: remote.service },
115
- remoteDispatch: remote.dispatch,
116
- };
117
- }
@@ -1,168 +0,0 @@
1
- /**
2
- * Linchpin helper that binds a typed host handler to an SDK-registered gateway
3
- * method descriptor BY ID.
4
- *
5
- * The SDK's `GatewayMethodCatalog` constructor auto-registers every builtin
6
- * descriptor (channels.* / email.* / calendar.* / ...) with `handler:undefined`.
7
- * The host attaches its implementation by looking up that canonical descriptor
8
- * via `catalog.get(id)` and re-registering it WITH the handler using
9
- * `{ replace: true }`. Only the handler slot changes; the SDK's id, schema,
10
- * access, scopes, and dangerous flags are preserved verbatim. No descriptor or
11
- * schema is ever authored here.
12
- */
13
- import type {
14
- GatewayMethodCatalog,
15
- GatewayMethodInvocation,
16
- GatewayMethodInvocationContext,
17
- } from './contracts.ts';
18
- import { HandlerError, REQUIRE_CONFIRM } from './errors.ts';
19
-
20
- /** Function returned by every registration; calling it removes the attached handler. */
21
- export type Unregister = () => void;
22
-
23
- /** Normalized, host-facing principal/auth context derived from the SDK invocation. */
24
- export interface HandlerContextEnvelope {
25
- readonly principalId: string;
26
- readonly admin: boolean;
27
- readonly scopes: string[];
28
- readonly explicitUserRequest: boolean;
29
- readonly authToken: string;
30
- }
31
-
32
- /** Typed, host-facing shape of a single method invocation. */
33
- export interface HandlerInvocation<TBody> {
34
- readonly body: TBody;
35
- readonly query: Record<string, string>;
36
- readonly context: HandlerContextEnvelope;
37
- }
38
-
39
- /** A host handler: receives the typed invocation, returns the method result. */
40
- export type TypedHandler<TBody, TResult> = (
41
- input: HandlerInvocation<TBody>,
42
- ) => Promise<TResult>;
43
-
44
- export interface RegisterHandlerOptions {
45
- /**
46
- * When true, the wrapper enforces a confirmation gate before the handler
47
- * runs: `body.confirm === true` AND `context.explicitUserRequest === true`.
48
- */
49
- readonly confirm?: boolean;
50
- }
51
-
52
- function errorMessage(error: unknown): string {
53
- if (error instanceof Error) return error.message;
54
- return String(error);
55
- }
56
-
57
- /**
58
- * Derive the host-facing context envelope from the raw SDK invocation context.
59
- * `explicitUserRequest` is carried in `context.metadata.explicitUserRequest`.
60
- */
61
- export function normalizeContext(c: GatewayMethodInvocationContext): HandlerContextEnvelope {
62
- const metadata = c.metadata ?? {};
63
- return {
64
- principalId: c.principalId ?? '',
65
- admin: c.admin === true,
66
- scopes: c.scopes ? [...c.scopes] : [],
67
- explicitUserRequest: metadata.explicitUserRequest === true,
68
- authToken: c.authToken ?? '',
69
- };
70
- }
71
-
72
- function normalizeQuery(query: GatewayMethodInvocation['query']): Record<string, string> {
73
- const out: Record<string, string> = {};
74
- if (!query) return out;
75
- for (const [key, value] of Object.entries(query)) {
76
- if (typeof value === 'string') out[key] = value;
77
- else if (value != null) out[key] = String(value);
78
- }
79
- return out;
80
- }
81
-
82
- /**
83
- * Guard a confirmation-gated mutation. Throws `HandlerError(REQUIRE_CONFIRM, 403)`
84
- * unless the caller both set `body.confirm === true` and the request was an
85
- * explicit user request.
86
- */
87
- export function assertConfirmed(
88
- body: unknown,
89
- ctx: { readonly explicitUserRequest: boolean },
90
- ): void {
91
- const confirmed =
92
- typeof body === 'object'
93
- && body !== null
94
- && (body as { confirm?: unknown }).confirm === true;
95
- if (!confirmed || ctx.explicitUserRequest !== true) {
96
- throw new HandlerError('explicit user confirmation required', REQUIRE_CONFIRM, 403);
97
- }
98
- }
99
-
100
- /**
101
- * Attach a typed handler to the SDK-registered descriptor identified by
102
- * `methodId`. Reuses the descriptor the catalog already holds and re-registers
103
- * it with the wrapped handler via `{ replace: true }`, flipping the builtin
104
- * method from HTTP-fallback to in-process execution.
105
- */
106
- export function registerCatalogHandler<TBody, TResult>(
107
- catalog: GatewayMethodCatalog,
108
- methodId: string,
109
- handler: TypedHandler<TBody, TResult>,
110
- options?: RegisterHandlerOptions,
111
- ): Unregister {
112
- const descriptor = catalog.get(methodId);
113
- if (!descriptor) {
114
- // 'METHOD_NOT_FOUND' (not the old locally-coined 'UNKNOWN_METHOD') so this lines
115
- // up byte-for-byte with SDKErrorCodes.METHOD_NOT_FOUND — the code the SDK's own
116
- // uncataloged-method 404 now carries (method-catalog.ts's GatewayMethodCatalog
117
- // .invoke(), daemon/control-plane.ts's invokeGatewayMethodCall, and daemon-sdk's
118
- // control-routes.ts getGatewayMethod/invokeGatewayMethod). A literal string, not
119
- // an import of SDKErrorCodes: the pinned SDK (0.38.0) predates that constant, and
120
- // matching the value this way needs no SDK version bump to stay aligned.
121
- throw new HandlerError(`Unknown gateway method: ${methodId}`, 'METHOD_NOT_FOUND', 404);
122
- }
123
-
124
- const wrapped = async (inv: GatewayMethodInvocation): Promise<unknown> => {
125
- const context = normalizeContext(inv.context);
126
- const body = inv.body as TBody;
127
- if (options?.confirm) assertConfirmed(inv.body, context);
128
- try {
129
- return await handler({ body, query: normalizeQuery(inv.query), context });
130
- } catch (error) {
131
- if (error instanceof HandlerError) throw error;
132
- throw new HandlerError(errorMessage(error), 'HANDLER_FAILED', 500);
133
- }
134
- };
135
-
136
- return catalog.register(descriptor, wrapped, { replace: true });
137
- }
138
-
139
- /** A single id→handler binding for batch registration. */
140
- export interface CatalogHandlerEntry {
141
- readonly id: string;
142
- readonly handler: TypedHandler<unknown, unknown>;
143
- readonly options?: RegisterHandlerOptions;
144
- }
145
-
146
- /**
147
- * Register many handlers at once. Returns a single `Unregister` that tears them
148
- * down in REVERSE registration order (best-effort: a failing teardown never
149
- * aborts the rest).
150
- */
151
- export function registerCatalogHandlers(
152
- catalog: GatewayMethodCatalog,
153
- entries: readonly CatalogHandlerEntry[],
154
- ): Unregister {
155
- const teardowns: Unregister[] = [];
156
- for (const entry of entries) {
157
- teardowns.push(registerCatalogHandler(catalog, entry.id, entry.handler, entry.options));
158
- }
159
- return () => {
160
- for (let i = teardowns.length - 1; i >= 0; i -= 1) {
161
- try {
162
- teardowns[i]!();
163
- } catch {
164
- // best-effort teardown; continue unwinding the rest
165
- }
166
- }
167
- };
168
- }
@@ -1,142 +0,0 @@
1
- import { mkdir, writeFile, chmod, rm } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
- import { randomBytes } from 'node:crypto';
4
- import type { PeerRecord } from '../peer-registry.ts';
5
- import type { CloudTerminalBackendConfig } from '../peer-registry.ts';
6
- import {
7
- type Backend,
8
- type BackendContext,
9
- type BackendDispatchResult,
10
- type DispatchPayload,
11
- BackendDispatchError,
12
- resolveTimeout,
13
- buildRemoteShellCommand,
14
- } from './types.ts';
15
- import { runProcess } from './process-runner.ts';
16
- import { tokenizeCommand } from './local-process.ts';
17
-
18
- /**
19
- * Cloud-terminal backend: executes a command in a managed cloud shell / VM via
20
- * the provider CLI (gcloud / aws / az). The provider credential is resolved from
21
- * the daemon credential store and supplied to the CLI via a 0600 credentials
22
- * file or a provider-specific env var — never as an argv token, never logged.
23
- */
24
- export function createCloudTerminalBackend(ctx: BackendContext): Backend {
25
- const credDir = join(ctx.homeDirectory, '.goodvibes', 'tui', 'operator', 'cloud-creds');
26
-
27
- async function writeCredentialFile(peerId: string, value: string): Promise<string> {
28
- await mkdir(credDir, { recursive: true });
29
- await chmod(credDir, 0o700).catch(() => {});
30
- const suffix = randomBytes(4).toString('hex');
31
- const path = join(credDir, `${peerId}.${suffix}.cred`);
32
- await writeFile(path, value, { mode: 0o600 });
33
- await chmod(path, 0o600).catch(() => {});
34
- return path;
35
- }
36
-
37
- function buildArgs(
38
- config: CloudTerminalBackendConfig,
39
- remoteCommand: string,
40
- ): { args: string[]; credEnvKey?: string } {
41
- switch (config.provider) {
42
- case 'gcp': {
43
- // gcloud compute ssh runs `command` on the target Cloud Shell / instance.
44
- const args = ['gcloud', 'compute', 'ssh'];
45
- if (config.projectId) args.push('--project', config.projectId);
46
- if (config.location) args.push('--zone', config.location);
47
- args.push(config.instance ?? 'cloudshell', '--command', remoteCommand);
48
- return { args, credEnvKey: 'CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE' };
49
- }
50
- case 'aws': {
51
- // aws ssm send-command style: run shell command on a managed instance.
52
- const args = ['aws', 'ssm', 'start-session'];
53
- if (config.location) args.push('--region', config.location);
54
- if (config.instance) args.push('--target', config.instance);
55
- args.push(
56
- '--document-name', 'AWS-StartInteractiveCommand',
57
- '--parameters', `command=${remoteCommand}`,
58
- );
59
- return { args, credEnvKey: 'AWS_SHARED_CREDENTIALS_FILE' };
60
- }
61
- case 'azure': {
62
- // az vm run-command invoke executes a script on the target VM.
63
- const args = ['az', 'vm', 'run-command', 'invoke'];
64
- if (config.projectId) args.push('--resource-group', config.projectId);
65
- if (config.instance) args.push('--name', config.instance);
66
- args.push(
67
- '--command-id', 'RunShellScript',
68
- '--scripts', remoteCommand,
69
- );
70
- return { args, credEnvKey: 'AZURE_AUTH_LOCATION' };
71
- }
72
- default:
73
- throw new BackendDispatchError(
74
- `Unsupported cloud provider: ${String(config.provider)}`,
75
- 'REMOTE_BACKEND_UNSUPPORTED_PROVIDER',
76
- );
77
- }
78
- }
79
-
80
- return {
81
- kind: 'cloud-terminal',
82
- async dispatch(
83
- peer: PeerRecord,
84
- command: string,
85
- payload?: DispatchPayload,
86
- ): Promise<BackendDispatchResult> {
87
- if (peer.backendConfig.kind !== 'cloud-terminal') {
88
- throw new BackendDispatchError(
89
- `Peer '${peer.peerId}' is not a cloud-terminal peer.`,
90
- 'REMOTE_BACKEND_KIND_MISMATCH',
91
- );
92
- }
93
- const config = peer.backendConfig as { kind: 'cloud-terminal' } & CloudTerminalBackendConfig;
94
- if (tokenizeCommand(command).length === 0) {
95
- throw new BackendDispatchError('Empty command.', 'REMOTE_BACKEND_BAD_COMMAND');
96
- }
97
- const credential = await ctx.credentials.resolveRef(config.credentialRef);
98
- if (!credential || credential.length === 0) {
99
- throw new BackendDispatchError(
100
- `Could not resolve cloud credential for peer '${peer.peerId}'.`,
101
- 'REMOTE_BACKEND_CREDENTIAL_MISSING',
102
- );
103
- }
104
- const remoteCommand = buildRemoteShellCommand(command, payload?.args);
105
- const { args, credEnvKey } = buildArgs(config, remoteCommand);
106
- const credPath = await writeCredentialFile(peer.peerId, credential);
107
- const env: Record<string, string> = { ...(payload?.env ?? {}) };
108
- if (credEnvKey) env[credEnvKey] = credPath;
109
-
110
- ctx.logger.info('remote cloud-terminal dispatch', {
111
- peerId: peer.peerId,
112
- provider: config.provider,
113
- });
114
- try {
115
- const result = await runProcess({
116
- args,
117
- timeoutMs: resolveTimeout(payload),
118
- env,
119
- ...(payload?.stdin !== undefined ? { stdin: payload.stdin } : {}),
120
- });
121
- return {
122
- exitCode: result.timedOut ? 124 : result.exitCode,
123
- stdout: result.stdout,
124
- stderr: result.timedOut
125
- ? `${result.stderr}\n[remote] cloud command timed out`
126
- : result.stderr,
127
- };
128
- } finally {
129
- // The plaintext provider credential file is single-use: remove it as
130
- // soon as the CLI has run (or failed) so credentials never accumulate
131
- // on disk under cloud-creds/.
132
- await rm(credPath, { force: true }).catch(() => {});
133
- }
134
- },
135
- async teardown(): Promise<void> {
136
- // Per-invocation cred files are already removed in dispatch's finally;
137
- // sweep the cloud-creds/ dir on teardown to clear any file orphaned by a
138
- // hard crash mid-dispatch so no provider credential outlives the daemon.
139
- await rm(credDir, { recursive: true, force: true }).catch(() => {});
140
- },
141
- };
142
- }
@@ -1,79 +0,0 @@
1
- import type { PeerRecord } from '../peer-registry.ts';
2
- import type { DockerBackendConfig } from '../peer-registry.ts';
3
- import {
4
- type Backend,
5
- type BackendContext,
6
- type BackendDispatchResult,
7
- type DispatchPayload,
8
- BackendDispatchError,
9
- resolveTimeout,
10
- buildRemoteShellCommand,
11
- } from './types.ts';
12
- import { runProcess } from './process-runner.ts';
13
- import { tokenizeCommand } from './local-process.ts';
14
-
15
- /**
16
- * Docker backend: runs `docker exec {containerName} {command}` against the local
17
- * Docker socket (or a configured DOCKER_HOST). The command is executed inside
18
- * the target container via `sh -c` so shell semantics survive the hop, while the
19
- * docker argv itself is fully tokenized (no shell on the daemon side).
20
- */
21
- export function createDockerBackend(ctx: BackendContext): Backend {
22
- return {
23
- kind: 'docker',
24
- async dispatch(
25
- peer: PeerRecord,
26
- command: string,
27
- payload?: DispatchPayload,
28
- ): Promise<BackendDispatchResult> {
29
- if (peer.backendConfig.kind !== 'docker') {
30
- throw new BackendDispatchError(
31
- `Peer '${peer.peerId}' is not a docker peer.`,
32
- 'REMOTE_BACKEND_KIND_MISMATCH',
33
- );
34
- }
35
- const config = peer.backendConfig as { kind: 'docker' } & DockerBackendConfig;
36
- if (tokenizeCommand(command).length === 0) {
37
- throw new BackendDispatchError('Empty command.', 'REMOTE_BACKEND_BAD_COMMAND');
38
- }
39
-
40
- // Resolve DOCKER_HOST. When it is a secret reference, pull the real value
41
- // from the credential store and pass it via env (never argv).
42
- const env: Record<string, string> = { ...(payload?.env ?? {}) };
43
- if (config.dockerHost) {
44
- const resolved = config.dockerHost.startsWith('goodvibes://')
45
- ? await ctx.credentials.resolveRef(config.dockerHost)
46
- : config.dockerHost;
47
- if (!resolved) {
48
- throw new BackendDispatchError(
49
- `Could not resolve dockerHost for peer '${peer.peerId}'.`,
50
- 'REMOTE_BACKEND_CREDENTIAL_MISSING',
51
- );
52
- }
53
- env.DOCKER_HOST = resolved;
54
- }
55
-
56
- const innerCommand = buildRemoteShellCommand(command, payload?.args);
57
-
58
- const args = ['docker', 'exec'];
59
- if (payload?.stdin !== undefined) args.push('-i');
60
- args.push(config.containerName, 'sh', '-c', innerCommand);
61
-
62
- ctx.logger.info('remote docker dispatch', {
63
- peerId: peer.peerId,
64
- container: config.containerName,
65
- });
66
- const result = await runProcess({
67
- args,
68
- timeoutMs: resolveTimeout(payload),
69
- env,
70
- ...(payload?.stdin !== undefined ? { stdin: payload.stdin } : {}),
71
- });
72
- return {
73
- exitCode: result.timedOut ? 124 : result.exitCode,
74
- stdout: result.stdout,
75
- stderr: result.timedOut ? `${result.stderr}\n[remote] docker exec timed out` : result.stderr,
76
- };
77
- },
78
- };
79
- }
@@ -1,40 +0,0 @@
1
- import type { PeerRecord } from '../peer-registry.ts';
2
- import { type Backend, type BackendContext } from './types.ts';
3
- import { createLocalProcessBackend } from './local-process.ts';
4
- import { createDockerBackend } from './docker.ts';
5
- import { createSshBackend } from './ssh.ts';
6
- import { createCloudTerminalBackend } from './cloud-terminal.ts';
7
-
8
- export type {
9
- Backend,
10
- BackendContext,
11
- BackendDispatchResult,
12
- DispatchPayload,
13
- } from './types.ts';
14
- export {
15
- BackendDispatchError,
16
- DEFAULT_SYNC_TIMEOUT_MS,
17
- MAX_SYNC_TIMEOUT_MS,
18
- resolveTimeout,
19
- } from './types.ts';
20
-
21
- /**
22
- * Build the full backend map keyed by backendKind. Each backend resolves its
23
- * own credentials lazily from the daemon credential store on dispatch; no
24
- * network or process work happens at construction time.
25
- */
26
- export function createBackends(
27
- ctx: BackendContext,
28
- ): Map<PeerRecord['backendKind'], Backend> {
29
- const backends: Backend[] = [
30
- createLocalProcessBackend(ctx),
31
- createDockerBackend(ctx),
32
- createSshBackend(ctx),
33
- createCloudTerminalBackend(ctx),
34
- ];
35
- const map = new Map<PeerRecord['backendKind'], Backend>();
36
- for (const backend of backends) {
37
- map.set(backend.kind, backend);
38
- }
39
- return map;
40
- }
@@ -1,113 +0,0 @@
1
- import type { PeerRecord } from '../peer-registry.ts';
2
- import type { LocalProcessBackendConfig } from '../peer-registry.ts';
3
- import {
4
- type Backend,
5
- type BackendContext,
6
- type BackendDispatchResult,
7
- type DispatchPayload,
8
- BackendDispatchError,
9
- resolveTimeout,
10
- } from './types.ts';
11
- import { runProcess } from './process-runner.ts';
12
-
13
- /** Split a command string into argv, honoring single/double quotes. */
14
- export function tokenizeCommand(command: string): string[] {
15
- const tokens: string[] = [];
16
- let current = '';
17
- let quote: '"' | "'" | null = null;
18
- let escaped = false;
19
- let started = false;
20
- for (const ch of command) {
21
- if (escaped) {
22
- current += ch;
23
- escaped = false;
24
- started = true;
25
- continue;
26
- }
27
- if (ch === '\\' && quote !== "'") {
28
- escaped = true;
29
- started = true;
30
- continue;
31
- }
32
- if (quote) {
33
- if (ch === quote) {
34
- quote = null;
35
- } else {
36
- current += ch;
37
- }
38
- continue;
39
- }
40
- if (ch === '"' || ch === "'") {
41
- quote = ch;
42
- started = true;
43
- continue;
44
- }
45
- if (ch === ' ' || ch === '\t' || ch === '\n') {
46
- if (started) {
47
- tokens.push(current);
48
- current = '';
49
- started = false;
50
- }
51
- continue;
52
- }
53
- current += ch;
54
- started = true;
55
- }
56
- if (started) tokens.push(current);
57
- if (quote) {
58
- throw new BackendDispatchError('Unterminated quote in command string.', 'REMOTE_BACKEND_BAD_COMMAND');
59
- }
60
- return tokens;
61
- }
62
-
63
- /**
64
- * Local-process backend: spawns the command directly on the daemon host. This is
65
- * the lowest-friction backend, used for self-hosted peers. An optional
66
- * allowlist on backendConfig restricts which executables may run.
67
- */
68
- export function createLocalProcessBackend(ctx: BackendContext): Backend {
69
- return {
70
- kind: 'local-process',
71
- async dispatch(
72
- peer: PeerRecord,
73
- command: string,
74
- payload?: DispatchPayload,
75
- ): Promise<BackendDispatchResult> {
76
- if (peer.backendConfig.kind !== 'local-process') {
77
- throw new BackendDispatchError(
78
- `Peer '${peer.peerId}' is not a local-process peer.`,
79
- 'REMOTE_BACKEND_KIND_MISMATCH',
80
- );
81
- }
82
- const config = peer.backendConfig as { kind: 'local-process' } & LocalProcessBackendConfig;
83
- const tokens = tokenizeCommand(command);
84
- if (tokens.length === 0) {
85
- throw new BackendDispatchError('Empty command.', 'REMOTE_BACKEND_BAD_COMMAND');
86
- }
87
- const executable = tokens[0]!;
88
- if (config.allowedCommands && config.allowedCommands.length > 0) {
89
- if (!config.allowedCommands.includes(executable)) {
90
- throw new BackendDispatchError(
91
- `Command '${executable}' is not in the peer allowlist.`,
92
- 'REMOTE_BACKEND_COMMAND_DENIED',
93
- );
94
- }
95
- }
96
- const args = [...tokens, ...(payload?.args ?? [])];
97
- const cwd = payload?.cwd ?? config.cwd;
98
- ctx.logger.info('remote local-process dispatch', { peerId: peer.peerId, executable });
99
- const result = await runProcess({
100
- args,
101
- timeoutMs: resolveTimeout(payload),
102
- ...(cwd !== undefined ? { cwd } : {}),
103
- ...(payload?.env !== undefined ? { env: payload.env } : {}),
104
- ...(payload?.stdin !== undefined ? { stdin: payload.stdin } : {}),
105
- });
106
- return {
107
- exitCode: result.timedOut ? 124 : result.exitCode,
108
- stdout: result.stdout,
109
- stderr: result.timedOut ? `${result.stderr}\n[remote] command timed out` : result.stderr,
110
- };
111
- },
112
- };
113
- }