@finalai/final-agent-provider 0.5.0 → 0.6.1

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.
Files changed (30) hide show
  1. package/HOSTING.md +3 -3
  2. package/README.md +4 -0
  3. package/WORKSPACE-EGRESS.md +7 -6
  4. package/dist/modules/channels/projection.d.mts +13 -7
  5. package/dist/modules/channels/projection.mjs +49 -31
  6. package/dist/modules/channels/projection.mjs.map +2 -2
  7. package/dist/modules/sandboxes/computer.d.mts +4 -3
  8. package/dist/modules/sandboxes/computer.mjs +22 -35
  9. package/dist/modules/sandboxes/computer.mjs.map +2 -2
  10. package/dist/modules/sandboxes/computers-api.d.mts +2 -17
  11. package/dist/modules/sandboxes/computers-api.mjs +27 -44
  12. package/dist/modules/sandboxes/computers-api.mjs.map +2 -2
  13. package/dist/modules/sandboxes/device-api.d.mts +3 -8
  14. package/dist/modules/sandboxes/device-api.mjs +17 -28
  15. package/dist/modules/sandboxes/device-api.mjs.map +3 -3
  16. package/dist/modules/sandboxes/device.d.mts +2 -1
  17. package/dist/modules/sandboxes/device.mjs +13 -5
  18. package/dist/modules/sandboxes/device.mjs.map +2 -2
  19. package/dist/modules/sandboxes/egress.d.mts +4 -1
  20. package/dist/modules/sandboxes/egress.mjs +20 -2
  21. package/dist/modules/sandboxes/egress.mjs.map +2 -2
  22. package/dist/modules/sandboxes/environment.d.mts +0 -3
  23. package/dist/modules/sandboxes/environment.mjs +2 -8
  24. package/dist/modules/sandboxes/environment.mjs.map +2 -2
  25. package/dist/modules/sandboxes/index.d.mts +1 -1
  26. package/dist/modules/sandboxes/index.mjs +0 -2
  27. package/dist/modules/sandboxes/index.mjs.map +2 -2
  28. package/dist/modules/sandboxes/testing/fake-backends.mjs +2 -2
  29. package/dist/modules/sandboxes/testing/fake-backends.mjs.map +2 -2
  30. package/package.json +5 -5
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/device-api.ts"],
4
- "sourcesContent": ["import {\n deviceEgressCreateRequestSchema,\n deviceEgressWorkspaceIdSchema,\n deviceEgressEnrollmentSchema,\n deviceEgressLeaseSchema,\n deviceEgressWorkspaceSchema,\n workspaceNetworkPolicySchema,\n deviceWorkspaceNetworkStateSchema,\n type WorkspaceNetworkPolicyIface,\n} from '@finalai/agent-protocol/device-egress';\nimport {\n ProcessInspectionOperation,\n processInspectionResultSchema,\n type ProcessInspectionRequestIface,\n type ProcessInspectionResultIface,\n} from '@finalai/agent-protocol/process-inspection';\nimport { jsonObjectSchema, jsonValueSchema, type JsonValue } from '@finalai/agent-provider';\nimport { SandboxEntryType, type SandboxActingUserIface } from '@finalai/agent-provider/sandbox';\nimport * as z from 'zod';\nimport { decodeBase64, encodeBase64 } from \"./bytes.mjs\";\nimport { DEVICE_API_ACTING_USER_HEADER } from \"./environment.mjs\";\nimport type {\n SandboxTransportIface,\n TransportDirEntryIface,\n TransportOutputIface,\n TransportStatIface,\n} from \"./transport.mjs\";\n\n// A client of the Device API, authenticated with host-issued user credentials\n// or customer-managed API keys. Device operations also name the acting user;\n// the API enforces ownership independently of the credential type.\n\n// The Device API's header naming the user a request acts for (a Final user id).\nexport { DEVICE_API_ACTING_USER_HEADER } from \"./environment.mjs\";\n\n// The organization and user a call acts for; the user is read on each call.\nexport interface DeviceApiCallerIface {\n organizationId: string;\n actingUser: SandboxActingUserIface;\n}\n\nexport interface DeviceApiConfigIface {\n // The Device API origin.\n url: string;\n // A credential for this organization and acting user; hosts may issue a\n // short-lived user token or return a customer-managed API key.\n // Workspace networking requires a trusted service credential when the user\n // is null (admission, policy persistence, and cleanup). User-only hosts cannot\n // enable that extension. Reconciliation may name a stored lease owner rather\n // than a present turn author; authorize that background work in host composition.\n credential: (args: {\n organizationId: string;\n actingUserId: string | null;\n }) => Promise<string | null>;\n // Per-user cache lifetime (default 60 s); keep below any issued token lifetime.\n credentialTtlMs?: number;\n fetch?: DeviceApiFetchIface;\n}\n\nexport interface DeviceApiFetchIface {\n (input: string, init: RequestInit): Promise<Response>;\n}\n\nexport enum DeviceApiLeaseAccess {\n Read = 'read',\n Write = 'write',\n}\n\nexport enum DeviceApiCapability {\n Files = 'files',\n Process = 'process',\n ComputerUse = 'computer-use',\n LocalMcp = 'local-mcp',\n}\n\nexport const DEVICE_API_COMPUTER_USE_SERVER = 'computer-use';\n\n// Unknown values from a newer API read as absent rather than failing the call.\nconst tolerantEnum = <T extends Record<string, string>>(values: T) =>\n z.string().transform((value): T[keyof T] | null => {\n const parsed = z.nativeEnum(values).safeParse(value);\n return parsed.success ? parsed.data : null;\n });\n\nconst deviceSchema = z.object({\n id: z.string(),\n organizationId: z.string(),\n displayName: z.string(),\n os: z.string(),\n online: z.boolean(),\n writable: z.boolean(),\n allowProcesses: z.boolean(),\n computerUseReady: z.boolean(),\n screenReady: z.boolean(),\n});\nexport type DeviceApiDeviceIface = z.infer<typeof deviceSchema>;\n\nconst leaseSchema = z.object({\n lease: z.string(),\n deviceId: z.string(),\n generation: z.number(),\n workspaceRoot: z.string(),\n platform: z.string(),\n access: z.nativeEnum(DeviceApiLeaseAccess),\n capabilities: z.array(tolerantEnum(DeviceApiCapability)),\n expiresAt: z.string(),\n});\nexport interface DeviceApiLeaseIface {\n lease: string;\n deviceId: string;\n generation: number;\n workspaceRoot: string;\n platform: string;\n access: DeviceApiLeaseAccess;\n capabilities: DeviceApiCapability[];\n expiresAtMs: number;\n}\n\ninterface ProcessInputBodyIface {\n bootId: string;\n dataBase64?: string;\n eof?: boolean;\n}\n\nconst errorBodySchema = z.object({ error: z.object({ code: z.string(), message: z.string() }) });\nconst statBodySchema = z.object({\n stat: z\n .object({\n type: tolerantEnum(SandboxEntryType),\n size: z.number(),\n modifiedAtMs: z.number().nullable(),\n mode: z.number().nullable(),\n })\n .nullable(),\n});\nconst dirBodySchema = z.object({\n entries: z.array(\n z.object({\n name: z.string(),\n type: tolerantEnum(SandboxEntryType),\n size: z.number().nullable(),\n }),\n ),\n});\nconst processSchema = z.object({ id: z.string(), bootId: z.string() });\nconst outputStreamSchema = z.object({\n dataBase64: z.string(),\n nextOffset: z.number(),\n eof: z.boolean(),\n});\nconst outputSchema = z.object({\n stdout: outputStreamSchema,\n stderr: outputStreamSchema,\n exited: z.boolean(),\n exitCode: z.number().nullable(),\n exitSignal: z.string().nullable(),\n});\nconst devicesSchema = z.object({ devices: z.array(deviceSchema) });\nconst serversSchema = z.object({ servers: z.array(z.string()) });\n// A Device server's tool as the API recorded it; checked against the tool\n// descriptor contract where the provider hands it on.\nconst catalogToolSchema = jsonObjectSchema;\nconst mcpCatalogSchema = z.object({\n computerUse: z.object({ tools: z.array(catalogToolSchema) }).nullable(),\n localServers: z\n .object({\n servers: z.array(\n z.object({ name: z.string(), tools: z.array(catalogToolSchema).nullable() }),\n ),\n })\n .nullable(),\n});\nexport type DeviceApiMcpCatalogIface = z.infer<typeof mcpCatalogSchema>;\nconst pipeReadSchema = z.object({ dataBase64: z.string().optional() });\nconst screenSchema = z.object({ url: z.string(), token: z.string(), expiresAt: z.string() });\nconst emptySchema = z.unknown();\n\n// One ranged read or write; the API splits it into the Device's own chunks.\nexport const DEVICE_API_FILE_CHUNK_BYTES = 4 * 1024 * 1024;\n// The API long-polls the Device for output up to this long.\nexport const DEVICE_API_OUTPUT_WAIT_MS = 15_000;\n\nexport enum DeviceApiClientErrorCode {\n // The host returned no credential for this user or trusted service call.\n CredentialMissing = 'credential_missing',\n // The session acts for no user, and a Device is only used for its owner.\n NoActingUser = 'no_acting_user',\n EgressEnrollmentLost = 'egress_enrollment_lost',\n}\n\nexport interface DeviceApiErrorIface extends Error {\n status: number | null;\n code: string;\n}\n\nconst apiError = (status: number, code: string, message: string): DeviceApiErrorIface =>\n Object.assign(new Error(`Device API ${status} ${code}: ${message}`), { status, code });\n\nconst credentialMissing = (actingUserId: string | null): DeviceApiErrorIface =>\n Object.assign(\n new Error(\n `Device API access is unavailable ${actingUserId == null ? 'for workspace networking (no acting user)' : 'for this acting user'}: configure the credential callback`,\n ),\n { status: null, code: DeviceApiClientErrorCode.CredentialMissing },\n );\n\nconst noActingUser = (): DeviceApiErrorIface =>\n Object.assign(\n new Error(\n 'this session acts for no user, and a Final Device is only used by sessions acting for its owner',\n ),\n { status: null, code: DeviceApiClientErrorCode.NoActingUser },\n );\n\nconst statusSchema = z.object({ status: z.number() });\nexport const deviceApiCodeOf = (cause: unknown): string | null =>\n z.object({ code: z.string() }).safeParse(cause).data?.code ?? null;\n\nexport const deviceApiStatusOf = (cause: Error): number | null =>\n statusSchema.safeParse(cause).data?.status ?? null;\n\nconst parseJson = (text: string): JsonValue => {\n try {\n return jsonValueSchema.parse(JSON.parse(text));\n } catch {\n return null;\n }\n};\n\nconst leaseOf = (raw: z.infer<typeof leaseSchema>): DeviceApiLeaseIface => ({\n lease: raw.lease,\n deviceId: raw.deviceId,\n generation: raw.generation,\n workspaceRoot: raw.workspaceRoot,\n platform: raw.platform,\n access: raw.access,\n capabilities: raw.capabilities.filter((capability) => capability != null),\n expiresAtMs: Date.parse(raw.expiresAt),\n});\n\nexport interface DeviceApiClientIface {\n egress: {\n networkState(args: {\n organizationId: string;\n workspaceId: string;\n }): Promise<z.infer<typeof deviceWorkspaceNetworkStateSchema>>;\n setNetworkPolicy(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n policy: WorkspaceNetworkPolicyIface;\n initializeIfMissing?: boolean;\n }): Promise<void>;\n workspace(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n }): Promise<z.infer<typeof deviceEgressWorkspaceSchema>>;\n create(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n deviceIds: string[];\n dnsResolvers?: string[];\n }): Promise<z.infer<typeof deviceEgressEnrollmentSchema>>;\n renew(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n }): Promise<z.infer<typeof deviceEgressLeaseSchema>>;\n activate(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n }): Promise<z.infer<typeof deviceEgressLeaseSchema>>;\n revoke(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n workspaceId: string;\n }): Promise<void>;\n disable(args: { caller: DeviceApiCallerIface; workspaceId: string }): Promise<void>;\n suspend(args: { caller: DeviceApiCallerIface; workspaceId: string }): Promise<void>;\n };\n releaseWorkspaceLeases(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n bindingId: string;\n }): Promise<void>;\n inspectProcesses(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n bindingId: string;\n request: ProcessInspectionRequestIface;\n }): Promise<ProcessInspectionResultIface>;\n getDevice(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n }): Promise<DeviceApiDeviceIface | null>;\n // The Devices of the user the call acts for.\n listDevices(args: { caller: DeviceApiCallerIface }): Promise<DeviceApiDeviceIface[]>;\n resolvePairing(args: {\n caller: DeviceApiCallerIface;\n code: string;\n }): Promise<DeviceApiDeviceIface | null>;\n lease(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n bindingId: string;\n access: DeviceApiLeaseAccess;\n ttlMs: number;\n afterGeneration?: number;\n }): Promise<DeviceApiLeaseIface>;\n recoverLease(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n bindingId: string;\n access: DeviceApiLeaseAccess;\n }): Promise<DeviceApiLeaseIface>;\n renew(args: {\n caller: DeviceApiCallerIface;\n lease: string;\n ttlMs: number;\n }): Promise<DeviceApiLeaseIface>;\n release(args: { caller: DeviceApiCallerIface; lease: string }): Promise<void>;\n // The sandbox transport over one lease; `lease()` is the current handle.\n transport(args: {\n caller: DeviceApiCallerIface;\n lease: () => Promise<string>;\n }): SandboxTransportIface;\n localMcpServers(args: { caller: DeviceApiCallerIface; lease: string }): Promise<string[]>;\n // What the Device's MCP servers last listed through the API, without a lease.\n mcpCatalog(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n }): Promise<DeviceApiMcpCatalogIface>;\n pipe(args: {\n caller: DeviceApiCallerIface;\n lease: string;\n server: string;\n action: 'open' | 'write' | 'read' | 'close';\n clientId: string;\n dataBase64?: string;\n signal?: AbortSignal;\n }): Promise<string>;\n screen(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n viewOnly?: boolean;\n }): Promise<{ url: string; token: string; expiresAt: string }>;\n}\n\nexport const createDeviceApiClient = (config: {\n api: DeviceApiConfigIface | (() => DeviceApiConfigIface);\n fetch?: DeviceApiFetchIface;\n now?: () => number;\n}): DeviceApiClientIface => {\n const now = config.now ?? Date.now;\n const readApi = () => (typeof config.api === 'function' ? config.api() : config.api);\n const keys = new Map<string, { key: string; expiresAtMs: number }>();\n\n const failure = async (response: Response): Promise<DeviceApiErrorIface> => {\n // Read as text so proxy and load balancer error pages survive.\n const text = await response.text().catch(() => '');\n const body = errorBodySchema.safeParse(parseJson(text));\n return body.success\n ? apiError(response.status, body.data.error.code, body.data.error.message)\n : apiError(response.status, 'http', text.slice(0, 200) || response.statusText);\n };\n\n // Keep user and trusted service credentials separate, including across API origins.\n const credentialFor = async (args: {\n organizationId: string;\n actingUserId: string | null;\n reread: boolean;\n api: DeviceApiConfigIface;\n }): Promise<string> => {\n const { organizationId, actingUserId, reread, api } = args;\n const cacheKey = JSON.stringify([api.url, organizationId, actingUserId]);\n const currentTime = now();\n for (const [key, entry] of keys) {\n if (entry.expiresAtMs <= currentTime) keys.delete(key);\n }\n const cached = keys.get(cacheKey);\n if (cached != null && !reread) return cached.key;\n const key = await api.credential({ organizationId, actingUserId });\n if (key == null) {\n keys.delete(cacheKey);\n throw credentialMissing(actingUserId);\n }\n keys.set(cacheKey, { key, expiresAtMs: now() + (api.credentialTtlMs ?? 60_000) });\n return key;\n };\n\n // One authenticated call for the user it acts for; a rejected key is read\n // again once, in case it was rotated.\n const send = async (args: {\n caller: DeviceApiCallerIface;\n method: string;\n path: string;\n query?: Record<string, string>;\n body?: BodyInit;\n contentType?: string;\n signal?: AbortSignal;\n anonymous?: boolean;\n }): Promise<Response> => {\n const api = readApi();\n const origin = api.url.replace(/\\/+$/, '');\n const url = new URL(`${origin}${args.path}`);\n for (const [key, value] of Object.entries(args.query ?? {})) url.searchParams.set(key, value);\n const actingUserId = await args.caller.actingUser.current();\n if (actingUserId == null && !args.anonymous) throw noActingUser();\n const attempt = async (refresh: boolean): Promise<Response> => {\n const headers = new Headers({\n authorization: `Bearer ${await credentialFor({ organizationId: args.caller.organizationId, actingUserId, reread: refresh, api })}`,\n });\n if (actingUserId != null) headers.set(DEVICE_API_ACTING_USER_HEADER, actingUserId);\n if (args.contentType != null) headers.set('content-type', args.contentType);\n return (config.fetch ?? api.fetch ?? fetch)(url.toString(), {\n method: args.method,\n headers,\n body: args.body,\n signal: args.signal,\n });\n };\n let response = await attempt(false);\n if (response.status === 401) {\n await response.text().catch(() => '');\n response = await attempt(true);\n }\n return response;\n };\n\n const json = async <T extends z.ZodType>(\n schema: T,\n args: Parameters<typeof send>[0] & { json?: unknown },\n ): Promise<z.infer<T>> => {\n const response = await send({\n ...args,\n body: args.json === undefined ? args.body : JSON.stringify(args.json),\n contentType: args.json === undefined ? args.contentType : 'application/json',\n });\n if (!response.ok) throw await failure(response);\n const text = await response.text();\n return schema.parse(text === '' ? null : parseJson(text));\n };\n\n // A 404 reads as absent.\n const orNull = async <T>(work: Promise<T>): Promise<T | null> => {\n try {\n return await work;\n } catch (cause) {\n if (cause instanceof Error && deviceApiStatusOf(cause) === 404) return null;\n throw cause;\n }\n };\n\n const leasePath = (lease: string, rest: string): string =>\n `/v1/leases/${encodeURIComponent(lease)}${rest}`;\n\n const transport: DeviceApiClientIface['transport'] = ({ caller, lease }) => {\n const call = async <T extends z.ZodType>(\n schema: T,\n args: Omit<Parameters<typeof json>[1], 'caller' | 'path'> & { path: string },\n ): Promise<z.infer<T>> =>\n json(schema, { ...args, caller, path: leasePath(await lease(), args.path) });\n const processPath = (id: string, rest: string): string =>\n `/processes/${encodeURIComponent(id)}${rest}`;\n return {\n kind: 'device-api',\n fileChunkBytes: DEVICE_API_FILE_CHUNK_BYTES,\n outputWaitMs: DEVICE_API_OUTPUT_WAIT_MS,\n stat: async ({ path, signal }): Promise<TransportStatIface | null> => {\n const { stat } = await call(statBodySchema, {\n method: 'GET',\n path: '/files/stat',\n query: { path },\n signal,\n });\n return stat == null ? null : { ...stat, type: stat.type ?? SandboxEntryType.Other };\n },\n readDir: async ({ path, signal }): Promise<TransportDirEntryIface[]> =>\n (\n await call(dirBodySchema, { method: 'GET', path: '/files/dir', query: { path }, signal })\n ).entries.map((entry) => ({ ...entry, type: entry.type ?? SandboxEntryType.Other })),\n readChunk: async ({ path, offset, length, signal }) => {\n const response = await send({\n caller,\n method: 'GET',\n path: leasePath(await lease(), '/files/content'),\n query: { path, offset: String(offset), length: String(length) },\n signal,\n });\n if (!response.ok) throw await failure(response);\n const bytes = new Uint8Array(await response.arrayBuffer());\n return { bytes, eof: bytes.byteLength < length };\n },\n writeChunk: async ({ path, offset, bytes, signal }) => {\n await call(emptySchema, {\n method: 'PUT',\n path: '/files/content',\n query: { path, offset: String(offset) },\n body: new Blob([bytes.slice()]),\n contentType: 'application/octet-stream',\n signal,\n });\n },\n createDirectory: async ({ path, signal }) => {\n await call(emptySchema, {\n method: 'POST',\n path: '/files/directories',\n json: { path },\n signal,\n });\n },\n remove: async ({ path, recursive, force, signal }) => {\n await call(emptySchema, {\n method: 'DELETE',\n path: '/files',\n query: { path, recursive: String(recursive), force: String(force) },\n signal,\n });\n },\n exec: async ({ id, command, cwd, env, timeoutMs, signal }) =>\n call(processSchema, {\n method: 'POST',\n path: '/processes',\n json: { id, command, cwd, env, timeoutMs },\n signal,\n }),\n output: async ({ process, stdoutOffset, stderrOffset, waitMs, signal }) => {\n const output = await call(outputSchema, {\n method: 'POST',\n path: processPath(process.id, '/output'),\n json: { bootId: process.bootId, stdoutOffset, stderrOffset, waitMs },\n signal,\n });\n const stream = (value: z.infer<typeof outputStreamSchema>) => ({\n data: decodeBase64(value.dataBase64),\n nextOffset: value.nextOffset,\n eof: value.eof,\n });\n const result: TransportOutputIface = {\n stdout: stream(output.stdout),\n stderr: stream(output.stderr),\n exited: output.exited,\n exitCode: output.exitCode,\n exitSignal: output.exitSignal,\n };\n return result;\n },\n input: async ({ process, data, eof, signal, terminate, abortSignal }) => {\n if (terminate === true || signal != null) {\n await call(emptySchema, {\n method: 'POST',\n path: processPath(process.id, '/kill'),\n json:\n terminate === true ? { bootId: process.bootId } : { bootId: process.bootId, signal },\n signal: abortSignal,\n });\n if (terminate === true) return;\n }\n if ((data != null && data.byteLength > 0) || eof === true) {\n const body: ProcessInputBodyIface = {\n bootId: process.bootId,\n };\n if (data != null && data.byteLength > 0) body.dataBase64 = encodeBase64(data);\n if (eof === true) body.eof = true;\n await call(emptySchema, {\n method: 'POST',\n path: processPath(process.id, '/input'),\n json: body,\n signal: abortSignal,\n });\n }\n },\n close: () => undefined,\n };\n };\n\n return {\n egress: {\n networkState: ({ organizationId, workspaceId }) =>\n json(deviceWorkspaceNetworkStateSchema, {\n caller: { organizationId, actingUser: { current: async () => null } },\n anonymous: true,\n method: 'GET',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/network-state`,\n signal: AbortSignal.timeout(30_000),\n }),\n setNetworkPolicy: async ({ caller, workspaceId, policy, initializeIfMissing }) => {\n const userId = await caller.actingUser.current();\n const anonymous = userId == null;\n const resolvedCaller = { ...caller, actingUser: { current: async () => userId } };\n const result = await json(z.object({ ok: z.boolean() }), {\n caller: resolvedCaller,\n method: initializeIfMissing === true ? 'POST' : 'PUT',\n anonymous,\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/${initializeIfMissing === true ? 'network-state/initialize' : anonymous ? 'network-state' : 'network-policy'}`,\n json: workspaceNetworkPolicySchema.parse(policy),\n signal: AbortSignal.timeout(30_000),\n });\n if (!result.ok) throw new Error('Device API did not save the workspace network policy');\n },\n workspace: ({ caller, workspaceId }) =>\n json(deviceEgressWorkspaceSchema, {\n caller,\n method: 'GET',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}`,\n signal: AbortSignal.timeout(30_000),\n }),\n create: ({ caller, ...input }) =>\n json(deviceEgressEnrollmentSchema, {\n caller,\n method: 'POST',\n path: '/v1/egress/leases',\n json: deviceEgressCreateRequestSchema.parse(input),\n signal: AbortSignal.timeout(180_000),\n }),\n renew: ({ caller, leaseId }) =>\n json(deviceEgressLeaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}/renew`,\n signal: AbortSignal.timeout(180_000),\n }),\n activate: ({ caller, leaseId }) =>\n json(deviceEgressLeaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}/activate`,\n signal: AbortSignal.timeout(60_000),\n }),\n revoke: async ({ caller, leaseId, workspaceId }) => {\n await json(emptySchema, {\n caller,\n method: 'DELETE',\n json: { workspaceId },\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n suspend: async ({\n caller,\n workspaceId,\n }: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n }) => {\n const userId = await caller.actingUser.current();\n const anonymous = userId == null;\n const resolvedCaller = { ...caller, actingUser: { current: async () => userId } };\n await json(emptySchema, {\n caller: resolvedCaller,\n anonymous,\n method: 'POST',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/${anonymous ? 'network-state/suspend' : 'suspend'}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n disable: async ({ caller, workspaceId }) => {\n await json(emptySchema, {\n caller,\n method: 'DELETE',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n },\n releaseWorkspaceLeases: async ({ caller, deviceId, bindingId }) => {\n const result = await json(z.object({ released: z.boolean() }), {\n caller,\n method: 'DELETE',\n path:\n '/v1/devices/' +\n encodeURIComponent(deviceId) +\n '/workspaces/' +\n encodeURIComponent(bindingId) +\n '/leases',\n });\n if (!result.released) throw new Error('The Device did not release its workspace leases');\n },\n inspectProcesses: ({ caller, deviceId, bindingId, request }) => {\n const suffix =\n request.operation === ProcessInspectionOperation.Available\n ? '/available'\n : 'processId' in request\n ? '/' + encodeURIComponent(request.processId)\n : '';\n const query: Record<string, string> = {};\n if (bindingId != null) query.bindingId = bindingId;\n if ('bootId' in request) query.bootId = request.bootId;\n if ('cursor' in request && request.cursor != null) query.cursor = request.cursor;\n if ('limit' in request && request.limit != null) query.limit = String(request.limit);\n return json(processInspectionResultSchema, {\n caller,\n method: request.operation === ProcessInspectionOperation.Stop ? 'DELETE' : 'GET',\n path: '/v1/devices/' + encodeURIComponent(deviceId) + '/processes' + suffix,\n query,\n });\n },\n getDevice: ({ caller, deviceId }) =>\n orNull(\n json(deviceSchema, {\n caller,\n method: 'GET',\n path: `/v1/devices/${encodeURIComponent(deviceId)}`,\n }),\n ),\n listDevices: async ({ caller }) =>\n (await json(devicesSchema, { caller, method: 'GET', path: '/v1/devices' })).devices,\n resolvePairing: ({ caller, code }) =>\n orNull(\n json(deviceSchema, {\n caller,\n method: 'POST',\n path: '/v1/pairings/resolve',\n json: { code },\n }),\n ),\n lease: async ({ caller, deviceId, sessionId, bindingId, access, ttlMs, afterGeneration }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/leases`,\n json: { sessionId, bindingId, access, ttlMs, afterGeneration },\n }),\n ),\n recoverLease: async ({ caller, deviceId, sessionId, bindingId, access }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/leases/recover`,\n json: { sessionId, bindingId, access },\n }),\n ),\n renew: async ({ caller, lease, ttlMs }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: leasePath(lease, '/renew'),\n json: { ttlMs },\n }),\n ),\n release: async ({ caller, lease }) => {\n await json(emptySchema, { caller, method: 'DELETE', path: leasePath(lease, '') });\n },\n transport,\n mcpCatalog: ({ caller, deviceId }) =>\n json(mcpCatalogSchema, {\n caller,\n method: 'GET',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/mcp`,\n }),\n localMcpServers: async ({ caller, lease }) =>\n (await json(serversSchema, { caller, method: 'GET', path: leasePath(lease, '/mcp') }))\n .servers,\n pipe: async ({ caller, lease, server, action, clientId, dataBase64, signal }) =>\n (\n await json(pipeReadSchema, {\n caller,\n method: 'POST',\n path: leasePath(lease, `/mcp/${encodeURIComponent(server)}/${action}`),\n json: dataBase64 == null ? { clientId } : { clientId, dataBase64 },\n signal,\n })\n ).dataBase64 ?? '',\n screen: ({ caller, deviceId, sessionId, viewOnly }) =>\n json(screenSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/screen`,\n json: { sessionId, viewOnly },\n }),\n };\n};\n"],
5
- "mappings": "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",
6
- "names": ["DEVICE_API_ACTING_USER_HEADER", "DeviceApiLeaseAccess", "DeviceApiCapability", "DeviceApiClientErrorCode", "key"]
4
+ "sourcesContent": ["import {\n deviceEgressCreateRequestSchema,\n deviceEgressWorkspaceIdSchema,\n deviceEgressEnrollmentSchema,\n deviceEgressLeaseSchema,\n deviceEgressWorkspaceSchema,\n workspaceNetworkPolicySchema,\n deviceWorkspaceNetworkStateSchema,\n type WorkspaceNetworkPolicyIface,\n} from '@finalai/agent-protocol/device-egress';\nimport {\n ProcessInspectionOperation,\n processInspectionResultSchema,\n type ProcessInspectionRequestIface,\n type ProcessInspectionResultIface,\n} from '@finalai/agent-protocol/process-inspection';\nimport { jsonObjectSchema, jsonValueSchema, type JsonValue } from '@finalai/agent-provider';\nimport {\n SandboxEntryType,\n type FinalPlatformAccessIface,\n type SandboxActingUserIface,\n type SandboxCredentialsIface,\n} from '@finalai/agent-provider/sandbox';\nimport * as z from 'zod';\nimport { decodeBase64, encodeBase64 } from \"./bytes.mjs\";\nimport { DEVICE_API_ACTING_USER_HEADER } from \"./environment.mjs\";\nimport type {\n SandboxTransportIface,\n TransportDirEntryIface,\n TransportOutputIface,\n TransportStatIface,\n} from \"./transport.mjs\";\n\n// A client of the Device API, authenticated with the context's\n// `credentials.deviceAccess`. Device operations also name the acting user; the API\n// enforces ownership independently of the token.\n\n// The Device API's header naming the user a request acts for (a Final user id).\nexport { DEVICE_API_ACTING_USER_HEADER } from \"./environment.mjs\";\n\n// The organization, credentials and user a call acts for; the user is read on each\n// call. Workspace networking also calls with no user (admission, policy\n// persistence and cleanup), which needs service access from `deviceAccess`.\nexport interface DeviceApiCallerIface {\n organizationId: string;\n credentials?: SandboxCredentialsIface;\n actingUser: SandboxActingUserIface;\n}\n\n// Transport options; the API origin and token come from the caller's credentials.\nexport interface DeviceApiConfigIface {\n fetch?: DeviceApiFetchIface;\n}\n\nexport interface DeviceApiFetchIface {\n (input: string, init: RequestInit): Promise<Response>;\n}\n\nexport enum DeviceApiLeaseAccess {\n Read = 'read',\n Write = 'write',\n}\n\nexport enum DeviceApiCapability {\n Files = 'files',\n Process = 'process',\n ComputerUse = 'computer-use',\n LocalMcp = 'local-mcp',\n}\n\nexport const DEVICE_API_COMPUTER_USE_SERVER = 'computer-use';\n\n// Unknown values from a newer API read as absent rather than failing the call.\nconst tolerantEnum = <T extends Record<string, string>>(values: T) =>\n z.string().transform((value): T[keyof T] | null => {\n const parsed = z.nativeEnum(values).safeParse(value);\n return parsed.success ? parsed.data : null;\n });\n\nconst deviceSchema = z.object({\n id: z.string(),\n organizationId: z.string(),\n displayName: z.string(),\n os: z.string(),\n online: z.boolean(),\n writable: z.boolean(),\n allowProcesses: z.boolean(),\n computerUseReady: z.boolean(),\n screenReady: z.boolean(),\n});\nexport type DeviceApiDeviceIface = z.infer<typeof deviceSchema>;\n\nconst leaseSchema = z.object({\n lease: z.string(),\n deviceId: z.string(),\n generation: z.number(),\n workspaceRoot: z.string(),\n platform: z.string(),\n access: z.nativeEnum(DeviceApiLeaseAccess),\n capabilities: z.array(tolerantEnum(DeviceApiCapability)),\n expiresAt: z.string(),\n});\nexport interface DeviceApiLeaseIface {\n lease: string;\n deviceId: string;\n generation: number;\n workspaceRoot: string;\n platform: string;\n access: DeviceApiLeaseAccess;\n capabilities: DeviceApiCapability[];\n expiresAtMs: number;\n}\n\ninterface ProcessInputBodyIface {\n bootId: string;\n dataBase64?: string;\n eof?: boolean;\n}\n\nconst errorBodySchema = z.object({ error: z.object({ code: z.string(), message: z.string() }) });\nconst statBodySchema = z.object({\n stat: z\n .object({\n type: tolerantEnum(SandboxEntryType),\n size: z.number(),\n modifiedAtMs: z.number().nullable(),\n mode: z.number().nullable(),\n })\n .nullable(),\n});\nconst dirBodySchema = z.object({\n entries: z.array(\n z.object({\n name: z.string(),\n type: tolerantEnum(SandboxEntryType),\n size: z.number().nullable(),\n }),\n ),\n});\nconst processSchema = z.object({ id: z.string(), bootId: z.string() });\nconst outputStreamSchema = z.object({\n dataBase64: z.string(),\n nextOffset: z.number(),\n eof: z.boolean(),\n});\nconst outputSchema = z.object({\n stdout: outputStreamSchema,\n stderr: outputStreamSchema,\n exited: z.boolean(),\n exitCode: z.number().nullable(),\n exitSignal: z.string().nullable(),\n});\nconst devicesSchema = z.object({ devices: z.array(deviceSchema) });\nconst serversSchema = z.object({ servers: z.array(z.string()) });\n// A Device server's tool as the API recorded it; checked against the tool\n// descriptor contract where the provider hands it on.\nconst catalogToolSchema = jsonObjectSchema;\nconst mcpCatalogSchema = z.object({\n computerUse: z.object({ tools: z.array(catalogToolSchema) }).nullable(),\n localServers: z\n .object({\n servers: z.array(\n z.object({ name: z.string(), tools: z.array(catalogToolSchema).nullable() }),\n ),\n })\n .nullable(),\n});\nexport type DeviceApiMcpCatalogIface = z.infer<typeof mcpCatalogSchema>;\nconst pipeReadSchema = z.object({ dataBase64: z.string().optional() });\nconst screenSchema = z.object({ url: z.string(), token: z.string(), expiresAt: z.string() });\nconst emptySchema = z.unknown();\n\n// One ranged read or write; the API splits it into the Device's own chunks.\nexport const DEVICE_API_FILE_CHUNK_BYTES = 4 * 1024 * 1024;\n// The API long-polls the Device for output up to this long.\nexport const DEVICE_API_OUTPUT_WAIT_MS = 15_000;\n\nexport enum DeviceApiClientErrorCode {\n // The host granted no access for this user or trusted service call.\n CredentialMissing = 'credential_missing',\n // The session acts for no user, and a Device is only used for its owner.\n NoActingUser = 'no_acting_user',\n EgressEnrollmentLost = 'egress_enrollment_lost',\n}\n\nexport interface DeviceApiErrorIface extends Error {\n status: number | null;\n code: string;\n}\n\nconst apiError = (status: number, code: string, message: string): DeviceApiErrorIface =>\n Object.assign(new Error(`Device API ${status} ${code}: ${message}`), { status, code });\n\nconst credentialMissing = (actingUserId: string | null): DeviceApiErrorIface =>\n Object.assign(\n new Error(\n `Device API access is unavailable ${actingUserId == null ? 'for workspace networking (no acting user)' : 'for this acting user'}: the host's credentials.deviceAccess granted none`,\n ),\n { status: null, code: DeviceApiClientErrorCode.CredentialMissing },\n );\n\nconst noActingUser = (): DeviceApiErrorIface =>\n Object.assign(\n new Error(\n 'this session acts for no user, and a Final Device is only used by sessions acting for its owner',\n ),\n { status: null, code: DeviceApiClientErrorCode.NoActingUser },\n );\n\nconst statusSchema = z.object({ status: z.number() });\nexport const deviceApiCodeOf = (cause: unknown): string | null =>\n z.object({ code: z.string() }).safeParse(cause).data?.code ?? null;\n\nexport const deviceApiStatusOf = (cause: Error): number | null =>\n statusSchema.safeParse(cause).data?.status ?? null;\n\nconst parseJson = (text: string): JsonValue => {\n try {\n return jsonValueSchema.parse(JSON.parse(text));\n } catch {\n return null;\n }\n};\n\nconst leaseOf = (raw: z.infer<typeof leaseSchema>): DeviceApiLeaseIface => ({\n lease: raw.lease,\n deviceId: raw.deviceId,\n generation: raw.generation,\n workspaceRoot: raw.workspaceRoot,\n platform: raw.platform,\n access: raw.access,\n capabilities: raw.capabilities.filter((capability) => capability != null),\n expiresAtMs: Date.parse(raw.expiresAt),\n});\n\nexport interface DeviceApiClientIface {\n egress: {\n networkState(args: {\n organizationId: string;\n credentials?: SandboxCredentialsIface;\n workspaceId: string;\n }): Promise<z.infer<typeof deviceWorkspaceNetworkStateSchema>>;\n setNetworkPolicy(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n policy: WorkspaceNetworkPolicyIface;\n initializeIfMissing?: boolean;\n }): Promise<void>;\n workspace(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n }): Promise<z.infer<typeof deviceEgressWorkspaceSchema>>;\n create(args: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n deviceIds: string[];\n dnsResolvers?: string[];\n }): Promise<z.infer<typeof deviceEgressEnrollmentSchema>>;\n renew(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n }): Promise<z.infer<typeof deviceEgressLeaseSchema>>;\n activate(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n }): Promise<z.infer<typeof deviceEgressLeaseSchema>>;\n revoke(args: {\n caller: DeviceApiCallerIface;\n leaseId: string;\n workspaceId: string;\n }): Promise<void>;\n disable(args: { caller: DeviceApiCallerIface; workspaceId: string }): Promise<void>;\n suspend(args: { caller: DeviceApiCallerIface; workspaceId: string }): Promise<void>;\n };\n releaseWorkspaceLeases(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n bindingId: string;\n }): Promise<void>;\n inspectProcesses(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n bindingId: string;\n request: ProcessInspectionRequestIface;\n }): Promise<ProcessInspectionResultIface>;\n getDevice(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n }): Promise<DeviceApiDeviceIface | null>;\n // The Devices of the user the call acts for.\n listDevices(args: { caller: DeviceApiCallerIface }): Promise<DeviceApiDeviceIface[]>;\n resolvePairing(args: {\n caller: DeviceApiCallerIface;\n code: string;\n }): Promise<DeviceApiDeviceIface | null>;\n lease(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n bindingId: string;\n access: DeviceApiLeaseAccess;\n ttlMs: number;\n afterGeneration?: number;\n }): Promise<DeviceApiLeaseIface>;\n recoverLease(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n bindingId: string;\n access: DeviceApiLeaseAccess;\n }): Promise<DeviceApiLeaseIface>;\n renew(args: {\n caller: DeviceApiCallerIface;\n lease: string;\n ttlMs: number;\n }): Promise<DeviceApiLeaseIface>;\n release(args: { caller: DeviceApiCallerIface; lease: string }): Promise<void>;\n // The sandbox transport over one lease; `lease()` is the current handle.\n transport(args: {\n caller: DeviceApiCallerIface;\n lease: () => Promise<string>;\n }): SandboxTransportIface;\n localMcpServers(args: { caller: DeviceApiCallerIface; lease: string }): Promise<string[]>;\n // What the Device's MCP servers last listed through the API, without a lease.\n mcpCatalog(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n }): Promise<DeviceApiMcpCatalogIface>;\n pipe(args: {\n caller: DeviceApiCallerIface;\n lease: string;\n server: string;\n action: 'open' | 'write' | 'read' | 'close';\n clientId: string;\n dataBase64?: string;\n signal?: AbortSignal;\n }): Promise<string>;\n screen(args: {\n caller: DeviceApiCallerIface;\n deviceId: string;\n sessionId: string;\n viewOnly?: boolean;\n }): Promise<{ url: string; token: string; expiresAt: string }>;\n}\n\nexport const createDeviceApiClient = (config: {\n api: DeviceApiConfigIface | (() => DeviceApiConfigIface);\n fetch?: DeviceApiFetchIface;\n}): DeviceApiClientIface => {\n const readApi = () => (typeof config.api === 'function' ? config.api() : config.api);\n const failure = async (response: Response): Promise<DeviceApiErrorIface> => {\n // Read as text so proxy and load balancer error pages survive.\n const text = await response.text().catch(() => '');\n const body = errorBodySchema.safeParse(parseJson(text));\n return body.success\n ? apiError(response.status, body.data.error.code, body.data.error.message)\n : apiError(response.status, 'http', text.slice(0, 200) || response.statusText);\n };\n\n const accessFor = async (args: {\n caller: DeviceApiCallerIface;\n actingUserId: string | null;\n refresh: boolean;\n }): Promise<FinalPlatformAccessIface> => {\n const access = await args.caller.credentials?.deviceAccess({\n actingUserId: args.actingUserId,\n refresh: args.refresh,\n });\n if (access == null) throw credentialMissing(args.actingUserId);\n return access;\n };\n\n // One authenticated call for the user it acts for; rejected access is asked for\n // again once, in case it expired.\n const send = async (args: {\n caller: DeviceApiCallerIface;\n method: string;\n path: string;\n query?: Record<string, string>;\n body?: BodyInit;\n contentType?: string;\n signal?: AbortSignal;\n anonymous?: boolean;\n }): Promise<Response> => {\n const api = readApi();\n const actingUserId = await args.caller.actingUser.current();\n if (actingUserId == null && !args.anonymous) throw noActingUser();\n const attempt = async (refresh: boolean): Promise<Response> => {\n const access = await accessFor({ caller: args.caller, actingUserId, refresh });\n const url = new URL(`${access.baseUrl.replace(/\\/+$/, '')}${args.path}`);\n for (const [key, value] of Object.entries(args.query ?? {})) url.searchParams.set(key, value);\n const headers = new Headers({ authorization: `Bearer ${access.token}` });\n if (actingUserId != null) headers.set(DEVICE_API_ACTING_USER_HEADER, actingUserId);\n if (args.contentType != null) headers.set('content-type', args.contentType);\n return (config.fetch ?? api.fetch ?? fetch)(url.toString(), {\n method: args.method,\n headers,\n body: args.body,\n signal: args.signal,\n });\n };\n let response = await attempt(false);\n if (response.status === 401) {\n await response.text().catch(() => '');\n response = await attempt(true);\n }\n return response;\n };\n\n const json = async <T extends z.ZodType>(\n schema: T,\n args: Parameters<typeof send>[0] & { json?: unknown },\n ): Promise<z.infer<T>> => {\n const response = await send({\n ...args,\n body: args.json === undefined ? args.body : JSON.stringify(args.json),\n contentType: args.json === undefined ? args.contentType : 'application/json',\n });\n if (!response.ok) throw await failure(response);\n const text = await response.text();\n return schema.parse(text === '' ? null : parseJson(text));\n };\n\n // A 404 reads as absent.\n const orNull = async <T>(work: Promise<T>): Promise<T | null> => {\n try {\n return await work;\n } catch (cause) {\n if (cause instanceof Error && deviceApiStatusOf(cause) === 404) return null;\n throw cause;\n }\n };\n\n const leasePath = (lease: string, rest: string): string =>\n `/v1/leases/${encodeURIComponent(lease)}${rest}`;\n\n const transport: DeviceApiClientIface['transport'] = ({ caller, lease }) => {\n const call = async <T extends z.ZodType>(\n schema: T,\n args: Omit<Parameters<typeof json>[1], 'caller' | 'path'> & { path: string },\n ): Promise<z.infer<T>> =>\n json(schema, { ...args, caller, path: leasePath(await lease(), args.path) });\n const processPath = (id: string, rest: string): string =>\n `/processes/${encodeURIComponent(id)}${rest}`;\n return {\n kind: 'device-api',\n fileChunkBytes: DEVICE_API_FILE_CHUNK_BYTES,\n outputWaitMs: DEVICE_API_OUTPUT_WAIT_MS,\n stat: async ({ path, signal }): Promise<TransportStatIface | null> => {\n const { stat } = await call(statBodySchema, {\n method: 'GET',\n path: '/files/stat',\n query: { path },\n signal,\n });\n return stat == null ? null : { ...stat, type: stat.type ?? SandboxEntryType.Other };\n },\n readDir: async ({ path, signal }): Promise<TransportDirEntryIface[]> =>\n (\n await call(dirBodySchema, { method: 'GET', path: '/files/dir', query: { path }, signal })\n ).entries.map((entry) => ({ ...entry, type: entry.type ?? SandboxEntryType.Other })),\n readChunk: async ({ path, offset, length, signal }) => {\n const response = await send({\n caller,\n method: 'GET',\n path: leasePath(await lease(), '/files/content'),\n query: { path, offset: String(offset), length: String(length) },\n signal,\n });\n if (!response.ok) throw await failure(response);\n const bytes = new Uint8Array(await response.arrayBuffer());\n return { bytes, eof: bytes.byteLength < length };\n },\n writeChunk: async ({ path, offset, bytes, signal }) => {\n await call(emptySchema, {\n method: 'PUT',\n path: '/files/content',\n query: { path, offset: String(offset) },\n body: new Blob([bytes.slice()]),\n contentType: 'application/octet-stream',\n signal,\n });\n },\n createDirectory: async ({ path, signal }) => {\n await call(emptySchema, {\n method: 'POST',\n path: '/files/directories',\n json: { path },\n signal,\n });\n },\n remove: async ({ path, recursive, force, signal }) => {\n await call(emptySchema, {\n method: 'DELETE',\n path: '/files',\n query: { path, recursive: String(recursive), force: String(force) },\n signal,\n });\n },\n exec: async ({ id, command, cwd, env, timeoutMs, signal }) =>\n call(processSchema, {\n method: 'POST',\n path: '/processes',\n json: { id, command, cwd, env, timeoutMs },\n signal,\n }),\n output: async ({ process, stdoutOffset, stderrOffset, waitMs, signal }) => {\n const output = await call(outputSchema, {\n method: 'POST',\n path: processPath(process.id, '/output'),\n json: { bootId: process.bootId, stdoutOffset, stderrOffset, waitMs },\n signal,\n });\n const stream = (value: z.infer<typeof outputStreamSchema>) => ({\n data: decodeBase64(value.dataBase64),\n nextOffset: value.nextOffset,\n eof: value.eof,\n });\n const result: TransportOutputIface = {\n stdout: stream(output.stdout),\n stderr: stream(output.stderr),\n exited: output.exited,\n exitCode: output.exitCode,\n exitSignal: output.exitSignal,\n };\n return result;\n },\n input: async ({ process, data, eof, signal, terminate, abortSignal }) => {\n if (terminate === true || signal != null) {\n await call(emptySchema, {\n method: 'POST',\n path: processPath(process.id, '/kill'),\n json:\n terminate === true ? { bootId: process.bootId } : { bootId: process.bootId, signal },\n signal: abortSignal,\n });\n if (terminate === true) return;\n }\n if ((data != null && data.byteLength > 0) || eof === true) {\n const body: ProcessInputBodyIface = {\n bootId: process.bootId,\n };\n if (data != null && data.byteLength > 0) body.dataBase64 = encodeBase64(data);\n if (eof === true) body.eof = true;\n await call(emptySchema, {\n method: 'POST',\n path: processPath(process.id, '/input'),\n json: body,\n signal: abortSignal,\n });\n }\n },\n close: () => undefined,\n };\n };\n\n return {\n egress: {\n networkState: ({ organizationId, credentials, workspaceId }) =>\n json(deviceWorkspaceNetworkStateSchema, {\n caller: { organizationId, credentials, actingUser: { current: async () => null } },\n anonymous: true,\n method: 'GET',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/network-state`,\n signal: AbortSignal.timeout(30_000),\n }),\n setNetworkPolicy: async ({ caller, workspaceId, policy, initializeIfMissing }) => {\n const userId = await caller.actingUser.current();\n const anonymous = userId == null;\n const resolvedCaller = { ...caller, actingUser: { current: async () => userId } };\n const result = await json(z.object({ ok: z.boolean() }), {\n caller: resolvedCaller,\n method: initializeIfMissing === true ? 'POST' : 'PUT',\n anonymous,\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/${initializeIfMissing === true ? 'network-state/initialize' : anonymous ? 'network-state' : 'network-policy'}`,\n json: workspaceNetworkPolicySchema.parse(policy),\n signal: AbortSignal.timeout(30_000),\n });\n if (!result.ok) throw new Error('Device API did not save the workspace network policy');\n },\n workspace: ({ caller, workspaceId }) =>\n json(deviceEgressWorkspaceSchema, {\n caller,\n method: 'GET',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}`,\n signal: AbortSignal.timeout(30_000),\n }),\n create: ({ caller, ...input }) =>\n json(deviceEgressEnrollmentSchema, {\n caller,\n method: 'POST',\n path: '/v1/egress/leases',\n json: deviceEgressCreateRequestSchema.parse(input),\n signal: AbortSignal.timeout(180_000),\n }),\n renew: ({ caller, leaseId }) =>\n json(deviceEgressLeaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}/renew`,\n signal: AbortSignal.timeout(180_000),\n }),\n activate: ({ caller, leaseId }) =>\n json(deviceEgressLeaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}/activate`,\n signal: AbortSignal.timeout(60_000),\n }),\n revoke: async ({ caller, leaseId, workspaceId }) => {\n await json(emptySchema, {\n caller,\n method: 'DELETE',\n json: { workspaceId },\n path: `/v1/egress/leases/${encodeURIComponent(leaseId)}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n suspend: async ({\n caller,\n workspaceId,\n }: {\n caller: DeviceApiCallerIface;\n workspaceId: string;\n }) => {\n const userId = await caller.actingUser.current();\n const anonymous = userId == null;\n const resolvedCaller = { ...caller, actingUser: { current: async () => userId } };\n await json(emptySchema, {\n caller: resolvedCaller,\n anonymous,\n method: 'POST',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}/${anonymous ? 'network-state/suspend' : 'suspend'}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n disable: async ({ caller, workspaceId }) => {\n await json(emptySchema, {\n caller,\n method: 'DELETE',\n path: `/v1/egress/workspaces/${encodeURIComponent(deviceEgressWorkspaceIdSchema.parse(workspaceId))}`,\n signal: AbortSignal.timeout(60_000),\n });\n },\n },\n releaseWorkspaceLeases: async ({ caller, deviceId, bindingId }) => {\n const result = await json(z.object({ released: z.boolean() }), {\n caller,\n method: 'DELETE',\n path:\n '/v1/devices/' +\n encodeURIComponent(deviceId) +\n '/workspaces/' +\n encodeURIComponent(bindingId) +\n '/leases',\n });\n if (!result.released) throw new Error('The Device did not release its workspace leases');\n },\n inspectProcesses: ({ caller, deviceId, bindingId, request }) => {\n const suffix =\n request.operation === ProcessInspectionOperation.Available\n ? '/available'\n : 'processId' in request\n ? '/' + encodeURIComponent(request.processId)\n : '';\n const query: Record<string, string> = {};\n if (bindingId != null) query.bindingId = bindingId;\n if ('bootId' in request) query.bootId = request.bootId;\n if ('cursor' in request && request.cursor != null) query.cursor = request.cursor;\n if ('limit' in request && request.limit != null) query.limit = String(request.limit);\n return json(processInspectionResultSchema, {\n caller,\n method: request.operation === ProcessInspectionOperation.Stop ? 'DELETE' : 'GET',\n path: '/v1/devices/' + encodeURIComponent(deviceId) + '/processes' + suffix,\n query,\n });\n },\n getDevice: ({ caller, deviceId }) =>\n orNull(\n json(deviceSchema, {\n caller,\n method: 'GET',\n path: `/v1/devices/${encodeURIComponent(deviceId)}`,\n }),\n ),\n listDevices: async ({ caller }) =>\n (await json(devicesSchema, { caller, method: 'GET', path: '/v1/devices' })).devices,\n resolvePairing: ({ caller, code }) =>\n orNull(\n json(deviceSchema, {\n caller,\n method: 'POST',\n path: '/v1/pairings/resolve',\n json: { code },\n }),\n ),\n lease: async ({ caller, deviceId, sessionId, bindingId, access, ttlMs, afterGeneration }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/leases`,\n json: { sessionId, bindingId, access, ttlMs, afterGeneration },\n }),\n ),\n recoverLease: async ({ caller, deviceId, sessionId, bindingId, access }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/leases/recover`,\n json: { sessionId, bindingId, access },\n }),\n ),\n renew: async ({ caller, lease, ttlMs }) =>\n leaseOf(\n await json(leaseSchema, {\n caller,\n method: 'POST',\n path: leasePath(lease, '/renew'),\n json: { ttlMs },\n }),\n ),\n release: async ({ caller, lease }) => {\n await json(emptySchema, { caller, method: 'DELETE', path: leasePath(lease, '') });\n },\n transport,\n mcpCatalog: ({ caller, deviceId }) =>\n json(mcpCatalogSchema, {\n caller,\n method: 'GET',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/mcp`,\n }),\n localMcpServers: async ({ caller, lease }) =>\n (await json(serversSchema, { caller, method: 'GET', path: leasePath(lease, '/mcp') }))\n .servers,\n pipe: async ({ caller, lease, server, action, clientId, dataBase64, signal }) =>\n (\n await json(pipeReadSchema, {\n caller,\n method: 'POST',\n path: leasePath(lease, `/mcp/${encodeURIComponent(server)}/${action}`),\n json: dataBase64 == null ? { clientId } : { clientId, dataBase64 },\n signal,\n })\n ).dataBase64 ?? '',\n screen: ({ caller, deviceId, sessionId, viewOnly }) =>\n json(screenSchema, {\n caller,\n method: 'POST',\n path: `/v1/devices/${encodeURIComponent(deviceId)}/screen`,\n json: { sessionId, viewOnly },\n }),\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["DEVICE_API_ACTING_USER_HEADER", "DeviceApiLeaseAccess", "DeviceApiCapability", "DeviceApiClientErrorCode"]
7
7
  }
