From fc1c3a54c3075990ec0dd0f97901bd46fe142923 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Thu, 25 Jun 2026 16:30:22 +0900 Subject: feat(ssh): wave 5c — host-bin registers exec-backend + ssh; transport-http barrel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wave 5c (final wiring) of transparent SSH support. - host-bin: register exec-backend + ssh in CORE_EXTENSIONS (exec-backend before the tool extensions that dependsOn it; ssh after, provides the remote-backend factory + ComputerService at boot). +@dispatch/exec-backend/@dispatch/ssh deps + tsconfig refs. - transport-http: CR-5 — re-export computerServiceHandle + ComputerService type from the package barrel (src/index.ts), mirroring lsp/mcp handles, so ssh imports the typed symbol cleanly (no more dist/seam.js subpath workaround). - orchestrator: added the @dispatch/exec-backend dep the host-bin agent missed + bun install. LIVE-VERIFIED: bun packages/host-bin/src/main.ts boots clean ('Dispatch booted', no disabled extensions) — exec-backend + ssh + all tool extensions load together. Verified: tsc -b EXIT 0, biome clean, 1690 vitest pass (+6 sshd-integration skipped). DEFERRED (CR-6): listComputers usageCount stays 0 until a conversation-store count-by-alias helper is added (non-blocking). Refs: notes/ssh-support-plan.md. No merge or push. --- bun.lock | 2 ++ packages/host-bin/package.json | 2 ++ packages/host-bin/src/main.ts | 14 ++++++++++++++ packages/host-bin/tsconfig.json | 6 ++++++ packages/transport-http/src/index.ts | 2 ++ tasks.md | 11 ++++++++--- 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index fbd64a4..b669d88 100644 --- a/bun.lock +++ b/bun.lock @@ -66,6 +66,7 @@ "@dispatch/cache-warming": "workspace:*", "@dispatch/conversation-store": "workspace:*", "@dispatch/credential-store": "workspace:*", + "@dispatch/exec-backend": "workspace:*", "@dispatch/journal-sink": "workspace:*", "@dispatch/kernel": "workspace:*", "@dispatch/lsp": "workspace:*", @@ -75,6 +76,7 @@ "@dispatch/provider-umans": "workspace:*", "@dispatch/session-orchestrator": "workspace:*", "@dispatch/skills": "workspace:*", + "@dispatch/ssh": "workspace:*", "@dispatch/storage-sqlite": "workspace:*", "@dispatch/surface-loaded-extensions": "workspace:*", "@dispatch/surface-registry": "workspace:*", diff --git a/packages/host-bin/package.json b/packages/host-bin/package.json index 568fd6c..64f436e 100644 --- a/packages/host-bin/package.json +++ b/packages/host-bin/package.json @@ -10,12 +10,14 @@ "@dispatch/auth-apikey": "workspace:*", "@dispatch/cache-warming": "workspace:*", "@dispatch/credential-store": "workspace:*", + "@dispatch/exec-backend": "workspace:*", "@dispatch/provider-openai-compat": "workspace:*", "@dispatch/provider-umans": "workspace:*", "@dispatch/message-queue": "workspace:*", "@dispatch/mcp": "workspace:*", "@dispatch/session-orchestrator": "workspace:*", "@dispatch/skills": "workspace:*", + "@dispatch/ssh": "workspace:*", "@dispatch/throughput-store": "workspace:*", "@dispatch/todo": "workspace:*", "@dispatch/transport-http": "workspace:*", diff --git a/packages/host-bin/src/main.ts b/packages/host-bin/src/main.ts index bd79497..571628f 100644 --- a/packages/host-bin/src/main.ts +++ b/packages/host-bin/src/main.ts @@ -4,6 +4,7 @@ import { extension as authApikeyExt } from "@dispatch/auth-apikey"; import { extension as cacheWarmingExt } from "@dispatch/cache-warming"; import { extension as conversationStoreExt } from "@dispatch/conversation-store"; import { createCredentialStoreExtension } from "@dispatch/credential-store"; +import { createExecBackendExtension } from "@dispatch/exec-backend"; import { createJournalSink } from "@dispatch/journal-sink"; import { type ConfigAccess, @@ -26,6 +27,7 @@ import { extension as providerOpenaiCompatExt } from "@dispatch/provider-openai- import { extension as providerUmansExt } from "@dispatch/provider-umans"; import { extension as sessionOrchestratorExt } from "@dispatch/session-orchestrator"; import { extension as skillsExt } from "@dispatch/skills"; +import { extension as sshExt } from "@dispatch/ssh"; import { createSqliteStorage, extension as storageSqliteExt } from "@dispatch/storage-sqlite"; import { createLoadedExtensionsExtension } from "@dispatch/surface-loaded-extensions"; import { createSurfaceRegistryExtension } from "@dispatch/surface-registry"; @@ -76,6 +78,11 @@ const CORE_EXTENSIONS: readonly Extension[] = [ authApikeyExt, providerOpenaiCompatExt, providerUmansExt, + // exec-backend must precede the tool extensions that + // `dependsOn: ["exec-backend"]` (tool-edit-file/read/shell/write). It + // provides the ExecBackendResolver the tools resolve through; placing it + // here keeps the activation DAG honest (it depends only on kernel). + createExecBackendExtension(), toolEditFileExt, toolReadFileExt, toolShellExt, @@ -91,6 +98,13 @@ const CORE_EXTENSIONS: readonly Extension[] = [ systemPromptExt, cacheWarmingExt, lspExt, + // ssh declares `dependsOn: ["exec-backend"]` and PROVIDES the remote + // exec-backend factory + the ComputerService the HTTP routes delegate to. + // Its lookups are lazy (tool-/request-time), but it is placed after + // exec-backend and the tool extensions (alongside the other standard + // tool-serving extensions) to keep the DAG honest — and before + // transport-http, whose routes consume the ComputerService it provides. + sshExt, createTransportHttpExtension(), // Surface extensions — dependency order: surface-registry first, then consumers. createSurfaceRegistryExtension(), diff --git a/packages/host-bin/tsconfig.json b/packages/host-bin/tsconfig.json index 771dc92..e445f13 100644 --- a/packages/host-bin/tsconfig.json +++ b/packages/host-bin/tsconfig.json @@ -10,6 +10,9 @@ { "path": "../cache-warming" }, + { + "path": "../exec-backend" + }, { "path": "../kernel" }, @@ -22,6 +25,9 @@ { "path": "../skills" }, + { + "path": "../ssh" + }, { "path": "../storage-sqlite" }, diff --git a/packages/transport-http/src/index.ts b/packages/transport-http/src/index.ts index 7165c55..192b00c 100644 --- a/packages/transport-http/src/index.ts +++ b/packages/transport-http/src/index.ts @@ -26,6 +26,7 @@ export { serializeEventLine, } from "./logic.js"; export type { + ComputerService, ConversationStore, CredentialStore, LspService, @@ -35,6 +36,7 @@ export type { } from "./seam.js"; export { cacheWarmHandle, + computerServiceHandle, conversationStoreHandle, credentialStoreHandle, isValidWorkspaceSlug, diff --git a/tasks.md b/tasks.md index 27d7b75..b14645c 100644 --- a/tasks.md +++ b/tasks.md @@ -45,9 +45,14 @@ owner-agents on disjoint packages). Provides remoteExecBackendFactoryHandle + computerServiceHandle. +45 tests (6 sshd integration tests skipped). tsc -b EXIT 0, biome clean, **1690 vitest** (was 1641). -- [ ] **Wave 5c**: host-bin — register exec-backend + ssh extensions; CR-5 - transport-http barrel re-export of computerServiceHandle; CR-6 - usageCount wiring (deferred-ok). +- [x] **Wave 5c**: host-bin — register exec-backend + ssh extensions in + CORE_EXTENSIONS (correct DAG order); transport-http CR-5 barrel re-export of + computerServiceHandle. orchestrator added missing @dispatch/exec-backend dep to + host-bin + bun install. **LIVE-VERIFIED**: server boots clean ("Dispatch booted", + no disabled extensions). tsc -b EXIT 0, biome clean, 1690 vitest (+6 sshd skipped). +- [ ] **DEFERRED — CR-6 usageCount**: `listComputers()` returns `usageCount: 0` until a + conversation-store count-by-alias helper + host-bin wiring is added (non-blocking — + discovery/connect/execute all work; only the count badge shows 0). Follow-up. - [ ] **DEFERRED — cache-warming**: computerId threading intentionally NOT done (user-deferred — cache-warming is not needed right now). Known limitation: a warm probe on a remote turn assembles the tool set WITHOUT the remote-drop -- cgit v1.2.3