@finalai/final-agent-provider 0.3.4 → 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/sandboxes/egress.ts"],
4
+ "sourcesContent": ["import * as z from 'zod';\nimport {\n WorkspaceEgressAction,\n workspaceEgressRequestSchema,\n deviceEgressWorkspaceIdSchema,\n workspaceEgressStatusSchema,\n type WorkspaceEgressRequestIface,\n type WorkspaceEgressStatusIface,\n type DeviceEgressLeaseIface,\n WorkspaceNetworkPolicy,\n workspaceNetworkPolicySchema,\n} from '@finalai/agent-protocol/device-egress';\nimport { SandboxAccess, type JsonValue } from '@finalai/agent-provider';\nimport {\n SandboxCapability,\n SandboxExecutionOperation,\n withSandboxNetworking,\n withSandboxOverrides,\n type SandboxNetworkingControllerIface,\n type SandboxNetworkingExtensionIface,\n} from '@finalai/agent-provider/sandbox';\nimport type {\n NetworkSandboxSessionIface,\n SandboxActingUserIface,\n SandboxRunResultIface,\n SandboxProviderHandleIface,\n NetworkPolicyIface,\n} from '@finalai/agent-provider/sandbox';\nimport {\n createDeviceApiClient,\n type DeviceApiClientIface,\n type DeviceApiConfigIface,\n deviceApiStatusOf,\n deviceApiCodeOf,\n DeviceApiClientErrorCode,\n} from \"./device-api.mjs\";\nimport {\n workspaceEgressBootstrap,\n cachedWorkspaceEgressBootstrap,\n workspaceEgressLauncher,\n} from \"./egress-bootstrap.mjs\";\nimport { sleep } from \"./bytes.mjs\";\n\nconst localStatusSchema = workspaceEgressStatusSchema.extend({\n architecture: z.string().optional(),\n networkPristine: z.boolean().optional(),\n policyRouting: z.boolean().optional(),\n helperReady: z.boolean().optional(),\n busy: z.boolean().optional(),\n configuring: z.boolean().optional(),\n controllerAlive: z.boolean().optional(),\n restorePending: z.boolean().optional(),\n choicePending: z.boolean().optional(),\n ownerUserId: z.string().nullable().optional(),\n workspaceId: z.string().nullable().optional(),\n});\n\ninterface ConfigurationOutcomeIface {\n result: z.infer<typeof localStatusSchema> | null;\n failures: unknown[];\n}\n\nconst validateApprovedDevices = (lease: DeviceEgressLeaseIface, approved: readonly string[]) => {\n if (\n lease.devices.length !== approved.length ||\n lease.devices.some(\n (device, index) => device.deviceId.toLowerCase() !== approved[index]?.toLowerCase(),\n )\n )\n throw Object.assign(\n new Error('Egress lease Devices do not match the approved ordered Device list'),\n { invalidEgressLease: true, code: 'configuration' },\n );\n};\n\nconst validateActiveLease = (lease: DeviceEgressLeaseIface, at: number) => {\n if (lease.state !== 'active' || !Number.isFinite(lease.expiresAtMs) || lease.expiresAtMs <= at)\n throw Object.assign(new Error('Egress lease is not active or has expired'), {\n invalidEgressLease: true,\n code: 'configuration',\n });\n};\n\nconst isPermanentAuthorizationFailure = (error: Error): boolean => {\n const pending = [error];\n const visited = new Set<Error>();\n while (pending.length > 0 && visited.size < 32) {\n const current = pending.pop();\n if (current == null || visited.has(current)) continue;\n visited.add(current);\n const status = deviceApiStatusOf(current);\n if (status != null && [401, 403, 404, 410].includes(status)) return true;\n if (current.cause instanceof Error) pending.push(current.cause);\n if (current instanceof AggregateError)\n for (const nested of current.errors) if (nested instanceof Error) pending.push(nested);\n }\n return false;\n};\n\nexport interface WorkspaceEgressManagerOptionsIface {\n // Raw, unguarded session; passing withWorkspaceEgress() here recursively deadlocks.\n sandbox: NetworkSandboxSessionIface;\n workspaceId: string;\n organizationId: string;\n actingUser: SandboxActingUserIface;\n api: DeviceApiConfigIface | (() => DeviceApiConfigIface);\n // Must execute in this workspace's isolated network namespace, as root with NET_ADMIN.\n // Run python3 -I -c source source (or a file with __file__); pass JSON on stdin.\n privilegedRun?: (request: { source: string; input: string }) => Promise<SandboxRunResultIface>;\n client?: Pick<DeviceApiClientIface, 'egress'>;\n fetch?: typeof fetch;\n // Restore the provider's outer network policy only after the namespace guard is installed.\n afterGuard?: (policy?: NetworkPolicyIface) => Promise<void>;\n // Optional outer-provider fence after namespace denial; unsupported providers may retain namespace-only denial.\n afterBlock?: () => Promise<void>;\n // Provider-confirmed deletion permits authorization cleanup without entering a missing namespace.\n namespaceExists?: () => Promise<boolean>;\n initialNetworkPolicy?: NetworkPolicyIface;\n onNetworkPolicy?: (policy: NetworkPolicyIface) => Promise<void>;\n allowConfiguration?: boolean;\n allowOwnerChange?: boolean;\n authorizeOwnerChange?: (actingUserId: string | null) => Promise<void>;\n onClose?: () => void;\n now?: () => number;\n onFailure?: (event: {\n operation: string;\n workspaceId: string;\n leaseId: string | null;\n reason: string;\n httpStatus: number | null;\n }) => void;\n}\n\nexport const suspendWorkspaceEgress = async (args: {\n api: DeviceApiConfigIface | (() => DeviceApiConfigIface);\n organizationId: string;\n workspaceId: string;\n actingUser: SandboxActingUserIface;\n}): Promise<void> => {\n await createDeviceApiClient({ api: args.api }).egress.suspend({\n caller: { organizationId: args.organizationId, actingUser: args.actingUser },\n workspaceId: args.workspaceId,\n });\n};\n\n// Host-owned lease renewal; callers tie close() to their provider handle's lifecycle.\nexport const createWorkspaceEgressManager = (options: WorkspaceEgressManagerOptionsIface) => {\n if (!deviceEgressWorkspaceIdSchema.safeParse(options.workspaceId).success)\n throw new Error(\n 'Device egress requires a stable workspaceId of 1\u2013256 characters without control characters',\n );\n const client = options.client ?? createDeviceApiClient({ api: options.api });\n const revokeLease = async (args: Parameters<typeof client.egress.revoke>[0]) => {\n try {\n await client.egress.revoke(args);\n } catch (cause) {\n const status = cause instanceof Error ? deviceApiStatusOf(cause) : null;\n if (status !== 404 && status !== 410) throw cause;\n }\n };\n const now = options.now ?? Date.now;\n const run =\n options.privilegedRun ??\n ((request) =>\n options.sandbox.run({\n command: 'sudo',\n args: ['-n', 'python3', '-I', '-c', workspaceEgressLauncher],\n stdin: JSON.stringify(request),\n timeoutMs: 35_000,\n }));\n let pending: Promise<unknown> = Promise.resolve();\n let owner: string | null | undefined;\n let current: DeviceEgressLeaseIface | null = null;\n let closed = false;\n let stopped = false;\n let recovered = false;\n let createdLease: { leaseId: string; userId: string } | null = null;\n let directPolicy: NetworkPolicyIface | undefined = options.initialNetworkPolicy;\n let directPolicyKnown = false;\n let requiresChoice = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let nextRenewAttempt = 0;\n let nextRecoveryAttempt = 0;\n let nextRecoveryProbeAt = 0;\n let initializing = false;\n let configurationToken: string | null = null;\n let pendingUnlock: string | null = null;\n let repairProviderPolicy = false;\n let configurationFailure: unknown = null;\n let notifiedClosed = false;\n const notifyClosed = () => {\n if (!notifiedClosed) {\n notifiedClosed = true;\n options.onClose?.();\n }\n };\n let cachedStatus: {\n at: number;\n userId: string | null;\n value: z.infer<typeof localStatusSchema>;\n } | null = null;\n const reportFailure = (operation: string, cause: unknown) => {\n const rawCode = z.object({ code: z.string() }).safeParse(cause).data?.code;\n const known = [\n 'credential_missing',\n 'no_acting_user',\n 'unauthorized',\n 'forbidden',\n 'not_found',\n 'unavailable',\n 'invalid',\n 'rate_limited',\n 'prerequisite',\n 'conflict',\n 'configuration',\n 'request_failed',\n 'egress_enrollment_lost',\n ];\n try {\n options.onFailure?.({\n operation,\n workspaceId: options.workspaceId,\n leaseId: current?.leaseId ?? null,\n reason:\n rawCode != null && known.includes(rawCode)\n ? rawCode\n : cause instanceof TypeError\n ? 'transport'\n : 'operation_failed',\n httpStatus: cause instanceof Error ? deviceApiStatusOf(cause) : null,\n });\n } catch {\n // Host telemetry must not interrupt fencing, claim cleanup, or renewal.\n console.warn('Workspace egress failure observer threw');\n }\n };\n const serialized = <T>(work: () => Promise<T>): Promise<T> => {\n const task = pending.then(work, work);\n pending = task.catch(() => undefined);\n return task;\n };\n let sourceDigest: Promise<string> | null = null;\n const execute = async (request: Record<string, JsonValue>) => {\n if (request.action === 'block' && configurationToken == null && pendingUnlock != null) {\n try {\n await execute({\n action: 'claim',\n configurationToken: pendingUnlock,\n refresh: true,\n verifyOnly: true,\n });\n } catch (cause) {\n if (!z.object({ code: z.literal('conflict') }).safeParse(cause).success) throw cause;\n pendingUnlock = null;\n }\n }\n if (\n configurationFailure != null &&\n request.action !== 'status' &&\n request.action !== 'unlock' &&\n request.action !== 'block'\n )\n throw configurationFailure;\n if (request.action !== 'status') cachedStatus = null;\n sourceDigest ??= crypto.subtle\n .digest('SHA-256', new TextEncoder().encode(workspaceEgressBootstrap))\n .then((hash) =>\n [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, '0')).join(''),\n );\n const input = JSON.stringify({\n ...request,\n configurationToken: request.configurationToken ?? configurationToken ?? pendingUnlock,\n workspaceId: options.workspaceId,\n });\n let result = await run({ source: cachedWorkspaceEgressBootstrap(await sourceDigest), input });\n if (result.exitCode === 0) {\n let response: unknown;\n try {\n response = JSON.parse(result.stdout);\n } catch {\n response = null;\n }\n if (z.object({ needsBootstrap: z.literal(true) }).safeParse(response).success)\n result = await run({ source: workspaceEgressBootstrap, input });\n }\n if (result.exitCode !== 0) {\n let failure: unknown;\n try {\n failure = JSON.parse(result.stdout);\n } catch {\n failure = null;\n }\n const parsed = z.object({ errorCode: z.string() }).safeParse(failure);\n const code =\n parsed.success &&\n [\n 'prerequisite',\n 'conflict',\n 'configuration',\n DeviceApiClientErrorCode.EgressEnrollmentLost,\n ].includes(parsed.data.errorCode)\n ? parsed.data.errorCode\n : 'prerequisite';\n throw Object.assign(\n new Error(\n `Workspace egress ${code} failed${code === 'prerequisite' ? ' (root, TUN, NET_ADMIN and policy routing required)' : ''}. Inspect the root-owned last-error.json for details`,\n ),\n { code },\n );\n }\n let raw: unknown;\n try {\n raw = JSON.parse(result.stdout);\n } catch {\n throw new Error('Invalid workspace egress status');\n }\n const status = localStatusSchema.parse(raw);\n if (request.action === 'block' && configurationToken == null && pendingUnlock != null) {\n try {\n await execute({ action: 'unlock', configurationToken: pendingUnlock });\n pendingUnlock = null;\n } catch (cause) {\n reportFailure('unlock', cause);\n }\n }\n return status;\n };\n const statusForGuard = async (userId: string | null) => {\n if (\n cachedStatus != null &&\n cachedStatus.userId === userId &&\n performance.now() - cachedStatus.at < 100\n )\n return cachedStatus.value;\n const value = await execute({ action: 'status' });\n cachedStatus = { at: performance.now(), userId, value };\n return value;\n };\n const callerFor = (userId: string | null) => ({\n organizationId: options.organizationId,\n actingUser: { current: async () => userId },\n });\n const block = async (userId: string | null, restoreDirect = false) => {\n current = null;\n const local = await execute({ action: 'block', ownerUserId: userId, restoreDirect }).catch(\n async (cause) => {\n if (z.object({ code: z.literal('conflict') }).safeParse(cause).success) throw cause;\n const fences = await Promise.allSettled([\n options.afterBlock?.(),\n options.afterGuard == null\n ? undefined\n : restoreNetwork({ mode: WorkspaceNetworkPolicy.DenyAll }),\n ]);\n const failures = fences.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n if (failures.length > 0)\n throw new AggregateError([cause, ...failures], 'Namespace and provider denial failed');\n throw cause;\n },\n );\n await options.afterBlock?.();\n return local;\n };\n const release = async (args: {\n userId: string | null;\n leaseId: string | null;\n nextOwner: string | null;\n suspendWorkspace?: boolean;\n restoreDirect?: boolean;\n }) => {\n const failures: unknown[] = [];\n let denied = false;\n let superseded = false;\n current = null;\n try {\n const local = await execute({\n action: 'block',\n ownerUserId: args.nextOwner,\n expectedLeaseId: args.suspendWorkspace === true ? null : args.leaseId,\n restoreDirect: args.restoreDirect ?? false,\n });\n denied = local.mode === 'blocked';\n superseded = !denied;\n } catch (cause) {\n superseded = z.object({ code: z.literal('conflict') }).safeParse(cause).success;\n failures.push(cause);\n }\n if (!superseded || args.suspendWorkspace === true)\n try {\n const fences = await Promise.allSettled([\n options.afterBlock?.(),\n (!denied || options.afterBlock == null) && options.afterGuard != null\n ? restoreNetwork({ mode: WorkspaceNetworkPolicy.DenyAll, allow: [] })\n : undefined,\n ]);\n const rejected = fences.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n if (rejected.length > 0) throw new AggregateError(rejected, 'Provider denial failed');\n repairProviderPolicy = false;\n } catch (cause) {\n failures.push(cause);\n }\n if (args.suspendWorkspace === true) {\n try {\n // Local owner/lease fields constrain the namespace guard, never API identity.\n await client.egress.suspend({\n caller: callerFor(args.userId),\n workspaceId: options.workspaceId,\n });\n createdLease = null;\n } catch (cause) {\n failures.push(cause);\n }\n } else if (args.userId != null && args.leaseId != null) {\n try {\n await revokeLease({\n caller: callerFor(args.userId),\n leaseId: args.leaseId,\n workspaceId: options.workspaceId,\n });\n if (createdLease?.leaseId === args.leaseId) createdLease = null;\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (failures.length > 0)\n throw new AggregateError(failures, 'Workspace network block or egress revocation failed');\n };\n let reportedPolicy: string | null = null;\n const reportLogicalPolicy = async () => {\n const logical =\n directPolicyKnown && directPolicy != null\n ? directPolicy\n : { mode: WorkspaceNetworkPolicy.DenyAll };\n const encoded = JSON.stringify(logical);\n if (encoded !== reportedPolicy) {\n await options.onNetworkPolicy?.(logical);\n reportedPolicy = encoded;\n }\n };\n const restoreNetwork = async (policy: { mode: string; allow?: string[] } | null) => {\n const parsed = workspaceNetworkPolicySchema.safeParse(policy);\n if (policy != null && !parsed.success)\n throw new Error('Saved workspace network policy is unsupported; networking remains blocked');\n const desired = parsed.success ? parsed.data : { mode: WorkspaceNetworkPolicy.DenyAll };\n if (options.afterGuard != null) await options.afterGuard(desired);\n else if (desired.mode !== WorkspaceNetworkPolicy.AllowAll || options.afterBlock != null)\n throw new Error('A provider policy-restoration hook is required; networking remains blocked');\n await reportLogicalPolicy();\n };\n const profileFor = async (userId: string) => {\n const caller = callerFor(userId);\n const profile = await client.egress.workspace({ caller, workspaceId: options.workspaceId });\n if (profile.networkPolicy != null) {\n directPolicy = workspaceNetworkPolicySchema.parse(profile.networkPolicy);\n directPolicyKnown = true;\n }\n if (profile.networkPolicy == null && options.initialNetworkPolicy == null) {\n requiresChoice = true;\n await block(userId);\n throw new Error(\n 'The host must supply the current network policy before opting in a workspace',\n );\n }\n if (profile.networkPolicy == null && options.initialNetworkPolicy != null) {\n const policy = workspaceNetworkPolicySchema.parse(options.initialNetworkPolicy);\n directPolicy = policy;\n await client.egress.setNetworkPolicy({\n caller: callerFor(null),\n workspaceId: options.workspaceId,\n policy,\n initializeIfMissing: true,\n });\n const initialized = await client.egress.workspace({\n caller,\n workspaceId: options.workspaceId,\n });\n if (initialized.networkPolicy != null) {\n directPolicy = workspaceNetworkPolicySchema.parse(initialized.networkPolicy);\n directPolicyKnown = true;\n }\n return initialized;\n }\n return profile;\n };\n const authorizeRouteMutation = async (\n userId: string | null,\n local: z.infer<typeof localStatusSchema>,\n ) => {\n if (\n options.allowOwnerChange === false &&\n local.ownerUserId != null &&\n local.ownerUserId !== userId\n )\n throw new Error('Workspace egress belongs to another actor; this binding requires its owner');\n if (local.ownerUserId != null && local.ownerUserId !== userId)\n await options.authorizeOwnerChange?.(userId);\n // An owned active lease permits local cleanup during an outage; other routes require fresh authority.\n if (\n current != null &&\n owner === userId &&\n local.ownerUserId === userId &&\n local.leaseId === current.leaseId &&\n current.state === 'active' &&\n current.expiresAtMs > now()\n )\n return;\n if (userId == null) {\n await client.egress.networkState({\n organizationId: options.organizationId,\n workspaceId: options.workspaceId,\n });\n return;\n }\n const profile = await client.egress.workspace({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n });\n if (options.allowOwnerChange === false && profile.lockedByOtherOwner)\n throw new Error('Workspace egress belongs to another actor; this binding requires its owner');\n };\n const waitReady = async (leaseId: string | null, mode: string) => {\n const deadline = performance.now() + 35_000;\n for (;;) {\n const result = await execute({ action: 'status' });\n if (result.mode === mode && (leaseId == null || result.leaseId === leaseId)) return result;\n if (performance.now() >= deadline)\n throw new Error('Workspace egress did not become ready; networking remains blocked');\n await sleep(200);\n }\n };\n const configureAttempt = async (userId: string, deviceIds: string[], dnsResolvers?: string[]) => {\n recovered = false;\n await authorizeRouteMutation(userId, await execute({ action: 'status' }));\n const local = await block(userId);\n if (local.policyRouting === false)\n throw new Error(\n 'This sandbox kernel does not support the Linux policy routing required for Device egress',\n );\n const caller = callerFor(userId);\n const profile = await profileFor(userId);\n if (\n options.afterGuard == null &&\n (directPolicy?.mode !== WorkspaceNetworkPolicy.AllowAll || options.afterBlock != null)\n )\n throw new Error('A provider policy-restoration hook is required before Device configuration');\n try {\n if (profile.lease != null)\n await revokeLease({\n caller,\n leaseId: profile.lease.leaseId,\n workspaceId: options.workspaceId,\n });\n if (\n profile.onlineDeviceIds != null &&\n deviceIds.every((id) =>\n profile.deviceIds.some((saved) => saved.toLowerCase() === id.toLowerCase()),\n ) &&\n !deviceIds.some((id) =>\n profile.onlineDeviceIds?.some((online) => online.toLowerCase() === id.toLowerCase()),\n )\n )\n throw new Error('No configured egress Device is online; networking remains blocked');\n const architecture = local.architecture ?? 'x86_64';\n const selectArtifact = (artifacts: DeviceEgressLeaseIface['helper']) => {\n const selected = [artifacts, ...(artifacts.alternatives ?? [])].find(\n (item) => (item.architecture ?? 'x86_64') === architecture,\n );\n if (selected == null)\n throw new Error(\n 'No approved networking helper is configured for this workspace architecture',\n );\n return selected;\n };\n const helper = selectArtifact(profile.helper);\n const helperUrl = new URL(helper.url);\n if (helperUrl.protocol !== 'https:') {\n throw new Error('Workspace networking artifacts require HTTPS');\n }\n const cached = await execute({ action: 'artifact', sha256: helper.sha256 });\n let bytes: Uint8Array | null = null;\n if (cached.helperReady !== true) {\n const response = await (options.fetch ?? fetch)(helperUrl, {\n redirect: 'error',\n signal: AbortSignal.timeout(60_000),\n });\n if (!response.ok || response.body == null) {\n await response.body?.cancel();\n throw new Error('Could not download the pinned workspace networking helper');\n }\n const chunks: Uint8Array[] = [];\n let size = 0;\n const reader = response.body.getReader();\n try {\n for (;;) {\n const next = await reader.read();\n if (next.done) break;\n size += next.value.byteLength;\n if (size > 128 * 1024 * 1024)\n throw new Error('Workspace networking helper exceeds its size limit');\n chunks.push(next.value);\n }\n } finally {\n await reader.cancel();\n }\n const downloaded = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n downloaded.set(chunk, offset);\n offset += chunk.byteLength;\n }\n const hash = [...new Uint8Array(await crypto.subtle.digest('SHA-256', downloaded))]\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n if (hash !== helper.sha256)\n throw new Error('Workspace networking helper failed integrity verification');\n bytes = downloaded;\n }\n const hash = helper.sha256;\n const helperPath =\n bytes == null\n ? '/run/final-workspace-egress/helper'\n : `/tmp/final-egress-${crypto.randomUUID()}`;\n let leaseId: string | null = null;\n const outcome: ConfigurationOutcomeIface = { result: null, failures: [] };\n try {\n if (bytes != null)\n await options.sandbox.writeBinaryFile({ path: helperPath, content: bytes });\n // Downloads and uploads can outlive the claim; do not enroll after another binding wins.\n const refreshed = await execute({ action: 'claim', configurationToken, refresh: true });\n if (refreshed.busy === true)\n throw new Error('Workspace configuration claim was superseded');\n const lease = await client.egress.create({\n caller,\n workspaceId: options.workspaceId,\n deviceIds,\n dnsResolvers,\n });\n leaseId = lease.leaseId;\n createdLease = { leaseId: lease.leaseId, userId };\n validateApprovedDevices(lease, deviceIds);\n if (lease.workspaceId !== options.workspaceId)\n throw new Error('Egress enrollment belongs to a different workspace');\n if (lease.state !== 'provisioning')\n throw new Error('Egress enrollment must return provisioning state before activation');\n if (selectArtifact(lease.helper).sha256 !== hash)\n throw new Error('Networking artifact changed during enrollment; retry configuration');\n // Allow transport only once local denial, artifact integrity, and lease ownership are established.\n await execute({ action: 'claim', configurationToken, refresh: true });\n repairProviderPolicy = true;\n await restoreNetwork({ mode: WorkspaceNetworkPolicy.AllowAll, allow: [] });\n await execute({ action: 'claim', configurationToken, refresh: true });\n await execute({\n action: 'configure',\n ownerUserId: userId,\n helperPath,\n config: { ...lease, helper, ownerUserId: userId, revision: crypto.randomUUID() },\n });\n await waitReady(lease.leaseId, 'enrolled');\n if (configurationFailure != null) throw configurationFailure;\n // Revalidate the root-owned claim immediately before publishing packet grants.\n const claim = await execute({ action: 'claim', configurationToken, refresh: true });\n if (claim.busy === true) throw new Error('Workspace configuration claim was superseded');\n const active = await client.egress.activate({ caller, leaseId: lease.leaseId });\n validateApprovedDevices(active, deviceIds);\n if (active.leaseId !== lease.leaseId)\n throw new Error('Egress activation returned a different lease');\n if (active.workspaceId !== options.workspaceId)\n throw new Error('Egress activation belongs to a different workspace');\n if (active.state !== 'active')\n throw new Error('Egress activation must return active state');\n validateActiveLease(active, now());\n await execute({ action: 'renew', lease: active });\n const result = await waitReady(lease.leaseId, 'device');\n repairProviderPolicy = false;\n current = active;\n recovered = true;\n nextRenewAttempt = 0;\n nextRecoveryAttempt = 0;\n outcome.result = result;\n } catch (cause) {\n outcome.failures.push(cause);\n try {\n await release({ userId, leaseId, nextOwner: userId });\n } catch (cleanup) {\n outcome.failures.push(cleanup);\n }\n }\n try {\n if (bytes != null) await options.sandbox.removePath({ path: helperPath, force: true });\n } catch (cleanup) {\n outcome.failures.push(cleanup);\n }\n if (outcome.failures.length > 0 && outcome.result != null) {\n try {\n await release({ userId, leaseId, nextOwner: userId });\n } catch (cleanup) {\n outcome.failures.push(cleanup);\n }\n }\n if (outcome.failures.length > 0)\n throw new AggregateError(outcome.failures, 'Egress configuration or cleanup failed');\n if (outcome.result == null) throw new Error('Egress configuration did not return a status');\n return outcome.result;\n } catch (cause) {\n try {\n if (options.afterBlock == null && directPolicy != null) {\n let ownsClaim = false;\n try {\n const claim = await execute({ action: 'claim', configurationToken, refresh: true });\n ownsClaim = claim.busy !== true;\n } catch (claim) {\n reportFailure('outer-policy-claim', claim);\n }\n if (ownsClaim && (await execute({ action: 'status' })).mode === 'blocked')\n await restoreNetwork(directPolicy);\n }\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n 'Egress configuration and outer policy restoration failed',\n );\n }\n throw cause;\n }\n };\n\n const verifyConfigurationClaim = async () => {\n const claim = await execute({\n action: 'claim',\n configurationToken,\n refresh: true,\n verifyOnly: true,\n });\n if (claim.busy === true) throw new Error('Workspace configuration claim was superseded');\n };\n\n const withConfigurationClaim = async <T>(\n work: () => Promise<T>,\n cleanup?: () => Promise<void>,\n waitForClaim = true,\n ): Promise<T> => {\n if (pendingUnlock != null) {\n await execute({ action: 'unlock', configurationToken: pendingUnlock });\n pendingUnlock = null;\n }\n const token = crypto.randomUUID();\n const deadline = performance.now() + 180_000;\n for (;;) {\n let claim: Awaited<ReturnType<typeof execute>>;\n try {\n claim = await execute({ action: 'claim', configurationToken: token });\n } catch (cause) {\n // The guest may have recorded this token before its response was lost.\n pendingUnlock = token;\n recovered = false;\n throw cause;\n }\n if (claim.busy !== true) break;\n if (!waitForClaim)\n throw Object.assign(new Error('Another binding owns workspace configuration'), {\n code: 'conflict',\n });\n if (performance.now() >= deadline)\n throw new Error('Another binding is configuring workspace egress; retry later');\n await sleep(200);\n }\n configurationToken = token;\n let refreshing = true;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let refresh: Promise<void> = Promise.resolve();\n const scheduleRefresh = () => {\n refreshTimer = setTimeout(() => {\n refresh = execute({ action: 'claim', configurationToken: token, refresh: true })\n .then((claim) => {\n if (claim.busy === true)\n throw new Error('Workspace configuration claim was superseded');\n })\n .catch((cause) => {\n configurationFailure = cause;\n reportFailure('configuration-claim', cause);\n });\n void refresh.then(() => {\n if (refreshing && configurationFailure == null) scheduleRefresh();\n });\n }, 60_000);\n if (typeof refreshTimer === 'object' && 'unref' in refreshTimer) refreshTimer.unref();\n };\n scheduleRefresh();\n let result: { value: T } | null = null;\n const failures: unknown[] = [];\n try {\n result = { value: await work() };\n } catch (cause) {\n failures.push(cause);\n }\n refreshing = false;\n if (refreshTimer != null) clearTimeout(refreshTimer);\n await refresh;\n if (configurationFailure != null && !failures.includes(configurationFailure))\n failures.push(configurationFailure);\n let cleaned = false;\n const clean = async () => {\n if (cleanup == null || cleaned) return;\n cleaned = true;\n try {\n await cleanup();\n } catch (cause) {\n failures.push(cause);\n reportFailure('configuration-cleanup', cause);\n }\n };\n if (failures.length > 0) await clean();\n try {\n await execute({ action: 'unlock', configurationToken: token });\n } catch (cause) {\n pendingUnlock = token;\n recovered = false;\n if (failures.length === 0) failures.push(cause);\n else reportFailure('unlock', cause);\n if (!cleaned && cleanup != null) {\n try {\n const claim = await execute({\n action: 'claim',\n configurationToken: token,\n refresh: true,\n });\n if (claim.busy === true) throw new Error('Workspace configuration claim was superseded');\n await clean();\n } catch (cleanupClaim) {\n failures.push(cleanupClaim);\n reportFailure('configuration-cleanup', cleanupClaim);\n }\n }\n }\n configurationToken = null;\n configurationFailure = null;\n if (repairProviderPolicy) {\n repairProviderPolicy = false;\n try {\n if (options.namespaceExists == null || (await options.namespaceExists()) !== false)\n await withConfigurationClaim(\n async () => {\n const latest = await execute({ action: 'status' });\n if (latest.leaseId != null) return;\n if (latest.choicePending === true || latest.mode !== 'direct') {\n if (options.afterBlock != null) await options.afterBlock();\n else await restoreNetwork({ mode: WorkspaceNetworkPolicy.DenyAll, allow: [] });\n await execute({ action: 'claim', configurationToken, refresh: true });\n return;\n }\n // Repair a late provider write against current state, never the superseded actor's policy.\n await block(latest.ownerUserId ?? null, true);\n const state = await client.egress.networkState({\n organizationId: options.organizationId,\n workspaceId: options.workspaceId,\n });\n if (state.enabled || state.networkPolicy == null)\n throw new Error(\n 'Current direct-access policy is unavailable; networking remains blocked',\n );\n await restoreNetwork(state.networkPolicy);\n await execute({ action: 'claim', configurationToken, refresh: true });\n await execute({ action: 'disable', ownerUserId: null });\n await waitReady(null, 'direct');\n },\n undefined,\n false,\n );\n } catch (cause) {\n if (!z.object({ code: z.literal('conflict') }).safeParse(cause).success)\n failures.push(cause);\n reportFailure('provider-policy-repair', cause);\n }\n }\n if (failures.length > 1)\n throw new AggregateError(\n failures,\n failures\n .map((failure) => (failure instanceof Error ? failure.message : String(failure)))\n .join('; '),\n { cause: failures[0] },\n );\n if (failures.length > 0) throw failures[0];\n if (result == null) throw new Error('Workspace egress configuration returned no result');\n return result.value;\n };\n\n const configure = (userId: string, deviceIds: string[], dnsResolvers?: string[]) =>\n withConfigurationClaim(\n () => configureAttempt(userId, deviceIds, dnsResolvers),\n async () => {\n if (\n current != null &&\n createdLease?.leaseId === current.leaseId &&\n createdLease.userId === userId\n )\n await release({ userId, leaseId: current.leaseId, nextOwner: userId });\n },\n );\n\n const recoverAttempt = async (userId: string | null, background: boolean) => {\n const local = await execute({ action: 'status' });\n if (local.ownerUserId != null && local.ownerUserId !== userId) {\n if (background) {\n requiresChoice = true;\n current = null;\n return;\n }\n await options.authorizeOwnerChange?.(userId);\n }\n if (local.mode === 'error' && local.ownerUserId !== userId) {\n requiresChoice = true;\n if (options.allowOwnerChange !== false) {\n await options.afterBlock?.();\n await restoreNetwork({ mode: WorkspaceNetworkPolicy.DenyAll, allow: [] });\n }\n throw new Error(\n 'Workspace egress enforcement is in error; explicitly configure or disable to repair',\n );\n }\n // Recovery holds the same namespace claim as explicit configuration and disable.\n // An actor change cannot inherit another person's exit, including after host restart.\n if (\n (local.ownerUserId != null && local.ownerUserId !== userId) ||\n (background && local.mode === 'blocked' && local.ownerUserId === null && userId != null)\n ) {\n if (options.allowOwnerChange === false)\n throw new Error(\n 'Workspace egress belongs to another actor; this binding requires its owner',\n );\n if (background) {\n requiresChoice = true;\n current = null;\n return;\n }\n await authorizeRouteMutation(userId, local);\n requiresChoice = true;\n await release({ userId, leaseId: local.leaseId, nextOwner: userId, suspendWorkspace: true });\n throw new Error(\n 'Workspace egress owner changed; explicitly configure or disable egress before running tools',\n );\n }\n const choicePending = local.choicePending ?? local.mode === 'blocked';\n if (userId == null) {\n const state = await client.egress.networkState({\n organizationId: options.organizationId,\n workspaceId: options.workspaceId,\n });\n if (state.enabled) {\n requiresChoice = true;\n await block(null);\n throw new Error(\n 'This workspace has Device egress configured; an acting user must choose its network policy',\n );\n }\n if (choicePending) {\n requiresChoice = true;\n await block(null);\n throw new Error('Workspace networking is blocked; explicitly configure or disable egress');\n }\n let policy = state.networkPolicy;\n if (policy == null) {\n if (options.initialNetworkPolicy == null) {\n requiresChoice = true;\n await block(null);\n throw new Error(\n 'The host must supply the current network policy before opting in a workspace',\n );\n }\n const initial = workspaceNetworkPolicySchema.parse(options.initialNetworkPolicy);\n await client.egress.setNetworkPolicy({\n caller: callerFor(null),\n workspaceId: options.workspaceId,\n policy: initial,\n initializeIfMissing: true,\n });\n policy = (\n await client.egress.networkState({\n organizationId: options.organizationId,\n workspaceId: options.workspaceId,\n })\n ).networkPolicy;\n }\n if (policy != null) {\n directPolicy = workspaceNetworkPolicySchema.parse(policy);\n directPolicyKnown = true;\n }\n await restoreNetwork(policy);\n if (local.mode !== 'direct' || local.restorePending === true) {\n await execute({ action: 'disable', ownerUserId: null });\n await waitReady(null, 'direct');\n }\n requiresChoice = false;\n return;\n }\n const desired = await profileFor(userId);\n if (desired.lockedByOtherOwner) {\n if (options.allowOwnerChange === false)\n throw new Error(\n 'Workspace egress belongs to another actor; this binding requires its owner',\n );\n requiresChoice = true;\n if (background) {\n current = null;\n return;\n }\n await block(userId);\n throw new Error(\n 'Workspace egress belongs to a different actor; configure or explicitly disable it before running tools',\n );\n }\n if (!desired.enabled) {\n if (choicePending) {\n requiresChoice = true;\n await block(userId);\n throw new Error('Workspace networking is blocked; explicitly configure or disable egress');\n }\n await restoreNetwork(desired.networkPolicy);\n if (local.mode !== 'direct' || local.restorePending === true) {\n await execute({ action: 'disable', ownerUserId: userId });\n await waitReady(null, 'direct');\n }\n current = null;\n return;\n }\n if (\n desired.lease != null &&\n (['device', 'reconnecting'].includes(local.mode) ||\n (['blocked', 'configuring'].includes(local.mode) && local.controllerAlive === true)) &&\n local.leaseId === desired.lease.leaseId\n ) {\n try {\n if (desired.lease.workspaceId !== options.workspaceId)\n throw new Error('Egress recovery belongs to a different workspace');\n validateApprovedDevices(desired.lease, desired.deviceIds);\n validateActiveLease(desired.lease, now());\n } catch (cause) {\n requiresChoice = true;\n if (options.allowOwnerChange !== false)\n await release({ userId, leaseId: desired.lease.leaseId, nextOwner: userId });\n throw cause;\n }\n current = desired.lease;\n await restoreNetwork({ mode: WorkspaceNetworkPolicy.AllowAll, allow: [] });\n if (local.mode === 'configuring' || local.expiresAtMs !== desired.lease.expiresAtMs) {\n await execute({ action: 'renew', lease: desired.lease });\n await waitReady(desired.lease.leaseId, 'device');\n }\n return;\n }\n if (options.allowOwnerChange === false)\n throw new Error(\n 'Workspace networking needs recovery by an active workspace binding before external access',\n );\n if (performance.now() < nextRecoveryAttempt)\n throw new Error(\n 'Workspace egress recovery is cooling down; retry later or explicitly configure',\n );\n nextRecoveryAttempt = performance.now() + 60_000;\n await configureAttempt(userId, desired.deviceIds, desired.dnsResolvers);\n nextRecoveryAttempt = 0;\n };\n const recover = async (userId: string | null, background: boolean) => {\n if (performance.now() < nextRecoveryProbeAt)\n throw new Error(\n 'Workspace egress recovery is cooling down; retry shortly or explicitly configure',\n );\n recovered = false;\n try {\n await withConfigurationClaim(\n () => recoverAttempt(userId, background),\n async () => {\n if (\n current != null &&\n createdLease?.leaseId === current.leaseId &&\n createdLease.userId === userId\n )\n await release({ userId, leaseId: current.leaseId, nextOwner: userId });\n },\n );\n recovered = true;\n nextRecoveryProbeAt = 0;\n } catch (cause) {\n if (cause instanceof Error && isPermanentAuthorizationFailure(cause)) {\n requiresChoice = true;\n try {\n if (options.allowOwnerChange !== false) await block(userId);\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n 'Egress recovery rejected and local denial failed',\n );\n }\n }\n if (!initializing && !requiresChoice) nextRecoveryProbeAt = performance.now() + 5_000;\n throw cause;\n }\n };\n const stableStatus = async (userId: string | null) => {\n const deadline = performance.now() + 180_000;\n for (;;) {\n const local = await statusForGuard(userId);\n if (local.configuring !== true) return local;\n if (performance.now() >= deadline)\n throw new Error('Another binding is configuring workspace egress; retry later');\n cachedStatus = null;\n await sleep(200);\n }\n };\n const maintain = async (background = false) => {\n if (closed) throw new Error('Workspace egress manager is closed');\n if (background && (requiresChoice || (recovered && current == null))) return;\n if (requiresChoice) {\n const actor = await options.actingUser.current();\n const local = await execute({ action: 'status' });\n const repaired =\n local.configuring !== true &&\n ((local.mode === 'direct' &&\n local.choicePending === false &&\n local.restorePending !== true &&\n local.ownerUserId == null) ||\n (local.mode === 'device' &&\n local.ownerUserId === actor &&\n local.expiresAtMs != null &&\n local.expiresAtMs > now()));\n if (!repaired)\n throw new Error('Explicitly configure or disable workspace egress before running tools');\n // Another authorized binding repaired the namespace; revalidate its saved route.\n requiresChoice = false;\n current = null;\n owner = undefined;\n recovered = false;\n cachedStatus = null;\n nextRecoveryProbeAt = 0;\n }\n if (background && owner === undefined) return;\n const userId = background ? (owner ?? null) : await options.actingUser.current();\n if (owner !== userId) {\n if (options.allowOwnerChange === false && owner !== undefined && current != null)\n throw new Error(\n 'Workspace egress belongs to another actor; this binding requires its owner',\n );\n if (owner !== undefined && current != null) {\n await authorizeRouteMutation(userId, await execute({ action: 'status' }));\n requiresChoice = true;\n const leaseId = current.leaseId;\n owner = userId;\n await release({ userId, leaseId, nextOwner: userId, suspendWorkspace: true });\n throw new Error(\n 'Workspace egress owner changed; configure or disable egress before running tools',\n );\n }\n // Recovery failures belong to the actor that attempted them.\n nextRecoveryProbeAt = 0;\n nextRecoveryAttempt = 0;\n // Retain the last foreground identity even when recovery fails transiently.\n owner = userId;\n await recover(userId, background);\n }\n if (!recovered) {\n await recover(userId, background);\n }\n if (background && requiresChoice) return;\n if (current != null && current.expiresAtMs <= now()) {\n await recover(userId, background);\n }\n const local = await stableStatus(userId);\n if (local.mode === 'blocked' && local.ownerUserId == null && local.leaseId == null) {\n requiresChoice = true;\n if (background) return;\n throw new Error(\n 'Workspace networking is blocked; explicitly configure or disable egress before running tools',\n );\n }\n if (local.mode === 'error' && local.ownerUserId !== userId) {\n requiresChoice = true;\n if (options.allowOwnerChange !== false) {\n await options.afterBlock?.();\n await restoreNetwork({ mode: WorkspaceNetworkPolicy.DenyAll, allow: [] });\n }\n throw new Error(\n 'Workspace egress enforcement is in error; explicitly configure or disable to repair',\n );\n }\n if (\n (local.ownerUserId != null && local.ownerUserId !== userId) ||\n (background && local.mode === 'blocked' && local.ownerUserId === null && userId != null)\n ) {\n if (options.allowOwnerChange === false)\n throw new Error(\n 'Workspace egress belongs to another actor; this binding requires its owner',\n );\n if (background) {\n requiresChoice = true;\n current = null;\n return;\n }\n await authorizeRouteMutation(userId, local);\n requiresChoice = true;\n await release({ userId, leaseId: local.leaseId, nextOwner: userId, suspendWorkspace: true });\n throw new Error(\n 'Workspace egress owner changed; configure or disable egress before running tools',\n );\n }\n if (\n (current != null && local.leaseId !== current.leaseId) ||\n (current == null && local.leaseId != null)\n ) {\n current = null;\n await recover(userId, background);\n return;\n }\n if (\n (local.mode === 'error' || (local.mode === 'blocked' && local.controllerAlive !== true)) &&\n local.ownerUserId === userId\n ) {\n // A live controller waits through Device outages; a dead controller needs recovery.\n current = null;\n await recover(userId, background);\n return;\n }\n if (\n current != null &&\n userId != null &&\n performance.now() >= nextRenewAttempt &&\n (current.expiresAtMs - now() < 10 * 60_000 ||\n ['blocked', 'reconnecting'].includes(local.mode))\n ) {\n try {\n const lease = await client.egress.renew({\n caller: callerFor(userId),\n leaseId: current.leaseId,\n });\n validateActiveLease(lease, now());\n validateApprovedDevices(\n lease,\n current.devices.map((device) => device.deviceId),\n );\n if (lease.leaseId !== current.leaseId)\n throw Object.assign(new Error('Egress renewal returned a different lease'), {\n invalidEgressLease: true,\n code: 'configuration',\n });\n if (lease.workspaceId !== options.workspaceId)\n throw Object.assign(new Error('Egress renewal belongs to a different workspace'), {\n invalidEgressLease: true,\n code: 'configuration',\n });\n await execute({ action: 'renew', lease });\n current = lease;\n nextRenewAttempt = performance.now() + 30_000;\n } catch (cause) {\n const status = cause instanceof Error ? deviceApiStatusOf(cause) : null;\n reportFailure('renew', cause);\n if (z.object({ invalidEgressLease: z.literal(true) }).safeParse(cause).success) {\n requiresChoice = true;\n const leaseId = current.leaseId;\n try {\n await release({ userId, leaseId, nextOwner: userId });\n } catch (cleanup) {\n throw new AggregateError([cause, cleanup], 'Invalid egress lease and cleanup failed');\n }\n throw cause;\n }\n if (deviceApiCodeOf(cause) === DeviceApiClientErrorCode.EgressEnrollmentLost) {\n const leaseId = current.leaseId;\n recovered = false;\n try {\n await release({ userId, leaseId, nextOwner: userId });\n } catch (cleanup) {\n throw new AggregateError([cause, cleanup], 'Egress renewal and cleanup failed');\n }\n current = null;\n nextRecoveryProbeAt = performance.now() + 5_000;\n throw cause;\n }\n if (status === 401 || status === 403 || status === 404 || status === 410) {\n if (status === 404) {\n const profile = await profileFor(userId).catch((lookup) => {\n nextRenewAttempt = performance.now() + 30_000;\n reportFailure('renew-profile', lookup);\n throw new AggregateError([cause, lookup], 'Egress renewal and profile lookup failed');\n });\n if (\n !profile.lockedByOtherOwner &&\n profile.configured === true &&\n !profile.enabled &&\n profile.networkPolicy != null\n ) {\n const latest = await execute({ action: 'status' });\n if (\n latest.mode === 'direct' &&\n latest.choicePending !== true &&\n latest.ownerUserId === userId\n ) {\n current = null;\n createdLease = null;\n recovered = false;\n requiresChoice = false;\n await recover(userId, background);\n return;\n }\n }\n if (\n !profile.lockedByOtherOwner &&\n profile.enabled &&\n profile.lease != null &&\n profile.lease.leaseId !== current.leaseId\n ) {\n current = null;\n recovered = false;\n await recover(userId, background);\n return;\n }\n }\n requiresChoice = true;\n try {\n await release({ userId, leaseId: current.leaseId, nextOwner: userId });\n } catch (cleanup) {\n throw new AggregateError([cause, cleanup], 'Egress renewal and cleanup failed');\n }\n throw cause;\n }\n nextRenewAttempt = performance.now() + 30_000;\n if (\n current.expiresAtMs > now() &&\n local.leaseId === current.leaseId &&\n (['device', 'reconnecting'].includes(local.mode) || local.controllerAlive === true)\n )\n return;\n throw cause;\n }\n }\n };\n const schedule = () => {\n if (closed) return;\n timer = setTimeout(() => {\n void serialized(() => maintain(true))\n .catch((cause) => reportFailure('maintenance', cause))\n .finally(schedule);\n }, 60_000);\n if (typeof timer === 'object' && 'unref' in timer) timer.unref();\n };\n const close = (stopWorkspace = false, onlyCurrent = false): Promise<void> =>\n serialized(async () => {\n if (stopped || (closed && !stopWorkspace)) return;\n if (onlyCurrent && (current == null || current.leaseId !== createdLease?.leaseId)) {\n closed = true;\n if (timer != null) clearTimeout(timer);\n timer = null;\n const created = createdLease;\n const results = await Promise.allSettled([\n (async () => {\n if (created == null) return;\n await revokeLease({\n caller: callerFor(created.userId),\n leaseId: created.leaseId,\n workspaceId: options.workspaceId,\n });\n createdLease = null;\n })(),\n (async () => {\n if (pendingUnlock == null) return;\n await execute({ action: 'unlock', configurationToken: pendingUnlock });\n pendingUnlock = null;\n })(),\n ]);\n notifyClosed();\n const failures = results.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n if (failures.length > 0) throw new AggregateError(failures, 'Owned egress cleanup failed');\n return;\n }\n closed = true;\n if (timer != null) clearTimeout(timer);\n if (!stopWorkspace) {\n try {\n if (pendingUnlock != null) {\n await execute({ action: 'unlock', configurationToken: pendingUnlock });\n pendingUnlock = null;\n }\n } finally {\n notifyClosed();\n }\n return;\n }\n timer = null;\n try {\n const failures: unknown[] = [];\n let userId: string | null = onlyCurrent ? (createdLease?.userId ?? owner ?? null) : null;\n if (!onlyCurrent) {\n try {\n userId = await options.actingUser.current();\n } catch (cause) {\n failures.push(cause);\n }\n }\n let leaseId = current?.leaseId ?? null;\n let needsBlock = current != null || requiresChoice;\n let namespaceExists = true;\n try {\n namespaceExists = (await options.namespaceExists?.()) ?? true;\n } catch (cause) {\n failures.push(cause);\n }\n if (!namespaceExists) {\n try {\n if (!onlyCurrent)\n await client.egress.suspend({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n });\n else if (userId != null && leaseId != null)\n await revokeLease({\n caller: callerFor(userId),\n leaseId,\n workspaceId: options.workspaceId,\n });\n } catch (cause) {\n failures.push(cause);\n }\n if (failures.length > 0)\n throw new AggregateError(failures, 'Workspace egress close or revocation failed');\n stopped = true;\n return;\n }\n if (pendingUnlock != null) {\n try {\n await execute({ action: 'unlock', configurationToken: pendingUnlock });\n pendingUnlock = null;\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (!onlyCurrent && leaseId == null && userId != null) {\n try {\n leaseId =\n (\n await client.egress.workspace({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n })\n ).lease?.leaseId ?? null;\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (leaseId == null) {\n try {\n needsBlock ||= (await execute({ action: 'status' })).mode !== 'direct';\n } catch (cause) {\n failures.push(cause);\n needsBlock = true;\n }\n }\n if (leaseId != null || needsBlock) {\n try {\n await release({ userId, leaseId, nextOwner: userId, suspendWorkspace: !onlyCurrent });\n } catch (cause) {\n failures.push(cause);\n }\n } else if (!onlyCurrent) {\n try {\n await client.egress.suspend({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n });\n } catch (cause) {\n failures.push(cause);\n }\n }\n if (failures.length > 0)\n throw new AggregateError(failures, 'Workspace egress close or revocation failed');\n stopped = true;\n } finally {\n notifyClosed();\n }\n });\n\n return {\n initialize: () =>\n serialized(async () => {\n initializing = true;\n try {\n await maintain();\n } catch (cause) {\n reportFailure('initialize', cause);\n /* Management remains available while execution is blocked. */\n } finally {\n initializing = false;\n }\n if (timer == null) schedule();\n }),\n guard: (args?: { background?: boolean }) =>\n serialized(async () => {\n await maintain(args?.background ?? false);\n if (requiresChoice)\n throw new Error('Explicitly configure or disable workspace egress before running tools');\n }),\n setNetworkPolicy: (\n policy: NetworkPolicyIface,\n apply: (policy: NetworkPolicyIface) => Promise<void>,\n ) =>\n serialized(async () => {\n if (closed) throw new Error('Workspace egress manager is closed');\n nextRecoveryProbeAt = 0;\n const userId = await options.actingUser.current();\n await withConfigurationClaim(async () => {\n const local = await execute({ action: 'status' });\n const deviceChoicePending = local.choicePending ?? local.mode === 'blocked';\n const validated = workspaceNetworkPolicySchema.parse(policy);\n const state = await client.egress.networkState({\n organizationId: options.organizationId,\n workspaceId: options.workspaceId,\n });\n if (current != null || state.enabled || deviceChoicePending)\n throw new Error(\n 'Disable Device egress before changing the saved direct-access network policy',\n );\n if (requiresChoice)\n await execute({ action: 'block', ownerUserId: userId, restoreDirect: true });\n try {\n await client.egress.setNetworkPolicy({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n policy: validated,\n });\n directPolicy = validated;\n directPolicyKnown = true;\n await apply(validated);\n await reportLogicalPolicy();\n await execute({ action: 'disable', ownerUserId: userId });\n await waitReady(null, 'direct');\n requiresChoice = false;\n recovered = true;\n owner = userId;\n } catch (cause) {\n requiresChoice = true;\n try {\n await release({ userId, leaseId: null, nextOwner: userId, restoreDirect: true });\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n 'Network policy update and egress cleanup failed',\n );\n }\n throw cause;\n }\n });\n }),\n egress: (request: WorkspaceEgressRequestIface): Promise<WorkspaceEgressStatusIface> =>\n serialized(async () => {\n if (closed) throw new Error('Workspace egress manager is closed');\n const parsed = workspaceEgressRequestSchema.parse(request);\n const userId = await options.actingUser.current();\n if (parsed.action === WorkspaceEgressAction.Status) {\n const local = await execute({ action: 'status' });\n return workspaceEgressStatusSchema.parse(local);\n }\n if (userId == null) throw new Error('Changing Device egress requires an acting user');\n if (parsed.action === WorkspaceEgressAction.Configure) {\n if (options.allowConfiguration === false)\n throw new Error(\n 'New workspace egress configuration is disabled; existing settings can be inspected or disabled',\n );\n if (parsed.deviceIds == null) throw new Error('Configure requires Device IDs');\n await authorizeRouteMutation(userId, await execute({ action: 'status' }));\n owner = userId;\n requiresChoice = false;\n nextRecoveryAttempt = 0;\n nextRecoveryProbeAt = 0;\n try {\n return workspaceEgressStatusSchema.parse(\n await configure(userId, parsed.deviceIds, parsed.dnsResolvers),\n );\n } catch (cause) {\n requiresChoice = true;\n reportFailure('configure', cause);\n throw cause;\n }\n }\n await authorizeRouteMutation(userId, await execute({ action: 'status' }));\n owner = userId;\n requiresChoice = false;\n nextRecoveryAttempt = 0;\n nextRecoveryProbeAt = 0;\n try {\n return await withConfigurationClaim(async () => {\n const local = await execute({ action: 'status' });\n await authorizeRouteMutation(userId, local);\n await verifyConfigurationClaim();\n if (local.mode !== 'direct') {\n try {\n await block(userId);\n } catch (cause) {\n // The controller can confirm emergency denial even when the full guard fails.\n await verifyConfigurationClaim();\n const denied = await execute({ action: 'status' });\n if (\n (denied.mode !== 'blocked' &&\n !(denied.mode === 'error' && denied.networkPristine === true)) ||\n denied.ownerUserId !== userId\n )\n throw cause;\n }\n }\n await verifyConfigurationClaim();\n await client.egress.disable({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n });\n createdLease = null;\n const profile = await client.egress.workspace({\n caller: callerFor(userId),\n workspaceId: options.workspaceId,\n });\n await verifyConfigurationClaim();\n repairProviderPolicy = true;\n if (profile.networkPolicy != null) {\n directPolicy = workspaceNetworkPolicySchema.parse(profile.networkPolicy);\n directPolicyKnown = true;\n }\n await restoreNetwork(profile.networkPolicy);\n await verifyConfigurationClaim();\n repairProviderPolicy = false;\n await execute({ action: 'disable', ownerUserId: userId });\n const result = workspaceEgressStatusSchema.parse(await waitReady(null, 'direct'));\n current = null;\n recovered = true;\n return result;\n });\n } catch (cause) {\n requiresChoice = true;\n throw cause;\n }\n }),\n close: (stopWorkspace = false) => close(stopWorkspace),\n closeOnFailure: () => close(true, true),\n };\n};\n\n// Persist the provider's policy before any boot fence, including passive first attachments.\nexport const preserveWorkspaceNetworkPolicy = async (options: {\n api: DeviceApiConfigIface | (() => DeviceApiConfigIface);\n organizationId: string;\n workspaceId: string;\n policy: NetworkPolicyIface;\n client?: Pick<DeviceApiClientIface, 'egress'>;\n}): Promise<void> => {\n deviceEgressWorkspaceIdSchema.parse(options.workspaceId);\n const api = typeof options.api === 'function' ? options.api() : options.api;\n await (options.client ?? createDeviceApiClient({ api })).egress.setNetworkPolicy({\n caller: { organizationId: options.organizationId, actingUser: { current: async () => null } },\n workspaceId: options.workspaceId,\n policy: options.policy,\n initializeIfMissing: true,\n });\n};\n\nexport type WorkspaceEgressManagerIface = ReturnType<typeof createWorkspaceEgressManager>;\n\nconst workspaceEgressController = (\n manager: WorkspaceEgressManagerIface,\n): SandboxNetworkingControllerIface => ({\n initialize: manager.initialize,\n guard: async (context) => {\n // The policy operation authorizes and repairs networking without requiring a usable tunnel.\n if (\n context == null ||\n ![SandboxExecutionOperation.SetNetworkPolicy, SandboxExecutionOperation.Egress].includes(\n context.operation,\n )\n )\n await manager.guard(context);\n },\n close: manager.close,\n closeOnFailure: manager.closeOnFailure,\n extendSandbox: (sandbox) => {\n const overrides: Partial<NetworkSandboxSessionIface> = { egress: manager.egress };\n if (sandbox.screen != null) {\n const screen = sandbox.screen.bind(sandbox);\n overrides.screen = async (args) => {\n if (args?.viewOnly === false)\n throw new Error(\n 'Managed workspace screen grants are view-only; use the guarded computer-use channel for input',\n );\n return screen({ ...args, viewOnly: true });\n };\n }\n if (sandbox.setNetworkPolicy != null) {\n const apply = sandbox.setNetworkPolicy.bind(sandbox);\n overrides.setNetworkPolicy = (policy) => manager.setNetworkPolicy(policy, apply);\n }\n return withSandboxOverrides(sandbox, overrides);\n },\n authorizeExternalAccess: async () => {\n await manager.guard();\n const status = await manager.egress({ action: WorkspaceEgressAction.Status });\n return { expiresAtMs: status.expiresAtMs == null ? null : status.expiresAtMs - 90_000 };\n },\n});\n\nexport interface WorkspaceDeviceNetworkingOptionsIface {\n api: WorkspaceEgressManagerOptionsIface['api'];\n mcpFetch?: typeof globalThis.fetch;\n needed: (args: {\n organizationId: string;\n workspaceId: string;\n teardown?: boolean;\n access?: SandboxAccess;\n }) => Promise<boolean>;\n allowConfiguration?: boolean;\n authorizeOwnerChange?: (args: {\n organizationId: string;\n workspaceId: string;\n actingUserId: string | null;\n }) => Promise<void>;\n}\n\n// Final Device is one opinionated implementation of the public networking extension contract.\nexport const createWorkspaceDeviceNetworking = (\n options: WorkspaceDeviceNetworkingOptionsIface,\n): SandboxNetworkingExtensionIface => ({\n capabilities: [SandboxCapability.Egress],\n fetch: options.mcpFetch,\n validateWorkspaceId: (workspaceId) => {\n deviceEgressWorkspaceIdSchema.parse(workspaceId);\n },\n enabled: ({ ctx, workspaceId, teardown, access }) =>\n options.needed({ organizationId: ctx.organizationId, workspaceId, teardown, access }),\n prepare: async ({ ctx, workspaceId, policy }) => {\n const client = createDeviceApiClient({ api: options.api });\n await preserveWorkspaceNetworkPolicy({\n client,\n api: options.api,\n organizationId: ctx.organizationId,\n workspaceId,\n policy,\n });\n try {\n const saved = await client.egress.networkState({\n organizationId: ctx.organizationId,\n workspaceId,\n });\n return workspaceNetworkPolicySchema.parse(saved.networkPolicy);\n } catch {\n // The initialized ledger remains authoritative; admission restores reporting after recovery.\n return { mode: WorkspaceNetworkPolicy.DenyAll, allow: [] };\n }\n },\n suspend: ({ ctx, workspaceId }) =>\n suspendWorkspaceEgress({\n api: options.api,\n organizationId: ctx.organizationId,\n workspaceId,\n actingUser: ctx.actingUser,\n }),\n controller: (args) =>\n workspaceEgressController(\n createWorkspaceEgressManager({\n sandbox: args.sandbox,\n workspaceId: args.workspaceId,\n organizationId: args.ctx.organizationId,\n actingUser: args.ctx.actingUser,\n api: options.api,\n initialNetworkPolicy: args.initialNetworkPolicy,\n onNetworkPolicy: args.ctx.platformNetworkPolicy,\n privilegedRun: args.privilegedRun,\n afterGuard: args.afterGuard,\n afterBlock: args.afterBlock,\n namespaceExists: args.namespaceExists,\n onClose: args.onClose,\n allowConfiguration:\n args.access === SandboxAccess.Write && options.allowConfiguration !== false,\n allowOwnerChange: args.allowOwnerChange ?? args.access === SandboxAccess.Write,\n authorizeOwnerChange: (actingUserId) =>\n options.authorizeOwnerChange?.({\n organizationId: args.ctx.organizationId,\n workspaceId: args.workspaceId,\n actingUserId,\n }) ?? Promise.resolve(),\n onFailure: (event) => args.log?.('workspace_egress.control_failure', { ...event }),\n }),\n ),\n});\n\nexport const withWorkspaceEgress = <S extends NetworkSandboxSessionIface>(options: {\n handle: SandboxProviderHandleIface<S>;\n manager: WorkspaceEgressManagerIface;\n access: SandboxAccess;\n beforeUse?: () => Promise<void>;\n initialized?: boolean;\n fetch?: typeof globalThis.fetch;\n}): Promise<SandboxProviderHandleIface<S>> =>\n withSandboxNetworking({\n ...options,\n controller: workspaceEgressController(options.manager),\n });\n\nexport const withWorkspaceAdmission = <S extends NetworkSandboxSessionIface>(options: {\n handle: SandboxProviderHandleIface<S>;\n access: SandboxAccess;\n admission: () => Promise<void>;\n fetch?: typeof globalThis.fetch;\n}): Promise<SandboxProviderHandleIface<S>> => withSandboxNetworking(options);\n"],
5
+ "mappings": "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",
6
+ "names": ["hash", "local"]
7
+ }
@@ -245,6 +245,7 @@ const readOnlySession = (session) => {
245
245
  destroy: readOnlyRefusal
246
246
  };