@@ -4,7 +4,8 @@ import * as z from 'zod';
4
4
  import { type DeviceApiConfigIface, type DeviceApiFetchIface } from "./device-api.mjs";
5
5
  export { DEVICE_API_ACTING_USER_HEADER, DeviceApiClientErrorCode } from "./device-api.mjs";
6
6
  export type { DeviceApiConfigIface, DeviceApiFetchIface } from "./device-api.mjs";
7
- export { DEVICE_API_KEY_SECRET, DEVICE_SANDBOX_SPECIFIER } from "./environment.mjs";
7
+ export { DEVICE_SANDBOX_SPECIFIER } from "./environment.mjs";
8
+ export type { FinalPlatformAccessIface } from '@finalai/agent-provider/sandbox';
8
9
  export { SandboxPlatform } from "./paths.mjs";
9
10
  export interface DeviceSandboxProviderConfigIface {
10
11
  api: DeviceApiConfigIface;
@@ -20,7 +20,7 @@ import { createMcpPipe } from "./mcp-pipe.mjs";
20
20
  import { sandboxPathsFor, SandboxPlatform } from "./paths.mjs";
21
21
  import { createTransportSession, sessionForAccess } from "./session.mjs";
22
22
  import { DEVICE_API_ACTING_USER_HEADER, DeviceApiClientErrorCode } from "./device-api.mjs";
23
- import { DEVICE_API_KEY_SECRET, DEVICE_SANDBOX_SPECIFIER } from "./environment.mjs";
23
+ import { DEVICE_SANDBOX_SPECIFIER } from "./environment.mjs";
24
24
  import { SandboxPlatform as SandboxPlatform2 } from "./paths.mjs";
25
25
  const deviceArtifactSchema = z.object({ version: z.literal(1), deviceId: z.string() });
26
26
  const deviceStateSchema = z.object({
@@ -53,7 +53,7 @@ const createDeviceSandboxProvider = (config) => {
53
53
  );
54
54
  const sleep = config.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
55
55
  const onlineWaitMs = config.onlineWaitMs ?? 0;
56
- const api = createDeviceApiClient({ api: config.api, fetch: config.fetch, now });
56
+ const api = createDeviceApiClient({ api: config.api, fetch: config.fetch });
57
57
  const awaitOnline = async (caller, deviceId, timeoutMs) => {
58
58
  const deadline = now() + timeoutMs;
59
59
  let pollMs = ONLINE_POLL_MS;
@@ -71,6 +71,7 @@ const createDeviceSandboxProvider = (config) => {
71
71
  const { ctx, access } = args;
72
72
  const caller = {
73
73
  organizationId: ctx.session.organizationId,
74
+ credentials: ctx.credentials,
74
75
  actingUser: ctx.actingUser
75
76
  };
76
77
  const bindingId = ctx.session.bindingId;
@@ -287,7 +288,11 @@ const createDeviceSandboxProvider = (config) => {
287
288
  awaitRunning: async (ctx, rawState, { timeoutMs }) => {
288
289
  const { deviceId } = deviceStateSchema.pick({ deviceId: true }).parse(rawState);
289
290
  await awaitOnline(
290
- { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },
291
+ {
292
+ organizationId: ctx.session.organizationId,
293
+ credentials: ctx.credentials,
294
+ actingUser: ctx.actingUser
295
+ },
291
296
  deviceId,
292
297
  timeoutMs
293
298
  );
@@ -329,7 +334,11 @@ const createDeviceSandboxProvider = (config) => {
329
334
  onSessionEnd: async (ctx, _artifact, rawState) => {
330
335
  const state = deviceStateSchema.parse(rawState);
331
336
  await api.releaseWorkspaceLeases({
332
- caller: { organizationId: ctx.session.organizationId, actingUser: ctx.actingUser },
337
+ caller: {
338
+ organizationId: ctx.session.organizationId,
339
+ credentials: ctx.credentials,
340
+ actingUser: ctx.actingUser
341
+ },
333
342
  deviceId: state.deviceId,
334
343
  bindingId: ctx.session.bindingId
335
344
  });
@@ -346,7 +355,6 @@ const createDeviceSandboxProvider = (config) => {
346
355
  };
347
356
  export {
348
357
  DEVICE_API_ACTING_USER_HEADER,
349
- DEVICE_API_KEY_SECRET,
350
358
  DEVICE_COMPUTER_USE_SERVER,
351
359
  DEVICE_SANDBOX_SPECIFIER,
352
360
  DeviceApiClientErrorCode,
@@ -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 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 host-provided credentials. 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 a credential callback scoped to organization/user.\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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",
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_SANDBOX_SPECIFIER } from \"./environment.mjs\";\nexport type { FinalPlatformAccessIface } from '@finalai/agent-provider/sandbox';\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, the Device's backend, exactly as a\n// 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 host-provided credentials. 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 // Transport options; the Device API origin and token come from each context's\n // `credentials.deviceAccess`.\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 });\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 credentials: ctx.credentials,\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 {\n organizationId: ctx.session.organizationId,\n credentials: ctx.credentials,\n actingUser: ctx.actingUser,\n },\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: {\n organizationId: ctx.session.organizationId,\n credentials: ctx.credentials,\n actingUser: ctx.actingUser,\n },\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
  }
@@ -1,12 +1,13 @@
1
1
  import { type WorkspaceEgressRequestIface, type WorkspaceEgressStatusIface } from '@finalai/agent-protocol/device-egress';
2
2
  import { SandboxAccess } from '@finalai/agent-provider';
3
3
  import { type SandboxNetworkingExtensionIface } from '@finalai/agent-provider/sandbox';
4
- import type { NetworkSandboxSessionIface, SandboxActingUserIface, SandboxRunResultIface, SandboxProviderHandleIface, NetworkPolicyIface } from '@finalai/agent-provider/sandbox';
4
+ import type { NetworkSandboxSessionIface, SandboxActingUserIface, SandboxCredentialsIface, SandboxRunResultIface, SandboxProviderHandleIface, NetworkPolicyIface } from '@finalai/agent-provider/sandbox';
5
5
  import { type DeviceApiClientIface, type DeviceApiConfigIface } from "./device-api.mjs";
6
6
  export interface WorkspaceEgressManagerOptionsIface {
7
7
  sandbox: NetworkSandboxSessionIface;
8
8
  workspaceId: string;
9
9
  organizationId: string;
10
+ credentials?: SandboxCredentialsIface;
10
11
  actingUser: SandboxActingUserIface;
11
12
  api: DeviceApiConfigIface | (() => DeviceApiConfigIface);
12
13
  privilegedRun?: (request: {
@@ -36,6 +37,7 @@ export interface WorkspaceEgressManagerOptionsIface {
36
37
  export declare const suspendWorkspaceEgress: (args: {
37
38
  api: DeviceApiConfigIface | (() => DeviceApiConfigIface);
38
39
  organizationId: string;
40
+ credentials?: SandboxCredentialsIface;
39
41
  workspaceId: string;
40
42
  actingUser: SandboxActingUserIface;
41
43
  }) => Promise<void>;
@@ -52,6 +54,7 @@ export declare const createWorkspaceEgressManager: (options: WorkspaceEgressMana
52
54
  export declare const preserveWorkspaceNetworkPolicy: (options: {
53
55
  api: DeviceApiConfigIface | (() => DeviceApiConfigIface);
54
56
  organizationId: string;
57
+ credentials?: SandboxCredentialsIface;
55
58
  workspaceId: string;
56
59
  policy: NetworkPolicyIface;
57
60
  client?: Pick<DeviceApiClientIface, "egress">;
@@ -73,7 +73,11 @@ const isPermanentAuthorizationFailure = (error) => {
73
73
  };
74
74
  const suspendWorkspaceEgress = async (args) => {
75
75
  await createDeviceApiClient({ api: args.api }).egress.suspend({
76
- caller: { organizationId: args.organizationId, actingUser: args.actingUser },
76
+ caller: {
77
+ organizationId: args.organizationId,
78
+ credentials: args.credentials,
79
+ actingUser: args.actingUser
80
+ },
77
81
  workspaceId: args.workspaceId
78
82
  });
79
83
  };
@@ -243,6 +247,7 @@ const createWorkspaceEgressManager = (options) => {
243
247
  };
244
248
  const callerFor = (userId) => ({
245
249
  organizationId: options.organizationId,
250
+ credentials: options.credentials,
246
251
  actingUser: { current: async () => userId }
247
252
  });
248
253
  const block = async (userId, restoreDirect = false) => {
@@ -386,6 +391,7 @@ const createWorkspaceEgressManager = (options) => {
386
391
  if (userId == null) {
387
392
  await client.egress.networkState({
388
393
  organizationId: options.organizationId,
394
+ credentials: options.credentials,
389
395
  workspaceId: options.workspaceId
390
396
  });
391
397
  return;
@@ -713,6 +719,7 @@ const createWorkspaceEgressManager = (options) => {
713
719
  await block(latest.ownerUserId ?? null, true);
714
720
  const state = await client.egress.networkState({
715
721
  organizationId: options.organizationId,
722
+ credentials: options.credentials,
716
723
  workspaceId: options.workspaceId
717
724
  });
718
725
  if (state.enabled || state.networkPolicy == null)
@@ -791,6 +798,7 @@ const createWorkspaceEgressManager = (options) => {
791
798
  if (userId == null) {
792
799
  const state = await client.egress.networkState({
793
800
  organizationId: options.organizationId,
801
+ credentials: options.credentials,
794
802
  workspaceId: options.workspaceId
795
803
  });
796
804
  if (state.enabled) {
@@ -823,6 +831,7 @@ const createWorkspaceEgressManager = (options) => {
823
831
  });
824
832
  policy = (await client.egress.networkState({
825
833
  organizationId: options.organizationId,
834
+ credentials: options.credentials,
826
835
  workspaceId: options.workspaceId
827
836
  })).networkPolicy;
828
837
  }
@@ -1288,6 +1297,7 @@ const createWorkspaceEgressManager = (options) => {
1288
1297
  const validated = workspaceNetworkPolicySchema.parse(policy);
1289
1298
  const state = await client.egress.networkState({
1290
1299
  organizationId: options.organizationId,
1300
+ credentials: options.credentials,
1291
1301
  workspaceId: options.workspaceId
1292
1302
  });
1293
1303
  if (current != null || state.enabled || deviceChoicePending)
@@ -1413,7 +1423,11 @@ const preserveWorkspaceNetworkPolicy = async (options) => {
1413
1423
  deviceEgressWorkspaceIdSchema.parse(options.workspaceId);
1414
1424
  const api = typeof options.api === "function" ? options.api() : options.api;
1415
1425
  await (options.client ?? createDeviceApiClient({ api })).egress.setNetworkPolicy({
1416
- caller: { organizationId: options.organizationId, actingUser: { current: async () => null } },
1426
+ caller: {
1427
+ organizationId: options.organizationId,
1428
+ credentials: options.credentials,
1429
+ actingUser: { current: async () => null }
1430
+ },
1417
1431
  workspaceId: options.workspaceId,
1418
1432
  policy: options.policy,
1419
1433
  initializeIfMissing: true
@@ -1466,12 +1480,14 @@ const createWorkspaceDeviceNetworking = (options) => ({
1466
1480
  client,
1467
1481
  api: options.api,
1468
1482
  organizationId: ctx.organizationId,
1483
+ credentials: ctx.credentials,
1469
1484
  workspaceId,
1470
1485
  policy
1471
1486
  });
1472
1487
  try {
1473
1488
  const saved = await client.egress.networkState({
1474
1489
  organizationId: ctx.organizationId,
1490
+ credentials: ctx.credentials,
1475
1491
  workspaceId
1476
1492
  });
1477
1493
  return workspaceNetworkPolicySchema.parse(saved.networkPolicy);
@@ -1482,6 +1498,7 @@ const createWorkspaceDeviceNetworking = (options) => ({
1482
1498
  suspend: ({ ctx, workspaceId }) => suspendWorkspaceEgress({
1483
1499
  api: options.api,
1484
1500
  organizationId: ctx.organizationId,
1501
+ credentials: ctx.credentials,
1485
1502
  workspaceId,
1486
1503
  actingUser: ctx.actingUser
1487
1504
  }),
@@ -1490,6 +1507,7 @@ const createWorkspaceDeviceNetworking = (options) => ({
1490
1507
  sandbox: args.sandbox,
1491
1508
  workspaceId: args.workspaceId,
1492
1509
  organizationId: args.ctx.organizationId,
1510
+ credentials: args.ctx.credentials,
1493
1511
  actingUser: args.ctx.actingUser,
1494
1512
  api: options.api,
1495
1513
  initialNetworkPolicy: args.initialNetworkPolicy,