@finalai/final-agent-provider 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/harnesses/adapters.mjs +5 -2
- package/dist/modules/harnesses/adapters.mjs.map +2 -2
- package/dist/modules/sandboxes/computer.mjs +19 -1
- package/dist/modules/sandboxes/computer.mjs.map +2 -2
- package/dist/modules/sandboxes/computers-api-transport.d.mts +0 -1
- package/dist/modules/sandboxes/computers-api-transport.mjs +4 -5
- package/dist/modules/sandboxes/computers-api-transport.mjs.map +2 -2
- package/package.json +2 -2
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const claudeCodeAdapterPackage = { "name": "@finalai/acp-adapter-claude-code", "version": "0.3.0" };
|
|
2
|
+
const codexAdapterPackage = { "name": "@finalai/acp-adapter-codex", "version": "0.2.1" };
|
|
1
3
|
import { defineAcpAdapter } from "@finalai/agent-definition/authoring";
|
|
2
4
|
import { FinalExtension } from "@finalai/agent-provider";
|
|
3
5
|
import { REQUIRED_FINAL_EXTENSIONS } from "../provider/general.mjs";
|
|
@@ -16,6 +18,7 @@ const NANOCODE_ACP_ADAPTER = defineAcpAdapter({
|
|
|
16
18
|
run: { worker: { program: "nanocode" } },
|
|
17
19
|
extensions: [...REQUIRED_FINAL_EXTENSIONS]
|
|
18
20
|
});
|
|
21
|
+
const releaseOf = (manifest) => `${manifest.name}@${manifest.version}`;
|
|
19
22
|
const permissionArgs = {
|
|
20
23
|
when: "configuration.permissionMode",
|
|
21
24
|
args: ["--permission-mode", "{{configuration.permissionMode}}"]
|
|
@@ -29,7 +32,7 @@ const CLAUDE_CODE_ACP_ADAPTER = defineAcpAdapter({
|
|
|
29
32
|
command: "npx",
|
|
30
33
|
args: [
|
|
31
34
|
"-y",
|
|
32
|
-
|
|
35
|
+
releaseOf(claudeCodeAdapterPackage),
|
|
33
36
|
permissionArgs,
|
|
34
37
|
"--",
|
|
35
38
|
"{{harness.command}}",
|
|
@@ -48,7 +51,7 @@ const CODEX_ACP_ADAPTER = defineAcpAdapter({
|
|
|
48
51
|
command: "npx",
|
|
49
52
|
args: [
|
|
50
53
|
"-y",
|
|
51
|
-
|
|
54
|
+
releaseOf(codexAdapterPackage),
|
|
52
55
|
permissionArgs,
|
|
53
56
|
"--",
|
|
54
57
|
"{{harness.command}}",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/harnesses/adapters.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "AAAA,SAAS,wBAAwB;AACjC,SAAS,sBAAsD;AAC/D,SAAS,iCAAiC;AAC1C,SAAS,iBAAiB,6BAA6B;AAShD,MAAM,iBAA4C,iBAAiB;AAAA,EACxE,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,OAAO;AAAA,EACtC,KAAK,EAAE,QAAQ,EAAE,SAAS,KAAK,EAAE;AAAA,EACjC,YAAY,CAAC,GAAG,yBAAyB;AAC3C,CAAC;AAEM,MAAM,uBAAkD,iBAAiB;AAAA,EAC9E,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,QAAQ;AAAA,EACvC,KAAK,EAAE,QAAQ,EAAE,SAAS,WAAW,EAAE;AAAA,EACvC,YAAY,CAAC,GAAG,yBAAyB;AAC3C,CAAC;
|
|
4
|
+
"sourcesContent": ["const claudeCodeAdapterPackage = {\"name\":\"@finalai/acp-adapter-claude-code\",\"version\":\"0.3.0\"};\nconst codexAdapterPackage = {\"name\":\"@finalai/acp-adapter-codex\",\"version\":\"0.2.1\"};\nimport { defineAcpAdapter } from '@finalai/agent-definition/authoring';\nimport { FinalExtension, type AcpAdapterDefinitionIface } from '@finalai/agent-provider';\nimport { REQUIRED_FINAL_EXTENSIONS } from \"../provider/general.mjs\";\nimport { FinalAcpAdapter, FinalHarnessInterface } from \"./names.mjs\";\n\n// Final's ACP adapters. Each implements ACP v2 and Final's ACP extensions and\n// advertises them in `initialize`; the general harness provider refuses an\n// adapter that does not (../provider/general.ts). Fork is optional.\n\n// The worker runtime's engines that map a harness program to ACP v2. The\n// worker program started is the engine; the harness's own program comes in\n// its input (`{ harness: { program }, configuration }`).\nexport const PI_ACP_ADAPTER: AcpAdapterDefinitionIface = defineAcpAdapter({\n title: 'Pi ACP adapter',\n description: 'Maps the Pi agent loop (Pi and the Final harness) to ACP v2 on a worker runtime.',\n adapts: [FinalHarnessInterface.PiAgent],\n run: { worker: { program: 'pi' } },\n extensions: [...REQUIRED_FINAL_EXTENSIONS],\n});\n\nexport const NANOCODE_ACP_ADAPTER: AcpAdapterDefinitionIface = defineAcpAdapter({\n title: 'nanocode ACP adapter',\n description: \"Maps nanocode's Claude and Codex engines to ACP v2 on a worker runtime.\",\n adapts: [FinalHarnessInterface.Nanocode],\n run: { worker: { program: 'nanocode' } },\n extensions: [...REQUIRED_FINAL_EXTENSIONS],\n});\n\n// The process adapters are published packages. Each takes the harness's\n// command line after `--` and launches it as the program it adapts; the\n// permission level is Final's (`ask`, `review`, `auto`), mapped by the\n// adapter onto the program's own modes.\n// An adapter package's exact release, as npx installs it: `npx -y <name>` alone resolves npm's\n// `latest` tag, which need not be the release these definitions were made with. The version is\n// the adapter package's own (inlined when this package is built).\nconst releaseOf = (manifest: { name: string; version: string }): string =>\n `${manifest.name}@${manifest.version}`;\n\nconst permissionArgs = {\n when: 'configuration.permissionMode',\n args: ['--permission-mode', '{{configuration.permissionMode}}'],\n};\n\nexport const CLAUDE_CODE_ACP_ADAPTER: AcpAdapterDefinitionIface = defineAcpAdapter({\n title: 'Claude Code ACP adapter',\n description: 'Runs Claude Code through the Claude Agent SDK and speaks ACP v2 on stdio.',\n adapts: [FinalHarnessInterface.ClaudeAgentSdk],\n run: {\n process: {\n command: 'npx',\n args: [\n '-y',\n releaseOf(claudeCodeAdapterPackage),\n permissionArgs,\n '--',\n '{{harness.command}}',\n { spread: 'harness.args' },\n ],\n },\n },\n extensions: [...REQUIRED_FINAL_EXTENSIONS, FinalExtension.Fork],\n});\n\nexport const CODEX_ACP_ADAPTER: AcpAdapterDefinitionIface = defineAcpAdapter({\n title: 'Codex ACP adapter',\n description: 'Runs the Codex app-server and speaks ACP v2 on stdio.',\n adapts: [FinalHarnessInterface.CodexAppServer],\n run: {\n process: {\n command: 'npx',\n args: [\n '-y',\n releaseOf(codexAdapterPackage),\n permissionArgs,\n '--',\n '{{harness.command}}',\n { spread: 'harness.args' },\n ],\n },\n },\n extensions: [...REQUIRED_FINAL_EXTENSIONS],\n});\n\nexport const FINAL_ACP_ADAPTERS: Record<FinalAcpAdapter, AcpAdapterDefinitionIface> = {\n [FinalAcpAdapter.Pi]: PI_ACP_ADAPTER,\n [FinalAcpAdapter.Nanocode]: NANOCODE_ACP_ADAPTER,\n [FinalAcpAdapter.ClaudeCode]: CLAUDE_CODE_ACP_ADAPTER,\n [FinalAcpAdapter.Codex]: CODEX_ACP_ADAPTER,\n};\n"],
|
|
5
|
+
"mappings": "AAAA,MAAM,2BAA2B,EAAC,QAAO,oCAAmC,WAAU,QAAO;AAC7F,MAAM,sBAAsB,EAAC,QAAO,8BAA6B,WAAU,QAAO;AAClF,SAAS,wBAAwB;AACjC,SAAS,sBAAsD;AAC/D,SAAS,iCAAiC;AAC1C,SAAS,iBAAiB,6BAA6B;AAShD,MAAM,iBAA4C,iBAAiB;AAAA,EACxE,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,OAAO;AAAA,EACtC,KAAK,EAAE,QAAQ,EAAE,SAAS,KAAK,EAAE;AAAA,EACjC,YAAY,CAAC,GAAG,yBAAyB;AAC3C,CAAC;AAEM,MAAM,uBAAkD,iBAAiB;AAAA,EAC9E,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,QAAQ;AAAA,EACvC,KAAK,EAAE,QAAQ,EAAE,SAAS,WAAW,EAAE;AAAA,EACvC,YAAY,CAAC,GAAG,yBAAyB;AAC3C,CAAC;AASD,MAAM,YAAY,CAAC,aACjB,GAAG,SAAS,IAAI,IAAI,SAAS,OAAO;AAEtC,MAAM,iBAAiB;AAAA,EACrB,MAAM;AAAA,EACN,MAAM,CAAC,qBAAqB,kCAAkC;AAChE;AAEO,MAAM,0BAAqD,iBAAiB;AAAA,EACjF,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,cAAc;AAAA,EAC7C,KAAK;AAAA,IACH,SAAS;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,wBAAwB;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE,QAAQ,eAAe;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY,CAAC,GAAG,2BAA2B,eAAe,IAAI;AAChE,CAAC;AAEM,MAAM,oBAA+C,iBAAiB;AAAA,EAC3E,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,sBAAsB,cAAc;AAAA,EAC7C,KAAK;AAAA,IACH,SAAS;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,mBAAmB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE,QAAQ,eAAe;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY,CAAC,GAAG,yBAAyB;AAC3C,CAAC;AAEM,MAAM,qBAAyE;AAAA,EACpF,CAAC,gBAAgB,EAAE,GAAG;AAAA,EACtB,CAAC,gBAAgB,QAAQ,GAAG;AAAA,EAC5B,CAAC,gBAAgB,UAAU,GAAG;AAAA,EAC9B,CAAC,gBAAgB,KAAK,GAAG;AAC3B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -447,6 +447,23 @@ const createComputerSandboxProvider = (config) => {
|
|
|
447
447
|
pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);
|
|
448
448
|
}
|
|
449
449
|
};
|
|
450
|
+
const awaitComputerSettled = async (client, computer, timeoutMs) => {
|
|
451
|
+
const deadline = now() + timeoutMs;
|
|
452
|
+
let pollMs = config.runningPollMs ?? 250;
|
|
453
|
+
let current = computer;
|
|
454
|
+
while (current?.state === ComputerState.Pending) {
|
|
455
|
+
const left = deadline - now();
|
|
456
|
+
if (left <= 0)
|
|
457
|
+
throw computerSandboxError(
|
|
458
|
+
"computer_not_running",
|
|
459
|
+
`computer ${current.name} did not settle within ${Math.round(timeoutMs / 1e3)} s (it is Pending)`
|
|
460
|
+
);
|
|
461
|
+
await sleep(Math.min(pollMs, left));
|
|
462
|
+
pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);
|
|
463
|
+
current = await client.getComputer(current.id);
|
|
464
|
+
}
|
|
465
|
+
return current == null || current.state === ComputerState.Deleted ? null : current;
|
|
466
|
+
};
|
|
450
467
|
const build = async (args) => {
|
|
451
468
|
const { ctx, key } = args;
|
|
452
469
|
const client = clientFor(ctx);
|
|
@@ -736,7 +753,8 @@ ${step.run}`,
|
|
|
736
753
|
const env = platformProcessEnvironment(ctx, {});
|
|
737
754
|
const policy = withPlatformEgressHosts(ctx, state.network);
|
|
738
755
|
const egress = computerEgressOf(policy);
|
|
739
|
-
const
|
|
756
|
+
const found = await findComputer(client, state);
|
|
757
|
+
const existing = found == null ? null : await awaitComputerSettled(client, found, runningWaitMs);
|
|
740
758
|
if (existing?.state === ComputerState.Error)
|
|
741
759
|
throw computerSandboxError(
|
|
742
760
|
"computer_gone",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/sandboxes/computer.ts"],
|
|
4
|
-
"sourcesContent": ["import { Capability, FilesAccess, ScreenAccess, ShellAccess } from '@finalai/agent-protocol';\nimport { NetworkPolicy, type JsonValue } from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n materializeSandboxSeeds,\n platformProcessEnvironment,\n PortProtocol,\n reportPlatformNetworkPolicy,\n SandboxCapability,\n sandboxSeedArtifact,\n sandboxSeedArtifactSchema,\n sandboxSeedFiles,\n sandboxSeedFilesForAttach,\n sandboxSeedIdentity,\n withPlatformEgressHosts,\n writePlatformFiles,\n type NetworkPolicyIface,\n type NetworkSandboxSessionIface,\n type SandboxEnvironmentImplementationIface,\n type SandboxPrepareContextIface,\n type SandboxProviderContextIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxResourceContextIface,\n type SandboxSetupIface,\n} from '@finalai/agent-provider/sandbox';\nimport {\n ComputerBaseState,\n ComputerCommandMode,\n ComputerEgressPolicy,\n ComputerIdlePolicy,\n ComputerImageState,\n ComputerState,\n type ComputerBaseIface,\n type ComputerImageIface,\n type ComputerInfoIface,\n} from '@finalai/computers';\nimport * as z from 'zod';\nimport {\n HOME_BASELINE_MISSING_EXIT_CODE,\n HOME_BASELINE_ROOT,\n homeBaselineScript,\n homeContentScript,\n} from \"./build-scripts.mjs\";\nimport { canonicalJson, sleep as defaultSleep, sha256Hex } from \"./bytes.mjs\";\nimport { computerEditor } from \"./computer-editor.mjs\";\nimport { readComputerSnapshot } from \"./computer-snapshots.mjs\";\nimport {\n createComputersApiClient,\n isComputersApiError,\n isComputersApiStatus,\n type ComputersApiClientIface,\n type ComputersApiConfigIface,\n type ComputersApiCredentialsIface,\n type CreateComputerBodyIface,\n} from \"./computers-api.mjs\";\nimport { createComputerUseEndpoint } from \"./computers-api-mcp.mjs\";\nimport { createComputersApiTransport } from \"./computers-api-transport.mjs\";\nimport {\n COMPUTER_PROVIDER,\n computerEnvironmentSchema,\n DEFAULT_COMPUTER_IMAGE,\n type ComputerBuildIface,\n type ComputerEnvironmentIface,\n} from \"./environment.mjs\";\nimport { createTransportSession, readOnlySession } from \"./session.mjs\";\nimport { toolDescriptorsOf } from \"./tool-catalog.mjs\";\nimport type { SandboxTransportIface } from \"./transport.mjs\";\n\nexport type { ComputersApiConfigIface } from \"./computers-api.mjs\";\nexport type { FinalPlatformAccessIface } from \"./environment.mjs\";\nexport { COMPUTER_PROVIDER } from \"./environment.mjs\";\n\n// The `computer` sandbox: a Final computer from the public Computers API, with\n// lifecycle, files and processes all through that API, exactly as a\n// third-party provider drives its vendor. Like every provider, the host runs\n// this handle and serves the handle RPC and MCP projection from it.\n//\n// A sandbox is one computer, named after the sandbox's id: `create` records\n// it and the first `attach` makes it, so creating a sandbox boots nothing. An\n// environment with build or verify steps is built once on a builder computer\n// and captured as a base (POST /v1/computers/:id/capture) that its computers\n// are created from. The sandbox setup's network policy is a create option, as\n// for any API customer; its repositories, steps and services are applied by\n// the platform through the handle.\n\nexport const WORKSPACE_ROOT = '/workspaces';\n\nconst DEFAULT_IDLE_TIMEOUT_SECONDS = 15 * 60;\nconst IDLE_TIMEOUT_MARGIN_SECONDS = 5 * 60;\n\nexport interface ComputerSandboxLogIface {\n (message: string, fields?: Record<string, string | number | boolean | null>): void;\n}\n\nexport interface ComputerSandboxProviderConfigIface {\n // The Computers API origin. Requests authenticate with the provider's\n // platform identity for it (ctx.identity), which the registration must be\n // granted.\n computersApiUrl: string;\n // Transport options.\n computersApi?: ComputersApiConfigIface;\n // A registry credential (`creg_...`) stored for private image references.\n registryCredentialId?: string;\n // Image for an environment that names none.\n defaultImage?: string;\n // Defaults for what an environment leaves out.\n regionSlug?: string;\n machine?: { vcpu?: number; memoryMb?: number; diskGb?: number };\n // How long attach waits for a registered image version to finish building.\n imageWaitMs?: number;\n imagePollMs?: number;\n // How long `prepare` waits for a base capture to publish.\n buildWaitMs?: number;\n buildPollMs?: number;\n // How long attach and a build wait for a computer to run before touching it\n // (default 5 min); polled from runningPollMs (default 250 ms), doubling to 5 s.\n runningWaitMs?: number;\n runningPollMs?: number;\n log?: ComputerSandboxLogIface;\n randomUuid?: () => string;\n now?: () => number;\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\n// An `image` base: `imageVersionId` is the registered version (`cimv_...`) of an\n// image reference, registered at prepare; a `lineage:` image resolves its newest\n// version at attach. A `captured` base is the environment's build, captured as\n// a base (`part_...`) that computers are created from.\nconst computerArtifactSchema = sandboxSeedArtifactSchema.extend({\n version: z.literal(1),\n key: z.string(),\n image: z.string(),\n diskGb: z.number().nullable(),\n base: z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('image'),\n image: z.string(),\n imageVersionId: z.string().nullable().default(null),\n }),\n z.object({ kind: z.literal('captured'), baseId: z.string() }),\n ]),\n});\n\nconst networkPolicySchema = z.object({\n mode: z.nativeEnum(NetworkPolicy),\n allow: z.array(z.string()).optional(),\n});\n\nconst computerStateSchema = z.object({\n version: z.literal(2),\n computerName: z.string(),\n // Null until the first attach creates the computer.\n computerId: z.string().nullable(),\n // The sandbox setup's network policy, enforced from the computer's first boot.\n network: networkPolicySchema,\n // Ports the setup's services listen on.\n ports: z.array(z.number().int()).default([]),\n});\n\nexport type ComputerSandboxArtifact = z.infer<typeof computerArtifactSchema>;\nexport type ComputerSandboxState = z.infer<typeof computerStateSchema>;\n\nexport interface ComputerSandboxSessionIface extends NetworkSandboxSessionIface {\n // What this computer's handle offers (the host reports it).\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type ComputerSandboxProviderIface = SandboxProviderIface<\n JsonValue,\n ComputerSandboxArtifact,\n ComputerSandboxState,\n ComputerSandboxSessionIface\n>;\n\nexport interface ComputerSandboxErrorIface extends Error {\n code:\n | 'artifact_unavailable'\n | 'computer_gone'\n | 'computer_not_running'\n | 'invalid_environment'\n | 'build_failed';\n}\n\nconst computerSandboxError = (\n code: ComputerSandboxErrorIface['code'],\n message: string,\n): ComputerSandboxErrorIface =>\n Object.assign(new Error(message), { name: 'ComputerSandboxError', code });\n\nconst HTTP_TOKEN_LIFETIME_MS = 60 * 60_000;\nconst HTTP_TOKEN_RENEW_MS = 5 * 60_000;\n\n// Builds run from here; the capture scrub removes /tmp/*.\nconst BUILD_ROOT = '/tmp/final-build';\n// What the Computers API's capture scrub removes, so the home check skips it.\nconst CAPTURE_SCRUBBED_PATHS = [\n '/home/user/.bash_history',\n '/home/user/.zsh_history',\n '/home/user/.sh_history',\n '/home/user/.git-credentials',\n '/home/user/.config/gh/hosts.yml',\n '/home/user/.npmrc',\n '/home/user/.pypirc',\n '/home/user/.cargo/credentials',\n '/home/user/.cargo/credentials.toml',\n '/home/user/.aws',\n '/home/user/.config/gcloud',\n '/home/user/.azure',\n '/home/user/.docker/config.json',\n '/home/user/.netrc',\n '/home/user/.ssh',\n];\nconst BUILDER_IDLE_TIMEOUT_SECONDS = 2 * 60 * 60;\n// Bumped when the meaning of the build inputs changes (forces rebuilds).\nconst ARTIFACT_KEY_VERSION = 1;\n// Part of a built base's key; bumping it rebuilds every base.\nconst PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION = 2;\n\ninterface ComputerEgressConfigIface {\n egress: ComputerEgressPolicy;\n allow?: string[];\n}\nconst computerEgressOf = (policy: NetworkPolicyIface): ComputerEgressConfigIface => {\n if (policy.mode === NetworkPolicy.AllowAll) return { egress: ComputerEgressPolicy.Internet };\n if (policy.mode === NetworkPolicy.DenyAll) return { egress: ComputerEgressPolicy.None };\n return { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow ?? [] };\n};\n\n// An allowlist also admits the platform's egress hosts, so its proxy stays reachable.\nconst egressFor = (\n ctx: Pick<SandboxResourceContextIface, 'platformEgressHosts'>,\n requested: NetworkPolicyIface,\n): ComputerEgressConfigIface => computerEgressOf(withPlatformEgressHosts(ctx, requested));\n\n// The setup's network as a computer can enforce it from boot: every host, none,\n// or an allowlist. A computer has no per-host deny list, so a setup naming one\n// is refused at create rather than run unenforced.\nexport const computerNetworkPolicyOf = (setup: SandboxSetupIface | null): NetworkPolicyIface => {\n const network = setup?.network;\n if (network == null) return { mode: NetworkPolicy.AllowAll };\n if ((network.deny ?? []).length > 0)\n throw computerSandboxError(\n 'invalid_environment',\n 'A Final computer cannot deny individual hosts; list the hosts to allow instead',\n );\n if (network.allow == null) return { mode: NetworkPolicy.AllowAll };\n return network.allow.length === 0\n ? { mode: NetworkPolicy.DenyAll }\n : { mode: NetworkPolicy.Allowlist, allow: [...network.allow] };\n};\n\nconst LINEAGE_PREFIX = 'lineage:';\n\nconst compactId = (id: string): string => id.replaceAll('-', '');\n\n// The computer's name: stable for the sandbox, so an attach retried after a\n// lost answer finds the computer it already created.\nexport const computerNameFor = async (sandboxId: string): Promise<string> =>\n `as-${(await sha256Hex(sandboxId)).slice(0, 24)}`;\n\nconst isRunningState = (state: ComputerState): boolean =>\n state === ComputerState.Running ||\n state === ComputerState.Paused ||\n state === ComputerState.Resuming;\n\n// Nothing runs on these to pause, and the Computers API refuses a pause of them:\n// stopped or shelved (the disk at rest), errored (resume reports it gone), or deleted.\nconst hasNothingToPause = (state: ComputerState): boolean =>\n state === ComputerState.Stopped ||\n state === ComputerState.Shelved ||\n state === ComputerState.Error ||\n state === ComputerState.Deleted;\n\n// A refusal (409), a missing computer (404) or a failed host command (5xx) can\n// mean the computer came to rest on its own; a request or auth failure cannot.\nconst pauseMayHaveSettled = (error: unknown): boolean =>\n isComputersApiError(error) &&\n error.statusCode != null &&\n (error.statusCode === 404 || error.statusCode === 409 || error.statusCode >= 500);\n\nconst RUNNING_POLL_MAX_MS = 5_000;\n\nexport const computerNeedsBuild = (build: ComputerBuildIface | undefined): boolean =>\n build != null && (build.steps.length > 0 || build.verify.length > 0);\n\n// The base's identity: a hash of the build-time inputs only, so identical\n// environments share one base.\nexport const computeComputerArtifactKey = async (inputs: {\n image: string;\n build: ComputerBuildIface | undefined;\n diskGb: number | null;\n}): Promise<string> => {\n if (!computerNeedsBuild(inputs.build)) {\n const hex = await sha256Hex(canonicalJson({ v: ARTIFACT_KEY_VERSION, image: inputs.image }));\n return `img-${hex.slice(0, 16)}`;\n }\n const hex = await sha256Hex(\n canonicalJson({\n v: ARTIFACT_KEY_VERSION,\n image: inputs.image,\n build: { steps: inputs.build?.steps ?? [], verify: inputs.build?.verify ?? [] },\n diskGb: inputs.diskGb,\n }),\n );\n return `pa-g${hex.slice(0, 16)}-c${PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION}`;\n};\n\n// What a computer's handle needs beyond the client: the sandbox it serves and\n// the platform's egress hosts its allowlist keeps.\ntype HandleContextIface = Pick<SandboxResourceContextIface, 'sandboxId' | 'platformEgressHosts'>;\n\nexport const createComputerSandboxProvider = (\n config: ComputerSandboxProviderConfigIface,\n): ComputerSandboxProviderIface => {\n const log: ComputerSandboxLogIface = config.log ?? (() => undefined);\n const randomUuid = config.randomUuid ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => Date.now());\n const sleep = config.sleep ?? defaultSleep;\n const runningWaitMs = config.runningWaitMs ?? 5 * 60_000;\n\n // An assertion for the Computers API before each request, and a new one\n // after a rejection.\n const credentialsFor = (ctx: SandboxProviderContextIface): ComputersApiCredentialsIface => ({\n computersAccess: async (args) => ({\n baseUrl: config.computersApiUrl,\n token: (\n await ctx.identity({ audience: config.computersApiUrl, refresh: args?.refresh === true })\n ).token,\n }),\n });\n\n const clientFor = (ctx: SandboxProviderContextIface): ComputersApiClientIface =>\n createComputersApiClient({\n config: config.computersApi ?? {},\n credentials: credentialsFor(ctx),\n });\n\n const registerImage = (client: ComputersApiClientIface, reference: string) =>\n client.registerImage(\n config.registryCredentialId == null\n ? { reference }\n : { reference, registryCredentialId: config.registryCredentialId },\n );\n\n // Computers are created from registered image versions, as any API customer's are.\n // A `lineage:` image is the newest ready version of that lineage; a reference\n // is registered once, at prepare, and registered again here when its version expired.\n const readyImageVersion = async (\n client: ComputersApiClientIface,\n base: { image: string; imageVersionId: string | null },\n ): Promise<string> => {\n if (base.image.startsWith(LINEAGE_PREFIX)) {\n const lineage = base.image.slice(LINEAGE_PREFIX.length);\n const [newest] = await client.listImages({ lineage, state: ComputerImageState.Ready });\n if (newest == null) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `the Computers API has no ready image version in lineage ${lineage}`,\n );\n }\n return newest.id;\n }\n let version: ComputerImageIface | null = null;\n if (base.imageVersionId != null) {\n try {\n version = await client.getImage(base.imageVersionId);\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n }\n if (version == null || version.state === ComputerImageState.Expired) {\n version = await registerImage(client, base.image);\n }\n const deadline = now() + (config.imageWaitMs ?? 15 * 60_000);\n while (\n version.state === ComputerImageState.Pending ||\n version.state === ComputerImageState.Building\n ) {\n if (now() >= deadline) throw new Error(`image ${base.image} is still building`);\n await sleep(config.imagePollMs ?? 5_000);\n version = await client.getImage(version.id);\n }\n if (version.state !== ComputerImageState.Ready) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `image ${base.image} is ${version.state}${version.error == null ? '' : `: ${version.error}`}`,\n );\n }\n return version.id;\n };\n\n const mcpClosers = new Map<string, Set<() => Promise<void>>>();\n const closeComputerMcp = async (computerId: string) => {\n const results = await Promise.allSettled(\n [...(mcpClosers.get(computerId) ?? [])].map((close) => close()),\n );\n for (const result of results) if (result.status === 'rejected') throw result.reason;\n };\n const deletedAfterFenceError = async (options: {\n client: ComputersApiClientIface;\n computerId: string;\n cause: unknown;\n }): Promise<boolean> => {\n if (isComputersApiStatus(options.cause, 404)) return true;\n if (!isComputersApiStatus(options.cause, 409)) return false;\n try {\n const current = await options.client.getComputer(options.computerId);\n return current == null || current.state === ComputerState.Deleted;\n } catch (lookup) {\n throw new AggregateError(\n [options.cause, lookup],\n 'Computer fence and deletion lookup failed',\n );\n }\n };\n\n // The provider's own session on a computer: the platform's files and seeds\n // are written through it, never through a host's grant.\n const setupSession = (args: {\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n }): { sandbox: NetworkSandboxSessionIface; transport: SandboxTransportIface } => {\n const transport = createComputersApiTransport({\n client: args.client,\n computerId: args.info.id,\n });\n const sandbox = createTransportSession({\n id: args.info.id,\n description: `setup of ${args.info.name}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n ports: [],\n getPortEndpoint: async () => {\n throw new Error('setup sessions expose no ports');\n },\n stop: async () => undefined,\n destroy: async () => undefined,\n },\n });\n return { sandbox, transport };\n };\n\n const buildHandle = async (args: {\n ctx: HandleContextIface;\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n ports: readonly number[];\n // A viewer's handle: it changes nothing, and stopping it leaves the computer alone.\n passive: boolean;\n closeSetup?: () => void;\n }): Promise<SandboxProviderHandleIface<ComputerSandboxSessionIface>> => {\n const { client, info } = args;\n const transport = createComputersApiTransport({ client, computerId: info.id });\n let httpToken: { token: string; expiresAtMs: number } | null = null;\n const session = createTransportSession({\n id: info.id,\n description: `Final computer ${info.name}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n ports: [...args.ports],\n // The computer's hostname with a preview token, which opens its HTTP ports only.\n getPortEndpoint: async ({ port, protocol }) => {\n const hostname = info.hostname ?? (await client.getComputer(info.id))?.hostname ?? null;\n if (hostname == null) throw new Error(`computer ${info.name} has no public hostname`);\n if (httpToken == null || httpToken.expiresAtMs - now() < HTTP_TOKEN_RENEW_MS) {\n const expiresAtMs = now() + HTTP_TOKEN_LIFETIME_MS;\n const token = await client.createPreviewToken({\n computerId: info.id,\n name: `agent sandbox ${args.ctx.sandboxId}`,\n expiresAt: new Date(expiresAtMs),\n });\n httpToken = { token, expiresAtMs };\n }\n const scheme = protocol === PortProtocol.Ws ? 'wss' : 'https';\n return {\n url: `${scheme}://${port === 443 ? hostname : `${hostname}:${port}`}`,\n headers: { authorization: `Bearer ${httpToken.token}` },\n };\n },\n stop: async () => {\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(info.id);\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n try {\n await client.action(info.id, 'stop');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n transport.close();\n args.closeSetup?.();\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer stop or MCP cleanup failed');\n },\n destroy: async () => {\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(info.id);\n } catch (cause) {\n failures.push(cause);\n }\n transport.close();\n try {\n await client.action(info.id, 'delete');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n },\n });\n let computerUseInstalled: boolean | null = null;\n if (!args.passive) {\n try {\n computerUseInstalled = (await client.computerUseStatus(info.id, AbortSignal.timeout(1000)))\n .installed;\n } catch {\n /* Optional discovery must never fail the sandbox. */\n }\n }\n const computerUse =\n args.passive || computerUseInstalled === false\n ? null\n : createComputerUseEndpoint({ client, computerId: info.id, cwd: WORKSPACE_ROOT });\n const closeMcp = async () => {\n try {\n await computerUse?.close();\n } catch (error) {\n log('computer_use.close_failed', {\n computerId: info.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n const closers = mcpClosers.get(info.id);\n closers?.delete(closeMcp);\n if (closers?.size === 0) mcpClosers.delete(info.id);\n };\n if (computerUse != null) {\n const closers = mcpClosers.get(info.id) ?? new Set<() => Promise<void>>();\n closers.add(closeMcp);\n mcpClosers.set(info.id, closers);\n }\n const capabilities = [SandboxCapability.Files, SandboxCapability.Ports];\n let screenAvailable = false;\n try {\n screenAvailable = (await client.screenStatus(info.id, AbortSignal.timeout(1000))).available;\n } catch {\n /* Optional desktop discovery leaves headless computers usable. */\n }\n if (screenAvailable) capabilities.push(SandboxCapability.Screen);\n if (computerUse != null) capabilities.push(SandboxCapability.ComputerUse);\n if (!args.passive)\n capabilities.push(\n SandboxCapability.Process,\n SandboxCapability.DurableProcesses,\n SandboxCapability.NetworkPolicy,\n );\n const full: ComputerSandboxSessionIface = {\n ...session,\n setNetworkPolicy: async (policy) => {\n if (args.passive) throw new Error('this sandbox handle is read-only');\n await client.setNetworkPolicy(info.id, egressFor(args.ctx, policy));\n },\n capabilities,\n };\n if (computerUse != null) full.computerUse = async () => computerUse.endpoint;\n if (screenAvailable) full.screen = (options) => client.openScreen(info.id, options);\n return {\n sandbox: args.passive ? readOnlySession(full) : full,\n onSandboxStop: async () => {\n const failures: unknown[] = [];\n for (const finish of [closeMcp, () => transport.close(), () => args.closeSetup?.()]) {\n try {\n await finish();\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, 'Computer MCP cleanup failed');\n },\n onSandboxDelete: async () => {\n const failures: unknown[] = [];\n try {\n await closeMcp();\n } catch (cause) {\n failures.push(cause);\n }\n transport.close();\n args.closeSetup?.();\n try {\n await client.action(info.id, 'delete');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n onRuntimeShutdown: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n args.closeSetup?.();\n }\n },\n };\n };\n\n // A captured base, once it is ready; a failed or expired one must be built again.\n const awaitBase = async (\n client: ComputersApiClientIface,\n baseId: string,\n key: string,\n ): Promise<ComputerBaseIface> => {\n const deadline = now() + (config.buildWaitMs ?? 30 * 60_000);\n for (;;) {\n const base = await client.getBase(baseId);\n if (base == null || base.state === ComputerBaseState.Expired) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `computer base ${key} (${baseId}) is ${base == null ? 'gone' : 'expired'}; prepare it again`,\n );\n }\n if (base.state === ComputerBaseState.Ready) return base;\n if (base.state === ComputerBaseState.Failed) {\n throw computerSandboxError(\n 'build_failed',\n `computer base ${key} failed to capture: ${base.error ?? 'unknown error'}`,\n );\n }\n if (now() >= deadline) throw new Error(`computer base ${key} is still capturing`);\n await sleep(config.buildPollMs ?? 5_000);\n }\n };\n\n // The Computers API answers a computer it created or started before the\n // computer has a host, and refuses commands and file writes until it runs\n // (`autoResume: false`), so nothing touches it before this resolves. Only\n // Running counts: a paused computer still refuses them.\n const awaitComputerRunning = async (\n client: ComputersApiClientIface,\n computerId: string,\n timeoutMs: number,\n ): Promise<ComputerInfoIface> => {\n const deadline = now() + timeoutMs;\n let pollMs = config.runningPollMs ?? 250;\n for (;;) {\n const computer = await client.getComputer(computerId);\n if (computer == null || computer.state === ComputerState.Deleted)\n throw computerSandboxError('computer_gone', `computer ${computerId} is gone`);\n if (computer.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `computer ${computer.name} is in the Error state`,\n );\n if (computer.state === ComputerState.Running) return computer;\n const left = deadline - now();\n if (left <= 0)\n throw computerSandboxError(\n 'computer_not_running',\n `computer ${computer.name} was not running within ${Math.round(timeoutMs / 1000)} s (it is ${ComputerState[computer.state]})`,\n );\n await sleep(Math.min(pollMs, left));\n pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);\n }\n };\n\n // Run build.steps, then build.verify, on a builder computer of the\n // environment's image, captured as a base its computers are created from.\n const build = async (args: {\n ctx: SandboxPrepareContextIface;\n image: string;\n build: ComputerBuildIface;\n machine: ComputerEnvironmentIface['machine'];\n region: string | null;\n key: string;\n }): Promise<ComputerSandboxArtifact> => {\n const { ctx, key } = args;\n const client = clientFor(ctx);\n const diskGb = args.machine?.diskGb ?? null;\n const imageVersionId = await readyImageVersion(client, {\n image: args.image,\n imageVersionId: null,\n });\n const body: CreateComputerBodyIface = {\n name: `ag-${key.slice(4, 20)}-${compactId(randomUuid()).slice(0, 8)}`,\n imageVersionId,\n ...args.machine,\n // The base is the root disk; a user volume would keep /home and /workspaces off it.\n userVolumeGb: null,\n // Nothing secret at create: the create env lands in the guest.\n env: {},\n commandMode: ComputerCommandMode.Custom,\n customCommand: 'sleep infinity',\n autoResume: false,\n idleTimeoutSeconds: BUILDER_IDLE_TIMEOUT_SECONDS,\n tags: ['final-agent-sandbox-build'],\n };\n if (args.region != null) body.regionSlug = args.region;\n // One builder per attempt: a retry after a failed build starts clean.\n const builder = await client.createComputer(\n body,\n `agent-guide-build-${(await sha256Hex(`${key}:${randomUuid()}`)).slice(0, 32)}`,\n );\n ctx.log?.(`building computer base ${key} on ${builder.name}`);\n try {\n await awaitComputerRunning(client, builder.id, runningWaitMs);\n const sandbox = setupSession({ client, info: builder, env: async () => ({}) }).sandbox;\n const prepared = await sandbox.run({\n command: '/bin/sh',\n args: ['-c', `mkdir -p ${BUILD_ROOT}\\n${homeBaselineScript()}`],\n cwd: '/',\n });\n if (prepared.exitCode !== 0) {\n throw computerSandboxError('build_failed', 'failed to record the pre-build home baseline');\n }\n const steps = [\n ...args.build.steps.map((step) => ({ step, label: 'build step' })),\n ...args.build.verify.map((step) => ({ step, label: 'verify step' })),\n ];\n for (const [index, { step, label }] of steps.entries()) {\n ctx.log?.(`${label} ${index + 1}/${steps.length}`);\n const result = await sandbox.run({\n command: `set -eu\\n${step.run}`,\n shell: true,\n cwd: BUILD_ROOT,\n timeoutMs: step.timeoutMinutes * 60_000,\n });\n if (result.exitCode !== 0) {\n throw computerSandboxError(\n 'build_failed',\n `${label} ${index + 1} failed (exit ${result.exitCode}): ${result.stderr.trim().slice(-2000)}`,\n );\n }\n }\n const homeContent = await sandbox.run({\n command: '/bin/sh',\n args: ['-c', homeContentScript({ excludedPaths: CAPTURE_SCRUBBED_PATHS })],\n cwd: '/',\n });\n if (homeContent.exitCode === HOME_BASELINE_MISSING_EXIT_CODE) {\n throw computerSandboxError(\n 'build_failed',\n `build steps removed ${HOME_BASELINE_ROOT}, which the home content check needs; leave /var/tmp/final-template-build in place.`,\n );\n }\n if (homeContent.exitCode !== 0) {\n const offending = homeContent.stdout\n .trim()\n .split('\\n')\n .filter((line) => line !== '');\n throw computerSandboxError(\n 'build_failed',\n `build steps left content under /home or /workspaces, which each computer's own volume hides: ${offending.join(', ')}. Install tools and configuration to system paths such as /usr/local, or point the tool's home there (for example CARGO_HOME=/usr/local/cargo, RUSTUP_HOME=/usr/local/rustup, NVM_DIR=/usr/local/nvm), put home files in /usr/share/final-vm/home-skel, and use /etc/gitconfig instead of git config --global.`,\n );\n }\n const captured = await client.captureComputer(builder.id, { retained: true });\n if (!captured.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the built base',\n );\n ctx.log?.(`capturing computer base ${key} as ${captured.id}`);\n const base = await awaitBase(client, captured.id, key);\n return {\n version: 1,\n key,\n image: args.image,\n diskGb: diskGb ?? base.diskGb,\n seedFiles: {},\n base: { kind: 'captured', baseId: base.id },\n };\n } finally {\n // The capture stopped the builder; it is not part of the base.\n try {\n await client.action(builder.id, 'delete');\n } catch (error) {\n log('computer_sandbox.builder_delete_failed', {\n computerId: builder.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n };\n\n const environment = (\n rawOptions?: JsonValue,\n ): SandboxEnvironmentImplementationIface<\n ComputerSandboxArtifact,\n ComputerSandboxState,\n ComputerSandboxSessionIface\n > => {\n const parsed = computerEnvironmentSchema.safeParse(rawOptions ?? {});\n if (!parsed.success) {\n throw computerSandboxError(\n 'invalid_environment',\n `invalid computer environment: ${parsed.error.message}`,\n );\n }\n const options = parsed.data;\n const image = options.image ?? config.defaultImage ?? DEFAULT_COMPUTER_IMAGE;\n const machine = options.machine ?? config.machine;\n const region = options.region ?? config.regionSlug ?? null;\n // Outlasts the platform's own idle parking, so the platform parks first.\n const idleTimeoutFor = (ctx: SandboxResourceContextIface): number =>\n options.idleTimeoutSeconds ??\n (ctx.lifecycle.parkAfterIdleMs == null\n ? DEFAULT_IDLE_TIMEOUT_SECONDS\n : Math.ceil(ctx.lifecycle.parkAfterIdleMs / 1000) + IDLE_TIMEOUT_MARGIN_SECONDS);\n const seedsFor = (ctx: SandboxPrepareContextIface): Record<string, string> =>\n sandboxSeedFiles({ files: ctx.files, resources: ctx.resources });\n const keyFor = async (files: Record<string, string>): Promise<string> => {\n const baseKey = await computeComputerArtifactKey({\n image,\n build: options.build,\n diskGb: machine?.diskGb ?? null,\n });\n return Object.keys(files).length === 0\n ? baseKey\n : `${baseKey}-s${await sha256Hex(sandboxSeedIdentity(files))}`;\n };\n const retainedBase = async (\n ctx: SandboxPrepareContextIface,\n baseKey: string,\n ): Promise<ComputerSandboxArtifact | null> => {\n const cached = computerArtifactSchema.safeParse(await ctx.artifacts?.get(baseKey));\n if (!cached.success || cached.data.key !== baseKey || cached.data.base.kind !== 'captured')\n return null;\n const client = clientFor(ctx);\n const base = await client.getBase(cached.data.base.baseId);\n if (base?.state !== ComputerBaseState.Ready) return null;\n if (!base.retained && !(await client.setBaseRetention(base.id, true)).retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n return cached.data;\n };\n\n const stateOf = (raw: JsonValue): ComputerSandboxState => {\n const state = computerStateSchema.safeParse(raw);\n if (!state.success)\n throw computerSandboxError(\n 'computer_gone',\n 'this sandbox was recorded by an older computer provider; create it again',\n );\n return state.data;\n };\n\n // The computer the state names, else one an interrupted attach created\n // under the sandbox's name; null when none exists.\n const findComputer = async (\n client: ComputersApiClientIface,\n state: ComputerSandboxState,\n ): Promise<ComputerInfoIface | null> => {\n const found = await client.getComputer(state.computerId ?? state.computerName);\n return found == null || found.state === ComputerState.Deleted ? null : found;\n };\n\n return {\n capabilities: async () => ({\n [Capability.Files]: FilesAccess.Write,\n [Capability.Shell]: ShellAccess.Execute,\n [Capability.ComputerUse]: ScreenAccess.Control,\n }),\n // The computer-use tools of this environment's image, from the Computers\n // API without a computer, so a sandbox lists them before its first attach.\n // Unknown when the API cannot tell: the first attach learns them.\n mcpCatalog: async (ctx) => {\n let tools: Awaited<ReturnType<ComputersApiClientIface['computerUseCatalog']>>;\n try {\n tools = await clientFor(ctx).computerUseCatalog({ image });\n } catch (error) {\n log('computer_use_catalog_unavailable', {\n image,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n return tools == null ? null : { computerUse: toolDescriptorsOf(tools), localMcp: null };\n },\n processes: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n if (state.computerId == null) throw new Error('this computer has not started yet');\n return clientFor(ctx).inspectProcesses(state.computerId, request);\n },\n editor: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n const computerId = state.computerId;\n if (computerId == null) {\n if (request.operation === 'available') return { available: false };\n throw new Error('this computer has not started yet');\n }\n const client = clientFor(ctx);\n const open = (expiresAtMs?: number) =>\n computerEditor({\n client,\n computerId,\n request,\n randomUuid,\n expiresAtMs,\n });\n return open();\n },\n readSnapshot: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n if (state.computerId == null) return null;\n return readComputerSnapshot({\n client: clientFor(ctx),\n computerId: state.computerId,\n request,\n });\n },\n artifactKey: async (ctx) => keyFor(seedsFor(ctx)),\n // Builds the base an environment with build steps needs, or registers an\n // image reference so its version builds ahead of the first attach (a\n // lineage needs nothing until then).\n prepare: async (ctx) => {\n const seedFiles = seedsFor(ctx);\n const key = await keyFor(seedFiles);\n const seedArtifact = await sandboxSeedArtifact(ctx, seedFiles);\n if (options.build != null && computerNeedsBuild(options.build)) {\n const baseKey = await keyFor({});\n const retained = await retainedBase(ctx, baseKey);\n if (retained != null) return { ...retained, key, ...seedArtifact };\n const built = await build({\n ctx,\n image,\n build: options.build,\n machine,\n region,\n key: baseKey,\n });\n await ctx.artifacts?.put(baseKey, built);\n return { ...built, key, ...seedArtifact };\n }\n const imageVersionId = image.startsWith(LINEAGE_PREFIX)\n ? null\n : (await registerImage(clientFor(ctx), image)).id;\n ctx.log?.(`computer base ${key} is image ${image}`);\n return {\n version: 1,\n key,\n image,\n diskGb: machine?.diskGb ?? null,\n ...seedArtifact,\n base: { kind: 'image', image, imageVersionId },\n };\n },\n // Records the computer; the first attach creates it. The setup's network\n // policy is checked now so a policy a computer cannot enforce never boots.\n create: async (ctx, { setup }) => {\n const network = computerNetworkPolicyOf(setup);\n const ports = [\n ...new Set(\n (setup?.services ?? []).flatMap((service) =>\n service.port == null ? [] : [service.port],\n ),\n ),\n ];\n return {\n state: {\n version: 2,\n computerName: await computerNameFor(ctx.sandboxId),\n computerId: null,\n network,\n ports,\n },\n region,\n };\n },\n awaitRunning: async (ctx, rawState, options) => {\n const state = stateOf(rawState);\n await awaitComputerRunning(\n clientFor(ctx),\n state.computerId ?? state.computerName,\n options.timeoutMs,\n );\n },\n attach: async (ctx, { artifact: rawArtifact, state: rawState }) => {\n const state = stateOf(rawState);\n const artifact = computerArtifactSchema.safeParse(rawArtifact);\n if (!artifact.success)\n throw computerSandboxError(\n 'artifact_unavailable',\n 'this computer base predates the current computer provider; prepare it again',\n );\n const base = artifact.data.base;\n if (computerNeedsBuild(options.build) && base.kind !== 'captured')\n throw computerSandboxError(\n 'artifact_unavailable',\n `computer base ${artifact.data.key} was prepared without its build steps; prepare it again`,\n );\n const client = clientFor(ctx);\n const env = platformProcessEnvironment(ctx, {});\n const policy = withPlatformEgressHosts(ctx, state.network);\n const egress = computerEgressOf(policy);\n const existing = await findComputer(client, state);\n if (existing?.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `Computer ${existing.id} (${existing.name}) is in the Error state. Recover it through the Computers API before retrying; its disk is preserved.`,\n );\n let info: ComputerInfoIface;\n let booted: boolean;\n if (existing != null) {\n info = existing;\n // A paused computer resumes with its processes; a stopped or shelved one boots.\n booted = !isRunningState(existing.state);\n if (existing.state === ComputerState.Paused) await client.action(existing.id, 'resume');\n else if (booted) await client.action(existing.id, 'start');\n } else {\n // A computer the state named but that no longer exists comes back\n // empty: the attach reports a fresh disk.\n booted = true;\n const source: Pick<CreateComputerBodyIface, 'baseId' | 'imageVersionId'> =\n base.kind === 'captured'\n ? { baseId: (await awaitBase(client, base.baseId, artifact.data.key)).id }\n : { imageVersionId: await readyImageVersion(client, base) };\n const body: CreateComputerBodyIface = {\n name: state.computerName,\n ...source,\n ...machine,\n env: {},\n autoResume: true,\n idleTimeoutSeconds: idleTimeoutFor(ctx),\n // The sandbox owns deletion; VM-level ephemeral disks cannot be paused.\n ephemeral: false,\n network: egress,\n tags: [\n 'final-agent-sandbox',\n `agent-sandbox:${ctx.sandboxId}`,\n 'agent-runtime-attachment:v1',\n 'agent-runtime-role:sandbox',\n ],\n };\n // Idle must preserve files: the sandbox is deleted only by its owner.\n body.idlePolicy = ComputerIdlePolicy.Pause;\n if (region != null) body.regionSlug = region;\n // A retry of this attach makes the same request; one after the\n // computer was deleted, or after re-registering the image, a new one.\n const idempotencyKey = `agent-sandbox-${(await sha256Hex(`${ctx.sandboxId}:${state.computerName}:${state.computerId ?? 'first'}:${source.baseId ?? source.imageVersionId}:false`)).slice(0, 32)}`;\n info = await client.createComputer(body, idempotencyKey);\n }\n const fresh = existing == null;\n log('computer_sandbox.attached', { computerId: info.id, fresh, booted });\n let cleanup: (() => Promise<void>) | null = null;\n try {\n info = await awaitComputerRunning(client, info.id, runningWaitMs);\n // A reused computer keeps whatever policy it last ran under; it gets the setup's again.\n if (!fresh) await client.setNetworkPolicy(info.id, egress);\n await reportPlatformNetworkPolicy(ctx, policy);\n const setup = setupSession({ client, info, env });\n cleanup = async () => setup.transport.close();\n await writePlatformFiles(ctx, setup.sandbox);\n // A new disk gets the workspace seeds once.\n if (fresh) {\n const seedMarker = `${WORKSPACE_ROOT}/.final/workspace-prepared/${await sha256Hex(artifact.data.key)}`;\n if ((await setup.sandbox.stat({ path: seedMarker })) == null) {\n await materializeSandboxSeeds({\n sandbox: setup.sandbox,\n root: WORKSPACE_ROOT,\n files: await sandboxSeedFilesForAttach(ctx, artifact.data),\n });\n await setup.sandbox.writeTextFile({ path: seedMarker, content: 'complete' });\n }\n }\n const handle = await buildHandle({\n ctx,\n client,\n info,\n env,\n ports: state.ports,\n passive: false,\n closeSetup: () => setup.transport.close(),\n });\n return {\n handle,\n region: info.regionSlug ?? region,\n state: { ...state, computerId: info.id },\n fresh,\n booted,\n };\n } catch (error) {\n let cause = error;\n try {\n await cleanup?.();\n } catch (cleanupError) {\n cause = new AggregateError(\n [error, cleanupError],\n 'Computer attach and setup cleanup failed',\n );\n }\n // No state reaches the caller on failure; remove only a computer this attach created.\n if (fresh) {\n try {\n await client.action(info.id, 'delete');\n } catch (cleanupError) {\n throw new AggregateError(\n [cause, cleanupError],\n `computer ${info.name} attach and cleanup failed`,\n );\n }\n }\n throw cause;\n }\n },\n attachPassive: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n const client = clientFor(ctx);\n const info = await findComputer(client, state);\n if (info == null || info.state !== ComputerState.Running)\n throw computerSandboxError(\n 'computer_not_running',\n 'computer is not running for passive access',\n );\n return buildHandle({\n ctx,\n client,\n info: await awaitComputerRunning(client, info.id, runningWaitMs),\n env: platformProcessEnvironment(ctx, {}),\n ports: state.ports,\n passive: true,\n });\n },\n // The computer pauses on its own idle policy; nothing to do.\n detach: async (_ctx, { state }) => stateOf(state),\n park: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n if (state.computerId == null) return state;\n const computerId = state.computerId;\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(computerId);\n } catch (cause) {\n failures.push(cause);\n }\n try {\n const client = clientFor(ctx);\n // Park reads the computer's state rather than trusting a pause's status\n // alone: a pause that cannot land would otherwise fail on every retry.\n let current: ComputerInfoIface | null | undefined;\n try {\n current = await client.getComputer(computerId);\n } catch (cause) {\n failures.push(cause);\n }\n if (current !== undefined && (current == null || hasNothingToPause(current.state))) {\n log('computer_sandbox.park_at_rest', {\n computerId,\n state: current?.state ?? null,\n });\n } else {\n // A paused computer is paused again: a resume may be in flight.\n try {\n await client.action(computerId, 'pause');\n } catch (error) {\n if (!pauseMayHaveSettled(error)) throw error;\n // Parked if it came to rest meanwhile (an idle pause or stop, a delete);\n // otherwise the pause did not happen and park is retried.\n const settled = await client.getComputer(computerId);\n if (\n settled != null &&\n settled.state !== ComputerState.Paused &&\n !hasNothingToPause(settled.state)\n )\n throw error;\n log('computer_sandbox.park_at_rest', {\n computerId,\n state: settled?.state ?? null,\n });\n }\n }\n } catch (cause) {\n failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, 'Computer pause failed');\n return state;\n },\n delete: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n const client = clientFor(ctx);\n const computer = await findComputer(client, state);\n if (computer == null) return;\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(computer.id);\n } catch (cause) {\n failures.push(cause);\n }\n log('computer_sandbox.delete', { computerId: computer.id });\n try {\n await client.action(computer.id, 'delete');\n } catch (error) {\n // A conflict is done only when the computer is already gone; one\n // mid-transition (an idle pause committing) is retried.\n if (!(await deletedAfterFenceError({ client, computerId: computer.id, cause: error })))\n failures.push(error);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n };\n };\n\n return defineSandboxProvider({\n name: COMPUTER_PROVIDER,\n stateProtocolVersion: 2,\n environment,\n });\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { Capability, FilesAccess, ScreenAccess, ShellAccess } from '@finalai/agent-protocol';\nimport { NetworkPolicy, type JsonValue } from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n materializeSandboxSeeds,\n platformProcessEnvironment,\n PortProtocol,\n reportPlatformNetworkPolicy,\n SandboxCapability,\n sandboxSeedArtifact,\n sandboxSeedArtifactSchema,\n sandboxSeedFiles,\n sandboxSeedFilesForAttach,\n sandboxSeedIdentity,\n withPlatformEgressHosts,\n writePlatformFiles,\n type NetworkPolicyIface,\n type NetworkSandboxSessionIface,\n type SandboxEnvironmentImplementationIface,\n type SandboxPrepareContextIface,\n type SandboxProviderContextIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxResourceContextIface,\n type SandboxSetupIface,\n} from '@finalai/agent-provider/sandbox';\nimport {\n ComputerBaseState,\n ComputerCommandMode,\n ComputerEgressPolicy,\n ComputerIdlePolicy,\n ComputerImageState,\n ComputerState,\n type ComputerBaseIface,\n type ComputerImageIface,\n type ComputerInfoIface,\n} from '@finalai/computers';\nimport * as z from 'zod';\nimport {\n HOME_BASELINE_MISSING_EXIT_CODE,\n HOME_BASELINE_ROOT,\n homeBaselineScript,\n homeContentScript,\n} from \"./build-scripts.mjs\";\nimport { canonicalJson, sleep as defaultSleep, sha256Hex } from \"./bytes.mjs\";\nimport { computerEditor } from \"./computer-editor.mjs\";\nimport { readComputerSnapshot } from \"./computer-snapshots.mjs\";\nimport {\n createComputersApiClient,\n isComputersApiError,\n isComputersApiStatus,\n type ComputersApiClientIface,\n type ComputersApiConfigIface,\n type ComputersApiCredentialsIface,\n type CreateComputerBodyIface,\n} from \"./computers-api.mjs\";\nimport { createComputerUseEndpoint } from \"./computers-api-mcp.mjs\";\nimport { createComputersApiTransport } from \"./computers-api-transport.mjs\";\nimport {\n COMPUTER_PROVIDER,\n computerEnvironmentSchema,\n DEFAULT_COMPUTER_IMAGE,\n type ComputerBuildIface,\n type ComputerEnvironmentIface,\n} from \"./environment.mjs\";\nimport { createTransportSession, readOnlySession } from \"./session.mjs\";\nimport { toolDescriptorsOf } from \"./tool-catalog.mjs\";\nimport type { SandboxTransportIface } from \"./transport.mjs\";\n\nexport type { ComputersApiConfigIface } from \"./computers-api.mjs\";\nexport type { FinalPlatformAccessIface } from \"./environment.mjs\";\nexport { COMPUTER_PROVIDER } from \"./environment.mjs\";\n\n// The `computer` sandbox: a Final computer from the public Computers API, with\n// lifecycle, files and processes all through that API, exactly as a\n// third-party provider drives its vendor. Like every provider, the host runs\n// this handle and serves the handle RPC and MCP projection from it.\n//\n// A sandbox is one computer, named after the sandbox's id: `create` records\n// it and the first `attach` makes it, so creating a sandbox boots nothing. An\n// environment with build or verify steps is built once on a builder computer\n// and captured as a base (POST /v1/computers/:id/capture) that its computers\n// are created from. The sandbox setup's network policy is a create option, as\n// for any API customer; its repositories, steps and services are applied by\n// the platform through the handle.\n\nexport const WORKSPACE_ROOT = '/workspaces';\n\nconst DEFAULT_IDLE_TIMEOUT_SECONDS = 15 * 60;\nconst IDLE_TIMEOUT_MARGIN_SECONDS = 5 * 60;\n\nexport interface ComputerSandboxLogIface {\n (message: string, fields?: Record<string, string | number | boolean | null>): void;\n}\n\nexport interface ComputerSandboxProviderConfigIface {\n // The Computers API origin. Requests authenticate with the provider's\n // platform identity for it (ctx.identity), which the registration must be\n // granted.\n computersApiUrl: string;\n // Transport options.\n computersApi?: ComputersApiConfigIface;\n // A registry credential (`creg_...`) stored for private image references.\n registryCredentialId?: string;\n // Image for an environment that names none.\n defaultImage?: string;\n // Defaults for what an environment leaves out.\n regionSlug?: string;\n machine?: { vcpu?: number; memoryMb?: number; diskGb?: number };\n // How long attach waits for a registered image version to finish building.\n imageWaitMs?: number;\n imagePollMs?: number;\n // How long `prepare` waits for a base capture to publish.\n buildWaitMs?: number;\n buildPollMs?: number;\n // How long attach and a build wait for a computer to run before touching it\n // (default 5 min); polled from runningPollMs (default 250 ms), doubling to 5 s.\n runningWaitMs?: number;\n runningPollMs?: number;\n log?: ComputerSandboxLogIface;\n randomUuid?: () => string;\n now?: () => number;\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\n// An `image` base: `imageVersionId` is the registered version (`cimv_...`) of an\n// image reference, registered at prepare; a `lineage:` image resolves its newest\n// version at attach. A `captured` base is the environment's build, captured as\n// a base (`part_...`) that computers are created from.\nconst computerArtifactSchema = sandboxSeedArtifactSchema.extend({\n version: z.literal(1),\n key: z.string(),\n image: z.string(),\n diskGb: z.number().nullable(),\n base: z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('image'),\n image: z.string(),\n imageVersionId: z.string().nullable().default(null),\n }),\n z.object({ kind: z.literal('captured'), baseId: z.string() }),\n ]),\n});\n\nconst networkPolicySchema = z.object({\n mode: z.nativeEnum(NetworkPolicy),\n allow: z.array(z.string()).optional(),\n});\n\nconst computerStateSchema = z.object({\n version: z.literal(2),\n computerName: z.string(),\n // Null until the first attach creates the computer.\n computerId: z.string().nullable(),\n // The sandbox setup's network policy, enforced from the computer's first boot.\n network: networkPolicySchema,\n // Ports the setup's services listen on.\n ports: z.array(z.number().int()).default([]),\n});\n\nexport type ComputerSandboxArtifact = z.infer<typeof computerArtifactSchema>;\nexport type ComputerSandboxState = z.infer<typeof computerStateSchema>;\n\nexport interface ComputerSandboxSessionIface extends NetworkSandboxSessionIface {\n // What this computer's handle offers (the host reports it).\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type ComputerSandboxProviderIface = SandboxProviderIface<\n JsonValue,\n ComputerSandboxArtifact,\n ComputerSandboxState,\n ComputerSandboxSessionIface\n>;\n\nexport interface ComputerSandboxErrorIface extends Error {\n code:\n | 'artifact_unavailable'\n | 'computer_gone'\n | 'computer_not_running'\n | 'invalid_environment'\n | 'build_failed';\n}\n\nconst computerSandboxError = (\n code: ComputerSandboxErrorIface['code'],\n message: string,\n): ComputerSandboxErrorIface =>\n Object.assign(new Error(message), { name: 'ComputerSandboxError', code });\n\nconst HTTP_TOKEN_LIFETIME_MS = 60 * 60_000;\nconst HTTP_TOKEN_RENEW_MS = 5 * 60_000;\n\n// Builds run from here; the capture scrub removes /tmp/*.\nconst BUILD_ROOT = '/tmp/final-build';\n// What the Computers API's capture scrub removes, so the home check skips it.\nconst CAPTURE_SCRUBBED_PATHS = [\n '/home/user/.bash_history',\n '/home/user/.zsh_history',\n '/home/user/.sh_history',\n '/home/user/.git-credentials',\n '/home/user/.config/gh/hosts.yml',\n '/home/user/.npmrc',\n '/home/user/.pypirc',\n '/home/user/.cargo/credentials',\n '/home/user/.cargo/credentials.toml',\n '/home/user/.aws',\n '/home/user/.config/gcloud',\n '/home/user/.azure',\n '/home/user/.docker/config.json',\n '/home/user/.netrc',\n '/home/user/.ssh',\n];\nconst BUILDER_IDLE_TIMEOUT_SECONDS = 2 * 60 * 60;\n// Bumped when the meaning of the build inputs changes (forces rebuilds).\nconst ARTIFACT_KEY_VERSION = 1;\n// Part of a built base's key; bumping it rebuilds every base.\nconst PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION = 2;\n\ninterface ComputerEgressConfigIface {\n egress: ComputerEgressPolicy;\n allow?: string[];\n}\nconst computerEgressOf = (policy: NetworkPolicyIface): ComputerEgressConfigIface => {\n if (policy.mode === NetworkPolicy.AllowAll) return { egress: ComputerEgressPolicy.Internet };\n if (policy.mode === NetworkPolicy.DenyAll) return { egress: ComputerEgressPolicy.None };\n return { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow ?? [] };\n};\n\n// An allowlist also admits the platform's egress hosts, so its proxy stays reachable.\nconst egressFor = (\n ctx: Pick<SandboxResourceContextIface, 'platformEgressHosts'>,\n requested: NetworkPolicyIface,\n): ComputerEgressConfigIface => computerEgressOf(withPlatformEgressHosts(ctx, requested));\n\n// The setup's network as a computer can enforce it from boot: every host, none,\n// or an allowlist. A computer has no per-host deny list, so a setup naming one\n// is refused at create rather than run unenforced.\nexport const computerNetworkPolicyOf = (setup: SandboxSetupIface | null): NetworkPolicyIface => {\n const network = setup?.network;\n if (network == null) return { mode: NetworkPolicy.AllowAll };\n if ((network.deny ?? []).length > 0)\n throw computerSandboxError(\n 'invalid_environment',\n 'A Final computer cannot deny individual hosts; list the hosts to allow instead',\n );\n if (network.allow == null) return { mode: NetworkPolicy.AllowAll };\n return network.allow.length === 0\n ? { mode: NetworkPolicy.DenyAll }\n : { mode: NetworkPolicy.Allowlist, allow: [...network.allow] };\n};\n\nconst LINEAGE_PREFIX = 'lineage:';\n\nconst compactId = (id: string): string => id.replaceAll('-', '');\n\n// The computer's name: stable for the sandbox, so an attach retried after a\n// lost answer finds the computer it already created.\nexport const computerNameFor = async (sandboxId: string): Promise<string> =>\n `as-${(await sha256Hex(sandboxId)).slice(0, 24)}`;\n\nconst isRunningState = (state: ComputerState): boolean =>\n state === ComputerState.Running ||\n state === ComputerState.Paused ||\n state === ComputerState.Resuming;\n\n// Nothing runs on these to pause, and the Computers API refuses a pause of them:\n// stopped or shelved (the disk at rest), errored (resume reports it gone), or deleted.\nconst hasNothingToPause = (state: ComputerState): boolean =>\n state === ComputerState.Stopped ||\n state === ComputerState.Shelved ||\n state === ComputerState.Error ||\n state === ComputerState.Deleted;\n\n// A refusal (409), a missing computer (404) or a failed host command (5xx) can\n// mean the computer came to rest on its own; a request or auth failure cannot.\nconst pauseMayHaveSettled = (error: unknown): boolean =>\n isComputersApiError(error) &&\n error.statusCode != null &&\n (error.statusCode === 404 || error.statusCode === 409 || error.statusCode >= 500);\n\nconst RUNNING_POLL_MAX_MS = 5_000;\n\nexport const computerNeedsBuild = (build: ComputerBuildIface | undefined): boolean =>\n build != null && (build.steps.length > 0 || build.verify.length > 0);\n\n// The base's identity: a hash of the build-time inputs only, so identical\n// environments share one base.\nexport const computeComputerArtifactKey = async (inputs: {\n image: string;\n build: ComputerBuildIface | undefined;\n diskGb: number | null;\n}): Promise<string> => {\n if (!computerNeedsBuild(inputs.build)) {\n const hex = await sha256Hex(canonicalJson({ v: ARTIFACT_KEY_VERSION, image: inputs.image }));\n return `img-${hex.slice(0, 16)}`;\n }\n const hex = await sha256Hex(\n canonicalJson({\n v: ARTIFACT_KEY_VERSION,\n image: inputs.image,\n build: { steps: inputs.build?.steps ?? [], verify: inputs.build?.verify ?? [] },\n diskGb: inputs.diskGb,\n }),\n );\n return `pa-g${hex.slice(0, 16)}-c${PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION}`;\n};\n\n// What a computer's handle needs beyond the client: the sandbox it serves and\n// the platform's egress hosts its allowlist keeps.\ntype HandleContextIface = Pick<SandboxResourceContextIface, 'sandboxId' | 'platformEgressHosts'>;\n\nexport const createComputerSandboxProvider = (\n config: ComputerSandboxProviderConfigIface,\n): ComputerSandboxProviderIface => {\n const log: ComputerSandboxLogIface = config.log ?? (() => undefined);\n const randomUuid = config.randomUuid ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => Date.now());\n const sleep = config.sleep ?? defaultSleep;\n const runningWaitMs = config.runningWaitMs ?? 5 * 60_000;\n\n // An assertion for the Computers API before each request, and a new one\n // after a rejection.\n const credentialsFor = (ctx: SandboxProviderContextIface): ComputersApiCredentialsIface => ({\n computersAccess: async (args) => ({\n baseUrl: config.computersApiUrl,\n token: (\n await ctx.identity({ audience: config.computersApiUrl, refresh: args?.refresh === true })\n ).token,\n }),\n });\n\n const clientFor = (ctx: SandboxProviderContextIface): ComputersApiClientIface =>\n createComputersApiClient({\n config: config.computersApi ?? {},\n credentials: credentialsFor(ctx),\n });\n\n const registerImage = (client: ComputersApiClientIface, reference: string) =>\n client.registerImage(\n config.registryCredentialId == null\n ? { reference }\n : { reference, registryCredentialId: config.registryCredentialId },\n );\n\n // Computers are created from registered image versions, as any API customer's are.\n // A `lineage:` image is the newest ready version of that lineage; a reference\n // is registered once, at prepare, and registered again here when its version expired.\n const readyImageVersion = async (\n client: ComputersApiClientIface,\n base: { image: string; imageVersionId: string | null },\n ): Promise<string> => {\n if (base.image.startsWith(LINEAGE_PREFIX)) {\n const lineage = base.image.slice(LINEAGE_PREFIX.length);\n const [newest] = await client.listImages({ lineage, state: ComputerImageState.Ready });\n if (newest == null) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `the Computers API has no ready image version in lineage ${lineage}`,\n );\n }\n return newest.id;\n }\n let version: ComputerImageIface | null = null;\n if (base.imageVersionId != null) {\n try {\n version = await client.getImage(base.imageVersionId);\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n }\n if (version == null || version.state === ComputerImageState.Expired) {\n version = await registerImage(client, base.image);\n }\n const deadline = now() + (config.imageWaitMs ?? 15 * 60_000);\n while (\n version.state === ComputerImageState.Pending ||\n version.state === ComputerImageState.Building\n ) {\n if (now() >= deadline) throw new Error(`image ${base.image} is still building`);\n await sleep(config.imagePollMs ?? 5_000);\n version = await client.getImage(version.id);\n }\n if (version.state !== ComputerImageState.Ready) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `image ${base.image} is ${version.state}${version.error == null ? '' : `: ${version.error}`}`,\n );\n }\n return version.id;\n };\n\n const mcpClosers = new Map<string, Set<() => Promise<void>>>();\n const closeComputerMcp = async (computerId: string) => {\n const results = await Promise.allSettled(\n [...(mcpClosers.get(computerId) ?? [])].map((close) => close()),\n );\n for (const result of results) if (result.status === 'rejected') throw result.reason;\n };\n const deletedAfterFenceError = async (options: {\n client: ComputersApiClientIface;\n computerId: string;\n cause: unknown;\n }): Promise<boolean> => {\n if (isComputersApiStatus(options.cause, 404)) return true;\n if (!isComputersApiStatus(options.cause, 409)) return false;\n try {\n const current = await options.client.getComputer(options.computerId);\n return current == null || current.state === ComputerState.Deleted;\n } catch (lookup) {\n throw new AggregateError(\n [options.cause, lookup],\n 'Computer fence and deletion lookup failed',\n );\n }\n };\n\n // The provider's own session on a computer: the platform's files and seeds\n // are written through it, never through a host's grant.\n const setupSession = (args: {\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n }): { sandbox: NetworkSandboxSessionIface; transport: SandboxTransportIface } => {\n const transport = createComputersApiTransport({\n client: args.client,\n computerId: args.info.id,\n });\n const sandbox = createTransportSession({\n id: args.info.id,\n description: `setup of ${args.info.name}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n ports: [],\n getPortEndpoint: async () => {\n throw new Error('setup sessions expose no ports');\n },\n stop: async () => undefined,\n destroy: async () => undefined,\n },\n });\n return { sandbox, transport };\n };\n\n const buildHandle = async (args: {\n ctx: HandleContextIface;\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n ports: readonly number[];\n // A viewer's handle: it changes nothing, and stopping it leaves the computer alone.\n passive: boolean;\n closeSetup?: () => void;\n }): Promise<SandboxProviderHandleIface<ComputerSandboxSessionIface>> => {\n const { client, info } = args;\n const transport = createComputersApiTransport({ client, computerId: info.id });\n let httpToken: { token: string; expiresAtMs: number } | null = null;\n const session = createTransportSession({\n id: info.id,\n description: `Final computer ${info.name}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n ports: [...args.ports],\n // The computer's hostname with a preview token, which opens its HTTP ports only.\n getPortEndpoint: async ({ port, protocol }) => {\n const hostname = info.hostname ?? (await client.getComputer(info.id))?.hostname ?? null;\n if (hostname == null) throw new Error(`computer ${info.name} has no public hostname`);\n if (httpToken == null || httpToken.expiresAtMs - now() < HTTP_TOKEN_RENEW_MS) {\n const expiresAtMs = now() + HTTP_TOKEN_LIFETIME_MS;\n const token = await client.createPreviewToken({\n computerId: info.id,\n name: `agent sandbox ${args.ctx.sandboxId}`,\n expiresAt: new Date(expiresAtMs),\n });\n httpToken = { token, expiresAtMs };\n }\n const scheme = protocol === PortProtocol.Ws ? 'wss' : 'https';\n return {\n url: `${scheme}://${port === 443 ? hostname : `${hostname}:${port}`}`,\n headers: { authorization: `Bearer ${httpToken.token}` },\n };\n },\n stop: async () => {\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(info.id);\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n try {\n await client.action(info.id, 'stop');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n transport.close();\n args.closeSetup?.();\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer stop or MCP cleanup failed');\n },\n destroy: async () => {\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(info.id);\n } catch (cause) {\n failures.push(cause);\n }\n transport.close();\n try {\n await client.action(info.id, 'delete');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n },\n });\n let computerUseInstalled: boolean | null = null;\n if (!args.passive) {\n try {\n computerUseInstalled = (await client.computerUseStatus(info.id, AbortSignal.timeout(1000)))\n .installed;\n } catch {\n /* Optional discovery must never fail the sandbox. */\n }\n }\n const computerUse =\n args.passive || computerUseInstalled === false\n ? null\n : createComputerUseEndpoint({ client, computerId: info.id, cwd: WORKSPACE_ROOT });\n const closeMcp = async () => {\n try {\n await computerUse?.close();\n } catch (error) {\n log('computer_use.close_failed', {\n computerId: info.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n const closers = mcpClosers.get(info.id);\n closers?.delete(closeMcp);\n if (closers?.size === 0) mcpClosers.delete(info.id);\n };\n if (computerUse != null) {\n const closers = mcpClosers.get(info.id) ?? new Set<() => Promise<void>>();\n closers.add(closeMcp);\n mcpClosers.set(info.id, closers);\n }\n const capabilities = [SandboxCapability.Files, SandboxCapability.Ports];\n let screenAvailable = false;\n try {\n screenAvailable = (await client.screenStatus(info.id, AbortSignal.timeout(1000))).available;\n } catch {\n /* Optional desktop discovery leaves headless computers usable. */\n }\n if (screenAvailable) capabilities.push(SandboxCapability.Screen);\n if (computerUse != null) capabilities.push(SandboxCapability.ComputerUse);\n if (!args.passive)\n capabilities.push(\n SandboxCapability.Process,\n SandboxCapability.DurableProcesses,\n SandboxCapability.NetworkPolicy,\n );\n const full: ComputerSandboxSessionIface = {\n ...session,\n setNetworkPolicy: async (policy) => {\n if (args.passive) throw new Error('this sandbox handle is read-only');\n await client.setNetworkPolicy(info.id, egressFor(args.ctx, policy));\n },\n capabilities,\n };\n if (computerUse != null) full.computerUse = async () => computerUse.endpoint;\n if (screenAvailable) full.screen = (options) => client.openScreen(info.id, options);\n return {\n sandbox: args.passive ? readOnlySession(full) : full,\n onSandboxStop: async () => {\n const failures: unknown[] = [];\n for (const finish of [closeMcp, () => transport.close(), () => args.closeSetup?.()]) {\n try {\n await finish();\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, 'Computer MCP cleanup failed');\n },\n onSandboxDelete: async () => {\n const failures: unknown[] = [];\n try {\n await closeMcp();\n } catch (cause) {\n failures.push(cause);\n }\n transport.close();\n args.closeSetup?.();\n try {\n await client.action(info.id, 'delete');\n } catch (cause) {\n if (!isComputersApiStatus(cause, 404)) failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n onRuntimeShutdown: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n args.closeSetup?.();\n }\n },\n };\n };\n\n // A captured base, once it is ready; a failed or expired one must be built again.\n const awaitBase = async (\n client: ComputersApiClientIface,\n baseId: string,\n key: string,\n ): Promise<ComputerBaseIface> => {\n const deadline = now() + (config.buildWaitMs ?? 30 * 60_000);\n for (;;) {\n const base = await client.getBase(baseId);\n if (base == null || base.state === ComputerBaseState.Expired) {\n throw computerSandboxError(\n 'artifact_unavailable',\n `computer base ${key} (${baseId}) is ${base == null ? 'gone' : 'expired'}; prepare it again`,\n );\n }\n if (base.state === ComputerBaseState.Ready) return base;\n if (base.state === ComputerBaseState.Failed) {\n throw computerSandboxError(\n 'build_failed',\n `computer base ${key} failed to capture: ${base.error ?? 'unknown error'}`,\n );\n }\n if (now() >= deadline) throw new Error(`computer base ${key} is still capturing`);\n await sleep(config.buildPollMs ?? 5_000);\n }\n };\n\n // The Computers API answers a computer it created or started before the\n // computer has a host, and refuses commands and file writes until it runs\n // (`autoResume: false`), so nothing touches it before this resolves. Only\n // Running counts: a paused computer still refuses them.\n const awaitComputerRunning = async (\n client: ComputersApiClientIface,\n computerId: string,\n timeoutMs: number,\n ): Promise<ComputerInfoIface> => {\n const deadline = now() + timeoutMs;\n let pollMs = config.runningPollMs ?? 250;\n for (;;) {\n const computer = await client.getComputer(computerId);\n if (computer == null || computer.state === ComputerState.Deleted)\n throw computerSandboxError('computer_gone', `computer ${computerId} is gone`);\n if (computer.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `computer ${computer.name} is in the Error state`,\n );\n if (computer.state === ComputerState.Running) return computer;\n const left = deadline - now();\n if (left <= 0)\n throw computerSandboxError(\n 'computer_not_running',\n `computer ${computer.name} was not running within ${Math.round(timeoutMs / 1000)} s (it is ${ComputerState[computer.state]})`,\n );\n await sleep(Math.min(pollMs, left));\n pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);\n }\n };\n\n // A computer between states (pausing, stopping, shelving) reads as Pending and\n // refuses actions and settings until it settles. Attach waits here before any\n // side effect, so retries against a stuck transition only read.\n const awaitComputerSettled = async (\n client: ComputersApiClientIface,\n computer: ComputerInfoIface,\n timeoutMs: number,\n ): Promise<ComputerInfoIface | null> => {\n const deadline = now() + timeoutMs;\n let pollMs = config.runningPollMs ?? 250;\n let current: ComputerInfoIface | null = computer;\n while (current?.state === ComputerState.Pending) {\n const left = deadline - now();\n if (left <= 0)\n throw computerSandboxError(\n 'computer_not_running',\n `computer ${current.name} did not settle within ${Math.round(timeoutMs / 1000)} s (it is Pending)`,\n );\n await sleep(Math.min(pollMs, left));\n pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);\n current = await client.getComputer(current.id);\n }\n return current == null || current.state === ComputerState.Deleted ? null : current;\n };\n\n // Run build.steps, then build.verify, on a builder computer of the\n // environment's image, captured as a base its computers are created from.\n const build = async (args: {\n ctx: SandboxPrepareContextIface;\n image: string;\n build: ComputerBuildIface;\n machine: ComputerEnvironmentIface['machine'];\n region: string | null;\n key: string;\n }): Promise<ComputerSandboxArtifact> => {\n const { ctx, key } = args;\n const client = clientFor(ctx);\n const diskGb = args.machine?.diskGb ?? null;\n const imageVersionId = await readyImageVersion(client, {\n image: args.image,\n imageVersionId: null,\n });\n const body: CreateComputerBodyIface = {\n name: `ag-${key.slice(4, 20)}-${compactId(randomUuid()).slice(0, 8)}`,\n imageVersionId,\n ...args.machine,\n // The base is the root disk; a user volume would keep /home and /workspaces off it.\n userVolumeGb: null,\n // Nothing secret at create: the create env lands in the guest.\n env: {},\n commandMode: ComputerCommandMode.Custom,\n customCommand: 'sleep infinity',\n autoResume: false,\n idleTimeoutSeconds: BUILDER_IDLE_TIMEOUT_SECONDS,\n tags: ['final-agent-sandbox-build'],\n };\n if (args.region != null) body.regionSlug = args.region;\n // One builder per attempt: a retry after a failed build starts clean.\n const builder = await client.createComputer(\n body,\n `agent-guide-build-${(await sha256Hex(`${key}:${randomUuid()}`)).slice(0, 32)}`,\n );\n ctx.log?.(`building computer base ${key} on ${builder.name}`);\n try {\n await awaitComputerRunning(client, builder.id, runningWaitMs);\n const sandbox = setupSession({ client, info: builder, env: async () => ({}) }).sandbox;\n const prepared = await sandbox.run({\n command: '/bin/sh',\n args: ['-c', `mkdir -p ${BUILD_ROOT}\\n${homeBaselineScript()}`],\n cwd: '/',\n });\n if (prepared.exitCode !== 0) {\n throw computerSandboxError('build_failed', 'failed to record the pre-build home baseline');\n }\n const steps = [\n ...args.build.steps.map((step) => ({ step, label: 'build step' })),\n ...args.build.verify.map((step) => ({ step, label: 'verify step' })),\n ];\n for (const [index, { step, label }] of steps.entries()) {\n ctx.log?.(`${label} ${index + 1}/${steps.length}`);\n const result = await sandbox.run({\n command: `set -eu\\n${step.run}`,\n shell: true,\n cwd: BUILD_ROOT,\n timeoutMs: step.timeoutMinutes * 60_000,\n });\n if (result.exitCode !== 0) {\n throw computerSandboxError(\n 'build_failed',\n `${label} ${index + 1} failed (exit ${result.exitCode}): ${result.stderr.trim().slice(-2000)}`,\n );\n }\n }\n const homeContent = await sandbox.run({\n command: '/bin/sh',\n args: ['-c', homeContentScript({ excludedPaths: CAPTURE_SCRUBBED_PATHS })],\n cwd: '/',\n });\n if (homeContent.exitCode === HOME_BASELINE_MISSING_EXIT_CODE) {\n throw computerSandboxError(\n 'build_failed',\n `build steps removed ${HOME_BASELINE_ROOT}, which the home content check needs; leave /var/tmp/final-template-build in place.`,\n );\n }\n if (homeContent.exitCode !== 0) {\n const offending = homeContent.stdout\n .trim()\n .split('\\n')\n .filter((line) => line !== '');\n throw computerSandboxError(\n 'build_failed',\n `build steps left content under /home or /workspaces, which each computer's own volume hides: ${offending.join(', ')}. Install tools and configuration to system paths such as /usr/local, or point the tool's home there (for example CARGO_HOME=/usr/local/cargo, RUSTUP_HOME=/usr/local/rustup, NVM_DIR=/usr/local/nvm), put home files in /usr/share/final-vm/home-skel, and use /etc/gitconfig instead of git config --global.`,\n );\n }\n const captured = await client.captureComputer(builder.id, { retained: true });\n if (!captured.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the built base',\n );\n ctx.log?.(`capturing computer base ${key} as ${captured.id}`);\n const base = await awaitBase(client, captured.id, key);\n return {\n version: 1,\n key,\n image: args.image,\n diskGb: diskGb ?? base.diskGb,\n seedFiles: {},\n base: { kind: 'captured', baseId: base.id },\n };\n } finally {\n // The capture stopped the builder; it is not part of the base.\n try {\n await client.action(builder.id, 'delete');\n } catch (error) {\n log('computer_sandbox.builder_delete_failed', {\n computerId: builder.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n };\n\n const environment = (\n rawOptions?: JsonValue,\n ): SandboxEnvironmentImplementationIface<\n ComputerSandboxArtifact,\n ComputerSandboxState,\n ComputerSandboxSessionIface\n > => {\n const parsed = computerEnvironmentSchema.safeParse(rawOptions ?? {});\n if (!parsed.success) {\n throw computerSandboxError(\n 'invalid_environment',\n `invalid computer environment: ${parsed.error.message}`,\n );\n }\n const options = parsed.data;\n const image = options.image ?? config.defaultImage ?? DEFAULT_COMPUTER_IMAGE;\n const machine = options.machine ?? config.machine;\n const region = options.region ?? config.regionSlug ?? null;\n // Outlasts the platform's own idle parking, so the platform parks first.\n const idleTimeoutFor = (ctx: SandboxResourceContextIface): number =>\n options.idleTimeoutSeconds ??\n (ctx.lifecycle.parkAfterIdleMs == null\n ? DEFAULT_IDLE_TIMEOUT_SECONDS\n : Math.ceil(ctx.lifecycle.parkAfterIdleMs / 1000) + IDLE_TIMEOUT_MARGIN_SECONDS);\n const seedsFor = (ctx: SandboxPrepareContextIface): Record<string, string> =>\n sandboxSeedFiles({ files: ctx.files, resources: ctx.resources });\n const keyFor = async (files: Record<string, string>): Promise<string> => {\n const baseKey = await computeComputerArtifactKey({\n image,\n build: options.build,\n diskGb: machine?.diskGb ?? null,\n });\n return Object.keys(files).length === 0\n ? baseKey\n : `${baseKey}-s${await sha256Hex(sandboxSeedIdentity(files))}`;\n };\n const retainedBase = async (\n ctx: SandboxPrepareContextIface,\n baseKey: string,\n ): Promise<ComputerSandboxArtifact | null> => {\n const cached = computerArtifactSchema.safeParse(await ctx.artifacts?.get(baseKey));\n if (!cached.success || cached.data.key !== baseKey || cached.data.base.kind !== 'captured')\n return null;\n const client = clientFor(ctx);\n const base = await client.getBase(cached.data.base.baseId);\n if (base?.state !== ComputerBaseState.Ready) return null;\n if (!base.retained && !(await client.setBaseRetention(base.id, true)).retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n return cached.data;\n };\n\n const stateOf = (raw: JsonValue): ComputerSandboxState => {\n const state = computerStateSchema.safeParse(raw);\n if (!state.success)\n throw computerSandboxError(\n 'computer_gone',\n 'this sandbox was recorded by an older computer provider; create it again',\n );\n return state.data;\n };\n\n // The computer the state names, else one an interrupted attach created\n // under the sandbox's name; null when none exists.\n const findComputer = async (\n client: ComputersApiClientIface,\n state: ComputerSandboxState,\n ): Promise<ComputerInfoIface | null> => {\n const found = await client.getComputer(state.computerId ?? state.computerName);\n return found == null || found.state === ComputerState.Deleted ? null : found;\n };\n\n return {\n capabilities: async () => ({\n [Capability.Files]: FilesAccess.Write,\n [Capability.Shell]: ShellAccess.Execute,\n [Capability.ComputerUse]: ScreenAccess.Control,\n }),\n // The computer-use tools of this environment's image, from the Computers\n // API without a computer, so a sandbox lists them before its first attach.\n // Unknown when the API cannot tell: the first attach learns them.\n mcpCatalog: async (ctx) => {\n let tools: Awaited<ReturnType<ComputersApiClientIface['computerUseCatalog']>>;\n try {\n tools = await clientFor(ctx).computerUseCatalog({ image });\n } catch (error) {\n log('computer_use_catalog_unavailable', {\n image,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n return tools == null ? null : { computerUse: toolDescriptorsOf(tools), localMcp: null };\n },\n processes: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n if (state.computerId == null) throw new Error('this computer has not started yet');\n return clientFor(ctx).inspectProcesses(state.computerId, request);\n },\n editor: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n const computerId = state.computerId;\n if (computerId == null) {\n if (request.operation === 'available') return { available: false };\n throw new Error('this computer has not started yet');\n }\n const client = clientFor(ctx);\n const open = (expiresAtMs?: number) =>\n computerEditor({\n client,\n computerId,\n request,\n randomUuid,\n expiresAtMs,\n });\n return open();\n },\n readSnapshot: async (ctx, rawState, request) => {\n const state = stateOf(rawState);\n if (state.computerId == null) return null;\n return readComputerSnapshot({\n client: clientFor(ctx),\n computerId: state.computerId,\n request,\n });\n },\n artifactKey: async (ctx) => keyFor(seedsFor(ctx)),\n // Builds the base an environment with build steps needs, or registers an\n // image reference so its version builds ahead of the first attach (a\n // lineage needs nothing until then).\n prepare: async (ctx) => {\n const seedFiles = seedsFor(ctx);\n const key = await keyFor(seedFiles);\n const seedArtifact = await sandboxSeedArtifact(ctx, seedFiles);\n if (options.build != null && computerNeedsBuild(options.build)) {\n const baseKey = await keyFor({});\n const retained = await retainedBase(ctx, baseKey);\n if (retained != null) return { ...retained, key, ...seedArtifact };\n const built = await build({\n ctx,\n image,\n build: options.build,\n machine,\n region,\n key: baseKey,\n });\n await ctx.artifacts?.put(baseKey, built);\n return { ...built, key, ...seedArtifact };\n }\n const imageVersionId = image.startsWith(LINEAGE_PREFIX)\n ? null\n : (await registerImage(clientFor(ctx), image)).id;\n ctx.log?.(`computer base ${key} is image ${image}`);\n return {\n version: 1,\n key,\n image,\n diskGb: machine?.diskGb ?? null,\n ...seedArtifact,\n base: { kind: 'image', image, imageVersionId },\n };\n },\n // Records the computer; the first attach creates it. The setup's network\n // policy is checked now so a policy a computer cannot enforce never boots.\n create: async (ctx, { setup }) => {\n const network = computerNetworkPolicyOf(setup);\n const ports = [\n ...new Set(\n (setup?.services ?? []).flatMap((service) =>\n service.port == null ? [] : [service.port],\n ),\n ),\n ];\n return {\n state: {\n version: 2,\n computerName: await computerNameFor(ctx.sandboxId),\n computerId: null,\n network,\n ports,\n },\n region,\n };\n },\n awaitRunning: async (ctx, rawState, options) => {\n const state = stateOf(rawState);\n await awaitComputerRunning(\n clientFor(ctx),\n state.computerId ?? state.computerName,\n options.timeoutMs,\n );\n },\n attach: async (ctx, { artifact: rawArtifact, state: rawState }) => {\n const state = stateOf(rawState);\n const artifact = computerArtifactSchema.safeParse(rawArtifact);\n if (!artifact.success)\n throw computerSandboxError(\n 'artifact_unavailable',\n 'this computer base predates the current computer provider; prepare it again',\n );\n const base = artifact.data.base;\n if (computerNeedsBuild(options.build) && base.kind !== 'captured')\n throw computerSandboxError(\n 'artifact_unavailable',\n `computer base ${artifact.data.key} was prepared without its build steps; prepare it again`,\n );\n const client = clientFor(ctx);\n const env = platformProcessEnvironment(ctx, {});\n const policy = withPlatformEgressHosts(ctx, state.network);\n const egress = computerEgressOf(policy);\n const found = await findComputer(client, state);\n const existing =\n found == null ? null : await awaitComputerSettled(client, found, runningWaitMs);\n if (existing?.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `Computer ${existing.id} (${existing.name}) is in the Error state. Recover it through the Computers API before retrying; its disk is preserved.`,\n );\n let info: ComputerInfoIface;\n let booted: boolean;\n if (existing != null) {\n info = existing;\n // A paused computer resumes with its processes; a stopped or shelved one boots.\n booted = !isRunningState(existing.state);\n if (existing.state === ComputerState.Paused) await client.action(existing.id, 'resume');\n else if (booted) await client.action(existing.id, 'start');\n } else {\n // A computer the state named but that no longer exists comes back\n // empty: the attach reports a fresh disk.\n booted = true;\n const source: Pick<CreateComputerBodyIface, 'baseId' | 'imageVersionId'> =\n base.kind === 'captured'\n ? { baseId: (await awaitBase(client, base.baseId, artifact.data.key)).id }\n : { imageVersionId: await readyImageVersion(client, base) };\n const body: CreateComputerBodyIface = {\n name: state.computerName,\n ...source,\n ...machine,\n env: {},\n autoResume: true,\n idleTimeoutSeconds: idleTimeoutFor(ctx),\n // The sandbox owns deletion; VM-level ephemeral disks cannot be paused.\n ephemeral: false,\n network: egress,\n tags: [\n 'final-agent-sandbox',\n `agent-sandbox:${ctx.sandboxId}`,\n 'agent-runtime-attachment:v1',\n 'agent-runtime-role:sandbox',\n ],\n };\n // Idle must preserve files: the sandbox is deleted only by its owner.\n body.idlePolicy = ComputerIdlePolicy.Pause;\n if (region != null) body.regionSlug = region;\n // A retry of this attach makes the same request; one after the\n // computer was deleted, or after re-registering the image, a new one.\n const idempotencyKey = `agent-sandbox-${(await sha256Hex(`${ctx.sandboxId}:${state.computerName}:${state.computerId ?? 'first'}:${source.baseId ?? source.imageVersionId}:false`)).slice(0, 32)}`;\n info = await client.createComputer(body, idempotencyKey);\n }\n const fresh = existing == null;\n log('computer_sandbox.attached', { computerId: info.id, fresh, booted });\n let cleanup: (() => Promise<void>) | null = null;\n try {\n info = await awaitComputerRunning(client, info.id, runningWaitMs);\n // A reused computer keeps whatever policy it last ran under; it gets the setup's again.\n if (!fresh) await client.setNetworkPolicy(info.id, egress);\n await reportPlatformNetworkPolicy(ctx, policy);\n const setup = setupSession({ client, info, env });\n cleanup = async () => setup.transport.close();\n await writePlatformFiles(ctx, setup.sandbox);\n // A new disk gets the workspace seeds once.\n if (fresh) {\n const seedMarker = `${WORKSPACE_ROOT}/.final/workspace-prepared/${await sha256Hex(artifact.data.key)}`;\n if ((await setup.sandbox.stat({ path: seedMarker })) == null) {\n await materializeSandboxSeeds({\n sandbox: setup.sandbox,\n root: WORKSPACE_ROOT,\n files: await sandboxSeedFilesForAttach(ctx, artifact.data),\n });\n await setup.sandbox.writeTextFile({ path: seedMarker, content: 'complete' });\n }\n }\n const handle = await buildHandle({\n ctx,\n client,\n info,\n env,\n ports: state.ports,\n passive: false,\n closeSetup: () => setup.transport.close(),\n });\n return {\n handle,\n region: info.regionSlug ?? region,\n state: { ...state, computerId: info.id },\n fresh,\n booted,\n };\n } catch (error) {\n let cause = error;\n try {\n await cleanup?.();\n } catch (cleanupError) {\n cause = new AggregateError(\n [error, cleanupError],\n 'Computer attach and setup cleanup failed',\n );\n }\n // No state reaches the caller on failure; remove only a computer this attach created.\n if (fresh) {\n try {\n await client.action(info.id, 'delete');\n } catch (cleanupError) {\n throw new AggregateError(\n [cause, cleanupError],\n `computer ${info.name} attach and cleanup failed`,\n );\n }\n }\n throw cause;\n }\n },\n attachPassive: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n const client = clientFor(ctx);\n const info = await findComputer(client, state);\n if (info == null || info.state !== ComputerState.Running)\n throw computerSandboxError(\n 'computer_not_running',\n 'computer is not running for passive access',\n );\n return buildHandle({\n ctx,\n client,\n info: await awaitComputerRunning(client, info.id, runningWaitMs),\n env: platformProcessEnvironment(ctx, {}),\n ports: state.ports,\n passive: true,\n });\n },\n // The computer pauses on its own idle policy; nothing to do.\n detach: async (_ctx, { state }) => stateOf(state),\n park: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n if (state.computerId == null) return state;\n const computerId = state.computerId;\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(computerId);\n } catch (cause) {\n failures.push(cause);\n }\n try {\n const client = clientFor(ctx);\n // Park reads the computer's state rather than trusting a pause's status\n // alone: a pause that cannot land would otherwise fail on every retry.\n let current: ComputerInfoIface | null | undefined;\n try {\n current = await client.getComputer(computerId);\n } catch (cause) {\n failures.push(cause);\n }\n if (current !== undefined && (current == null || hasNothingToPause(current.state))) {\n log('computer_sandbox.park_at_rest', {\n computerId,\n state: current?.state ?? null,\n });\n } else {\n // A paused computer is paused again: a resume may be in flight.\n try {\n await client.action(computerId, 'pause');\n } catch (error) {\n if (!pauseMayHaveSettled(error)) throw error;\n // Parked if it came to rest meanwhile (an idle pause or stop, a delete);\n // otherwise the pause did not happen and park is retried.\n const settled = await client.getComputer(computerId);\n if (\n settled != null &&\n settled.state !== ComputerState.Paused &&\n !hasNothingToPause(settled.state)\n )\n throw error;\n log('computer_sandbox.park_at_rest', {\n computerId,\n state: settled?.state ?? null,\n });\n }\n }\n } catch (cause) {\n failures.push(cause);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, 'Computer pause failed');\n return state;\n },\n delete: async (ctx, { state: rawState }) => {\n const state = stateOf(rawState);\n const client = clientFor(ctx);\n const computer = await findComputer(client, state);\n if (computer == null) return;\n const failures: unknown[] = [];\n try {\n await closeComputerMcp(computer.id);\n } catch (cause) {\n failures.push(cause);\n }\n log('computer_sandbox.delete', { computerId: computer.id });\n try {\n await client.action(computer.id, 'delete');\n } catch (error) {\n // A conflict is done only when the computer is already gone; one\n // mid-transition (an idle pause committing) is retried.\n if (!(await deletedAfterFenceError({ client, computerId: computer.id, cause: error })))\n failures.push(error);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1)\n throw new AggregateError(failures, 'Computer delete or MCP cleanup failed');\n },\n };\n };\n\n return defineSandboxProvider({\n name: COMPUTER_PROVIDER,\n stateProtocolVersion: 2,\n environment,\n });\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["COMPUTER_PROVIDER", "hex", "options"]
|
|
7
7
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ComputersApiClientIface } from "./computers-api.mjs";
|
|
2
2
|
import type { SandboxTransportIface } from "./transport.mjs";
|
|
3
|
-
export declare const DEFAULT_EXEC_USER = "user";
|
|
4
3
|
export interface CreateComputersApiTransportArgsIface {
|
|
5
4
|
client: ComputersApiClientIface;
|
|
6
5
|
computerId: string;
|
|
@@ -8,7 +8,6 @@ import { shellQuote } from "./paths.mjs";
|
|
|
8
8
|
const FILE_CHUNK_BYTES = 1024 * 1024;
|
|
9
9
|
const PROCESS_GONE_MESSAGE = /process not found|stale boot id/i;
|
|
10
10
|
const OUTPUT_WAIT_MS = 25e3;
|
|
11
|
-
const DEFAULT_EXEC_USER = "user";
|
|
12
11
|
const toOutput = (output) => ({
|
|
13
12
|
stdout: {
|
|
14
13
|
data: decodeBase64(output.stdout.dataB64),
|
|
@@ -36,13 +35,13 @@ const findTypes = /* @__PURE__ */ new Map([
|
|
|
36
35
|
["l", SandboxEntryType.Symlink]
|
|
37
36
|
]);
|
|
38
37
|
const createComputersApiTransport = (args) => {
|
|
39
|
-
const user = args.user
|
|
38
|
+
const user = args.user;
|
|
40
39
|
const readyTimeoutMs = args.readyTimeoutMs ?? 12e4;
|
|
41
40
|
const capture = async (script) => {
|
|
42
41
|
const result = await args.client.run(args.computerId, {
|
|
43
42
|
command: script,
|
|
44
43
|
cwd: "/",
|
|
45
|
-
user,
|
|
44
|
+
...user == null ? {} : { user },
|
|
46
45
|
readyTimeoutMs,
|
|
47
46
|
autoResume: false,
|
|
48
47
|
timeoutMs: 6e4
|
|
@@ -144,7 +143,8 @@ const createComputersApiTransport = (args) => {
|
|
|
144
143
|
);
|
|
145
144
|
},
|
|
146
145
|
exec: async ({ command, cwd, env, timeoutMs }) => {
|
|
147
|
-
const body = { command, cwd, env,
|
|
146
|
+
const body = { command, cwd, env, readyTimeoutMs, autoResume: false };
|
|
147
|
+
if (user != null) body.user = user;
|
|
148
148
|
if (timeoutMs != null) body.timeoutMs = timeoutMs;
|
|
149
149
|
return args.client.exec(args.computerId, body);
|
|
150
150
|
},
|
|
@@ -198,7 +198,6 @@ const createComputersApiTransport = (args) => {
|
|
|
198
198
|
};
|
|
199
199
|
};
|
|
200
200
|
export {
|
|
201
|
-
DEFAULT_EXEC_USER,
|
|
202
201
|
createComputersApiTransport
|
|
203
202
|
};
|
|
204
203
|
//# sourceMappingURL=computers-api-transport.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/sandboxes/computers-api-transport.ts"],
|
|
4
|
-
"sourcesContent": ["import { SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { decodeBase64, encodeBase64 } from \"./bytes.mjs\";\nimport {\n isComputersApiError,\n isComputersApiStatus,\n type ComputerProcessOutputIface,\n type ComputersApiClientIface,\n type ExecBodyIface,\n} from \"./computers-api.mjs\";\nimport { shellQuote } from \"./paths.mjs\";\nimport type {\n SandboxTransportIface,\n TransportDirEntryIface,\n TransportOutputIface,\n TransportStatIface,\n} from \"./transport.mjs\";\n\n// The public Computers API as a sandbox transport: files are ranged base64 reads and\n// replace-then-append writes; processes are managed processes with offset-polled\n// output. The API has no stat, list or remove, so those run as one short command.\n\nconst FILE_CHUNK_BYTES = 1024 * 1024;\n// The guest agent's answers (409) for an unknown process and one from an earlier boot.\nconst PROCESS_GONE_MESSAGE = /process not found|stale boot id/i;\n// The service caps a long-poll at 30 s.\nconst OUTPUT_WAIT_MS = 25_000;\
|
|
5
|
-
"mappings": "AAAA,SAAS,wBAAwB;AACjC,SAAS,cAAc,oBAAoB;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AACP,SAAS,kBAAkB;AAY3B,MAAM,mBAAmB,OAAO;AAEhC,MAAM,uBAAuB;AAE7B,MAAM,iBAAiB;
|
|
4
|
+
"sourcesContent": ["import { SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { decodeBase64, encodeBase64 } from \"./bytes.mjs\";\nimport {\n isComputersApiError,\n isComputersApiStatus,\n type ComputerProcessOutputIface,\n type ComputersApiClientIface,\n type ExecBodyIface,\n} from \"./computers-api.mjs\";\nimport { shellQuote } from \"./paths.mjs\";\nimport type {\n SandboxTransportIface,\n TransportDirEntryIface,\n TransportOutputIface,\n TransportStatIface,\n} from \"./transport.mjs\";\n\n// The public Computers API as a sandbox transport: files are ranged base64 reads and\n// replace-then-append writes; processes are managed processes with offset-polled\n// output. The API has no stat, list or remove, so those run as one short command.\n\nconst FILE_CHUNK_BYTES = 1024 * 1024;\n// The guest agent's answers (409) for an unknown process and one from an earlier boot.\nconst PROCESS_GONE_MESSAGE = /process not found|stale boot id/i;\n// The service caps a long-poll at 30 s.\nconst OUTPUT_WAIT_MS = 25_000;\n\nconst toOutput = (output: ComputerProcessOutputIface): TransportOutputIface => ({\n stdout: {\n data: decodeBase64(output.stdout.dataB64),\n nextOffset: output.stdout.nextOffset,\n eof: output.stdout.eof,\n },\n stderr: {\n data: decodeBase64(output.stderr.dataB64),\n nextOffset: output.stderr.nextOffset,\n eof: output.stderr.eof,\n },\n exited: output.state === 'exited',\n exitCode: output.result?.exitCode ?? null,\n exitSignal: output.result?.signal ?? null,\n});\n\nconst statTypes = new Map([\n ['regular file', SandboxEntryType.File],\n ['regular empty file', SandboxEntryType.File],\n ['directory', SandboxEntryType.Directory],\n ['symbolic link', SandboxEntryType.Symlink],\n]);\nconst findTypes = new Map([\n ['f', SandboxEntryType.File],\n ['d', SandboxEntryType.Directory],\n ['l', SandboxEntryType.Symlink],\n]);\n\nexport interface CreateComputersApiTransportArgsIface {\n client: ComputersApiClientIface;\n computerId: string;\n // Who commands run as; unset, the image's own user (its `USER`), which any image has. Naming\n // an account the image lacks fails every command.\n user?: string;\n // How long a call waits for a waking computer to accept processes.\n readyTimeoutMs?: number;\n}\n\nexport const createComputersApiTransport = (\n args: CreateComputersApiTransportArgsIface,\n): SandboxTransportIface => {\n const user = args.user;\n const readyTimeoutMs = args.readyTimeoutMs ?? 120_000;\n\n // A short helper command, read to completion.\n const capture = async (\n script: string,\n ): Promise<{ exitCode: number | null; stdout: string; stderr: string }> => {\n const result = await args.client.run(args.computerId, {\n command: script,\n cwd: '/',\n ...(user == null ? {} : { user }),\n readyTimeoutMs,\n autoResume: false,\n timeoutMs: 60_000,\n });\n let output = toOutput(result);\n const stdout: Uint8Array[] = [output.stdout.data];\n const stderr: Uint8Array[] = [output.stderr.data];\n while (!(output.exited && output.stdout.eof && output.stderr.eof)) {\n output = toOutput(\n await args.client.output({\n computerId: args.computerId,\n processId: result.id,\n bootId: result.bootId,\n stdoutOffset: output.stdout.nextOffset,\n stderrOffset: output.stderr.nextOffset,\n waitMs: OUTPUT_WAIT_MS,\n }),\n );\n stdout.push(output.stdout.data);\n stderr.push(output.stderr.data);\n }\n const decode = (chunks: Uint8Array[]): string => {\n const decoder = new TextDecoder();\n return (\n chunks.map((chunk) => decoder.decode(chunk, { stream: true })).join('') + decoder.decode()\n );\n };\n return { exitCode: output.exitCode, stdout: decode(stdout), stderr: decode(stderr) };\n };\n\n const failIfNonZero = (\n label: string,\n result: { exitCode: number | null; stderr: string },\n ): void => {\n if (result.exitCode !== 0)\n throw new Error(`${label}: ${result.stderr.trim() || `exit ${result.exitCode}`}`);\n };\n\n return {\n kind: 'computers-api',\n fileChunkBytes: FILE_CHUNK_BYTES,\n outputWaitMs: OUTPUT_WAIT_MS,\n stat: async ({ path }): Promise<TransportStatIface | null> => {\n const quoted = shellQuote(path);\n const result = await capture(\n `if [ ! -e ${quoted} ] && [ ! -L ${quoted} ]; then echo missing; exit 0; fi; stat -c '%F|%s|%Y|%a' -- ${quoted}`,\n );\n failIfNonZero(`stat ${path}`, result);\n const line = result.stdout.trim();\n if (line === 'missing') return null;\n const [kind, size, mtime, mode] = line.split('|');\n return {\n type: statTypes.get(kind ?? '') ?? SandboxEntryType.Other,\n size: Number(size ?? 0),\n modifiedAtMs: mtime == null ? null : Number(mtime) * 1000,\n mode: mode == null ? null : Number.parseInt(mode, 8),\n };\n },\n readDir: async ({ path }): Promise<TransportDirEntryIface[]> => {\n const quoted = shellQuote(path);\n const result = await capture(\n `[ -d ${quoted} ] || { echo 'Not a directory' >&2; exit 2; }; find ${quoted} -mindepth 1 -maxdepth 1 -printf '%y\\\\t%s\\\\t%f\\\\0'`,\n );\n failIfNonZero(`list ${path}`, result);\n return result.stdout\n .split('\\0')\n .filter((entry) => entry !== '')\n .map((entry) => {\n const [kind, size, ...name] = entry.split('\\t');\n return {\n name: name.join('\\t'),\n type: findTypes.get(kind ?? '') ?? SandboxEntryType.Other,\n size: size == null ? null : Number(size),\n };\n });\n },\n readChunk: async ({ path, offset, length, signal }) => {\n const read = await args.client.readFile({\n computerId: args.computerId,\n path,\n offset,\n length,\n signal,\n });\n return { bytes: decodeBase64(read.dataB64), eof: read.eof };\n },\n writeChunk: async ({ path, offset, bytes, signal }) => {\n await args.client.writeFile({\n computerId: args.computerId,\n path,\n dataB64: encodeBase64(bytes),\n append: offset > 0,\n signal,\n });\n },\n createDirectory: async ({ path }) => {\n failIfNonZero(`mkdir ${path}`, await capture(`mkdir -p -- ${shellQuote(path)}`));\n },\n remove: async ({ path, recursive, force }) => {\n const quoted = shellQuote(path);\n const flags = `${recursive ? 'r' : ''}${force ? 'f' : ''}`;\n const removeDirectory = recursive ? `rm -${flags} -- ${quoted}` : `rmdir -- ${quoted}`;\n const removeFile = `rm ${force ? '-f ' : ''}-- ${quoted}`;\n failIfNonZero(\n `remove ${path}`,\n await capture(\n `if [ -d ${quoted} ] && [ ! -L ${quoted} ]; then ${removeDirectory}; else ${removeFile}; fi`,\n ),\n );\n },\n exec: async ({ command, cwd, env, timeoutMs }) => {\n const body: ExecBodyIface = { command, cwd, env, readyTimeoutMs, autoResume: false };\n if (user != null) body.user = user;\n if (timeoutMs != null) body.timeoutMs = timeoutMs;\n return args.client.exec(args.computerId, body);\n },\n output: async ({ process, stdoutOffset, stderrOffset, waitMs, signal }) =>\n toOutput(\n await args.client.output({\n computerId: args.computerId,\n processId: process.id,\n bootId: process.bootId,\n stdoutOffset,\n stderrOffset,\n waitMs,\n signal,\n }),\n ),\n input: async ({ process, data, eof, signal, terminate }) => {\n if (terminate === true) {\n await args.client.terminate({\n computerId: args.computerId,\n processId: process.id,\n bootId: process.bootId,\n });\n return;\n }\n const base = { bootId: process.bootId };\n if (data != null && data.byteLength > 0) {\n await args.client.input({\n computerId: args.computerId,\n processId: process.id,\n body: { ...base, dataB64: encodeBase64(data) },\n });\n }\n if (signal != null) {\n await args.client.input({\n computerId: args.computerId,\n processId: process.id,\n body: { ...base, signal },\n });\n }\n if (eof === true) {\n await args.client.input({\n computerId: args.computerId,\n processId: process.id,\n body: { ...base, eof: true },\n });\n }\n },\n // Managed processes run in the computer and are found again by id and\n // boot until it boots again or is deleted.\n processGone: (cause) =>\n isComputersApiStatus(cause, 404) ||\n (isComputersApiStatus(cause, 409) &&\n isComputersApiError(cause) &&\n PROCESS_GONE_MESSAGE.test(cause.message)),\n close: () => undefined,\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finalai/final-agent-provider",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Final's harness and ACP adapter definitions and the general harness provider, computer, device and local sandbox providers, and Final's MCP gateway integration.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"@agentclientprotocol/sdk": "1.8.0",
|
|
135
135
|
"@finalai/agent-protocol": "0.13.0",
|
|
136
136
|
"@finalai/agent-provider": "0.14.0",
|
|
137
|
-
"@finalai/computers": "0.3.
|
|
137
|
+
"@finalai/computers": "0.3.2",
|
|
138
138
|
"zod": "4.6.6",
|
|
139
139
|
"@finalai/agent-definition": "0.13.0"
|
|
140
140
|
},
|