diff options
Diffstat (limited to 'packages/transport-http/src/extension.ts')
| -rw-r--r-- | packages/transport-http/src/extension.ts | 277 |
1 files changed, 154 insertions, 123 deletions
diff --git a/packages/transport-http/src/extension.ts b/packages/transport-http/src/extension.ts index 4ab43ce..effbadd 100644 --- a/packages/transport-http/src/extension.ts +++ b/packages/transport-http/src/extension.ts @@ -1,140 +1,171 @@ import type { Extension, HostAPI, Manifest } from "@dispatch/kernel"; import { createApp } from "./app.js"; import { - type ComputerService, - cacheWarmHandle, - compactionHandle, - computerServiceHandle, - conversationStoreHandle, - credentialStoreHandle, - lspServiceHandle, - mcpServiceHandle, - sessionOrchestratorHandle, - systemPromptHandle, - throughputStoreHandle, + type ComputerService, + type ConcurrencyService, + cacheWarmHandle, + compactionHandle, + computerServiceHandle, + concurrencyServiceHandle, + conversationStoreHandle, + credentialStoreHandle, + heartbeatServiceHandle, + type LspService, + lspServiceHandle, + mcpServiceHandle, + sessionOrchestratorHandle, + systemPromptHandle, + throughputStoreHandle, } from "./seam.js"; export const manifest: Manifest = { - id: "transport-http", - name: "Transport HTTP", - version: "0.0.0", - apiVersion: "^0.1.0", - trust: "bundled", - dependsOn: [ - "conversation-store", - "credential-store", - "lsp", - "mcp", - "session-orchestrator", - "throughput-store", - ], - capabilities: { network: true }, - contributes: { - routes: [ - "/chat", - "/chat/warm", - "/computers", - "/computers/:alias", - "/computers/:alias/status", - "/computers/:alias/test", - "/conversations", - "/conversations/:id", - "/conversations/:id/close", - "/conversations/:id/compact", - "/conversations/:id/compact-percent", - "/conversations/:id/computer", - "/conversations/:id/cwd", - "/conversations/:id/last", - "/conversations/:id/lsp", - "/conversations/:id/mcp", - "/conversations/:id/open", - "/conversations/:id/queue", - "/conversations/:id/reasoning-effort", - "/conversations/:id/status", - "/conversations/:id/stop", - "/conversations/:id/title", - "/health", - "/models", - "/metrics/throughput", - "/system-prompt", - "/system-prompt/variables", - "/workspaces", - "/workspaces/:id", - "/workspaces/:id/title", - "/workspaces/:id/default-cwd", - "/workspaces/:id/default-computer", - ], - }, - activation: "eager", + id: "transport-http", + name: "Transport HTTP", + version: "0.0.0", + apiVersion: "^0.1.0", + trust: "bundled", + dependsOn: [ + "conversation-store", + "credential-store", + "heartbeat", + "mcp", + "session-orchestrator", + "throughput-store", + ], + capabilities: { network: true }, + contributes: { + routes: [ + "/chat", + "/chat/warm", + "/computers", + "/computers/:alias", + "/computers/:alias/status", + "/computers/:alias/test", + "/concurrency/limits", + "/concurrency/limits/:providerId", + "/concurrency/status", + "/conversations", + "/conversations/:id", + "/conversations/:id/close", + "/conversations/:id/compact", + "/conversations/:id/compact-percent", + "/conversations/:id/computer", + "/conversations/:id/cwd", + "/conversations/:id/last", + "/conversations/:id/lsp", + "/conversations/:id/mcp", + "/conversations/:id/open", + "/conversations/:id/queue", + "/conversations/:id/queue/:messageId", + "/conversations/:id/reasoning-effort", + "/conversations/:id/status", + "/conversations/:id/stop", + "/conversations/:id/title", + "/health", + "/models", + "/metrics/throughput", + "/system-prompt", + "/system-prompt/variables", + "/workspaces", + "/workspaces/:id", + "/workspaces/:id/default-cwd", + "/workspaces/:id/default-computer", + "/workspaces/:id/heartbeat", + "/workspaces/:id/heartbeat/runs", + "/workspaces/:id/heartbeat/runs/:runId/stop", + "/workspaces/:id/star", + "/workspaces/:id/title", + ], + }, + activation: "eager", }; export function createTransportHttpExtension(): Extension & { - readonly _testServer: ReturnType<typeof Bun.serve> | undefined; + readonly _testServer: ReturnType<typeof Bun.serve> | undefined; } { - let server: ReturnType<typeof Bun.serve> | undefined; + let server: ReturnType<typeof Bun.serve> | undefined; - return { - get _testServer() { - return server; - }, - manifest, - async activate(host: HostAPI) { - const conversationStore = host.getService(conversationStoreHandle); - const orchestrator = host.getService(sessionOrchestratorHandle); - const credentialStore = host.getService(credentialStoreHandle); - const throughputStore = host.getService(throughputStoreHandle); - const warmService = host.getService(cacheWarmHandle); - const compactionService = host.getService(compactionHandle); - const lspService = host.getService(lspServiceHandle); - const mcpService = host.getService(mcpServiceHandle); - const systemPromptService = host.getService(systemPromptHandle); - // Optional: the `ssh` extension provides ComputerService. It is NOT in - // dependsOn (ssh may be absent), so resolve defensively — when no - // provider registered the handle, the computer routes degrade to - // empty/disconnected (see app.ts). Wrapped because getService throws - // for an unregistered handle. - let computerService: ComputerService | undefined; - try { - computerService = host.getService(computerServiceHandle); - } catch { - computerService = undefined; - } - const logger = host.logger; + return { + get _testServer() { + return server; + }, + manifest, + async activate(host: HostAPI) { + const conversationStore = host.getService(conversationStoreHandle); + const orchestrator = host.getService(sessionOrchestratorHandle); + const credentialStore = host.getService(credentialStoreHandle); + const throughputStore = host.getService(throughputStoreHandle); + const warmService = host.getService(cacheWarmHandle); + const compactionService = host.getService(compactionHandle); + // Optional: the `lsp` extension may be disabled (hot-fix). Wrapped because + // getService throws for an unregistered handle — degrades to no diagnostics. + let lspService: LspService | undefined; + try { + lspService = host.getService(lspServiceHandle); + } catch { + lspService = undefined; + } + const mcpService = host.getService(mcpServiceHandle); + const systemPromptService = host.getService(systemPromptHandle); + const heartbeatService = host.getService(heartbeatServiceHandle); + // Optional: the `ssh` extension provides ComputerService. It is NOT in + // dependsOn (ssh may be absent), so resolve defensively — when no + // provider registered the handle, the computer routes degrade to + // empty/disconnected (see app.ts). Wrapped because getService throws + // for an unregistered handle. + let computerService: ComputerService | undefined; + try { + computerService = host.getService(computerServiceHandle); + } catch { + computerService = undefined; + } + // Optional: the `provider-concurrency` extension provides the + // concurrency limiter service. NOT in dependsOn (may be absent), so + // resolve defensively — when absent the /concurrency/* routes degrade. + let concurrencyService: ConcurrencyService | undefined; + try { + concurrencyService = host.getService(concurrencyServiceHandle); + } catch { + concurrencyService = undefined; + } + const logger = host.logger; - const app = createApp({ - conversationStore, - orchestrator, - credentialStore, - throughputStore, - warmService, - compactionService, - lspService, - mcpService, - systemPromptService, - ...(computerService !== undefined ? { computerService } : {}), - logger, - emit: host.emit.bind(host), - ...(process.env.DISPATCH_WEB_DIR !== undefined - ? { webDir: process.env.DISPATCH_WEB_DIR } - : {}), - }); + const app = createApp({ + conversationStore, + orchestrator, + credentialStore, + throughputStore, + warmService, + compactionService, + ...(lspService !== undefined ? { lspService } : {}), + mcpService, + systemPromptService, + heartbeatService, + ...(computerService !== undefined ? { computerService } : {}), + ...(concurrencyService !== undefined ? { concurrencyService } : {}), + logger, + emit: host.emit.bind(host), + ...(process.env.DISPATCH_WEB_DIR !== undefined + ? { webDir: process.env.DISPATCH_WEB_DIR } + : {}), + }); - const port = host.config.get<number>("httpPort") ?? 24203; + const port = host.config.get<number>("httpPort") ?? 24203; - server = Bun.serve({ - port, - fetch: app.fetch, - idleTimeout: 0, - }); + server = Bun.serve({ + port, + fetch: app.fetch, + idleTimeout: 0, + }); - logger.info("transport-http: listening", { port }); - }, + logger.info("transport-http: listening", { port }); + }, - deactivate() { - if (server) { - server.stop(); - server = undefined; - } - }, - }; + deactivate() { + if (server) { + server.stop(); + server = undefined; + } + }, + }; } |