247
247
  if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;
248
+ delete restricted.egress;
248
249
  const screen = session.screen;
249
250
  if (screen != null)
250
251
  restricted.screen = async (options) => {
@@ -256,15 +257,19 @@ const readOnlySession = (session) => {
256
257
  const fileWriteRefusal = async () => {
257
258
  throw new Error("this sandbox binding runs processes but does not write files");
258
259
  };
259
- const executeOnlySession = (session) => ({
260
- ...session,
261
- writeFile: fileWriteRefusal,
262
- writeBinaryFile: fileWriteRefusal,
263
- writeTextFile: fileWriteRefusal,
264
- removePath: fileWriteRefusal,
265
- stop: fileWriteRefusal,
266
- destroy: fileWriteRefusal
267
- });
260
+ const executeOnlySession = (session) => {
261
+ const restricted = {
262
+ ...session,
263
+ writeFile: fileWriteRefusal,
264
+ writeBinaryFile: fileWriteRefusal,
265
+ writeTextFile: fileWriteRefusal,
266
+ removePath: fileWriteRefusal,
267
+ stop: fileWriteRefusal,
268
+ destroy: fileWriteRefusal
269
+ };
270
+ delete restricted.egress;
271
+ return restricted;
272
+ };
268
273
  const sessionForAccess = (session, access) => access === SandboxAccess.Read ? readOnlySession(session) : access === SandboxAccess.Execute ? executeOnlySession(session) : session;
269
274
  export {
270
275
  createTransportSession,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/session.ts"],
4
- "sourcesContent": ["import { SandboxAccess } from '@finalai/agent-provider';\nimport type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport { exitStatus, type SandboxTransportIface, type TransportProcessIface } from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n}\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n const { stream: stdout } = stdoutPush;\n const { stream: stderr } = stderrPush;\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n\n const kill = async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n const onAbort = (): void => {\n void kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n\n void (async () => {\n let stdoutOffset = 0;\n let stderrOffset = 0;\n let waitMs = transport.outputWaitMs;\n try {\n for (;;) {\n const output = await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n });\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n } finally {\n options.abortSignal?.removeEventListener('abort', onAbort);\n }\n })();\n\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n for await (const chunk of rechunk(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n stdout,\n stderr,\n write,\n wait: () => exit,\n kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess(options, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding is read-only');\n};\n\n// A read binding's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the lease the provider took.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n\nconst fileWriteRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding runs processes but does not write files');\n};\n\n// An execute binding's view of a handle: reads and processes pass through; file\n// writes and lifecycle are refused.\nexport const executeOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => ({\n ...session,\n writeFile: fileWriteRefusal,\n writeBinaryFile: fileWriteRefusal,\n writeTextFile: fileWriteRefusal,\n removePath: fileWriteRefusal,\n stop: fileWriteRefusal,\n destroy: fileWriteRefusal,\n});\n\n// The view of a handle that a binding's access allows.\nexport const sessionForAccess = <S extends NetworkSandboxSessionIface>(\n session: S,\n access: SandboxAccess,\n): S =>\n access === SandboxAccess.Read\n ? readOnlySession(session)\n : access === SandboxAccess.Execute\n ? executeOnlySession(session)\n : session;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { SandboxAccess } from '@finalai/agent-provider';\nimport type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport { exitStatus, type SandboxTransportIface, type TransportProcessIface } from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n}\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n const { stream: stdout } = stdoutPush;\n const { stream: stderr } = stderrPush;\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n\n const kill = async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n const onAbort = (): void => {\n void kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n\n void (async () => {\n let stdoutOffset = 0;\n let stderrOffset = 0;\n let waitMs = transport.outputWaitMs;\n try {\n for (;;) {\n const output = await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n });\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n } finally {\n options.abortSignal?.removeEventListener('abort', onAbort);\n }\n })();\n\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n for await (const chunk of rechunk(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n stdout,\n stderr,\n write,\n wait: () => exit,\n kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess(options, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding is read-only');\n};\n\n// A read binding's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the lease the provider took.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n delete restricted.egress;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n\nconst fileWriteRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding runs processes but does not write files');\n};\n\n// An execute binding's view of a handle: reads and processes pass through; file\n// writes and lifecycle are refused.\nexport const executeOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: fileWriteRefusal,\n writeBinaryFile: fileWriteRefusal,\n writeTextFile: fileWriteRefusal,\n removePath: fileWriteRefusal,\n stop: fileWriteRefusal,\n destroy: fileWriteRefusal,\n };\n delete restricted.egress;\n return restricted;\n};\n\n// The view of a handle that a binding's access allows.\nexport const sessionForAccess = <S extends NetworkSandboxSessionIface>(\n session: S,\n access: SandboxAccess,\n): S =>\n access === SandboxAccess.Read\n ? readOnlySession(session)\n : access === SandboxAccess.Execute\n ? executeOnlySession(session)\n : session;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -92,6 +92,7 @@ const createFakeComputersApi = (args = {}) => {
92
92
  id: computer.id,
93
93
  name: computer.name,
94
94
  state: computer.state,
95
+ network: computer.body.network ?? { egress: ComputerEgressPolicy.Internet },
95
96
  imageVersionId: z.string().nullable().catch(null).parse(computer.body.imageVersionId ?? null),
96
97
  teamId: z.string().nullable().catch(null).parse(computer.body.teamId ?? null),
97
98
  hostname: `${computer.name}-k3p9x7qd.virtual-machine.lax-2.example`,
@@ -248,8 +249,9 @@ const createFakeComputersApi = (args = {}) => {
248
249
  expiresAt: new Date(Date.now() + 9e5).toISOString()
249
250
  });
250
251
  if (request.method === "PATCH" && rest === "") {
251
- const patch = createComputerSchema.pick({ network: true }).parse(body);
252
+ const patch = createComputerSchema.pick({ network: true, autoResume: true }).parse(body);
252
253
  if (patch.network != null) computer.body.network = patch.network;
254
+ if (patch.autoResume != null) computer.body.autoResume = patch.autoResume;
253
255
  return json({ computer: wire(computer) });
254
256
  }
255
257
  if (request.method === "GET" && rest === "/computer-use")