MCPcopy Create free account
hub / github.com/cloudflare/computer / WorkspaceShellRouter

Class WorkspaceShellRouter

packages/computer/src/workspace.ts:1002–1124  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1000// expects a WorkspaceShell without having to thread the union
1001// type through.
1002class WorkspaceShellRouter {
1003 readonly #defaultId: string;
1004 readonly #shellFor: (id: string) => Promise<{ shell: WorkspaceShell; handle: BackendHandle }>;
1005 readonly #resolveId: (id: string | undefined) => string;
1006 readonly #onError: (id: string, handle: BackendHandle, error: unknown) => void;
1007
1008 constructor(
1009 defaultId: string,
1010 shellFor: (id: string) => Promise<{ shell: WorkspaceShell; handle: BackendHandle }>,
1011 resolveId: (id: string | undefined) => string,
1012 onError: (id: string, handle: BackendHandle, error: unknown) => void,
1013 ) {
1014 this.#defaultId = defaultId;
1015 this.#shellFor = shellFor;
1016 this.#resolveId = resolveId;
1017 this.#onError = onError;
1018 }
1019
1020 async exec(command: string, options: { backend?: string } & Record<string, unknown> = {}) {
1021 const id = this.#resolveId(options.backend) || this.#defaultId;
1022 // Capture the BackendHandle here, at dispatch time. A late
1023 // failure from this command's stream must invalidate THIS
1024 // handle, not whatever the cache holds when the rejection
1025 // eventually fires; a concurrent reconnect may have already
1026 // swapped in a newer handle that we must not clobber.
1027 const { shell, handle: dispatchHandle } = await this.#shellFor(id);
1028 const { backend: _backend, ...rest } = options;
1029 let execHandle: unknown;
1030 try {
1031 execHandle = await (shell.exec as unknown as (c: string, o: typeof rest) => Promise<unknown>)(
1032 command,
1033 rest,
1034 );
1035 } catch (error) {
1036 this.#onError(id, dispatchHandle, error);
1037 throw error;
1038 }
1039 return this.#wrapHandle(id, dispatchHandle, execHandle);
1040 }
1041
1042 async get(id: string, options: { backend?: string } & Record<string, unknown> = {}) {
1043 const backendId = this.#resolveId(options.backend) || this.#defaultId;
1044 const { shell, handle: dispatchHandle } = await this.#shellFor(backendId);
1045 const { backend: _backend, ...rest } = options;
1046 let execHandle: unknown;
1047 try {
1048 execHandle = await (shell.get as unknown as (e: string, o: typeof rest) => Promise<unknown>)(
1049 id,
1050 rest,
1051 );
1052 } catch (error) {
1053 this.#onError(backendId, dispatchHandle, error);
1054 throw error;
1055 }
1056 return this.#wrapHandle(backendId, dispatchHandle, execHandle);
1057 }
1058
1059 async kill(

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected