summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-25 16:30:22 +0900
committerAdam Malczewski <[email protected]>2026-06-25 16:30:22 +0900
commitfc1c3a54c3075990ec0dd0f97901bd46fe142923 (patch)
treea87b9debbba69b37b38a5645645fb105f6e4caa1
parent652010b6c054b69d813e8a2c724d6db039242119 (diff)
downloaddispatch-fc1c3a54c3075990ec0dd0f97901bd46fe142923.tar.gz
dispatch-fc1c3a54c3075990ec0dd0f97901bd46fe142923.zip
feat(ssh): wave 5c — host-bin registers exec-backend + ssh; transport-http barrel
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.
-rw-r--r--bun.lock2
-rw-r--r--packages/host-bin/package.json2
-rw-r--r--packages/host-bin/src/main.ts14
-rw-r--r--packages/host-bin/tsconfig.json6
-rw-r--r--packages/transport-http/src/index.ts2
-rw-r--r--tasks.md11
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
@@ -11,6 +11,9 @@
"path": "../cache-warming"
},
{
+ "path": "../exec-backend"
+ },
+ {
"path": "../kernel"
},
{
@@ -23,6 +26,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