@pellux/goodvibes-tui 1.27.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/CHANGELOG.md +127 -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 +3 -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 +9 -122
  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 +21 -33
  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 +4 -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 -693
  288. package/src/daemon/fatal-boot-report.ts +0 -111
  289. package/src/daemon/handlers/context.ts +0 -29
  290. package/src/daemon/handlers/contracts.ts +0 -77
  291. package/src/daemon/handlers/credentials.ts +0 -139
  292. package/src/daemon/handlers/drafts/draft-store.ts +0 -427
  293. package/src/daemon/handlers/drafts/index.ts +0 -17
  294. package/src/daemon/handlers/drafts/register.ts +0 -331
  295. package/src/daemon/handlers/errors.ts +0 -18
  296. package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
  297. package/src/daemon/handlers/inbox/index.ts +0 -284
  298. package/src/daemon/handlers/inbox/mapping.ts +0 -192
  299. package/src/daemon/handlers/inbox/poller.ts +0 -212
  300. package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
  301. package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
  302. package/src/daemon/handlers/inbox/providers/email.ts +0 -152
  303. package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
  304. package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
  305. package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
  306. package/src/daemon/handlers/index.ts +0 -117
  307. package/src/daemon/handlers/register.ts +0 -168
  308. package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
  309. package/src/daemon/handlers/remote/backends/docker.ts +0 -79
  310. package/src/daemon/handlers/remote/backends/index.ts +0 -40
  311. package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
  312. package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
  313. package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
  314. package/src/daemon/handlers/remote/backends/types.ts +0 -97
  315. package/src/daemon/handlers/remote/dispatcher.ts +0 -181
  316. package/src/daemon/handlers/remote/index.ts +0 -119
  317. package/src/daemon/handlers/remote/peer-registry.ts +0 -357
  318. package/src/daemon/handlers/remote/service.ts +0 -191
  319. package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
  320. package/src/daemon/handlers/routing/index.ts +0 -261
  321. package/src/daemon/handlers/routing/route-store.ts +0 -319
  322. package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
  323. package/src/daemon/handlers/sqlite-store.ts +0 -278
  324. package/src/daemon/handlers/triage/index.ts +0 -57
  325. package/src/daemon/handlers/triage/integration.ts +0 -213
  326. package/src/daemon/handlers/triage/pipeline.ts +0 -274
  327. package/src/daemon/handlers/triage/scorer.ts +0 -287
  328. package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
  329. package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
  330. package/src/daemon/handlers/triage/tagger/index.ts +0 -184
  331. package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
  332. package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
  333. package/src/daemon/handlers/triage/types.ts +0 -50
  334. package/src/daemon/lifecycle.ts +0 -41
  335. package/src/daemon/provision-wake-model.ts +0 -81
  336. package/src/daemon/safe-serve.ts +0 -61
  337. package/src/daemon/send/channels.ts +0 -200
  338. package/src/daemon/send/command.ts +0 -332
  339. package/src/daemon/send/composition.ts +0 -99
  340. package/src/daemon/send/failure-text.ts +0 -93
  341. package/src/daemon/send/inert-text.ts +0 -225
  342. package/src/daemon/send/stdin.ts +0 -24
  343. package/src/daemon/service-commands.ts +0 -329
  344. package/src/export/cost-utils.ts +0 -319
  345. package/src/input/selection.ts +0 -135
  346. package/src/plugins/loader.ts +0 -15
  347. package/src/renderer/bottom-bar.ts +0 -58
  348. package/src/renderer/conversation-tree.ts +0 -228
  349. package/src/runtime/agent-graph-composition.ts +0 -78
  350. package/src/runtime/channel-composition.ts +0 -46
  351. package/src/runtime/cluster-composition.ts +0 -124
  352. package/src/runtime/cluster-group-composition.ts +0 -284
  353. package/src/runtime/code-index-services.ts +0 -167
  354. package/src/runtime/daemon-handler-composition.ts +0 -76
  355. package/src/runtime/device-posture-composition.ts +0 -110
  356. package/src/runtime/durability-housekeeping.ts +0 -183
  357. package/src/runtime/durability-services.ts +0 -155
  358. package/src/runtime/embedded-service-factories.ts +0 -74
  359. package/src/runtime/feature-settings.ts +0 -154
  360. package/src/runtime/fleet-needs-input-push.ts +0 -70
  361. package/src/runtime/fleet-services.ts +0 -41
  362. package/src/runtime/idle-power-services.ts +0 -85
  363. package/src/runtime/mail-composition.ts +0 -65
  364. package/src/runtime/memory-fold.ts +0 -55
  365. package/src/runtime/operator-token-cleanup.ts +0 -109
  366. package/src/runtime/path-shadow.ts +0 -418
  367. package/src/runtime/perf/panel-health-monitor.ts +0 -18
  368. package/src/runtime/provider-optimizer-wiring.ts +0 -55
  369. package/src/runtime/reachability-notice.ts +0 -100
  370. package/src/runtime/remote-execution-composition.ts +0 -62
  371. package/src/runtime/session-liveness-marker.ts +0 -257
  372. package/src/runtime/session-pointer-surface.ts +0 -22
  373. package/src/runtime/session-storage-services.ts +0 -41
  374. package/src/runtime/surface-feature-flags.ts +0 -96
  375. package/src/runtime/terminal-output-guard.ts +0 -235
  376. package/src/runtime/trust/workspace-registration.ts +0 -192
  377. package/src/runtime/trust/workspace-trust.ts +0 -229
  378. package/src/runtime/ui/index.ts +0 -39
  379. package/src/runtime/ui/model-picker/data-provider.ts +0 -182
  380. package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
  381. package/src/runtime/ui/model-picker/index.ts +0 -59
  382. package/src/runtime/ui/model-picker/types.ts +0 -153
  383. package/src/runtime/ui/provider-health/data-provider.ts +0 -244
  384. package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
  385. package/src/runtime/ui/provider-health/index.ts +0 -46
  386. package/src/runtime/ui/provider-health/types.ts +0 -146
  387. package/src/runtime/ui-events.ts +0 -1
  388. package/src/runtime/ui-read-model-helpers.ts +0 -1
  389. package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
  390. package/src/runtime/ui-read-models-observability-options.ts +0 -1
  391. package/src/runtime/ui-read-models-observability-remote.ts +0 -1
  392. package/src/runtime/ui-read-models-observability-security.ts +0 -1
  393. package/src/runtime/ui-read-models-observability-system.ts +0 -1
  394. package/src/runtime/ui-read-models-observability.ts +0 -1
  395. package/src/runtime/ui-service-queries.ts +0 -1
  396. package/src/runtime/voice-setup-services.ts +0 -98
  397. package/src/runtime/workstream-attempts-validation.ts +0 -77
  398. package/src/runtime/workstream-draft-edits.ts +0 -95
  399. package/src/runtime/workstream-draft-store.ts +0 -274
  400. package/src/runtime/workstream-draft-types.ts +0 -42
  401. package/src/runtime/workstream-services.ts +0 -373
  402. package/src/tools/index.ts +0 -1
  403. package/src/types/grid.ts +0 -48
  404. package/src/types/sql-js.d.ts +0 -15
  405. 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
- }