@finalai/final-agent-provider 0.2.1 → 0.2.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.
@@ -29,6 +29,8 @@ export interface ComputerSandboxProviderConfigIface {
29
29
  buildPollMs?: number;
30
30
  shelveWaitMs?: number;
31
31
  shelvePollMs?: number;
32
+ runningWaitMs?: number;
33
+ runningPollMs?: number;
32
34
  log?: ComputerSandboxLogIface;
33
35
  randomUuid?: () => string;
34
36
  now?: () => number;
@@ -11,6 +11,7 @@ import {
11
11
  PLATFORM_ENVIRONMENT_NAMES,
12
12
  platformProcessEnvironment,
13
13
  PortProtocol,
14
+ reportPlatformNetworkPolicy,
14
15
  SandboxCapability,
15
16
  sandboxSeedArtifact,
16
17
  sandboxSeedArtifactSchema,
@@ -134,12 +135,12 @@ const CAPTURE_SCRUBBED_PATHS = [
134
135
  "/home/user/.ssh"
135
136
  ];
136
137
  const BUILDER_IDLE_TIMEOUT_SECONDS = 2 * 60 * 60;
137
- const egressFor = (ctx, requested) => {
138
- const policy = withPlatformEgressHosts(ctx, requested);
138
+ const computerEgressOf = (policy) => {
139
139
  if (policy.mode === NetworkPolicy.AllowAll) return { egress: ComputerEgressPolicy.Internet };
140
140
  if (policy.mode === NetworkPolicy.DenyAll) return { egress: ComputerEgressPolicy.None };
141
141
  return { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow ?? [] };
142
142
  };
143
+ const egressFor = (ctx, requested) => computerEgressOf(withPlatformEgressHosts(ctx, requested));
143
144
  const LINEAGE_PREFIX = "lineage:";
144
145
  const portOf = (url) => {
145
146
  try {
@@ -157,6 +158,7 @@ const sandboxWorkspaceOf = {
157
158
  [ComputerWorkspacePolicy.Ephemeral]: SandboxWorkspace.Ephemeral
158
159
  };
159
160
  const isRunningState = (state) => state === ComputerState.Running || state === ComputerState.Paused || state === ComputerState.Resuming;
161
+ const RUNNING_POLL_MAX_MS = 5e3;
160
162
  const createComputerSandboxProvider = (config) => {
161
163
  const log = config.log ?? (() => void 0);
162
164
  const randomUuid = config.randomUuid ?? (() => crypto.randomUUID());
@@ -164,6 +166,7 @@ const createComputerSandboxProvider = (config) => {
164
166
  const sleep = config.sleep ?? defaultSleep;
165
167
  const defaultImage = config.defaultImage ?? DEFAULT_COMPUTER_IMAGE;
166
168
  const credentials = createComputersApiCredentials(config.computersApi, now);
169
+ const runningWaitMs = config.runningWaitMs ?? 5 * 6e4;
167
170
  const clientFor = (organizationId) => createComputersApiClient({ config: config.computersApi, credentials, organizationId });
168
171
  const registerImage = (client, reference) => client.registerImage(
169
172
  config.registryCredentialId == null ? { reference } : { reference, registryCredentialId: config.registryCredentialId }
@@ -435,6 +438,29 @@ ${commandHelp}`}`,
435
438
  await sleep(config.buildPollMs ?? 5e3);
436
439
  }
437
440
  };
441
+ const awaitComputerRunning = async (client, computerId, timeoutMs) => {
442
+ const deadline = now() + timeoutMs;
443
+ let pollMs = config.runningPollMs ?? 250;
444
+ for (; ; ) {
445
+ const computer = await client.getComputer(computerId);
446
+ if (computer == null || computer.state === ComputerState.Deleted)
447
+ throw computerSandboxError("computer_gone", `computer ${computerId} is gone`);
448
+ if (computer.state === ComputerState.Error)
449
+ throw computerSandboxError(
450
+ "computer_gone",
451
+ `computer ${computer.name} is in the Error state`
452
+ );
453
+ if (computer.state === ComputerState.Running) return computer;
454
+ const left = deadline - now();
455
+ if (left <= 0)
456
+ throw computerSandboxError(
457
+ "computer_not_running",
458
+ `computer ${computer.name} was not running within ${Math.round(timeoutMs / 1e3)} s (it is ${ComputerState[computer.state]})`
459
+ );
460
+ await sleep(Math.min(pollMs, left));
461
+ pollMs = Math.min(pollMs * 2, RUNNING_POLL_MAX_MS);
462
+ }
463
+ };
438
464
  const awaitShelved = async (client, computerId) => {
439
465
  const deadline = now() + (config.shelveWaitMs ?? 5 * 6e4);
440
466
  for (; ; ) {
@@ -475,6 +501,7 @@ ${commandHelp}`}`,
475
501
  );
476
502
  ctx.log?.(`building computer base ${key} on ${builder.name}`);
477
503
  try {
504
+ await awaitComputerRunning(client, builder.id, runningWaitMs);
478
505
  const sandbox = setupSession({ client, info: builder, env: async () => ({}) }).sandbox;
479
506
  const prepared = await sandbox.run({
480
507
  command: "/bin/sh",
@@ -579,6 +606,11 @@ ${step.run}`,
579
606
  log
580
607
  });
581
608
  };
609
+ const awaitRunning = (ctx, rawState, options2) => awaitComputerRunning(
610
+ clientFor(ctx.session.organizationId),
611
+ computerStateSchema.pick({ computerId: true }).parse(rawState).computerId,
612
+ options2.timeoutMs
613
+ );
582
614
  return {
583
615
  processes: async (ctx, rawState, request) => {
584
616
  const state = computerStateSchema.parse(rawState);
@@ -677,10 +709,14 @@ ${step.run}`,
677
709
  base: { kind: "image", image: spec.image, imageVersionId }
678
710
  };
679
711
  },
712
+ awaitRunning: async (ctx, state, options2) => {
713
+ await awaitRunning(ctx, state, options2);
714
+ },
680
715
  start: async (ctx, openOptions, rawArtifact) => {
681
716
  const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;
682
717
  const spec = await resolve(ctx.guides);
683
- const egress = egressFor(ctx, spec.parameters.networkPolicy);
718
+ const policy = withPlatformEgressHosts(ctx, spec.parameters.networkPolicy);
719
+ const egress = computerEgressOf(policy);
684
720
  const artifact = computerArtifactSchema.safeParse(rawArtifact);
685
721
  if (!artifact.success) {
686
722
  throw computerSandboxError(
@@ -736,8 +772,12 @@ ${step.run}`,
736
772
  const idempotencyKey = `agent-sandbox-${(await sha256Hex(`${ctx.session.bindingId}:${name}:${source.baseId ?? source.imageVersionId}`)).slice(0, 32)}`;
737
773
  info = await client.createComputer(body, idempotencyKey);
738
774
  }
739
- log("computer_sandbox.started", { computerId: info.id, reused: existing != null });
775
+ const reused = existing != null && existing.id === info.id;
776
+ log("computer_sandbox.started", { computerId: info.id, reused });
740
777
  try {
778
+ info = await awaitRunning(ctx, { computerId: info.id }, { timeoutMs: runningWaitMs });
779
+ if (reused) await client.setNetworkPolicy(info.id, egress);
780
+ await reportPlatformNetworkPolicy(ctx, policy);
741
781
  const setup = setupSession({ client, info, env });
742
782
  await writePlatformFiles(ctx, setup.sandbox);
743
783
  await mountRepositories({
@@ -774,7 +814,7 @@ ${step.run}`,
774
814
  }
775
815
  };
776
816
  } catch (error) {
777
- if (existing == null || existing.id !== info.id) {
817
+ if (!reused) {
778
818
  try {
779
819
  await client.action(info.id, "delete");
780
820
  } catch (cleanupError) {
@@ -796,6 +836,7 @@ ${step.run}`,
796
836
  "computer_not_running",
797
837
  "computer is not running for passive access"
798
838
  );
839
+ await awaitRunning(ctx, state, { timeoutMs: runningWaitMs });
799
840
  const spec = await resolve(ctx.guides);
800
841
  const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));
801
842
  return (await buildHandle({ ctx, client, info, spec, access: state.access, env })).handle;
@@ -810,16 +851,20 @@ ${step.run}`,
810
851
  const rebooted = !isRunningState(info.state);
811
852
  if (info.state === ComputerState.Paused) await client.action(info.id, "resume");
812
853
  else if (rebooted) await client.action(info.id, "start");
854
+ const running = await awaitRunning(ctx, state, { timeoutMs: runningWaitMs });
813
855
  const spec = await resolve(ctx.guides);
814
856
  const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));
815
- const setup = setupSession({ client, info, env });
857
+ const policy = withPlatformEgressHosts(ctx, spec.parameters.networkPolicy);
858
+ await client.setNetworkPolicy(running.id, computerEgressOf(policy));
859
+ await reportPlatformNetworkPolicy(ctx, policy);
860
+ const setup = setupSession({ client, info: running, env });
816
861
  await writePlatformFiles(ctx, setup.sandbox);
817
862
  await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });
818
863
  if (rebooted) await startServicesFor({ setup, spec, env });
819
864
  const { handle } = await buildHandle({
820
865
  ctx,
821
866
  client,
822
- info,
867
+ info: running,
823
868
  spec,
824
869
  access: state.access,
825
870
  env
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/computer.ts"],
4
- "sourcesContent": ["import { ProcessInspectionOperation } from '@finalai/agent-protocol/process-inspection';\nimport {\n formatProviderRef,\n NetworkPolicy,\n packageRef,\n SandboxAccess,\n type JsonValue,\n} from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n materializeSandboxSeeds,\n PLATFORM_ENVIRONMENT_NAMES,\n platformProcessEnvironment,\n PortProtocol,\n SandboxCapability,\n sandboxSeedArtifact,\n sandboxSeedArtifactSchema,\n sandboxSeedFiles,\n sandboxSeedFilesForStart,\n sandboxSeedIdentity,\n SandboxWorkspace,\n withPlatformEgressHosts,\n writePlatformFiles,\n type NetworkPolicyIface,\n type NetworkSandboxSessionIface,\n type SandboxGuidesIface,\n type SandboxPrepareContextIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxProviderImplementationIface,\n type SandboxStartContextIface,\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 { sleep as defaultSleep, sha256Hex } from \"./bytes.mjs\";\nimport { computerEditor } from \"./computer-editor.mjs\";\nimport { readComputerSnapshot } from \"./computer-snapshots.mjs\";\nimport {\n createComputersApiClient,\n createComputersApiCredentials,\n isComputersApiStatus,\n type ComputersApiClientIface,\n type ComputersApiConfigIface,\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_SANDBOX_SPECIFIER,\n computerEnvironmentSchema,\n computerOpenOptionsSchema,\n ComputerWorkspacePolicy,\n} from \"./environment.mjs\";\nimport {\n computeComputerArtifactKey,\n computerNeedsBuild,\n DEFAULT_COMPUTER_IMAGE,\n resolveComputerSpec,\n type ResolvedComputerSpecIface,\n} from \"./guide.mjs\";\nimport { createTransportSession, sessionForAccess } from \"./session.mjs\";\nimport type { SandboxTransportIface } from \"./transport.mjs\";\nimport {\n guideCommands,\n installGuideCommands,\n mountRepositories,\n repositoryPath,\n runWorkspaceSetup,\n startServices,\n WORKSPACE_ROOT,\n type GuideCommandIface,\n type SetupLogIface,\n} from \"./workspace-setup.mjs\";\n\nexport type { ComputersApiConfigIface, ComputersApiCredentialIface } from \"./computers-api.mjs\";\nexport {\n COMPUTER_SANDBOX_SPECIFIER,\n COMPUTERS_API_KEY_SECRET,\n COMPUTERS_API_TEAM_SECRET,\n} from \"./environment.mjs\";\nexport { computeComputerArtifactKey } from \"./guide.mjs\";\nexport type { ComputerGuideVersionIface } from \"./guide.mjs\";\nexport type { RepositoryCloneSourceIface } from \"./workspace-setup.mjs\";\n\n// The `computer` sandbox: a Final computer from the\n// public Computers API, set up from a computer setup guide, with lifecycle,\n// files and processes all through that API and the organization's own API key,\n// exactly as a third-party provider drives its vendor. Like every\n// provider, it is served by the session service, which runs this handle and\n// serves the handle RPC and MCP projection from it.\n//\n// A guide with build or verify steps is built once on a builder computer and\n// captured as a base (POST /v1/computers/:id/capture); its computers are created\n// from that base. Network and idle policies are create options, as for any\n// API customer.\n//\n// Guides, variables and repository credentials come from the contract's\n// prepare and start contexts (`guides`, `variables`, `repositories`), which the\n// session service serves to every provider alike.\n\nexport interface ComputerSandboxLogIface {\n (message: string, fields?: Record<string, string | number | boolean | null>): void;\n}\n\nexport interface ComputerSandboxProviderConfigIface {\n // The public Computers API, and each organization's credential for it.\n computersApi: ComputersApiConfigIface;\n // A registry credential (`creg_...`) the organization stored for private image references.\n registryCredentialId?: string;\n // Image for an empty environment without an organization default guide.\n defaultImage?: string;\n regionSlug?: string;\n machine?: { vcpu?: number; memoryMb?: number; diskGb?: number };\n idleTimeoutSeconds?: number;\n // How long `start` waits for a registered image version to finish building.\n imageWaitMs?: number;\n imagePollMs?: number;\n // How long `prepare` waits for a guide's base capture to publish.\n buildWaitMs?: number;\n buildPollMs?: number;\n // How long ending a conversation workspace waits for its computer to shelve.\n shelveWaitMs?: number;\n shelvePollMs?: 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 start. A `captured` base is a guide's build, captured as a base\n// (`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 computerStateSchema = z.object({\n version: z.literal(1),\n computerId: z.string(),\n computerName: z.string(),\n workspace: z.nativeEnum(ComputerWorkspacePolicy),\n access: z.nativeEnum(SandboxAccess),\n guideVersionId: z.string().nullable(),\n setupHash: z.string().nullable(),\n});\n\n// The provider's own view of a computer while it sets it up.\ninterface SetupSessionIface {\n sandbox: NetworkSandboxSessionIface;\n transport: SandboxTransportIface;\n}\n\nexport type ComputerSandboxArtifact = z.infer<typeof computerArtifactSchema>;\nexport type ComputerSandboxState = z.infer<typeof computerStateSchema>;\n\n// What Build needs to know about a started computer beyond the handle.\nexport interface ComputerSandboxDescriptionIface {\n provider: 'computer';\n computerId: string;\n computerName: string;\n workspaceRoot: string;\n transport: string;\n guide: { slug: string; number: number } | null;\n repositories: { alias: string; path: string; repository: string }[];\n services: { name: string; readyUrl: string | null }[];\n commands: GuideCommandIface[];\n capabilities: SandboxCapability[];\n}\n\nexport interface ComputerSandboxSessionIface extends NetworkSandboxSessionIface {\n describe(): ComputerSandboxDescriptionIface;\n // What this computer's handle offers (the session service reports it).\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type ComputerSandboxProviderIface = SandboxProviderIface<\n JsonValue,\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\n// FINAL_NODE_* and the session basics belong to the platform (shared/src/sandbox-templates/reserved.ts),\n// as do the platform environment's variables (the egress proxy and its placeholders).\nconst RESERVED_ENV = new Set([\n ...PLATFORM_ENVIRONMENT_NAMES,\n 'DISPLAY',\n 'XDG_RUNTIME_DIR',\n 'PATH',\n 'HOME',\n 'USER',\n 'SHELL',\n 'HOSTNAME',\n]);\nconst isReservedEnvName = (name: string): boolean =>\n name.startsWith('FINAL_NODE_') || RESERVED_ENV.has(name);\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// Guide publication supplies build inputs in files; agent revisions supply workspace seeds.\nconst seedsFor = (ctx: SandboxPrepareContextIface): Record<string, string> =>\n sandboxSeedFiles({\n files: ctx.resources.guide == null ? ctx.files : {},\n resources: ctx.resources,\n });\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\ninterface ComputerEgressConfigIface {\n egress: ComputerEgressPolicy;\n allow?: string[];\n}\n\n// An allowlist also admits the platform's egress hosts, so its proxy stays reachable.\nconst egressFor = (\n ctx: SandboxStartContextIface,\n requested: NetworkPolicyIface,\n): ComputerEgressConfigIface => {\n const policy = withPlatformEgressHosts(ctx, requested);\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\nconst LINEAGE_PREFIX = 'lineage:';\n\nconst portOf = (url: string): number | null => {\n try {\n const parsed = new URL(url);\n if (parsed.port !== '') return Number(parsed.port);\n return parsed.protocol === 'https:' ? 443 : 80;\n } catch {\n return null;\n }\n};\n\nconst compactId = (id: string): string => id.replaceAll('-', '');\n\nconst sandboxWorkspaceOf = {\n [ComputerWorkspacePolicy.Session]: SandboxWorkspace.Session,\n [ComputerWorkspacePolicy.Conversation]: SandboxWorkspace.Conversation,\n [ComputerWorkspacePolicy.Ephemeral]: SandboxWorkspace.Ephemeral,\n} satisfies Record<ComputerWorkspacePolicy, SandboxWorkspace>;\n\nconst isRunningState = (state: ComputerState): boolean =>\n state === ComputerState.Running ||\n state === ComputerState.Paused ||\n state === ComputerState.Resuming;\n\nexport const createComputerSandboxProvider = (\n config: ComputerSandboxProviderConfigIface,\n): ComputerSandboxProviderIface => {\n const log: SetupLogIface = 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 defaultImage = config.defaultImage ?? DEFAULT_COMPUTER_IMAGE;\n const credentials = createComputersApiCredentials(config.computersApi, now);\n\n const clientFor = (organizationId: string): ComputersApiClientIface =>\n createComputersApiClient({ config: config.computersApi, credentials, organizationId });\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 (the\n // organization's or the platform's); a reference is registered once, at prepare,\n // 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 loadVariables = async (\n ctx: SandboxStartContextIface,\n spec: ResolvedComputerSpecIface,\n ): Promise<Record<string, string>> => {\n const env: Record<string, string> = {};\n for (const [name, value] of Object.entries(spec.parameters.env)) {\n if (isReservedEnvName(name))\n throw computerSandboxError('invalid_environment', `${name} is reserved`);\n env[name] = value;\n }\n for (const name of spec.parameters.variables) {\n if (isReservedEnvName(name))\n throw computerSandboxError('invalid_environment', `${name} is reserved`);\n const value = await ctx.variables.get(name);\n if (value == null)\n throw computerSandboxError('invalid_environment', `variable ${name} is not set`);\n env[name] = value;\n }\n return env;\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 buildHandle = async (args: {\n ctx: SandboxStartContextIface;\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n spec: ResolvedComputerSpecIface;\n access: SandboxAccess;\n env: () => Promise<Record<string, string>>;\n }): Promise<{ handle: SandboxProviderHandleIface<ComputerSandboxSessionIface> }> => {\n const { client, info, spec } = args;\n const commands = await guideCommands(spec.template);\n const commandHelp = commands\n .map(\n (command) =>\n `Guide command ${command.name}: bash ${command.path}${command.description == null ? '' : ` \u2014 ${command.description}`}`,\n )\n .join('\\n');\n const transport = createComputersApiTransport({ client, computerId: info.id });\n const ports = [\n ...new Set(\n spec.template.services.flatMap((service) => {\n const port = service.ready == null ? null : portOf(service.ready.url);\n return port == null ? [] : [port];\n }),\n ),\n ];\n let httpToken: { token: string; expiresAtMs: number } | null = null;\n const session = createTransportSession({\n id: info.id,\n description: `Final computer ${info.name}${spec.guide == null ? '' : ` (${spec.guide.title} v${spec.guide.number})`}${commands.length === 0 ? '' : `\\n${commandHelp}`}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n 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.session.bindingId}`,\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 await closeComputerMcp(info.id);\n await client.action(info.id, 'stop');\n },\n destroy: async () => {\n await closeComputerMcp(info.id);\n transport.close();\n try {\n await client.action(info.id, 'delete');\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n },\n },\n });\n let computerUseInstalled: boolean | null = null;\n if (args.access !== SandboxAccess.Read) {\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.access === SandboxAccess.Read || 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.access !== SandboxAccess.Read)\n capabilities.push(SandboxCapability.Process, SandboxCapability.NetworkPolicy);\n const description: ComputerSandboxDescriptionIface = {\n provider: 'computer',\n computerId: info.id,\n computerName: info.name,\n workspaceRoot: WORKSPACE_ROOT,\n transport: transport.kind,\n guide: spec.guide == null ? null : { slug: spec.guide.slug, number: spec.guide.number },\n repositories: spec.parameters.repositories.map((repository) => ({\n alias: repository.alias,\n path: repositoryPath(repository.alias),\n repository: repository.repository,\n })),\n services: spec.template.services.map((service) => ({\n name: service.name,\n readyUrl: service.ready?.url ?? null,\n })),\n commands,\n capabilities,\n };\n const full: ComputerSandboxSessionIface = {\n ...session,\n setNetworkPolicy: async (policy) => {\n if (args.access === SandboxAccess.Read)\n throw new Error('this sandbox binding is read-only');\n await client.setNetworkPolicy(info.id, egressFor(args.ctx, policy));\n },\n describe: () => description,\n capabilities,\n };\n if (computerUse != null) full.computerUse = async () => computerUse.endpoint;\n if (screenAvailable) {\n full.screen = (options) => client.openScreen(info.id, options);\n }\n const sandbox = sessionForAccess(full, args.access);\n return {\n handle: {\n sandbox,\n onSandboxStop: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n },\n onSandboxDelete: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n try {\n await client.action(info.id, 'delete');\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n },\n onRuntimeShutdown: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n },\n },\n };\n };\n\n // Setup (repositories, workspace.setup, services) is the provider's own work, so it\n // runs with the organization's credential, never through the binding's lease: a\n // read binding still gets a set-up computer.\n const setupSession = (args: {\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n }): SetupSessionIface => {\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 // 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 const awaitShelved = async (client: ComputersApiClientIface, computerId: string) => {\n const deadline = now() + (config.shelveWaitMs ?? 5 * 60_000);\n for (;;) {\n const computer = await client.getComputer(computerId);\n if (\n computer == null ||\n computer.state === ComputerState.Shelved ||\n computer.state === ComputerState.Deleted\n )\n return;\n if (computer.state === ComputerState.Error)\n throw computerSandboxError('computer_gone', `computer ${computerId} failed to shelve`);\n if (now() >= deadline) throw new Error(`computer ${computerId} is still shelving`);\n await sleep(config.shelvePollMs ?? 2_000);\n }\n };\n\n // Run build.steps, then build.verify, on a builder computer of the guide's\n // image, captured as a base its computers are created from.\n const build = async (\n ctx: SandboxPrepareContextIface,\n spec: ResolvedComputerSpecIface,\n key: string,\n ): Promise<ComputerSandboxArtifact> => {\n const client = clientFor(ctx.organizationId);\n const diskGb = config.machine?.diskGb ?? null;\n const imageVersionId = await readyImageVersion(client, {\n image: spec.image,\n imageVersionId: null,\n });\n const body: CreateComputerBodyIface = {\n name: `ag-${key.slice(4, 20)}-${compactId(randomUuid()).slice(0, 8)}`,\n imageVersionId,\n ...config.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 (config.regionSlug != null) body.regionSlug = config.regionSlug;\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 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 ...spec.template.build.steps.map((step) => ({ step, label: 'build step' })),\n ...spec.template.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: spec.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 ): SandboxProviderImplementationIface<\n JsonValue,\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 resolve = (guides: SandboxGuidesIface): Promise<ResolvedComputerSpecIface> =>\n resolveComputerSpec({ options, guides, defaultImage });\n const keyFor = async (\n spec: ResolvedComputerSpecIface,\n files: Record<string, string>,\n ): Promise<string> => {\n const baseKey = await computeComputerArtifactKey({\n image: spec.image,\n template: spec.template,\n diskGb: config.machine?.diskGb ?? null,\n });\n return Object.keys(files).length === 0\n ? baseKey\n : `${baseKey}-s${await sha256Hex(sandboxSeedIdentity(files))}`;\n };\n\n const startServicesFor = async (args: {\n setup: SetupSessionIface;\n spec: ResolvedComputerSpecIface;\n env: () => Promise<Record<string, string>>;\n }): Promise<void> => {\n await startServices({\n sandbox: args.setup.sandbox,\n transport: args.setup.transport,\n template: args.spec.template,\n // Services run for the computer's life, with the platform's values as they are now.\n env: await args.env(),\n randomUuid,\n log,\n });\n };\n\n return {\n processes: async (ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n if (\n request.operation === ProcessInspectionOperation.Stop &&\n state.access === SandboxAccess.Read\n )\n throw new Error('stopping processes requires execute access');\n const result = await clientFor(ctx.organizationId).inspectProcesses(\n state.computerId,\n request,\n );\n return request.operation === ProcessInspectionOperation.Available && 'available' in result\n ? { ...result, canStop: state.access !== SandboxAccess.Read }\n : result;\n },\n editor: async (_ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n if (state.access !== SandboxAccess.Write) {\n if (request.operation === 'available') return { available: false };\n throw new Error('editor requires write access');\n }\n return computerEditor({\n client: clientFor(_ctx.organizationId),\n computerId: state.computerId,\n request,\n randomUuid,\n });\n },\n readSnapshot: async (ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n return readComputerSnapshot({\n client: clientFor(ctx.organizationId),\n computerId: state.computerId,\n request,\n });\n },\n // The merged parameters' workspace: the binding's, else the saved version's default.\n workspace: async (ctx) =>\n sandboxWorkspaceOf[(await resolve(ctx.guides)).parameters.workspace],\n artifactKey: async (ctx) => keyFor(await resolve(ctx.guides), seedsFor(ctx)),\n // Registers an image reference so its version builds ahead of the first start;\n // a lineage needs nothing until then.\n prepare: async (ctx) => {\n const spec = await resolve(ctx.guides);\n const seedFiles = seedsFor(ctx);\n const key = await keyFor(spec, seedFiles);\n const seedArtifact = await sandboxSeedArtifact(ctx, seedFiles);\n if (computerNeedsBuild(spec)) {\n const baseKey = await keyFor(spec, {});\n const prepared = spec.guide?.preparedArtifact;\n if (\n prepared?.key === baseKey &&\n prepared.providerRef === formatProviderRef(packageRef(COMPUTER_SANDBOX_SPECIFIER))\n ) {\n const cached = computerArtifactSchema.safeParse(prepared.artifact);\n if (\n cached.success &&\n cached.data.key === baseKey &&\n cached.data.base.kind === 'captured'\n ) {\n const base = await clientFor(ctx.organizationId).getBase(cached.data.base.baseId);\n if (base?.state === ComputerBaseState.Ready) {\n if (!base.retained) {\n const retained = await clientFor(ctx.organizationId).setBaseRetention(\n base.id,\n true,\n );\n if (!retained.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n }\n return { ...cached.data, key, ...seedArtifact };\n }\n }\n }\n const cached = computerArtifactSchema.safeParse(await ctx.artifacts?.get(baseKey));\n if (\n cached.success &&\n cached.data.key === baseKey &&\n cached.data.base.kind === 'captured'\n ) {\n const base = await clientFor(ctx.organizationId).getBase(cached.data.base.baseId);\n if (base?.state === ComputerBaseState.Ready) {\n if (!base.retained) {\n const retained = await clientFor(ctx.organizationId).setBaseRetention(\n base.id,\n true,\n );\n if (!retained.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n }\n return { ...cached.data, key, ...seedArtifact };\n }\n }\n const built = await build(ctx, spec, baseKey);\n await ctx.artifacts?.put(baseKey, built);\n return { ...built, key, ...seedArtifact };\n }\n const imageVersionId = spec.image.startsWith(LINEAGE_PREFIX)\n ? null\n : (await registerImage(clientFor(ctx.organizationId), spec.image)).id;\n ctx.log?.(`computer base ${key} is image ${spec.image}`);\n return {\n version: 1,\n key,\n image: spec.image,\n diskGb: config.machine?.diskGb ?? null,\n ...seedArtifact,\n base: { kind: 'image', image: spec.image, imageVersionId },\n };\n },\n start: async (ctx, openOptions, rawArtifact) => {\n const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;\n const spec = await resolve(ctx.guides);\n const egress = egressFor(ctx, spec.parameters.networkPolicy);\n const artifact = computerArtifactSchema.safeParse(rawArtifact);\n if (!artifact.success) {\n throw computerSandboxError(\n 'artifact_unavailable',\n 'this computer base predates the public Computers API provider; prepare it again',\n );\n }\n const base = artifact.data.base;\n if (computerNeedsBuild(spec) && 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 }\n // Variables resolve before anything is created, so a missing one costs nothing.\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n const client = clientFor(ctx.session.organizationId);\n const workspace = spec.parameters.workspace;\n const name =\n workspace === ComputerWorkspacePolicy.Conversation && ctx.session.conversationId != null\n ? `ac-${(await sha256Hex(`${ctx.session.conversationId}:${ctx.session.target}`)).slice(0, 24)}`\n : `ab-${compactId(ctx.session.bindingId)}`;\n const existing = await client.getComputer(name);\n if (existing?.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `Computer ${existing.id} (${name}) is in the Error state. Recover it through the Computers API before retrying; its workspace is preserved.`,\n );\n let info: ComputerInfoIface;\n let fresh = true;\n if (existing != null && existing.state !== ComputerState.Deleted) {\n info = existing;\n fresh = !isRunningState(existing.state);\n if (existing.state === ComputerState.Paused) await client.action(existing.id, 'resume');\n else if (fresh) await client.action(existing.id, 'start');\n } else {\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,\n ...source,\n ...config.machine,\n env: {},\n autoResume: true,\n idleTimeoutSeconds: config.idleTimeoutSeconds ?? 15 * 60,\n // Provider teardown owns deletion; VM-level ephemeral disks cannot be paused.\n ephemeral: false,\n network: egress,\n tags: [\n 'final-agent-sandbox',\n `agent-binding:${ctx.session.bindingId}`,\n 'agent-runtime-attachment:v1',\n 'agent-runtime-role:sandbox',\n ],\n };\n // Session teardown owns deletion, including ephemeral computers. Idle must preserve files.\n body.idlePolicy = ComputerIdlePolicy.Pause;\n if (config.regionSlug != null) body.regionSlug = config.regionSlug;\n // Keyed by the source too: a retry after re-registering is a different request.\n const idempotencyKey = `agent-sandbox-${(await sha256Hex(`${ctx.session.bindingId}:${name}:${source.baseId ?? source.imageVersionId}`)).slice(0, 32)}`;\n info = await client.createComputer(body, idempotencyKey);\n }\n log('computer_sandbox.started', { computerId: info.id, reused: existing != null });\n try {\n const setup = setupSession({ client, info, env });\n await writePlatformFiles(ctx, setup.sandbox);\n await mountRepositories({\n sandbox: setup.sandbox,\n repositories: spec.parameters.repositories,\n resolver: ctx.repositories,\n log,\n });\n await materializeSandboxSeeds({\n sandbox: setup.sandbox,\n root: WORKSPACE_ROOT,\n files: await sandboxSeedFilesForStart(ctx, artifact.data),\n });\n await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });\n const setupHash = await runWorkspaceSetup({\n sandbox: setup.sandbox,\n template: spec.template,\n repositories: spec.parameters.repositories,\n log,\n });\n if (fresh) await startServicesFor({ setup, spec, env });\n const { handle } = await buildHandle({ ctx, client, info, spec, access, env });\n return {\n handle,\n region: info.regionSlug ?? config.regionSlug ?? null,\n state: {\n version: 1,\n computerId: info.id,\n computerName: info.name,\n workspace,\n access,\n guideVersionId: spec.guide?.versionId ?? null,\n setupHash,\n },\n };\n } catch (error) {\n // No state reaches the caller on failure; clean up only this start's new computer.\n if (existing == null || existing.id !== info.id) {\n try {\n await client.action(info.id, 'delete');\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n `computer ${info.name} setup and cleanup failed`,\n );\n }\n }\n throw error;\n }\n },\n resumePassive: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n const info = await client.getComputer(state.computerId);\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 const spec = await resolve(ctx.guides);\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n return (await buildHandle({ ctx, client, info, spec, access: state.access, env })).handle;\n },\n resume: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n const info = await client.getComputer(state.computerId);\n if (\n info == null ||\n info.state === ComputerState.Deleted ||\n info.state === ComputerState.Error\n ) {\n throw computerSandboxError('computer_gone', `computer ${state.computerName} is gone`);\n }\n // Computers pause when idle, so a resume usually continues in place; one the\n // platform stopped or shelved meanwhile boots again.\n const rebooted = !isRunningState(info.state);\n if (info.state === ComputerState.Paused) await client.action(info.id, 'resume');\n else if (rebooted) await client.action(info.id, 'start');\n const spec = await resolve(ctx.guides);\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n const setup = setupSession({ client, info, env });\n await writePlatformFiles(ctx, setup.sandbox);\n await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });\n // Processes survive a pause; a stopped or shelved computer booted again.\n if (rebooted) await startServicesFor({ setup, spec, env });\n const { handle } = await buildHandle({\n ctx,\n client,\n info,\n spec,\n access: state.access,\n env,\n });\n return handle;\n },\n park: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n await closeComputerMcp(state.computerId);\n try {\n await clientFor(ctx.session.organizationId).action(state.computerId, 'pause');\n } catch (error) {\n // Already paused or stopped: nothing to do.\n if (!isComputersApiStatus(error, 409)) throw error;\n }\n return state;\n },\n onSessionEnd: async (ctx, _artifact, rawState, { reason }) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n // A conversation workspace outlives its binding (the conversation was\n // archived, or its workspace replaced): it is shelved, its disk backed up\n // to storage with no host held, and the next binding for the\n // conversation starts it again by name. Session and ephemeral disks end\n // with their binding.\n const action = state.workspace === ComputerWorkspacePolicy.Conversation ? 'stop' : 'delete';\n log('computer_sandbox.session_end', { computerId: state.computerId, reason, action });\n try {\n await client.action(state.computerId, action);\n } catch (error) {\n if (isComputersApiStatus(error, 404)) return;\n if (!isComputersApiStatus(error, 409)) throw error;\n // A conflict is done only when the computer is already where the action\n // takes it; one mid-transition (an idle pause committing) is retried.\n const current = await client.getComputer(state.computerId);\n const settled =\n current == null ||\n current.state === ComputerState.Deleted ||\n (action === 'stop' && current.state === ComputerState.Shelved);\n if (!settled) throw error;\n return;\n }\n // `stop` returns once the shelve is scheduled: the cleanup (and the\n // session service's fence on reusing the workspace) lasts until it is.\n if (action === 'stop') await awaitShelved(client, state.computerId);\n },\n };\n };\n\n return defineSandboxProvider({\n name: 'computer',\n stateProtocolVersion: 1,\n environment,\n });\n};\n"],
5
- "mappings": "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",
6
- "names": ["COMPUTER_SANDBOX_SPECIFIER", "computeComputerArtifactKey", "cached"]
4
+ "sourcesContent": ["import { ProcessInspectionOperation } from '@finalai/agent-protocol/process-inspection';\nimport {\n formatProviderRef,\n NetworkPolicy,\n packageRef,\n SandboxAccess,\n type JsonValue,\n} from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n materializeSandboxSeeds,\n PLATFORM_ENVIRONMENT_NAMES,\n platformProcessEnvironment,\n PortProtocol,\n reportPlatformNetworkPolicy,\n SandboxCapability,\n sandboxSeedArtifact,\n sandboxSeedArtifactSchema,\n sandboxSeedFiles,\n sandboxSeedFilesForStart,\n sandboxSeedIdentity,\n SandboxWorkspace,\n withPlatformEgressHosts,\n writePlatformFiles,\n type NetworkPolicyIface,\n type NetworkSandboxSessionIface,\n type SandboxGuidesIface,\n type SandboxPrepareContextIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxProviderImplementationIface,\n type SandboxStartContextIface,\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 { sleep as defaultSleep, sha256Hex } from \"./bytes.mjs\";\nimport { computerEditor } from \"./computer-editor.mjs\";\nimport { readComputerSnapshot } from \"./computer-snapshots.mjs\";\nimport {\n createComputersApiClient,\n createComputersApiCredentials,\n isComputersApiStatus,\n type ComputersApiClientIface,\n type ComputersApiConfigIface,\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_SANDBOX_SPECIFIER,\n computerEnvironmentSchema,\n computerOpenOptionsSchema,\n ComputerWorkspacePolicy,\n} from \"./environment.mjs\";\nimport {\n computeComputerArtifactKey,\n computerNeedsBuild,\n DEFAULT_COMPUTER_IMAGE,\n resolveComputerSpec,\n type ResolvedComputerSpecIface,\n} from \"./guide.mjs\";\nimport { createTransportSession, sessionForAccess } from \"./session.mjs\";\nimport type { SandboxTransportIface } from \"./transport.mjs\";\nimport {\n guideCommands,\n installGuideCommands,\n mountRepositories,\n repositoryPath,\n runWorkspaceSetup,\n startServices,\n WORKSPACE_ROOT,\n type GuideCommandIface,\n type SetupLogIface,\n} from \"./workspace-setup.mjs\";\n\nexport type { ComputersApiConfigIface, ComputersApiCredentialIface } from \"./computers-api.mjs\";\nexport {\n COMPUTER_SANDBOX_SPECIFIER,\n COMPUTERS_API_KEY_SECRET,\n COMPUTERS_API_TEAM_SECRET,\n} from \"./environment.mjs\";\nexport { computeComputerArtifactKey } from \"./guide.mjs\";\nexport type { ComputerGuideVersionIface } from \"./guide.mjs\";\nexport type { RepositoryCloneSourceIface } from \"./workspace-setup.mjs\";\n\n// The `computer` sandbox: a Final computer from the\n// public Computers API, set up from a computer setup guide, with lifecycle,\n// files and processes all through that API and the organization's own API key,\n// exactly as a third-party provider drives its vendor. Like every\n// provider, it is served by the session service, which runs this handle and\n// serves the handle RPC and MCP projection from it.\n//\n// A guide with build or verify steps is built once on a builder computer and\n// captured as a base (POST /v1/computers/:id/capture); its computers are created\n// from that base. Network and idle policies are create options, as for any\n// API customer.\n//\n// Guides, variables and repository credentials come from the contract's\n// prepare and start contexts (`guides`, `variables`, `repositories`), which the\n// session service serves to every provider alike.\n\nexport interface ComputerSandboxLogIface {\n (message: string, fields?: Record<string, string | number | boolean | null>): void;\n}\n\nexport interface ComputerSandboxProviderConfigIface {\n // The public Computers API, and each organization's credential for it.\n computersApi: ComputersApiConfigIface;\n // A registry credential (`creg_...`) the organization stored for private image references.\n registryCredentialId?: string;\n // Image for an empty environment without an organization default guide.\n defaultImage?: string;\n regionSlug?: string;\n machine?: { vcpu?: number; memoryMb?: number; diskGb?: number };\n idleTimeoutSeconds?: number;\n // How long `start` waits for a registered image version to finish building.\n imageWaitMs?: number;\n imagePollMs?: number;\n // How long `prepare` waits for a guide's base capture to publish.\n buildWaitMs?: number;\n buildPollMs?: number;\n // How long ending a conversation workspace waits for its computer to shelve.\n shelveWaitMs?: number;\n shelvePollMs?: number;\n // How long start, resume and a guide build wait for a computer to run before\n // touching it (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 start. A `captured` base is a guide's build, captured as a base\n// (`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 computerStateSchema = z.object({\n version: z.literal(1),\n computerId: z.string(),\n computerName: z.string(),\n workspace: z.nativeEnum(ComputerWorkspacePolicy),\n access: z.nativeEnum(SandboxAccess),\n guideVersionId: z.string().nullable(),\n setupHash: z.string().nullable(),\n});\n\n// The provider's own view of a computer while it sets it up.\ninterface SetupSessionIface {\n sandbox: NetworkSandboxSessionIface;\n transport: SandboxTransportIface;\n}\n\nexport type ComputerSandboxArtifact = z.infer<typeof computerArtifactSchema>;\nexport type ComputerSandboxState = z.infer<typeof computerStateSchema>;\n\n// What Build needs to know about a started computer beyond the handle.\nexport interface ComputerSandboxDescriptionIface {\n provider: 'computer';\n computerId: string;\n computerName: string;\n workspaceRoot: string;\n transport: string;\n guide: { slug: string; number: number } | null;\n repositories: { alias: string; path: string; repository: string }[];\n services: { name: string; readyUrl: string | null }[];\n commands: GuideCommandIface[];\n capabilities: SandboxCapability[];\n}\n\nexport interface ComputerSandboxSessionIface extends NetworkSandboxSessionIface {\n describe(): ComputerSandboxDescriptionIface;\n // What this computer's handle offers (the session service reports it).\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type ComputerSandboxProviderIface = SandboxProviderIface<\n JsonValue,\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\n// FINAL_NODE_* and the session basics belong to the platform (shared/src/sandbox-templates/reserved.ts),\n// as do the platform environment's variables (the egress proxy and its placeholders).\nconst RESERVED_ENV = new Set([\n ...PLATFORM_ENVIRONMENT_NAMES,\n 'DISPLAY',\n 'XDG_RUNTIME_DIR',\n 'PATH',\n 'HOME',\n 'USER',\n 'SHELL',\n 'HOSTNAME',\n]);\nconst isReservedEnvName = (name: string): boolean =>\n name.startsWith('FINAL_NODE_') || RESERVED_ENV.has(name);\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// Guide publication supplies build inputs in files; agent revisions supply workspace seeds.\nconst seedsFor = (ctx: SandboxPrepareContextIface): Record<string, string> =>\n sandboxSeedFiles({\n files: ctx.resources.guide == null ? ctx.files : {},\n resources: ctx.resources,\n });\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\ninterface ComputerEgressConfigIface {\n egress: ComputerEgressPolicy;\n allow?: string[];\n}\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: SandboxStartContextIface,\n requested: NetworkPolicyIface,\n): ComputerEgressConfigIface => computerEgressOf(withPlatformEgressHosts(ctx, requested));\n\nconst LINEAGE_PREFIX = 'lineage:';\n\nconst portOf = (url: string): number | null => {\n try {\n const parsed = new URL(url);\n if (parsed.port !== '') return Number(parsed.port);\n return parsed.protocol === 'https:' ? 443 : 80;\n } catch {\n return null;\n }\n};\n\nconst compactId = (id: string): string => id.replaceAll('-', '');\n\nconst sandboxWorkspaceOf = {\n [ComputerWorkspacePolicy.Session]: SandboxWorkspace.Session,\n [ComputerWorkspacePolicy.Conversation]: SandboxWorkspace.Conversation,\n [ComputerWorkspacePolicy.Ephemeral]: SandboxWorkspace.Ephemeral,\n} satisfies Record<ComputerWorkspacePolicy, SandboxWorkspace>;\n\nconst isRunningState = (state: ComputerState): boolean =>\n state === ComputerState.Running ||\n state === ComputerState.Paused ||\n state === ComputerState.Resuming;\n\nconst RUNNING_POLL_MAX_MS = 5_000;\n\nexport const createComputerSandboxProvider = (\n config: ComputerSandboxProviderConfigIface,\n): ComputerSandboxProviderIface => {\n const log: SetupLogIface = 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 defaultImage = config.defaultImage ?? DEFAULT_COMPUTER_IMAGE;\n const credentials = createComputersApiCredentials(config.computersApi, now);\n const runningWaitMs = config.runningWaitMs ?? 5 * 60_000;\n\n const clientFor = (organizationId: string): ComputersApiClientIface =>\n createComputersApiClient({ config: config.computersApi, credentials, organizationId });\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 (the\n // organization's or the platform's); a reference is registered once, at prepare,\n // 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 loadVariables = async (\n ctx: SandboxStartContextIface,\n spec: ResolvedComputerSpecIface,\n ): Promise<Record<string, string>> => {\n const env: Record<string, string> = {};\n for (const [name, value] of Object.entries(spec.parameters.env)) {\n if (isReservedEnvName(name))\n throw computerSandboxError('invalid_environment', `${name} is reserved`);\n env[name] = value;\n }\n for (const name of spec.parameters.variables) {\n if (isReservedEnvName(name))\n throw computerSandboxError('invalid_environment', `${name} is reserved`);\n const value = await ctx.variables.get(name);\n if (value == null)\n throw computerSandboxError('invalid_environment', `variable ${name} is not set`);\n env[name] = value;\n }\n return env;\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 buildHandle = async (args: {\n ctx: SandboxStartContextIface;\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n spec: ResolvedComputerSpecIface;\n access: SandboxAccess;\n env: () => Promise<Record<string, string>>;\n }): Promise<{ handle: SandboxProviderHandleIface<ComputerSandboxSessionIface> }> => {\n const { client, info, spec } = args;\n const commands = await guideCommands(spec.template);\n const commandHelp = commands\n .map(\n (command) =>\n `Guide command ${command.name}: bash ${command.path}${command.description == null ? '' : ` \u2014 ${command.description}`}`,\n )\n .join('\\n');\n const transport = createComputersApiTransport({ client, computerId: info.id });\n const ports = [\n ...new Set(\n spec.template.services.flatMap((service) => {\n const port = service.ready == null ? null : portOf(service.ready.url);\n return port == null ? [] : [port];\n }),\n ),\n ];\n let httpToken: { token: string; expiresAtMs: number } | null = null;\n const session = createTransportSession({\n id: info.id,\n description: `Final computer ${info.name}${spec.guide == null ? '' : ` (${spec.guide.title} v${spec.guide.number})`}${commands.length === 0 ? '' : `\\n${commandHelp}`}`,\n workspaceRoot: WORKSPACE_ROOT,\n transport,\n baseEnv: args.env,\n randomUuid,\n network: {\n 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.session.bindingId}`,\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 await closeComputerMcp(info.id);\n await client.action(info.id, 'stop');\n },\n destroy: async () => {\n await closeComputerMcp(info.id);\n transport.close();\n try {\n await client.action(info.id, 'delete');\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n },\n },\n });\n let computerUseInstalled: boolean | null = null;\n if (args.access !== SandboxAccess.Read) {\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.access === SandboxAccess.Read || 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.access !== SandboxAccess.Read)\n capabilities.push(SandboxCapability.Process, SandboxCapability.NetworkPolicy);\n const description: ComputerSandboxDescriptionIface = {\n provider: 'computer',\n computerId: info.id,\n computerName: info.name,\n workspaceRoot: WORKSPACE_ROOT,\n transport: transport.kind,\n guide: spec.guide == null ? null : { slug: spec.guide.slug, number: spec.guide.number },\n repositories: spec.parameters.repositories.map((repository) => ({\n alias: repository.alias,\n path: repositoryPath(repository.alias),\n repository: repository.repository,\n })),\n services: spec.template.services.map((service) => ({\n name: service.name,\n readyUrl: service.ready?.url ?? null,\n })),\n commands,\n capabilities,\n };\n const full: ComputerSandboxSessionIface = {\n ...session,\n setNetworkPolicy: async (policy) => {\n if (args.access === SandboxAccess.Read)\n throw new Error('this sandbox binding is read-only');\n await client.setNetworkPolicy(info.id, egressFor(args.ctx, policy));\n },\n describe: () => description,\n capabilities,\n };\n if (computerUse != null) full.computerUse = async () => computerUse.endpoint;\n if (screenAvailable) {\n full.screen = (options) => client.openScreen(info.id, options);\n }\n const sandbox = sessionForAccess(full, args.access);\n return {\n handle: {\n sandbox,\n onSandboxStop: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n },\n onSandboxDelete: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n try {\n await client.action(info.id, 'delete');\n } catch (error) {\n if (!isComputersApiStatus(error, 404)) throw error;\n }\n },\n onRuntimeShutdown: async () => {\n try {\n await closeMcp();\n } finally {\n transport.close();\n }\n },\n },\n };\n };\n\n // Setup (repositories, workspace.setup, services) is the provider's own work, so it\n // runs with the organization's credential, never through the binding's lease: a\n // read binding still gets a set-up computer.\n const setupSession = (args: {\n client: ComputersApiClientIface;\n info: ComputerInfoIface;\n env: () => Promise<Record<string, string>>;\n }): SetupSessionIface => {\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 // 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 const awaitShelved = async (client: ComputersApiClientIface, computerId: string) => {\n const deadline = now() + (config.shelveWaitMs ?? 5 * 60_000);\n for (;;) {\n const computer = await client.getComputer(computerId);\n if (\n computer == null ||\n computer.state === ComputerState.Shelved ||\n computer.state === ComputerState.Deleted\n )\n return;\n if (computer.state === ComputerState.Error)\n throw computerSandboxError('computer_gone', `computer ${computerId} failed to shelve`);\n if (now() >= deadline) throw new Error(`computer ${computerId} is still shelving`);\n await sleep(config.shelvePollMs ?? 2_000);\n }\n };\n\n // Run build.steps, then build.verify, on a builder computer of the guide's\n // image, captured as a base its computers are created from.\n const build = async (\n ctx: SandboxPrepareContextIface,\n spec: ResolvedComputerSpecIface,\n key: string,\n ): Promise<ComputerSandboxArtifact> => {\n const client = clientFor(ctx.organizationId);\n const diskGb = config.machine?.diskGb ?? null;\n const imageVersionId = await readyImageVersion(client, {\n image: spec.image,\n imageVersionId: null,\n });\n const body: CreateComputerBodyIface = {\n name: `ag-${key.slice(4, 20)}-${compactId(randomUuid()).slice(0, 8)}`,\n imageVersionId,\n ...config.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 (config.regionSlug != null) body.regionSlug = config.regionSlug;\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 ...spec.template.build.steps.map((step) => ({ step, label: 'build step' })),\n ...spec.template.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: spec.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 ): SandboxProviderImplementationIface<\n JsonValue,\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 resolve = (guides: SandboxGuidesIface): Promise<ResolvedComputerSpecIface> =>\n resolveComputerSpec({ options, guides, defaultImage });\n const keyFor = async (\n spec: ResolvedComputerSpecIface,\n files: Record<string, string>,\n ): Promise<string> => {\n const baseKey = await computeComputerArtifactKey({\n image: spec.image,\n template: spec.template,\n diskGb: config.machine?.diskGb ?? null,\n });\n return Object.keys(files).length === 0\n ? baseKey\n : `${baseKey}-s${await sha256Hex(sandboxSeedIdentity(files))}`;\n };\n\n const startServicesFor = async (args: {\n setup: SetupSessionIface;\n spec: ResolvedComputerSpecIface;\n env: () => Promise<Record<string, string>>;\n }): Promise<void> => {\n await startServices({\n sandbox: args.setup.sandbox,\n transport: args.setup.transport,\n template: args.spec.template,\n // Services run for the computer's life, with the platform's values as they are now.\n env: await args.env(),\n randomUuid,\n log,\n });\n };\n\n const awaitRunning = (\n ctx: SandboxStartContextIface,\n rawState: Pick<ComputerSandboxState, 'computerId'>,\n options: { timeoutMs: number },\n ): Promise<ComputerInfoIface> =>\n awaitComputerRunning(\n clientFor(ctx.session.organizationId),\n computerStateSchema.pick({ computerId: true }).parse(rawState).computerId,\n options.timeoutMs,\n );\n\n return {\n processes: async (ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n if (\n request.operation === ProcessInspectionOperation.Stop &&\n state.access === SandboxAccess.Read\n )\n throw new Error('stopping processes requires execute access');\n const result = await clientFor(ctx.organizationId).inspectProcesses(\n state.computerId,\n request,\n );\n return request.operation === ProcessInspectionOperation.Available && 'available' in result\n ? { ...result, canStop: state.access !== SandboxAccess.Read }\n : result;\n },\n editor: async (_ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n if (state.access !== SandboxAccess.Write) {\n if (request.operation === 'available') return { available: false };\n throw new Error('editor requires write access');\n }\n return computerEditor({\n client: clientFor(_ctx.organizationId),\n computerId: state.computerId,\n request,\n randomUuid,\n });\n },\n readSnapshot: async (ctx, rawState, request) => {\n const state = computerStateSchema.parse(rawState);\n return readComputerSnapshot({\n client: clientFor(ctx.organizationId),\n computerId: state.computerId,\n request,\n });\n },\n // The merged parameters' workspace: the binding's, else the saved version's default.\n workspace: async (ctx) =>\n sandboxWorkspaceOf[(await resolve(ctx.guides)).parameters.workspace],\n artifactKey: async (ctx) => keyFor(await resolve(ctx.guides), seedsFor(ctx)),\n // Registers an image reference so its version builds ahead of the first start;\n // a lineage needs nothing until then.\n prepare: async (ctx) => {\n const spec = await resolve(ctx.guides);\n const seedFiles = seedsFor(ctx);\n const key = await keyFor(spec, seedFiles);\n const seedArtifact = await sandboxSeedArtifact(ctx, seedFiles);\n if (computerNeedsBuild(spec)) {\n const baseKey = await keyFor(spec, {});\n const prepared = spec.guide?.preparedArtifact;\n if (\n prepared?.key === baseKey &&\n prepared.providerRef === formatProviderRef(packageRef(COMPUTER_SANDBOX_SPECIFIER))\n ) {\n const cached = computerArtifactSchema.safeParse(prepared.artifact);\n if (\n cached.success &&\n cached.data.key === baseKey &&\n cached.data.base.kind === 'captured'\n ) {\n const base = await clientFor(ctx.organizationId).getBase(cached.data.base.baseId);\n if (base?.state === ComputerBaseState.Ready) {\n if (!base.retained) {\n const retained = await clientFor(ctx.organizationId).setBaseRetention(\n base.id,\n true,\n );\n if (!retained.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n }\n return { ...cached.data, key, ...seedArtifact };\n }\n }\n }\n const cached = computerArtifactSchema.safeParse(await ctx.artifacts?.get(baseKey));\n if (\n cached.success &&\n cached.data.key === baseKey &&\n cached.data.base.kind === 'captured'\n ) {\n const base = await clientFor(ctx.organizationId).getBase(cached.data.base.baseId);\n if (base?.state === ComputerBaseState.Ready) {\n if (!base.retained) {\n const retained = await clientFor(ctx.organizationId).setBaseRetention(\n base.id,\n true,\n );\n if (!retained.retained)\n throw computerSandboxError(\n 'build_failed',\n 'the Computers API did not retain the prepared base',\n );\n }\n return { ...cached.data, key, ...seedArtifact };\n }\n }\n const built = await build(ctx, spec, baseKey);\n await ctx.artifacts?.put(baseKey, built);\n return { ...built, key, ...seedArtifact };\n }\n const imageVersionId = spec.image.startsWith(LINEAGE_PREFIX)\n ? null\n : (await registerImage(clientFor(ctx.organizationId), spec.image)).id;\n ctx.log?.(`computer base ${key} is image ${spec.image}`);\n return {\n version: 1,\n key,\n image: spec.image,\n diskGb: config.machine?.diskGb ?? null,\n ...seedArtifact,\n base: { kind: 'image', image: spec.image, imageVersionId },\n };\n },\n awaitRunning: async (ctx, state, options) => {\n await awaitRunning(ctx, state, options);\n },\n start: async (ctx, openOptions, rawArtifact) => {\n const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;\n const spec = await resolve(ctx.guides);\n const policy = withPlatformEgressHosts(ctx, spec.parameters.networkPolicy);\n const egress = computerEgressOf(policy);\n const artifact = computerArtifactSchema.safeParse(rawArtifact);\n if (!artifact.success) {\n throw computerSandboxError(\n 'artifact_unavailable',\n 'this computer base predates the public Computers API provider; prepare it again',\n );\n }\n const base = artifact.data.base;\n if (computerNeedsBuild(spec) && 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 }\n // Variables resolve before anything is created, so a missing one costs nothing.\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n const client = clientFor(ctx.session.organizationId);\n const workspace = spec.parameters.workspace;\n const name =\n workspace === ComputerWorkspacePolicy.Conversation && ctx.session.conversationId != null\n ? `ac-${(await sha256Hex(`${ctx.session.conversationId}:${ctx.session.target}`)).slice(0, 24)}`\n : `ab-${compactId(ctx.session.bindingId)}`;\n const existing = await client.getComputer(name);\n if (existing?.state === ComputerState.Error)\n throw computerSandboxError(\n 'computer_gone',\n `Computer ${existing.id} (${name}) is in the Error state. Recover it through the Computers API before retrying; its workspace is preserved.`,\n );\n let info: ComputerInfoIface;\n let fresh = true;\n if (existing != null && existing.state !== ComputerState.Deleted) {\n info = existing;\n fresh = !isRunningState(existing.state);\n if (existing.state === ComputerState.Paused) await client.action(existing.id, 'resume');\n else if (fresh) await client.action(existing.id, 'start');\n } else {\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,\n ...source,\n ...config.machine,\n env: {},\n autoResume: true,\n idleTimeoutSeconds: config.idleTimeoutSeconds ?? 15 * 60,\n // Provider teardown owns deletion; VM-level ephemeral disks cannot be paused.\n ephemeral: false,\n network: egress,\n tags: [\n 'final-agent-sandbox',\n `agent-binding:${ctx.session.bindingId}`,\n 'agent-runtime-attachment:v1',\n 'agent-runtime-role:sandbox',\n ],\n };\n // Session teardown owns deletion, including ephemeral computers. Idle must preserve files.\n body.idlePolicy = ComputerIdlePolicy.Pause;\n if (config.regionSlug != null) body.regionSlug = config.regionSlug;\n // Keyed by the source too: a retry after re-registering is a different request.\n const idempotencyKey = `agent-sandbox-${(await sha256Hex(`${ctx.session.bindingId}:${name}:${source.baseId ?? source.imageVersionId}`)).slice(0, 32)}`;\n info = await client.createComputer(body, idempotencyKey);\n }\n const reused = existing != null && existing.id === info.id;\n log('computer_sandbox.started', { computerId: info.id, reused });\n try {\n info = await awaitRunning(ctx, { computerId: info.id }, { timeoutMs: runningWaitMs });\n // A reused computer keeps whatever policy it last ran under; it gets the spec's again.\n if (reused) await client.setNetworkPolicy(info.id, egress);\n await reportPlatformNetworkPolicy(ctx, policy);\n const setup = setupSession({ client, info, env });\n await writePlatformFiles(ctx, setup.sandbox);\n await mountRepositories({\n sandbox: setup.sandbox,\n repositories: spec.parameters.repositories,\n resolver: ctx.repositories,\n log,\n });\n await materializeSandboxSeeds({\n sandbox: setup.sandbox,\n root: WORKSPACE_ROOT,\n files: await sandboxSeedFilesForStart(ctx, artifact.data),\n });\n await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });\n const setupHash = await runWorkspaceSetup({\n sandbox: setup.sandbox,\n template: spec.template,\n repositories: spec.parameters.repositories,\n log,\n });\n if (fresh) await startServicesFor({ setup, spec, env });\n const { handle } = await buildHandle({ ctx, client, info, spec, access, env });\n return {\n handle,\n region: info.regionSlug ?? config.regionSlug ?? null,\n state: {\n version: 1,\n computerId: info.id,\n computerName: info.name,\n workspace,\n access,\n guideVersionId: spec.guide?.versionId ?? null,\n setupHash,\n },\n };\n } catch (error) {\n // No state reaches the caller on failure; clean up only this start's new computer.\n if (!reused) {\n try {\n await client.action(info.id, 'delete');\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n `computer ${info.name} setup and cleanup failed`,\n );\n }\n }\n throw error;\n }\n },\n resumePassive: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n const info = await client.getComputer(state.computerId);\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 await awaitRunning(ctx, state, { timeoutMs: runningWaitMs });\n const spec = await resolve(ctx.guides);\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n return (await buildHandle({ ctx, client, info, spec, access: state.access, env })).handle;\n },\n resume: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n const info = await client.getComputer(state.computerId);\n if (\n info == null ||\n info.state === ComputerState.Deleted ||\n info.state === ComputerState.Error\n ) {\n throw computerSandboxError('computer_gone', `computer ${state.computerName} is gone`);\n }\n // Computers pause when idle, so a resume usually continues in place; one the\n // platform stopped or shelved meanwhile boots again.\n const rebooted = !isRunningState(info.state);\n if (info.state === ComputerState.Paused) await client.action(info.id, 'resume');\n else if (rebooted) await client.action(info.id, 'start');\n const running = await awaitRunning(ctx, state, { timeoutMs: runningWaitMs });\n const spec = await resolve(ctx.guides);\n const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));\n // The spec's policy again, whatever the computer last ran under.\n const policy = withPlatformEgressHosts(ctx, spec.parameters.networkPolicy);\n await client.setNetworkPolicy(running.id, computerEgressOf(policy));\n await reportPlatformNetworkPolicy(ctx, policy);\n const setup = setupSession({ client, info: running, env });\n await writePlatformFiles(ctx, setup.sandbox);\n await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });\n // Processes survive a pause; a stopped or shelved computer booted again.\n if (rebooted) await startServicesFor({ setup, spec, env });\n const { handle } = await buildHandle({\n ctx,\n client,\n info: running,\n spec,\n access: state.access,\n env,\n });\n return handle;\n },\n park: async (ctx, _artifact, rawState) => {\n const state = computerStateSchema.parse(rawState);\n await closeComputerMcp(state.computerId);\n try {\n await clientFor(ctx.session.organizationId).action(state.computerId, 'pause');\n } catch (error) {\n // Already paused or stopped: nothing to do.\n if (!isComputersApiStatus(error, 409)) throw error;\n }\n return state;\n },\n onSessionEnd: async (ctx, _artifact, rawState, { reason }) => {\n const state = computerStateSchema.parse(rawState);\n const client = clientFor(ctx.session.organizationId);\n // A conversation workspace outlives its binding (the conversation was\n // archived, or its workspace replaced): it is shelved, its disk backed up\n // to storage with no host held, and the next binding for the\n // conversation starts it again by name. Session and ephemeral disks end\n // with their binding.\n const action = state.workspace === ComputerWorkspacePolicy.Conversation ? 'stop' : 'delete';\n log('computer_sandbox.session_end', { computerId: state.computerId, reason, action });\n try {\n await client.action(state.computerId, action);\n } catch (error) {\n if (isComputersApiStatus(error, 404)) return;\n if (!isComputersApiStatus(error, 409)) throw error;\n // A conflict is done only when the computer is already where the action\n // takes it; one mid-transition (an idle pause committing) is retried.\n const current = await client.getComputer(state.computerId);\n const settled =\n current == null ||\n current.state === ComputerState.Deleted ||\n (action === 'stop' && current.state === ComputerState.Shelved);\n if (!settled) throw error;\n return;\n }\n // `stop` returns once the shelve is scheduled: the cleanup (and the\n // session service's fence on reusing the workspace) lasts until it is.\n if (action === 'stop') await awaitShelved(client, state.computerId);\n },\n };\n };\n\n return defineSandboxProvider({\n name: 'computer',\n stateProtocolVersion: 1,\n environment,\n });\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["COMPUTER_SANDBOX_SPECIFIER", "computeComputerArtifactKey", "options", "cached"]
7
7
  }
@@ -10,6 +10,8 @@ export interface DeviceSandboxProviderConfigIface {
10
10
  api: DeviceApiConfigIface;
11
11
  fetch?: DeviceApiFetchIface;
12
12
  leaseTtlMs?: number;
13
+ onlineWaitMs?: number;
14
+ sleep?: (ms: number) => Promise<void>;
13
15
  log?: (message: string, fields?: Record<string, string | number | boolean | null>) => void;
14
16
  randomUuid?: () => string;
15
17
  now?: () => number;
@@ -38,6 +38,8 @@ const descriptorsOf = (tools) => tools.flatMap((tool) => {
38
38
  return parsed.success ? [parsed.data] : [];
39
39
  });
40
40
  const LEASE_RENEW_MARGIN_MS = 5 * 6e4;
41
+ const ONLINE_POLL_MS = 500;
42
+ const ONLINE_POLL_MAX_MS = 5e3;
41
43
  const MAX_LEASE_TTL_MS = 60 * 6e4;
42
44
  const MIN_LEASE_TTL_MS = 6e4;
43
45
  const platformOf = (platform) => platform === "windows" ? SandboxPlatform.Windows : SandboxPlatform.Posix;
@@ -49,7 +51,22 @@ const createDeviceSandboxProvider = (config) => {
49
51
  MIN_LEASE_TTL_MS,
50
52
  Math.min(config.leaseTtlMs ?? 15 * 6e4, MAX_LEASE_TTL_MS)
51
53
  );
54
+ const sleep = config.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
55
+ const onlineWaitMs = config.onlineWaitMs ?? 0;
52
56
  const api = createDeviceApiClient({ api: config.api, fetch: config.fetch, now });
57
+ const awaitOnline = async (caller, deviceId, timeoutMs) => {
58
+ const deadline = now() + timeoutMs;
59
+ let pollMs = ONLINE_POLL_MS;
60
+ for (; ; ) {
61
+ const device = await api.getDevice({ caller, deviceId });
62
+ if (device == null) throw new Error(`device ${deviceId} was not found`);
63
+ if (device.online) return device;
64
+ const left = deadline - now();
65
+ if (left <= 0) throw new Error(`${device.displayName} is not connected`);
66
+ await sleep(Math.min(pollMs, left));
67
+ pollMs = Math.min(pollMs * 2, ONLINE_POLL_MAX_MS);
68
+ }
69
+ };
53
70
  const attach = async (args) => {
54
71
  const { ctx, access } = args;
55
72
  const caller = {
@@ -57,9 +74,7 @@ const createDeviceSandboxProvider = (config) => {
57
74
  actingUser: ctx.actingUser
58
75
  };
59
76
  const bindingId = ctx.session.bindingId;
60
- const device = await api.getDevice({ caller, deviceId: args.deviceId });
61
- if (device == null) throw new Error(`device ${args.deviceId} was not found`);
62
- if (!device.online) throw new Error(`${device.displayName} is not connected`);
77
+ const device = await awaitOnline(caller, args.deviceId, onlineWaitMs);
63
78
  if (access !== SandboxAccess.Read && !device.writable) {
64
79
  throw new Error(`${device.displayName} does not permit writes`);
65
80
  }
@@ -269,6 +284,14 @@ const createDeviceSandboxProvider = (config) => {
269
284
  localMcp: localKnown ? localMcp : null
270
285
  };
271
286
  },
287
+ awaitRunning: async (ctx, rawState, { timeoutMs }) => {
288
+ const { deviceId } = deviceStateSchema.pick({ deviceId: true }).parse(rawState);
289
+ await awaitOnline(
290
+ { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },
291
+ deviceId,
292
+ timeoutMs
293
+ );
294
+ },
272
295
  artifactKey: async (ctx) => `device:${await resolveDeviceId(ctx)}`,
273
296
  prepare: async (ctx) => ({ version: 1, deviceId: await resolveDeviceId(ctx) }),
274
297
  start: async (ctx, openOptions, rawArtifact) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/device.ts"],
4
- "sourcesContent": ["import { ProcessInspectionOperation } from '@finalai/agent-protocol/process-inspection';\nimport {\n SandboxAccess,\n toolDescriptorSchema,\n type JsonObject,\n type JsonValue,\n type ToolDescriptorIface,\n} from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n SandboxCapability,\n type McpChannelEndpointIface,\n type NetworkSandboxSessionIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxProviderImplementationIface,\n type SandboxStartContextIface,\n} from '@finalai/agent-provider/sandbox';\nimport * as z from 'zod';\nimport { commandEncoderFor } from \"./commands.mjs\";\nimport {\n createDeviceApiClient,\n DEVICE_API_COMPUTER_USE_SERVER,\n DeviceApiCapability,\n DeviceApiLeaseAccess,\n type DeviceApiCallerIface,\n type DeviceApiConfigIface,\n type DeviceApiFetchIface,\n type DeviceApiLeaseIface,\n} from \"./device-api.mjs\";\nimport { computerOpenOptionsSchema, deviceEnvironmentSchema } from \"./environment.mjs\";\nimport { createMcpPipe } from \"./mcp-pipe.mjs\";\nimport { sandboxPathsFor, SandboxPlatform } from \"./paths.mjs\";\nimport { createTransportSession, sessionForAccess } from \"./session.mjs\";\n\nexport { DEVICE_API_ACTING_USER_HEADER, DeviceApiClientErrorCode } from \"./device-api.mjs\";\nexport type { DeviceApiConfigIface, DeviceApiFetchIface } from \"./device-api.mjs\";\nexport { DEVICE_API_KEY_SECRET, DEVICE_SANDBOX_SPECIFIER } from \"./environment.mjs\";\nexport { SandboxPlatform } from \"./paths.mjs\";\n\n// The `device` sandbox: a user's own computer running Final Device. The\n// provider is a client of the Device API (device-api-service), the Device's\n// backend, exactly as a vendor provider is a client of its vendor's API: it\n// leases a workspace there and drives files, processes, computer use and the\n// screen through that API with the organization's own API key. It knows nothing of how\n// the Device API reaches the Device (DEVICE_DIRECT_ENDPOINT.md). A Device is one\n// person's machine: every call names the user the session acts for\n// (ctx.actingUser, read per call since it changes between turns), and the Device\n// API refuses a Device that user does not own.\n\nexport interface DeviceSandboxProviderConfigIface {\n // The Device API origin, and each organization's own API key for it.\n api: DeviceApiConfigIface;\n fetch?: DeviceApiFetchIface;\n // Device leases last at most an hour; renewed while in use.\n leaseTtlMs?: number;\n log?: (message: string, fields?: Record<string, string | number | boolean | null>) => void;\n randomUuid?: () => string;\n now?: () => number;\n}\n\nconst deviceArtifactSchema = z.object({ version: z.literal(1), deviceId: z.string() });\nconst deviceStateSchema = z.object({\n version: z.literal(1),\n deviceId: z.string(),\n generation: z.number().int().min(1),\n access: z.nativeEnum(SandboxAccess),\n});\nexport type DeviceSandboxArtifact = z.infer<typeof deviceArtifactSchema>;\nexport type DeviceSandboxState = z.infer<typeof deviceStateSchema>;\n\nexport const DEVICE_COMPUTER_USE_SERVER = DEVICE_API_COMPUTER_USE_SERVER;\n\nexport interface DeviceSandboxSessionIface extends NetworkSandboxSessionIface {\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type DeviceSandboxProviderIface = SandboxProviderIface<\n JsonValue,\n JsonValue,\n DeviceSandboxArtifact,\n DeviceSandboxState,\n DeviceSandboxSessionIface\n>;\n\n// The Device API's recorded tools as tool descriptors; one that does not fit\n// the contract is left out.\nconst descriptorsOf = (tools: readonly JsonObject[]): ToolDescriptorIface[] =>\n tools.flatMap((tool) => {\n const parsed = toolDescriptorSchema.safeParse({\n ...tool,\n description: tool.description ?? tool.title ?? tool.name,\n });\n return parsed.success ? [parsed.data] : [];\n });\n\nconst LEASE_RENEW_MARGIN_MS = 5 * 60_000;\nconst MAX_LEASE_TTL_MS = 60 * 60_000;\nconst MIN_LEASE_TTL_MS = 60_000;\n\nconst platformOf = (platform: string): SandboxPlatform =>\n platform === 'windows' ? SandboxPlatform.Windows : SandboxPlatform.Posix;\n\nexport const createDeviceSandboxProvider = (\n config: DeviceSandboxProviderConfigIface,\n): DeviceSandboxProviderIface => {\n const randomUuid = config.randomUuid ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => Date.now());\n const log = config.log ?? (() => undefined);\n const leaseTtlMs = Math.max(\n MIN_LEASE_TTL_MS,\n Math.min(config.leaseTtlMs ?? 15 * 60_000, MAX_LEASE_TTL_MS),\n );\n const api = createDeviceApiClient({ api: config.api, fetch: config.fetch, now });\n\n const attach = async (args: {\n ctx: SandboxStartContextIface;\n deviceId: string;\n afterGeneration: number | null;\n passive?: boolean;\n access: SandboxAccess;\n }): Promise<{\n handle: SandboxProviderHandleIface<DeviceSandboxSessionIface>;\n generation: number;\n }> => {\n const { ctx, access } = args;\n const caller: DeviceApiCallerIface = {\n organizationId: ctx.session.organizationId,\n actingUser: ctx.actingUser,\n };\n const bindingId = ctx.session.bindingId;\n const device = await api.getDevice({ caller, deviceId: args.deviceId });\n if (device == null) throw new Error(`device ${args.deviceId} was not found`);\n if (!device.online) throw new Error(`${device.displayName} is not connected`);\n // Processes need the Device's write lease, so execute access does too.\n if (access !== SandboxAccess.Read && !device.writable) {\n throw new Error(`${device.displayName} does not permit writes`);\n }\n const leaseAccess =\n access === SandboxAccess.Read ? DeviceApiLeaseAccess.Read : DeviceApiLeaseAccess.Write;\n let current: DeviceApiLeaseIface =\n args.passive === true\n ? await api.recoverLease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n })\n : await api.lease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n ttlMs: leaseTtlMs,\n afterGeneration: args.afterGeneration ?? undefined,\n });\n if (\n args.passive === true &&\n (current.deviceId !== device.id ||\n current.access !== leaseAccess ||\n current.generation < (args.afterGeneration ?? 0) ||\n current.expiresAtMs <= now())\n )\n throw new Error('The existing Device lease is unavailable');\n let renewing: Promise<DeviceApiLeaseIface> | null = null;\n // The current lease handle, renewed shortly before it lapses.\n const lease = async (): Promise<string> => {\n if (current.expiresAtMs - now() < LEASE_RENEW_MARGIN_MS) {\n renewing ??= (\n args.passive === true\n ? api.recoverLease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n })\n : api.renew({ caller, lease: current.lease, ttlMs: leaseTtlMs })\n ).finally(() => {\n renewing = null;\n });\n current = await renewing;\n }\n return current.lease;\n };\n let released = false;\n const release = async (): Promise<void> => {\n if (released) return;\n released = true;\n await api.release({ caller, lease: current.lease });\n };\n\n const platform = platformOf(current.platform);\n const paths = sandboxPathsFor(platform);\n const session = createTransportSession({\n id: `${device.id}:${bindingId}`,\n description: `${device.displayName} (Final Device)`,\n workspaceRoot: current.workspaceRoot,\n transport: api.transport({ caller, lease }),\n baseEnv: async () => ({}),\n randomUuid,\n paths,\n commands: commandEncoderFor(platform),\n network: {\n ports: [],\n getPortEndpoint: async () => {\n throw new Error('Final Device sandboxes expose no ports');\n },\n stop: release,\n destroy: release,\n },\n });\n\n const offered = new Set(current.capabilities);\n const processes = offered.has(DeviceApiCapability.Process);\n const localMcp = offered.has(DeviceApiCapability.LocalMcp);\n const computerUse = offered.has(DeviceApiCapability.ComputerUse);\n const capabilities = [SandboxCapability.Files];\n if (processes) capabilities.push(SandboxCapability.Process);\n if (localMcp) capabilities.push(SandboxCapability.LocalMcp);\n if (computerUse) capabilities.push(SandboxCapability.ComputerUse);\n if (device.screenReady) capabilities.push(SandboxCapability.Screen);\n\n // The Device's computer-use server, or one of its local MCP servers, is a byte\n // pipe in the Device API (`/v1/leases/:lease/mcp/:server/{open,write,read,close}`):\n // a channel endpoint whoever runs this handle opens in process.\n const channelEndpoint = (server: string): McpChannelEndpointIface => ({\n name: server,\n connect: async () => {\n const pipe = openMcpPipe(server);\n return {\n send: (message, options) => pipe.send(message, options?.abortSignal),\n receive: (options) => pipe.receive(options?.abortSignal),\n close: () => pipe.close(),\n };\n },\n });\n const openMcpPipe = (server: string) => {\n const clientId = randomUuid();\n const request = async (\n action: 'open' | 'write' | 'read' | 'close',\n dataBase64?: string,\n signal?: AbortSignal,\n ): Promise<string> =>\n api.pipe({\n caller,\n lease: await lease(),\n server,\n action,\n clientId,\n dataBase64,\n signal,\n });\n return createMcpPipe({\n wire: {\n open: async (signal) => {\n await request('open', undefined, signal);\n },\n write: async (data, signal) => {\n await request('write', data, signal);\n },\n read: (signal) => request('read', undefined, signal),\n close: async () => {\n await request('close').catch(() => undefined);\n },\n },\n });\n };\n const sandbox: DeviceSandboxSessionIface = { ...session, capabilities };\n if (computerUse) {\n sandbox.computerUse = async () => channelEndpoint(DEVICE_COMPUTER_USE_SERVER);\n }\n if (localMcp) {\n sandbox.localMcp = async () =>\n (await api.localMcpServers({ caller, lease: await lease() })).map(channelEndpoint);\n }\n if (device.screenReady) {\n sandbox.screen = (options) =>\n api.screen({\n caller,\n deviceId: device.id,\n sessionId: randomUuid(),\n viewOnly: options?.viewOnly ?? true,\n });\n }\n log('device_sandbox.attached', { deviceId: device.id, generation: current.generation });\n return {\n generation: current.generation,\n handle: {\n // The Device enforces the read lease too; the view refuses before a round trip.\n sandbox: sessionForAccess(sandbox, access),\n onSandboxStop: release,\n onSandboxDelete: release,\n onRuntimeShutdown: async () => undefined,\n },\n };\n };\n\n const environment = (\n rawOptions?: JsonValue,\n ): SandboxProviderImplementationIface<\n JsonValue,\n DeviceSandboxArtifact,\n DeviceSandboxState,\n DeviceSandboxSessionIface\n > => {\n const parsed = deviceEnvironmentSchema.safeParse(rawOptions ?? {});\n if (!parsed.success) throw new Error(`invalid device environment: ${parsed.error.message}`);\n const options = parsed.data;\n // The Device the environment names; the Device API checks on every call\n // that the acting user owns it.\n const resolveDeviceId = async (caller: DeviceApiCallerIface): Promise<string> => {\n if ('deviceId' in options) return options.deviceId;\n if ('pairing' in options) {\n const device = await api.resolvePairing({ caller, code: options.pairing });\n if (device == null) throw new Error('the Final Device pairing code is unknown or expired');\n return device.id;\n }\n // An unnamed binding uses the only Device of the user the session acts\n // for (the API lists only that user's Devices), never another member's.\n const devices = await api.listDevices({ caller });\n const [only] = devices;\n if (devices.length !== 1 || only == null) {\n throw new Error(\n devices.length === 0\n ? 'the user this session acts for has no Final Device'\n : 'the user this session acts for has several Final Devices; name one by id or pairing code',\n );\n }\n return only.id;\n };\n return {\n processes: async (ctx, rawState, request) => {\n const state = deviceStateSchema.parse(rawState);\n if (\n request.operation === ProcessInspectionOperation.Stop &&\n state.access === SandboxAccess.Read\n )\n throw new Error('stopping processes requires execute access');\n return api.inspectProcesses({\n caller: ctx,\n deviceId: state.deviceId,\n bindingId: ctx.bindingId,\n request,\n });\n },\n // What a lease on this Device grants, known from the registry without\n // leasing (the Device API's rule: processes, local MCP and computer use with\n // a write lease on a Device that allows processes). The computer-use\n // driver's readiness is checked when leased.\n capabilities: async (ctx) => {\n const device = await api.getDevice({\n caller: ctx,\n deviceId: await resolveDeviceId(ctx),\n });\n if (device == null) return null;\n const offered = [SandboxCapability.Files];\n if (device.writable && device.allowProcesses) {\n offered.push(\n SandboxCapability.Process,\n SandboxCapability.LocalMcp,\n SandboxCapability.ComputerUse,\n );\n }\n if (device.screenReady) offered.push(SandboxCapability.Screen);\n return offered;\n },\n // What the Device's servers last listed through the Device API (it records\n // them from the MCP pipes), so the projection lists them without leasing.\n // A Device the API has never seen list gives unknown; its first lease does.\n mcpCatalog: async (ctx) => {\n const catalog = await api.mcpCatalog({\n caller: ctx,\n deviceId: await resolveDeviceId(ctx),\n });\n const local = catalog.localServers;\n const localMcp: Record<string, ToolDescriptorIface[]> = {};\n let localKnown = local != null;\n for (const server of local?.servers ?? []) {\n if (server.tools == null) localKnown = false;\n else localMcp[server.name] = descriptorsOf(server.tools);\n }\n return {\n computerUse:\n catalog.computerUse == null ? null : descriptorsOf(catalog.computerUse.tools),\n localMcp: localKnown ? localMcp : null,\n };\n },\n artifactKey: async (ctx) => `device:${await resolveDeviceId(ctx)}`,\n prepare: async (ctx) => ({ version: 1, deviceId: await resolveDeviceId(ctx) }),\n start: async (ctx, openOptions, rawArtifact) => {\n const artifact = deviceArtifactSchema.parse(rawArtifact);\n const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;\n const { handle, generation } = await attach({\n ctx,\n deviceId: artifact.deviceId,\n afterGeneration: null,\n access,\n });\n return { handle, state: { version: 1, deviceId: artifact.deviceId, generation, access } };\n },\n // A Device never takes a lease back at an old generation once it lapsed,\n // so every attach leases a later one.\n resume: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n return (\n await attach({\n ctx,\n deviceId: state.deviceId,\n afterGeneration: state.generation,\n access: state.access,\n })\n ).handle;\n },\n resumePassive: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n return (\n await attach({\n ctx,\n deviceId: state.deviceId,\n afterGeneration: state.generation,\n access: state.access,\n passive: true,\n })\n ).handle;\n },\n onSessionEnd: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n await api.releaseWorkspaceLeases({\n caller: { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },\n deviceId: state.deviceId,\n bindingId: ctx.session.bindingId,\n });\n },\n // The lease lapses on its own; the next generation retires its processes.\n park: async (_ctx, _artifact, rawState) => deviceStateSchema.parse(rawState),\n };\n };\n\n return defineSandboxProvider({\n name: 'device',\n stateProtocolVersion: 1,\n environment,\n });\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { ProcessInspectionOperation } from '@finalai/agent-protocol/process-inspection';\nimport {\n SandboxAccess,\n toolDescriptorSchema,\n type JsonObject,\n type JsonValue,\n type ToolDescriptorIface,\n} from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n SandboxCapability,\n type McpChannelEndpointIface,\n type NetworkSandboxSessionIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxProviderImplementationIface,\n type SandboxStartContextIface,\n} from '@finalai/agent-provider/sandbox';\nimport * as z from 'zod';\nimport { commandEncoderFor } from \"./commands.mjs\";\nimport {\n createDeviceApiClient,\n DEVICE_API_COMPUTER_USE_SERVER,\n DeviceApiCapability,\n DeviceApiLeaseAccess,\n type DeviceApiCallerIface,\n type DeviceApiConfigIface,\n type DeviceApiDeviceIface,\n type DeviceApiFetchIface,\n type DeviceApiLeaseIface,\n} from \"./device-api.mjs\";\nimport { computerOpenOptionsSchema, deviceEnvironmentSchema } from \"./environment.mjs\";\nimport { createMcpPipe } from \"./mcp-pipe.mjs\";\nimport { sandboxPathsFor, SandboxPlatform } from \"./paths.mjs\";\nimport { createTransportSession, sessionForAccess } from \"./session.mjs\";\n\nexport { DEVICE_API_ACTING_USER_HEADER, DeviceApiClientErrorCode } from \"./device-api.mjs\";\nexport type { DeviceApiConfigIface, DeviceApiFetchIface } from \"./device-api.mjs\";\nexport { DEVICE_API_KEY_SECRET, DEVICE_SANDBOX_SPECIFIER } from \"./environment.mjs\";\nexport { SandboxPlatform } from \"./paths.mjs\";\n\n// The `device` sandbox: a user's own computer running Final Device. The\n// provider is a client of the Device API (device-api-service), the Device's\n// backend, exactly as a vendor provider is a client of its vendor's API: it\n// leases a workspace there and drives files, processes, computer use and the\n// screen through that API with the organization's own API key. It knows nothing of how\n// the Device API reaches the Device (DEVICE_DIRECT_ENDPOINT.md). A Device is one\n// person's machine: every call names the user the session acts for\n// (ctx.actingUser, read per call since it changes between turns), and the Device\n// API refuses a Device that user does not own.\n\nexport interface DeviceSandboxProviderConfigIface {\n // The Device API origin, and each organization's own API key for it.\n api: DeviceApiConfigIface;\n fetch?: DeviceApiFetchIface;\n // Device leases last at most an hour; renewed while in use.\n leaseTtlMs?: number;\n // How long start and resume wait for an offline Device to connect (default 0:\n // an offline Device fails at once); polled from 500 ms, doubling to 5 s.\n onlineWaitMs?: number;\n sleep?: (ms: number) => Promise<void>;\n log?: (message: string, fields?: Record<string, string | number | boolean | null>) => void;\n randomUuid?: () => string;\n now?: () => number;\n}\n\nconst deviceArtifactSchema = z.object({ version: z.literal(1), deviceId: z.string() });\nconst deviceStateSchema = z.object({\n version: z.literal(1),\n deviceId: z.string(),\n generation: z.number().int().min(1),\n access: z.nativeEnum(SandboxAccess),\n});\nexport type DeviceSandboxArtifact = z.infer<typeof deviceArtifactSchema>;\nexport type DeviceSandboxState = z.infer<typeof deviceStateSchema>;\n\nexport const DEVICE_COMPUTER_USE_SERVER = DEVICE_API_COMPUTER_USE_SERVER;\n\nexport interface DeviceSandboxSessionIface extends NetworkSandboxSessionIface {\n readonly capabilities: readonly SandboxCapability[];\n}\n\nexport type DeviceSandboxProviderIface = SandboxProviderIface<\n JsonValue,\n JsonValue,\n DeviceSandboxArtifact,\n DeviceSandboxState,\n DeviceSandboxSessionIface\n>;\n\n// The Device API's recorded tools as tool descriptors; one that does not fit\n// the contract is left out.\nconst descriptorsOf = (tools: readonly JsonObject[]): ToolDescriptorIface[] =>\n tools.flatMap((tool) => {\n const parsed = toolDescriptorSchema.safeParse({\n ...tool,\n description: tool.description ?? tool.title ?? tool.name,\n });\n return parsed.success ? [parsed.data] : [];\n });\n\nconst LEASE_RENEW_MARGIN_MS = 5 * 60_000;\nconst ONLINE_POLL_MS = 500;\nconst ONLINE_POLL_MAX_MS = 5_000;\nconst MAX_LEASE_TTL_MS = 60 * 60_000;\nconst MIN_LEASE_TTL_MS = 60_000;\n\nconst platformOf = (platform: string): SandboxPlatform =>\n platform === 'windows' ? SandboxPlatform.Windows : SandboxPlatform.Posix;\n\nexport const createDeviceSandboxProvider = (\n config: DeviceSandboxProviderConfigIface,\n): DeviceSandboxProviderIface => {\n const randomUuid = config.randomUuid ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => Date.now());\n const log = config.log ?? (() => undefined);\n const leaseTtlMs = Math.max(\n MIN_LEASE_TTL_MS,\n Math.min(config.leaseTtlMs ?? 15 * 60_000, MAX_LEASE_TTL_MS),\n );\n const sleep =\n config.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));\n const onlineWaitMs = config.onlineWaitMs ?? 0;\n const api = createDeviceApiClient({ api: config.api, fetch: config.fetch, now });\n\n // A Device runs when it is connected to the Device API; nothing is leased before.\n const awaitOnline = async (\n caller: DeviceApiCallerIface,\n deviceId: string,\n timeoutMs: number,\n ): Promise<DeviceApiDeviceIface> => {\n const deadline = now() + timeoutMs;\n let pollMs = ONLINE_POLL_MS;\n for (;;) {\n const device = await api.getDevice({ caller, deviceId });\n if (device == null) throw new Error(`device ${deviceId} was not found`);\n if (device.online) return device;\n const left = deadline - now();\n if (left <= 0) throw new Error(`${device.displayName} is not connected`);\n await sleep(Math.min(pollMs, left));\n pollMs = Math.min(pollMs * 2, ONLINE_POLL_MAX_MS);\n }\n };\n\n const attach = async (args: {\n ctx: SandboxStartContextIface;\n deviceId: string;\n afterGeneration: number | null;\n passive?: boolean;\n access: SandboxAccess;\n }): Promise<{\n handle: SandboxProviderHandleIface<DeviceSandboxSessionIface>;\n generation: number;\n }> => {\n const { ctx, access } = args;\n const caller: DeviceApiCallerIface = {\n organizationId: ctx.session.organizationId,\n actingUser: ctx.actingUser,\n };\n const bindingId = ctx.session.bindingId;\n // The provider's awaitRunning, before the lease.\n const device = await awaitOnline(caller, args.deviceId, onlineWaitMs);\n // Processes need the Device's write lease, so execute access does too.\n if (access !== SandboxAccess.Read && !device.writable) {\n throw new Error(`${device.displayName} does not permit writes`);\n }\n const leaseAccess =\n access === SandboxAccess.Read ? DeviceApiLeaseAccess.Read : DeviceApiLeaseAccess.Write;\n let current: DeviceApiLeaseIface =\n args.passive === true\n ? await api.recoverLease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n })\n : await api.lease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n ttlMs: leaseTtlMs,\n afterGeneration: args.afterGeneration ?? undefined,\n });\n if (\n args.passive === true &&\n (current.deviceId !== device.id ||\n current.access !== leaseAccess ||\n current.generation < (args.afterGeneration ?? 0) ||\n current.expiresAtMs <= now())\n )\n throw new Error('The existing Device lease is unavailable');\n let renewing: Promise<DeviceApiLeaseIface> | null = null;\n // The current lease handle, renewed shortly before it lapses.\n const lease = async (): Promise<string> => {\n if (current.expiresAtMs - now() < LEASE_RENEW_MARGIN_MS) {\n renewing ??= (\n args.passive === true\n ? api.recoverLease({\n caller,\n deviceId: device.id,\n sessionId: ctx.session.id,\n bindingId,\n access: leaseAccess,\n })\n : api.renew({ caller, lease: current.lease, ttlMs: leaseTtlMs })\n ).finally(() => {\n renewing = null;\n });\n current = await renewing;\n }\n return current.lease;\n };\n let released = false;\n const release = async (): Promise<void> => {\n if (released) return;\n released = true;\n await api.release({ caller, lease: current.lease });\n };\n\n const platform = platformOf(current.platform);\n const paths = sandboxPathsFor(platform);\n const session = createTransportSession({\n id: `${device.id}:${bindingId}`,\n description: `${device.displayName} (Final Device)`,\n workspaceRoot: current.workspaceRoot,\n transport: api.transport({ caller, lease }),\n baseEnv: async () => ({}),\n randomUuid,\n paths,\n commands: commandEncoderFor(platform),\n network: {\n ports: [],\n getPortEndpoint: async () => {\n throw new Error('Final Device sandboxes expose no ports');\n },\n stop: release,\n destroy: release,\n },\n });\n\n const offered = new Set(current.capabilities);\n const processes = offered.has(DeviceApiCapability.Process);\n const localMcp = offered.has(DeviceApiCapability.LocalMcp);\n const computerUse = offered.has(DeviceApiCapability.ComputerUse);\n const capabilities = [SandboxCapability.Files];\n if (processes) capabilities.push(SandboxCapability.Process);\n if (localMcp) capabilities.push(SandboxCapability.LocalMcp);\n if (computerUse) capabilities.push(SandboxCapability.ComputerUse);\n if (device.screenReady) capabilities.push(SandboxCapability.Screen);\n\n // The Device's computer-use server, or one of its local MCP servers, is a byte\n // pipe in the Device API (`/v1/leases/:lease/mcp/:server/{open,write,read,close}`):\n // a channel endpoint whoever runs this handle opens in process.\n const channelEndpoint = (server: string): McpChannelEndpointIface => ({\n name: server,\n connect: async () => {\n const pipe = openMcpPipe(server);\n return {\n send: (message, options) => pipe.send(message, options?.abortSignal),\n receive: (options) => pipe.receive(options?.abortSignal),\n close: () => pipe.close(),\n };\n },\n });\n const openMcpPipe = (server: string) => {\n const clientId = randomUuid();\n const request = async (\n action: 'open' | 'write' | 'read' | 'close',\n dataBase64?: string,\n signal?: AbortSignal,\n ): Promise<string> =>\n api.pipe({\n caller,\n lease: await lease(),\n server,\n action,\n clientId,\n dataBase64,\n signal,\n });\n return createMcpPipe({\n wire: {\n open: async (signal) => {\n await request('open', undefined, signal);\n },\n write: async (data, signal) => {\n await request('write', data, signal);\n },\n read: (signal) => request('read', undefined, signal),\n close: async () => {\n await request('close').catch(() => undefined);\n },\n },\n });\n };\n const sandbox: DeviceSandboxSessionIface = { ...session, capabilities };\n if (computerUse) {\n sandbox.computerUse = async () => channelEndpoint(DEVICE_COMPUTER_USE_SERVER);\n }\n if (localMcp) {\n sandbox.localMcp = async () =>\n (await api.localMcpServers({ caller, lease: await lease() })).map(channelEndpoint);\n }\n if (device.screenReady) {\n sandbox.screen = (options) =>\n api.screen({\n caller,\n deviceId: device.id,\n sessionId: randomUuid(),\n viewOnly: options?.viewOnly ?? true,\n });\n }\n log('device_sandbox.attached', { deviceId: device.id, generation: current.generation });\n return {\n generation: current.generation,\n handle: {\n // The Device enforces the read lease too; the view refuses before a round trip.\n sandbox: sessionForAccess(sandbox, access),\n onSandboxStop: release,\n onSandboxDelete: release,\n onRuntimeShutdown: async () => undefined,\n },\n };\n };\n\n const environment = (\n rawOptions?: JsonValue,\n ): SandboxProviderImplementationIface<\n JsonValue,\n DeviceSandboxArtifact,\n DeviceSandboxState,\n DeviceSandboxSessionIface\n > => {\n const parsed = deviceEnvironmentSchema.safeParse(rawOptions ?? {});\n if (!parsed.success) throw new Error(`invalid device environment: ${parsed.error.message}`);\n const options = parsed.data;\n // The Device the environment names; the Device API checks on every call\n // that the acting user owns it.\n const resolveDeviceId = async (caller: DeviceApiCallerIface): Promise<string> => {\n if ('deviceId' in options) return options.deviceId;\n if ('pairing' in options) {\n const device = await api.resolvePairing({ caller, code: options.pairing });\n if (device == null) throw new Error('the Final Device pairing code is unknown or expired');\n return device.id;\n }\n // An unnamed binding uses the only Device of the user the session acts\n // for (the API lists only that user's Devices), never another member's.\n const devices = await api.listDevices({ caller });\n const [only] = devices;\n if (devices.length !== 1 || only == null) {\n throw new Error(\n devices.length === 0\n ? 'the user this session acts for has no Final Device'\n : 'the user this session acts for has several Final Devices; name one by id or pairing code',\n );\n }\n return only.id;\n };\n return {\n processes: async (ctx, rawState, request) => {\n const state = deviceStateSchema.parse(rawState);\n if (\n request.operation === ProcessInspectionOperation.Stop &&\n state.access === SandboxAccess.Read\n )\n throw new Error('stopping processes requires execute access');\n return api.inspectProcesses({\n caller: ctx,\n deviceId: state.deviceId,\n bindingId: ctx.bindingId,\n request,\n });\n },\n // What a lease on this Device grants, known from the registry without\n // leasing (the Device API's rule: processes, local MCP and computer use with\n // a write lease on a Device that allows processes). The computer-use\n // driver's readiness is checked when leased.\n capabilities: async (ctx) => {\n const device = await api.getDevice({\n caller: ctx,\n deviceId: await resolveDeviceId(ctx),\n });\n if (device == null) return null;\n const offered = [SandboxCapability.Files];\n if (device.writable && device.allowProcesses) {\n offered.push(\n SandboxCapability.Process,\n SandboxCapability.LocalMcp,\n SandboxCapability.ComputerUse,\n );\n }\n if (device.screenReady) offered.push(SandboxCapability.Screen);\n return offered;\n },\n // What the Device's servers last listed through the Device API (it records\n // them from the MCP pipes), so the projection lists them without leasing.\n // A Device the API has never seen list gives unknown; its first lease does.\n mcpCatalog: async (ctx) => {\n const catalog = await api.mcpCatalog({\n caller: ctx,\n deviceId: await resolveDeviceId(ctx),\n });\n const local = catalog.localServers;\n const localMcp: Record<string, ToolDescriptorIface[]> = {};\n let localKnown = local != null;\n for (const server of local?.servers ?? []) {\n if (server.tools == null) localKnown = false;\n else localMcp[server.name] = descriptorsOf(server.tools);\n }\n return {\n computerUse:\n catalog.computerUse == null ? null : descriptorsOf(catalog.computerUse.tools),\n localMcp: localKnown ? localMcp : null,\n };\n },\n awaitRunning: async (ctx, rawState, { timeoutMs }) => {\n const { deviceId } = deviceStateSchema.pick({ deviceId: true }).parse(rawState);\n await awaitOnline(\n { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },\n deviceId,\n timeoutMs,\n );\n },\n artifactKey: async (ctx) => `device:${await resolveDeviceId(ctx)}`,\n prepare: async (ctx) => ({ version: 1, deviceId: await resolveDeviceId(ctx) }),\n start: async (ctx, openOptions, rawArtifact) => {\n const artifact = deviceArtifactSchema.parse(rawArtifact);\n const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;\n const { handle, generation } = await attach({\n ctx,\n deviceId: artifact.deviceId,\n afterGeneration: null,\n access,\n });\n return { handle, state: { version: 1, deviceId: artifact.deviceId, generation, access } };\n },\n // A Device never takes a lease back at an old generation once it lapsed,\n // so every attach leases a later one.\n resume: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n return (\n await attach({\n ctx,\n deviceId: state.deviceId,\n afterGeneration: state.generation,\n access: state.access,\n })\n ).handle;\n },\n resumePassive: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n return (\n await attach({\n ctx,\n deviceId: state.deviceId,\n afterGeneration: state.generation,\n access: state.access,\n passive: true,\n })\n ).handle;\n },\n onSessionEnd: async (ctx, _artifact, rawState) => {\n const state = deviceStateSchema.parse(rawState);\n await api.releaseWorkspaceLeases({\n caller: { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },\n deviceId: state.deviceId,\n bindingId: ctx.session.bindingId,\n });\n },\n // The lease lapses on its own; the next generation retires its processes.\n park: async (_ctx, _artifact, rawState) => deviceStateSchema.parse(rawState),\n };\n };\n\n return defineSandboxProvider({\n name: 'device',\n stateProtocolVersion: 1,\n environment,\n });\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["SandboxPlatform"]
7
7
  }
@@ -50,6 +50,9 @@ export interface FakeComputersApiIface {
50
50
  imageBuildReads: {
51
51
  count: number;
52
52
  };
53
+ bootReads: {
54
+ count: number;
55
+ };
53
56
  computerByName(name: string): FakeComputerIface | undefined;
54
57
  }
55
58
  export declare const FAKE_COMPUTERS_API_KEY = "fk_org_api_key";
@@ -7,7 +7,16 @@ import { posix } from "node:path";
7
7
  import * as z from "zod";
8
8
  import { concatBytes, decodeBase64, encodeBase64 } from "../bytes.mjs";
9
9
  import { createFakeMachine, readFakeOutput } from "./fake-machine.mjs";
10
- const STATE = { Running: 3, Paused: 4, Stopped: 5, Deleted: 9, Shelved: 10 };
10
+ const STATE = {
11
+ Pending: 1,
12
+ Running: 3,
13
+ Paused: 4,
14
+ Stopped: 5,
15
+ Resuming: 6,
16
+ Deleted: 9,
17
+ Shelved: 10
18
+ };
19
+ const NOT_RUNNING = "Computer is not running; resume it explicitly before this operation";
11
20
  const FAKE_COMPUTERS_API_KEY = "fk_org_api_key";
12
21
  const FAKE_PLATFORM_SANDBOX_IMAGE = "cimv_0190e0000000700080000000000001";
13
22
  const json = (body, status = 200) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
@@ -59,6 +68,16 @@ const createFakeComputersApi = (args = {}) => {
59
68
  const shelveReads = { count: 0 };
60
69
  const shelving = /* @__PURE__ */ new Map();
61
70
  const imageBuildReads = { count: 1 };
71
+ const bootReads = { count: 1 };
72
+ const booting = /* @__PURE__ */ new Map();
73
+ const boot = (computer, state) => {
74
+ if (bootReads.count <= 0) {
75
+ computer.state = STATE.Running;
76
+ return;
77
+ }
78
+ computer.state = state;
79
+ booting.set(computer.id, bootReads.count);
80
+ };
62
81
  const imageReads = /* @__PURE__ */ new Map();
63
82
  const bases = /* @__PURE__ */ new Map();
64
83
  const baseCaptureReads = { count: 1 };
@@ -134,10 +153,11 @@ const createFakeComputersApi = (args = {}) => {
134
153
  const computer2 = {
135
154
  id,
136
155
  name,
137
- state: STATE.Running,
156
+ state: STATE.Pending,
138
157
  body: jsonObjectSchema.parse(body),
139
158
  machine: args.machineFor?.({ id, name }) ?? createFakeMachine()
140
159
  };
160
+ boot(computer2, STATE.Pending);
141
161
  computers.set(id, computer2);
142
162
  if (key != null) byIdempotency.set(key, id);
143
163
  return json({ computer: wire(computer2) });
@@ -236,6 +256,13 @@ const createFakeComputersApi = (args = {}) => {
236
256
  installed: args.computerUseAvailable ?? false
237
257
  });
238
258
  if (request.method === "GET" && rest === "") {
259
+ const starting = booting.get(computer.id);
260
+ if (starting != null) {
261
+ if (starting <= 0) {
262
+ booting.delete(computer.id);
263
+ computer.state = STATE.Running;
264
+ } else booting.set(computer.id, starting - 1);
265
+ }
239
266
  const left = shelving.get(computer.id);
240
267
  if (left != null) {
241
268
  if (left <= 0) {
@@ -268,8 +295,10 @@ const createFakeComputersApi = (args = {}) => {
268
295
  actions.push({ computerId: computer.id, action: name });
269
296
  if (actionConflicts.has(name))
270
297
  return json({ error: "a lifecycle transition is committing" }, 409);
298
+ if (name !== "resume" && name !== "start") booting.delete(computer.id);
271
299
  if (name === "pause") computer.state = STATE.Paused;
272
- if (name === "resume" || name === "start") computer.state = STATE.Running;
300
+ if (name === "resume") boot(computer, STATE.Resuming);
301
+ if (name === "start") boot(computer, STATE.Pending);
273
302
  if (name === "stop") {
274
303
  computer.state = shelveReads.count > 0 ? STATE.Stopped : STATE.Shelved;
275
304
  if (shelveReads.count > 0) shelving.set(computer.id, shelveReads.count);
@@ -277,6 +306,8 @@ const createFakeComputersApi = (args = {}) => {
277
306
  if (name === "delete") computer.state = STATE.Deleted;
278
307
  return json({ computer: wire(computer) });
279
308
  }
309
+ if (computer.state !== STATE.Running && (rest === "/exec" || rest === "/run" || rest === "/files" || rest.startsWith("/processes/")))
310
+ return json({ error: NOT_RUNNING }, 409);
280
311
  if (request.method === "POST" && (rest === "/exec" || rest === "/run")) {
281
312
  const parsed = z.object({
282
313
  command: z.string(),
@@ -365,6 +396,7 @@ const createFakeComputersApi = (args = {}) => {
365
396
  actionConflicts,
366
397
  shelveReads,
367
398
  imageBuildReads,
399
+ bootReads,
368
400
  computerByName: (name) => [...computers.values()].find((computer) => computer.name === name)
369
401
  };
370
402
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sandboxes/testing/fake-backends.ts"],
4
- "sourcesContent": ["import {\n jsonObjectSchema,\n jsonValueSchema,\n type JsonObject,\n type JsonValue,\n} from '@finalai/agent-provider';\nimport { ComputerEgressPolicy } from '@finalai/computers';\nimport { posix } from 'node:path';\nimport * as z from 'zod';\nimport { concatBytes, decodeBase64, encodeBase64 } from \"../bytes.mjs\";\nimport { createFakeMachine, readFakeOutput, type FakeMachineIface } from \"./fake-machine.mjs\";\n\n// A fake public Computers API (vm-service `/v1` over fetch, API-key bearer),\n// backed by in-memory machines. The `device` provider's fakes live with the\n// Device API (device-api-service/src/testing), which it is tested against.\n\nexport interface FakeComputerIface {\n id: string;\n name: string;\n state: number;\n body: JsonObject;\n machine: FakeMachineIface;\n}\n\nexport interface FakeImageIface {\n id: string;\n source: 'platform' | 'customer';\n reference: string;\n lineage: string;\n state: 'pending' | 'building' | 'ready' | 'failed' | 'expired';\n error: string | null;\n}\n\nexport interface FakeBaseIface {\n id: string;\n computerId: string;\n state: 'capturing' | 'ready' | 'failed' | 'expired';\n error: string | null;\n retained: boolean;\n}\n\nexport interface FakeComputersApiIface {\n fetch: typeof fetch;\n computers: Map<string, FakeComputerIface>;\n images: Map<string, FakeImageIface>;\n bases: Map<string, FakeBaseIface>;\n // Base reads a fresh capture answers `capturing` before it settles.\n baseCaptureReads: { count: number };\n // Set: the next captures settle `failed` with this error instead of `ready`.\n captureFailure: { error: string | null };\n requests: { method: string; path: string; body: JsonValue; headers: Headers }[];\n actions: { computerId: string; action: string }[];\n // Actions answered 409 (a conflicting transition) without changing the computer.\n actionConflicts: Set<string>;\n // Computer reads a stopped computer answers `stopped` before it is shelved.\n shelveReads: { count: number };\n // Image reads a fresh registration answers `building` before it is ready.\n imageBuildReads: { count: number };\n computerByName(name: string): FakeComputerIface | undefined;\n}\n\nconst STATE = { Running: 3, Paused: 4, Stopped: 5, Deleted: 9, Shelved: 10 } as const;\nexport const FAKE_COMPUTERS_API_KEY = 'fk_org_api_key';\nexport const FAKE_PLATFORM_SANDBOX_IMAGE = 'cimv_0190e0000000700080000000000001';\n\nconst json = (body: JsonValue, status = 200): Response =>\n new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } });\n\n// What POST /v1/computers accepts (vm-service/src/routes/v1.ts); anything else,\n// such as the internal surface's image, lineage, projectArtifact or the\n// platform-only policies, is refused so a test fails when the provider asks for it.\nconst createComputerSchema = z.strictObject({\n name: z.string().optional(),\n regionSlug: z.string().optional(),\n imageVersionId: z.string().startsWith('cimv_').optional(),\n baseId: z.string().startsWith('part_').optional(),\n idlePolicy: z.enum(['shelve', 'pause', 'delete']).optional(),\n network: z\n .strictObject({\n egress: z.nativeEnum(ComputerEgressPolicy),\n allow: z.array(z.string()).optional(),\n })\n .optional(),\n teamId: z.string().startsWith('team_').optional(),\n vcpu: z.number().optional(),\n memoryMb: z.number().optional(),\n diskGb: z.number().optional(),\n userVolumeGb: z.number().nullable().optional(),\n env: z.record(z.string(), z.string()).optional(),\n setupScript: z.string().optional(),\n commandMode: z.number().optional(),\n customCommand: z.string().optional(),\n httpPort: z.number().optional(),\n httpPublic: z.boolean().optional(),\n ephemeral: z.boolean().optional(),\n idleTimeoutSeconds: z.number().optional(),\n autoResume: z.boolean().optional(),\n tags: z.array(z.string()).optional(),\n comment: z.string().optional(),\n});\n\nexport const createFakeComputersApi = (\n args: {\n machineFor?: (computer: { id: string; name: string }) => FakeMachineIface;\n computerUseAvailable?: boolean;\n screenAvailable?: boolean;\n } = {},\n): FakeComputersApiIface => {\n const computers = new Map<string, FakeComputerIface>();\n const images = new Map<string, FakeImageIface>([\n [\n FAKE_PLATFORM_SANDBOX_IMAGE,\n {\n id: FAKE_PLATFORM_SANDBOX_IMAGE,\n source: 'platform',\n reference: 'ghcr.io/final/sandbox:release',\n lineage: 'sandbox',\n state: 'ready',\n error: null,\n },\n ],\n ]);\n const requests: FakeComputersApiIface['requests'] = [];\n const actions: FakeComputersApiIface['actions'] = [];\n const actionConflicts = new Set<string>();\n const shelveReads = { count: 0 };\n const shelving = new Map<string, number>();\n const imageBuildReads = { count: 1 };\n const imageReads = new Map<string, number>();\n const bases = new Map<string, FakeBaseIface>();\n const baseCaptureReads = { count: 1 };\n const captureFailure: FakeComputersApiIface['captureFailure'] = { error: null };\n const captureErrors = new Map<string, string>();\n const baseReads = new Map<string, number>();\n let computerCount = 0;\n const byIdempotency = new Map<string, string>();\n\n const wire = (computer: FakeComputerIface) => ({\n id: computer.id,\n name: computer.name,\n state: computer.state,\n imageVersionId: z\n .string()\n .nullable()\n .catch(null)\n .parse(computer.body.imageVersionId ?? null),\n teamId: z\n .string()\n .nullable()\n .catch(null)\n .parse(computer.body.teamId ?? null),\n hostname: `${computer.name}-k3p9x7qd.virtual-machine.lax-2.example`,\n tags: [],\n });\n const imageWire = (image: FakeImageIface) => ({\n ...image,\n digest: `sha256:${image.id}`,\n sizes: ['standard'],\n registryCredentialId: null,\n createdAt: null,\n readyAt: null,\n lastUsedAt: null,\n });\n const baseWire = (base: FakeBaseIface) => ({\n ...base,\n image: 'ghcr.io/final/sandbox:release',\n digest: `sha256:${'b'.repeat(64)}`,\n diskGb: 20,\n createdAt: null,\n readyAt: null,\n lastUsedAt: null,\n });\n const find = (idOrName: string): FakeComputerIface | undefined =>\n computers.get(idOrName) ??\n [...computers.values()].find(\n (computer) => computer.name === idOrName && computer.state !== STATE.Deleted,\n );\n\n const handle = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const text = request.method === 'GET' ? '' : await request.text();\n const body = text === '' ? null : jsonValueSchema.parse(JSON.parse(text));\n requests.push({ method: request.method, path: url.pathname, body, headers: request.headers });\n if (!url.pathname.startsWith('/v1/')) return json({ error: 'not found' }, 404);\n if (request.headers.get('authorization') !== `Bearer ${FAKE_COMPUTERS_API_KEY}`) {\n return json({ error: 'unauthorized' }, 401);\n }\n const path = url.pathname.slice('/v1'.length);\n if (request.method === 'POST' && path === '/computers') {\n const parsed = createComputerSchema.safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n if ((parsed.data.imageVersionId == null) === (parsed.data.baseId == null)) {\n return json({ error: 'pass exactly one of imageVersionId and baseId' }, 400);\n }\n if (parsed.data.imageVersionId != null) {\n const image = images.get(parsed.data.imageVersionId);\n if (image == null) return json({ error: 'image version not found' }, 404);\n if (image.state !== 'ready') return json({ error: `image version is ${image.state}` }, 409);\n }\n if (parsed.data.baseId != null) {\n const base = bases.get(parsed.data.baseId);\n if (base == null) return json({ error: 'base not found' }, 404);\n if (base.state !== 'ready') return json({ error: `base is ${base.state}` }, 409);\n }\n const key = request.headers.get('idempotency-key');\n if (parsed.data.ephemeral === true && parsed.data.idlePolicy === 'pause')\n return json({ error: 'ephemeral VMs are always deleted when idle' }, 400);\n const existing = key == null ? undefined : computers.get(byIdempotency.get(key) ?? '');\n if (existing != null) return json({ computer: wire(existing) });\n computerCount += 1;\n const id = `comp_0190a0000000700080000000${String(computerCount).padStart(4, '0')}`;\n const name = parsed.data.name ?? `computer-${computerCount}`;\n const computer: FakeComputerIface = {\n id,\n name,\n state: STATE.Running,\n body: jsonObjectSchema.parse(body),\n machine: args.machineFor?.({ id, name }) ?? createFakeMachine(),\n };\n computers.set(id, computer);\n if (key != null) byIdempotency.set(key, id);\n return json({ computer: wire(computer) });\n }\n if (request.method === 'GET' && path === '/images') {\n const lineage = url.searchParams.get('lineage');\n const state = url.searchParams.get('state');\n const matching = [...images.values()]\n .filter((image) => lineage == null || image.lineage === lineage)\n .filter((image) => state == null || image.state === state)\n .reverse();\n return json({ images: matching.map(imageWire) });\n }\n if (request.method === 'POST' && path === '/images') {\n const parsed = z\n .strictObject({\n reference: z.string(),\n registryCredentialId: z.string().optional(),\n sizes: z.array(z.string()).optional(),\n })\n .safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n const known = [...images.values()].find(\n (image) =>\n image.reference === parsed.data.reference &&\n (image.state === 'pending' || image.state === 'building' || image.state === 'ready'),\n );\n if (known != null) return json({ image: imageWire(known) });\n const id = `cimv_0190f0000000700080000000${String(images.size + 1).padStart(4, '0')}`;\n const image: FakeImageIface = {\n id,\n source: 'customer',\n reference: parsed.data.reference,\n lineage: parsed.data.reference,\n state: 'building',\n error: null,\n };\n images.set(id, image);\n return json({ image: imageWire(image) }, 201);\n }\n const imageMatch = /^\\/images\\/([^/]+)$/.exec(path);\n if (request.method === 'GET' && imageMatch != null) {\n const image = images.get(decodeURIComponent(imageMatch[1] ?? ''));\n if (image == null) return json({ error: 'image not found' }, 404);\n const reads = (imageReads.get(image.id) ?? 0) + 1;\n imageReads.set(image.id, reads);\n if (image.state === 'building' && reads > imageBuildReads.count) image.state = 'ready';\n return json({ image: imageWire(image) });\n }\n if (request.method === 'POST' && path === '/tokens') {\n const parsed = z\n .strictObject({\n name: z.string(),\n computerId: z.string().startsWith('comp_').optional(),\n scopes: z.array(z.string()).optional(),\n expiresAt: z.string().optional(),\n })\n .safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n return json({ id: 'ctok_1', token: 'fvm1.http-token' });\n }\n const baseMatch = /^\\/bases\\/([^/]+)$/.exec(path);\n if (request.method === 'PATCH' && baseMatch != null) {\n const base = bases.get(decodeURIComponent(baseMatch[1] ?? ''));\n if (base == null) return json({ error: 'base not found' }, 404);\n const retained = z.object({ retained: z.boolean() }).parse(body);\n base.retained = retained.retained;\n return json({ base: baseWire(base) });\n }\n if (request.method === 'GET' && baseMatch != null) {\n const base = bases.get(decodeURIComponent(baseMatch[1] ?? ''));\n if (base == null) return json({ error: 'base not found' }, 404);\n const reads = (baseReads.get(base.id) ?? 0) + 1;\n baseReads.set(base.id, reads);\n if (base.state === 'capturing' && reads > baseCaptureReads.count) {\n const error = captureErrors.get(base.id) ?? null;\n base.state = error == null ? 'ready' : 'failed';\n base.error = error;\n }\n return json({ base: baseWire(base) });\n }\n const computerMatch = /^\\/computers\\/([^/]+)(\\/.*)?$/.exec(path);\n if (computerMatch == null) return json({ error: `no route ${path}` }, 404);\n const computer = find(decodeURIComponent(computerMatch[1] ?? ''));\n if (computer == null || computer.state === STATE.Deleted)\n return json({ error: 'computer not found' }, 404);\n const rest = computerMatch[2] ?? '';\n const machine = computer.machine;\n if (request.method === 'GET' && rest === '/screen')\n return json({ available: args.screenAvailable ?? false });\n if (request.method === 'POST' && rest === '/screen')\n return json({\n url: `https://computer-api.example/v1/computers/${computer.id}/screen/view#screen-token`,\n token: 'screen-token',\n expiresAt: new Date(Date.now() + 900_000).toISOString(),\n });\n if (request.method === 'PATCH' && rest === '') {\n const patch = createComputerSchema.pick({ network: true }).parse(body);\n if (patch.network != null) computer.body.network = patch.network;\n return json({ computer: wire(computer) });\n }\n if (request.method === 'GET' && rest === '/computer-use')\n return json({\n available: args.computerUseAvailable ?? false,\n installed: args.computerUseAvailable ?? false,\n });\n if (request.method === 'GET' && rest === '') {\n const left = shelving.get(computer.id);\n if (left != null) {\n if (left <= 0) {\n shelving.delete(computer.id);\n computer.state = STATE.Shelved;\n } else shelving.set(computer.id, left - 1);\n }\n return json({ computer: wire(computer) });\n }\n if (request.method === 'POST' && rest === '/capture') {\n if (computer.state !== STATE.Running) return json({ error: 'not running' }, 409);\n if (computer.body.userVolumeGb !== null) return json({ error: 'has a user volume' }, 409);\n const id = `part_0190b0000000700080000000${String(bases.size + 1).padStart(4, '0')}`;\n const capture = z.object({ retained: z.boolean().default(false) }).parse(body ?? {});\n const base: FakeBaseIface = {\n id,\n computerId: computer.id,\n state: 'capturing',\n error: null,\n retained: capture.retained,\n };\n bases.set(id, base);\n if (captureFailure.error != null) captureErrors.set(id, captureFailure.error);\n computer.state = STATE.Stopped;\n return json({ base: baseWire(base) }, 202);\n }\n const action = /^\\/actions\\/(.+)$/.exec(rest);\n if (request.method === 'POST' && action != null) {\n const name = action[1] ?? '';\n actions.push({ computerId: computer.id, action: name });\n if (actionConflicts.has(name))\n return json({ error: 'a lifecycle transition is committing' }, 409);\n if (name === 'pause') computer.state = STATE.Paused;\n if (name === 'resume' || name === 'start') computer.state = STATE.Running;\n // A computer that is not ephemeral shelves on stop (vm-service vm-ops).\n if (name === 'stop') {\n computer.state = shelveReads.count > 0 ? STATE.Stopped : STATE.Shelved;\n if (shelveReads.count > 0) shelving.set(computer.id, shelveReads.count);\n }\n if (name === 'delete') computer.state = STATE.Deleted;\n return json({ computer: wire(computer) });\n }\n if (request.method === 'POST' && (rest === '/exec' || rest === '/run')) {\n const parsed = z\n .object({\n command: z.string(),\n cwd: z.string().optional(),\n env: z.record(z.string(), z.string()).optional(),\n })\n .parse(body);\n const process = machine.exec({\n id: `proc-${machine.execs.length + 1}`,\n command: parsed.command,\n cwd: parsed.cwd ?? '/',\n env: parsed.env ?? {},\n });\n if (rest === '/exec')\n return json({ id: process.id, bootId: process.bootId, pid: 1, state: 'running' });\n const output = await readFakeOutput(process, { stdout: 0, stderr: 0, waitMs: 50 });\n return json({\n id: process.id,\n bootId: process.bootId,\n pid: 1,\n timedOut: false,\n elapsedMs: 1,\n ...outputBody(output, process, 0, 0),\n });\n }\n const processMatch = /^\\/processes\\/([^/]+)\\/(output|input|terminate)$/.exec(rest);\n if (processMatch != null) {\n const process = machine.processes.get(processMatch[1] ?? '');\n if (process == null) return json({ error: 'process not found' }, 404);\n if (processMatch[2] === 'output') {\n const stdoutOffset = Number(url.searchParams.get('stdoutOffset') ?? 0);\n const stderrOffset = Number(url.searchParams.get('stderrOffset') ?? 0);\n const output = await readFakeOutput(process, {\n stdout: stdoutOffset,\n stderr: stderrOffset,\n waitMs: Number(url.searchParams.get('waitMs') ?? 0),\n });\n return json(outputBody(output, process, stdoutOffset, stderrOffset));\n }\n if (processMatch[2] === 'terminate') {\n process.terminate();\n return json({ ok: true });\n }\n const input = z\n .object({\n dataB64: z.string().optional(),\n eof: z.boolean().optional(),\n signal: z.string().optional(),\n })\n .parse(body);\n if (input.dataB64 != null) process.write(decodeBase64(input.dataB64));\n if (input.eof === true) process.eof();\n if (input.signal != null) process.terminate(input.signal);\n return json({ ok: true });\n }\n if (rest === '/files' && request.method === 'GET') {\n const path = url.searchParams.get('path') ?? '';\n // Reads follow symlinks.\n const content = machine.files.get(machine.links.get(path) ?? path);\n if (content == null) return json({ error: `${path}: No such file or directory` }, 502);\n const offset = Number(url.searchParams.get('offset') ?? 0);\n const length = Number(url.searchParams.get('length') ?? content.byteLength);\n const slice = content.subarray(offset, offset + length);\n return json({\n dataB64: encodeBase64(slice),\n eof: offset + slice.byteLength >= content.byteLength,\n offset,\n });\n }\n if (rest === '/files' && request.method === 'PUT') {\n const parsed = z\n .object({ path: z.string(), dataB64: z.string(), append: z.boolean().optional() })\n .parse(body);\n if (!machine.dirs.has(posix.dirname(parsed.path)))\n return json({ error: 'No such file or directory' }, 502);\n const data = decodeBase64(parsed.dataB64);\n const previous =\n parsed.append === true\n ? (machine.files.get(parsed.path) ?? new Uint8Array())\n : new Uint8Array();\n machine.files.set(parsed.path, concatBytes([previous, data]));\n return json({ bytesWritten: data.byteLength });\n }\n return json({ error: `no route ${request.method} ${path}` }, 404);\n };\n\n return {\n fetch: async (input, init) => handle(new Request(input, init)),\n computers,\n images,\n bases,\n baseCaptureReads,\n captureFailure,\n requests,\n actions,\n actionConflicts,\n shelveReads,\n imageBuildReads,\n computerByName: (name) => [...computers.values()].find((computer) => computer.name === name),\n };\n};\n\nconst outputBody = (\n output: { stdout: Uint8Array; stderr: Uint8Array; exited: boolean },\n process: {\n exitCode: number | null;\n signal: string | null;\n stdout: Uint8Array;\n stderr: Uint8Array;\n },\n stdoutOffset: number,\n stderrOffset: number,\n) => ({\n stdout: {\n dataB64: encodeBase64(output.stdout),\n offset: stdoutOffset,\n nextOffset: stdoutOffset + output.stdout.byteLength,\n eof: output.exited && stdoutOffset + output.stdout.byteLength >= process.stdout.byteLength,\n },\n stderr: {\n dataB64: encodeBase64(output.stderr),\n offset: stderrOffset,\n nextOffset: stderrOffset + output.stderr.byteLength,\n eof: output.exited && stderrOffset + output.stderr.byteLength >= process.stderr.byteLength,\n },\n state: output.exited ? 'exited' : 'running',\n result: output.exited ? { exitCode: process.exitCode, signal: process.signal } : null,\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n jsonObjectSchema,\n jsonValueSchema,\n type JsonObject,\n type JsonValue,\n} from '@finalai/agent-provider';\nimport { ComputerEgressPolicy } from '@finalai/computers';\nimport { posix } from 'node:path';\nimport * as z from 'zod';\nimport { concatBytes, decodeBase64, encodeBase64 } from \"../bytes.mjs\";\nimport { createFakeMachine, readFakeOutput, type FakeMachineIface } from \"./fake-machine.mjs\";\n\n// A fake public Computers API (vm-service `/v1` over fetch, API-key bearer),\n// backed by in-memory machines. The `device` provider's fakes live with the\n// Device API (device-api-service/src/testing), which it is tested against.\n\nexport interface FakeComputerIface {\n id: string;\n name: string;\n state: number;\n body: JsonObject;\n machine: FakeMachineIface;\n}\n\nexport interface FakeImageIface {\n id: string;\n source: 'platform' | 'customer';\n reference: string;\n lineage: string;\n state: 'pending' | 'building' | 'ready' | 'failed' | 'expired';\n error: string | null;\n}\n\nexport interface FakeBaseIface {\n id: string;\n computerId: string;\n state: 'capturing' | 'ready' | 'failed' | 'expired';\n error: string | null;\n retained: boolean;\n}\n\nexport interface FakeComputersApiIface {\n fetch: typeof fetch;\n computers: Map<string, FakeComputerIface>;\n images: Map<string, FakeImageIface>;\n bases: Map<string, FakeBaseIface>;\n // Base reads a fresh capture answers `capturing` before it settles.\n baseCaptureReads: { count: number };\n // Set: the next captures settle `failed` with this error instead of `ready`.\n captureFailure: { error: string | null };\n requests: { method: string; path: string; body: JsonValue; headers: Headers }[];\n actions: { computerId: string; action: string }[];\n // Actions answered 409 (a conflicting transition) without changing the computer.\n actionConflicts: Set<string>;\n // Computer reads a stopped computer answers `stopped` before it is shelved.\n shelveReads: { count: number };\n // Image reads a fresh registration answers `building` before it is ready.\n imageBuildReads: { count: number };\n // Computer reads a created or started computer answers `pending` (a resumed\n // one `resuming`) before it runs; until then commands and files answer 409.\n bootReads: { count: number };\n computerByName(name: string): FakeComputerIface | undefined;\n}\n\nconst STATE = {\n Pending: 1,\n Running: 3,\n Paused: 4,\n Stopped: 5,\n Resuming: 6,\n Deleted: 9,\n Shelved: 10,\n} as const;\nconst NOT_RUNNING = 'Computer is not running; resume it explicitly before this operation';\nexport const FAKE_COMPUTERS_API_KEY = 'fk_org_api_key';\nexport const FAKE_PLATFORM_SANDBOX_IMAGE = 'cimv_0190e0000000700080000000000001';\n\nconst json = (body: JsonValue, status = 200): Response =>\n new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } });\n\n// What POST /v1/computers accepts (vm-service/src/routes/v1.ts); anything else,\n// such as the internal surface's image, lineage, projectArtifact or the\n// platform-only policies, is refused so a test fails when the provider asks for it.\nconst createComputerSchema = z.strictObject({\n name: z.string().optional(),\n regionSlug: z.string().optional(),\n imageVersionId: z.string().startsWith('cimv_').optional(),\n baseId: z.string().startsWith('part_').optional(),\n idlePolicy: z.enum(['shelve', 'pause', 'delete']).optional(),\n network: z\n .strictObject({\n egress: z.nativeEnum(ComputerEgressPolicy),\n allow: z.array(z.string()).optional(),\n })\n .optional(),\n teamId: z.string().startsWith('team_').optional(),\n vcpu: z.number().optional(),\n memoryMb: z.number().optional(),\n diskGb: z.number().optional(),\n userVolumeGb: z.number().nullable().optional(),\n env: z.record(z.string(), z.string()).optional(),\n setupScript: z.string().optional(),\n commandMode: z.number().optional(),\n customCommand: z.string().optional(),\n httpPort: z.number().optional(),\n httpPublic: z.boolean().optional(),\n ephemeral: z.boolean().optional(),\n idleTimeoutSeconds: z.number().optional(),\n autoResume: z.boolean().optional(),\n tags: z.array(z.string()).optional(),\n comment: z.string().optional(),\n});\n\nexport const createFakeComputersApi = (\n args: {\n machineFor?: (computer: { id: string; name: string }) => FakeMachineIface;\n computerUseAvailable?: boolean;\n screenAvailable?: boolean;\n } = {},\n): FakeComputersApiIface => {\n const computers = new Map<string, FakeComputerIface>();\n const images = new Map<string, FakeImageIface>([\n [\n FAKE_PLATFORM_SANDBOX_IMAGE,\n {\n id: FAKE_PLATFORM_SANDBOX_IMAGE,\n source: 'platform',\n reference: 'ghcr.io/final/sandbox:release',\n lineage: 'sandbox',\n state: 'ready',\n error: null,\n },\n ],\n ]);\n const requests: FakeComputersApiIface['requests'] = [];\n const actions: FakeComputersApiIface['actions'] = [];\n const actionConflicts = new Set<string>();\n const shelveReads = { count: 0 };\n const shelving = new Map<string, number>();\n const imageBuildReads = { count: 1 };\n const bootReads = { count: 1 };\n const booting = new Map<string, number>();\n const boot = (computer: FakeComputerIface, state: number) => {\n if (bootReads.count <= 0) {\n computer.state = STATE.Running;\n return;\n }\n computer.state = state;\n booting.set(computer.id, bootReads.count);\n };\n const imageReads = new Map<string, number>();\n const bases = new Map<string, FakeBaseIface>();\n const baseCaptureReads = { count: 1 };\n const captureFailure: FakeComputersApiIface['captureFailure'] = { error: null };\n const captureErrors = new Map<string, string>();\n const baseReads = new Map<string, number>();\n let computerCount = 0;\n const byIdempotency = new Map<string, string>();\n\n const wire = (computer: FakeComputerIface) => ({\n id: computer.id,\n name: computer.name,\n state: computer.state,\n imageVersionId: z\n .string()\n .nullable()\n .catch(null)\n .parse(computer.body.imageVersionId ?? null),\n teamId: z\n .string()\n .nullable()\n .catch(null)\n .parse(computer.body.teamId ?? null),\n hostname: `${computer.name}-k3p9x7qd.virtual-machine.lax-2.example`,\n tags: [],\n });\n const imageWire = (image: FakeImageIface) => ({\n ...image,\n digest: `sha256:${image.id}`,\n sizes: ['standard'],\n registryCredentialId: null,\n createdAt: null,\n readyAt: null,\n lastUsedAt: null,\n });\n const baseWire = (base: FakeBaseIface) => ({\n ...base,\n image: 'ghcr.io/final/sandbox:release',\n digest: `sha256:${'b'.repeat(64)}`,\n diskGb: 20,\n createdAt: null,\n readyAt: null,\n lastUsedAt: null,\n });\n const find = (idOrName: string): FakeComputerIface | undefined =>\n computers.get(idOrName) ??\n [...computers.values()].find(\n (computer) => computer.name === idOrName && computer.state !== STATE.Deleted,\n );\n\n const handle = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const text = request.method === 'GET' ? '' : await request.text();\n const body = text === '' ? null : jsonValueSchema.parse(JSON.parse(text));\n requests.push({ method: request.method, path: url.pathname, body, headers: request.headers });\n if (!url.pathname.startsWith('/v1/')) return json({ error: 'not found' }, 404);\n if (request.headers.get('authorization') !== `Bearer ${FAKE_COMPUTERS_API_KEY}`) {\n return json({ error: 'unauthorized' }, 401);\n }\n const path = url.pathname.slice('/v1'.length);\n if (request.method === 'POST' && path === '/computers') {\n const parsed = createComputerSchema.safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n if ((parsed.data.imageVersionId == null) === (parsed.data.baseId == null)) {\n return json({ error: 'pass exactly one of imageVersionId and baseId' }, 400);\n }\n if (parsed.data.imageVersionId != null) {\n const image = images.get(parsed.data.imageVersionId);\n if (image == null) return json({ error: 'image version not found' }, 404);\n if (image.state !== 'ready') return json({ error: `image version is ${image.state}` }, 409);\n }\n if (parsed.data.baseId != null) {\n const base = bases.get(parsed.data.baseId);\n if (base == null) return json({ error: 'base not found' }, 404);\n if (base.state !== 'ready') return json({ error: `base is ${base.state}` }, 409);\n }\n const key = request.headers.get('idempotency-key');\n if (parsed.data.ephemeral === true && parsed.data.idlePolicy === 'pause')\n return json({ error: 'ephemeral VMs are always deleted when idle' }, 400);\n const existing = key == null ? undefined : computers.get(byIdempotency.get(key) ?? '');\n if (existing != null) return json({ computer: wire(existing) });\n computerCount += 1;\n const id = `comp_0190a0000000700080000000${String(computerCount).padStart(4, '0')}`;\n const name = parsed.data.name ?? `computer-${computerCount}`;\n const computer: FakeComputerIface = {\n id,\n name,\n state: STATE.Pending,\n body: jsonObjectSchema.parse(body),\n machine: args.machineFor?.({ id, name }) ?? createFakeMachine(),\n };\n boot(computer, STATE.Pending);\n computers.set(id, computer);\n if (key != null) byIdempotency.set(key, id);\n return json({ computer: wire(computer) });\n }\n if (request.method === 'GET' && path === '/images') {\n const lineage = url.searchParams.get('lineage');\n const state = url.searchParams.get('state');\n const matching = [...images.values()]\n .filter((image) => lineage == null || image.lineage === lineage)\n .filter((image) => state == null || image.state === state)\n .reverse();\n return json({ images: matching.map(imageWire) });\n }\n if (request.method === 'POST' && path === '/images') {\n const parsed = z\n .strictObject({\n reference: z.string(),\n registryCredentialId: z.string().optional(),\n sizes: z.array(z.string()).optional(),\n })\n .safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n const known = [...images.values()].find(\n (image) =>\n image.reference === parsed.data.reference &&\n (image.state === 'pending' || image.state === 'building' || image.state === 'ready'),\n );\n if (known != null) return json({ image: imageWire(known) });\n const id = `cimv_0190f0000000700080000000${String(images.size + 1).padStart(4, '0')}`;\n const image: FakeImageIface = {\n id,\n source: 'customer',\n reference: parsed.data.reference,\n lineage: parsed.data.reference,\n state: 'building',\n error: null,\n };\n images.set(id, image);\n return json({ image: imageWire(image) }, 201);\n }\n const imageMatch = /^\\/images\\/([^/]+)$/.exec(path);\n if (request.method === 'GET' && imageMatch != null) {\n const image = images.get(decodeURIComponent(imageMatch[1] ?? ''));\n if (image == null) return json({ error: 'image not found' }, 404);\n const reads = (imageReads.get(image.id) ?? 0) + 1;\n imageReads.set(image.id, reads);\n if (image.state === 'building' && reads > imageBuildReads.count) image.state = 'ready';\n return json({ image: imageWire(image) });\n }\n if (request.method === 'POST' && path === '/tokens') {\n const parsed = z\n .strictObject({\n name: z.string(),\n computerId: z.string().startsWith('comp_').optional(),\n scopes: z.array(z.string()).optional(),\n expiresAt: z.string().optional(),\n })\n .safeParse(body);\n if (!parsed.success) return json({ error: 'invalid body' }, 400);\n return json({ id: 'ctok_1', token: 'fvm1.http-token' });\n }\n const baseMatch = /^\\/bases\\/([^/]+)$/.exec(path);\n if (request.method === 'PATCH' && baseMatch != null) {\n const base = bases.get(decodeURIComponent(baseMatch[1] ?? ''));\n if (base == null) return json({ error: 'base not found' }, 404);\n const retained = z.object({ retained: z.boolean() }).parse(body);\n base.retained = retained.retained;\n return json({ base: baseWire(base) });\n }\n if (request.method === 'GET' && baseMatch != null) {\n const base = bases.get(decodeURIComponent(baseMatch[1] ?? ''));\n if (base == null) return json({ error: 'base not found' }, 404);\n const reads = (baseReads.get(base.id) ?? 0) + 1;\n baseReads.set(base.id, reads);\n if (base.state === 'capturing' && reads > baseCaptureReads.count) {\n const error = captureErrors.get(base.id) ?? null;\n base.state = error == null ? 'ready' : 'failed';\n base.error = error;\n }\n return json({ base: baseWire(base) });\n }\n const computerMatch = /^\\/computers\\/([^/]+)(\\/.*)?$/.exec(path);\n if (computerMatch == null) return json({ error: `no route ${path}` }, 404);\n const computer = find(decodeURIComponent(computerMatch[1] ?? ''));\n if (computer == null || computer.state === STATE.Deleted)\n return json({ error: 'computer not found' }, 404);\n const rest = computerMatch[2] ?? '';\n const machine = computer.machine;\n if (request.method === 'GET' && rest === '/screen')\n return json({ available: args.screenAvailable ?? false });\n if (request.method === 'POST' && rest === '/screen')\n return json({\n url: `https://computer-api.example/v1/computers/${computer.id}/screen/view#screen-token`,\n token: 'screen-token',\n expiresAt: new Date(Date.now() + 900_000).toISOString(),\n });\n if (request.method === 'PATCH' && rest === '') {\n const patch = createComputerSchema.pick({ network: true }).parse(body);\n if (patch.network != null) computer.body.network = patch.network;\n return json({ computer: wire(computer) });\n }\n if (request.method === 'GET' && rest === '/computer-use')\n return json({\n available: args.computerUseAvailable ?? false,\n installed: args.computerUseAvailable ?? false,\n });\n if (request.method === 'GET' && rest === '') {\n const starting = booting.get(computer.id);\n if (starting != null) {\n if (starting <= 0) {\n booting.delete(computer.id);\n computer.state = STATE.Running;\n } else booting.set(computer.id, starting - 1);\n }\n const left = shelving.get(computer.id);\n if (left != null) {\n if (left <= 0) {\n shelving.delete(computer.id);\n computer.state = STATE.Shelved;\n } else shelving.set(computer.id, left - 1);\n }\n return json({ computer: wire(computer) });\n }\n if (request.method === 'POST' && rest === '/capture') {\n if (computer.state !== STATE.Running) return json({ error: 'not running' }, 409);\n if (computer.body.userVolumeGb !== null) return json({ error: 'has a user volume' }, 409);\n const id = `part_0190b0000000700080000000${String(bases.size + 1).padStart(4, '0')}`;\n const capture = z.object({ retained: z.boolean().default(false) }).parse(body ?? {});\n const base: FakeBaseIface = {\n id,\n computerId: computer.id,\n state: 'capturing',\n error: null,\n retained: capture.retained,\n };\n bases.set(id, base);\n if (captureFailure.error != null) captureErrors.set(id, captureFailure.error);\n computer.state = STATE.Stopped;\n return json({ base: baseWire(base) }, 202);\n }\n const action = /^\\/actions\\/(.+)$/.exec(rest);\n if (request.method === 'POST' && action != null) {\n const name = action[1] ?? '';\n actions.push({ computerId: computer.id, action: name });\n if (actionConflicts.has(name))\n return json({ error: 'a lifecycle transition is committing' }, 409);\n if (name !== 'resume' && name !== 'start') booting.delete(computer.id);\n if (name === 'pause') computer.state = STATE.Paused;\n if (name === 'resume') boot(computer, STATE.Resuming);\n if (name === 'start') boot(computer, STATE.Pending);\n // A computer that is not ephemeral shelves on stop (vm-service vm-ops).\n if (name === 'stop') {\n computer.state = shelveReads.count > 0 ? STATE.Stopped : STATE.Shelved;\n if (shelveReads.count > 0) shelving.set(computer.id, shelveReads.count);\n }\n if (name === 'delete') computer.state = STATE.Deleted;\n return json({ computer: wire(computer) });\n }\n if (\n computer.state !== STATE.Running &&\n (rest === '/exec' || rest === '/run' || rest === '/files' || rest.startsWith('/processes/'))\n )\n return json({ error: NOT_RUNNING }, 409);\n if (request.method === 'POST' && (rest === '/exec' || rest === '/run')) {\n const parsed = z\n .object({\n command: z.string(),\n cwd: z.string().optional(),\n env: z.record(z.string(), z.string()).optional(),\n })\n .parse(body);\n const process = machine.exec({\n id: `proc-${machine.execs.length + 1}`,\n command: parsed.command,\n cwd: parsed.cwd ?? '/',\n env: parsed.env ?? {},\n });\n if (rest === '/exec')\n return json({ id: process.id, bootId: process.bootId, pid: 1, state: 'running' });\n const output = await readFakeOutput(process, { stdout: 0, stderr: 0, waitMs: 50 });\n return json({\n id: process.id,\n bootId: process.bootId,\n pid: 1,\n timedOut: false,\n elapsedMs: 1,\n ...outputBody(output, process, 0, 0),\n });\n }\n const processMatch = /^\\/processes\\/([^/]+)\\/(output|input|terminate)$/.exec(rest);\n if (processMatch != null) {\n const process = machine.processes.get(processMatch[1] ?? '');\n if (process == null) return json({ error: 'process not found' }, 404);\n if (processMatch[2] === 'output') {\n const stdoutOffset = Number(url.searchParams.get('stdoutOffset') ?? 0);\n const stderrOffset = Number(url.searchParams.get('stderrOffset') ?? 0);\n const output = await readFakeOutput(process, {\n stdout: stdoutOffset,\n stderr: stderrOffset,\n waitMs: Number(url.searchParams.get('waitMs') ?? 0),\n });\n return json(outputBody(output, process, stdoutOffset, stderrOffset));\n }\n if (processMatch[2] === 'terminate') {\n process.terminate();\n return json({ ok: true });\n }\n const input = z\n .object({\n dataB64: z.string().optional(),\n eof: z.boolean().optional(),\n signal: z.string().optional(),\n })\n .parse(body);\n if (input.dataB64 != null) process.write(decodeBase64(input.dataB64));\n if (input.eof === true) process.eof();\n if (input.signal != null) process.terminate(input.signal);\n return json({ ok: true });\n }\n if (rest === '/files' && request.method === 'GET') {\n const path = url.searchParams.get('path') ?? '';\n // Reads follow symlinks.\n const content = machine.files.get(machine.links.get(path) ?? path);\n if (content == null) return json({ error: `${path}: No such file or directory` }, 502);\n const offset = Number(url.searchParams.get('offset') ?? 0);\n const length = Number(url.searchParams.get('length') ?? content.byteLength);\n const slice = content.subarray(offset, offset + length);\n return json({\n dataB64: encodeBase64(slice),\n eof: offset + slice.byteLength >= content.byteLength,\n offset,\n });\n }\n if (rest === '/files' && request.method === 'PUT') {\n const parsed = z\n .object({ path: z.string(), dataB64: z.string(), append: z.boolean().optional() })\n .parse(body);\n if (!machine.dirs.has(posix.dirname(parsed.path)))\n return json({ error: 'No such file or directory' }, 502);\n const data = decodeBase64(parsed.dataB64);\n const previous =\n parsed.append === true\n ? (machine.files.get(parsed.path) ?? new Uint8Array())\n : new Uint8Array();\n machine.files.set(parsed.path, concatBytes([previous, data]));\n return json({ bytesWritten: data.byteLength });\n }\n return json({ error: `no route ${request.method} ${path}` }, 404);\n };\n\n return {\n fetch: async (input, init) => handle(new Request(input, init)),\n computers,\n images,\n bases,\n baseCaptureReads,\n captureFailure,\n requests,\n actions,\n actionConflicts,\n shelveReads,\n imageBuildReads,\n bootReads,\n computerByName: (name) => [...computers.values()].find((computer) => computer.name === name),\n };\n};\n\nconst outputBody = (\n output: { stdout: Uint8Array; stderr: Uint8Array; exited: boolean },\n process: {\n exitCode: number | null;\n signal: string | null;\n stdout: Uint8Array;\n stderr: Uint8Array;\n },\n stdoutOffset: number,\n stderrOffset: number,\n) => ({\n stdout: {\n dataB64: encodeBase64(output.stdout),\n offset: stdoutOffset,\n nextOffset: stdoutOffset + output.stdout.byteLength,\n eof: output.exited && stdoutOffset + output.stdout.byteLength >= process.stdout.byteLength,\n },\n stderr: {\n dataB64: encodeBase64(output.stderr),\n offset: stderrOffset,\n nextOffset: stderrOffset + output.stderr.byteLength,\n eof: output.exited && stderrOffset + output.stderr.byteLength >= process.stderr.byteLength,\n },\n state: output.exited ? 'exited' : 'running',\n result: output.exited ? { exitCode: process.exitCode, signal: process.signal } : null,\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["computer", "image", "path"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finalai/final-agent-provider",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "private": false,
5
5
  "description": "Final's provider package: serverless, remote and local harnesses; the computer and device sandboxes; the messaging, schedule and event channels.",
6
6
  "license": "Apache-2.0",
@@ -210,12 +210,12 @@
210
210
  "@agentclientprotocol/sdk": "1.8.0",
211
211
  "@finalai/acp-session": "0.1.4",
212
212
  "@finalai/agent-protocol": "0.1.4",
213
- "@finalai/agent-provider": "0.1.6",
213
+ "@finalai/agent-provider": "0.1.7",
214
214
  "@finalai/computers": "0.1.4",
215
215
  "@finalai/websockets": "0.1.4",
216
216
  "ws": "^8.21.3",
217
217
  "zod": "4.6.5",
218
- "@finalai/agent-definition": "0.1.5"
218
+ "@finalai/agent-definition": "0.1.6"
219
219
  },
220
220
  "engines": {
221
221
  "node": ">=26"