diff --git a/packages/computer/src/backend.ts b/packages/computer/src/backend.ts index 0156fd2c..ca9b517a 100644 --- a/packages/computer/src/backend.ts +++ b/packages/computer/src/backend.ts @@ -20,6 +20,22 @@ import type { WorkspaceRPC } from "@cloudflare/computer-rpc"; +// The handles the Workspace owns and injects into a backend when +// it connects. The Workspace constructor builds `db`/`fs` itself, +// after the caller has already constructed the backends and passed +// them in, so a backend cannot capture them at its own +// construction time. `connect(host)` is how the Workspace hands +// over the storage-layer handles once they exist. Shell and +// container backends ignore the bag (they reach the host through +// their own transport); the in-process module backend uses it. +export interface WorkspaceBackendHost { + readonly db: import("@cloudflare/dofs").Database; + readonly waitUntil?: (promise: Promise) => void; + readonly fs: import("@cloudflare/dofs").WorkspaceFilesystem; + readonly git: import("./git/index.js").GitClient; + readonly artifacts: import("./artifacts/index.js").ArtifactClient; +} + export interface WorkspaceBackend { // User-supplied selector. Passed in `ExecOptions.backend` and // `Workspace.push(id)` / `Workspace.pull(id)` to address this @@ -48,8 +64,10 @@ export interface WorkspaceBackend { // Materialise a connection. Called lazily on first use, once // per backend per workspace lifetime. The Workspace caches the // resulting handle by `id`; subsequent exec / push / pull - // calls reuse it. - connect(): Promise; + // calls reuse it. The Workspace always passes its host bag; + // backends that reach the host through their own transport + // ignore it. + connect(host: WorkspaceBackendHost): Promise; } export interface BackendHandle { diff --git a/packages/computer/src/runtime/types.ts b/packages/computer/src/runtime/types.ts index 3fe7c341..52d505ce 100644 --- a/packages/computer/src/runtime/types.ts +++ b/packages/computer/src/runtime/types.ts @@ -160,14 +160,7 @@ export interface WorkspaceModuleBackendHandle { close(): Promise; } -export interface WorkspaceModuleBackendHost { - readonly db: import("@cloudflare/dofs").Database; - /** Attach detached backend work to the host event lifetime. */ - readonly waitUntil?: (promise: Promise) => void; - readonly fs: import("@cloudflare/dofs").WorkspaceFilesystem; - readonly git: import("../git/index.js").GitClient; - readonly artifacts: import("../artifacts/index.js").ArtifactClient; -} +export type WorkspaceModuleBackendHost = import("../backend.js").WorkspaceBackendHost; export interface WorkspaceModuleBackend { readonly protocol: "module"; diff --git a/packages/computer/src/workspace.ts b/packages/computer/src/workspace.ts index e8f81c03..e75ada0f 100644 --- a/packages/computer/src/workspace.ts +++ b/packages/computer/src/workspace.ts @@ -857,7 +857,14 @@ export class Workspace { this.#observer, "workspace.connect", { "workspace.backend.id": id, "workspace.backend.type": backend.type }, - () => backend.connect(), + () => + backend.connect({ + db: this.#db, + waitUntil: this.#waitUntil, + fs: this.#fs, + git: this.#gitFactory ? this.git : DISABLED_GIT_CLIENT, + artifacts: this.#artifacts, + }), ); if (generation !== this.#connectionGeneration) { await handle.close().catch(() => undefined);