@finalai/final-agent-provider 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/HOSTING.md +334 -245
  2. package/README.md +126 -40
  3. package/WORKSPACE-EGRESS.md +11 -11
  4. package/dist/modules/catalog.d.mts +9 -0
  5. package/dist/modules/catalog.mjs +21 -0
  6. package/dist/modules/catalog.mjs.map +7 -0
  7. package/dist/modules/harnesses/acp-agent.d.mts +4 -0
  8. package/dist/modules/harnesses/acp-agent.mjs +35 -0
  9. package/dist/modules/harnesses/acp-agent.mjs.map +7 -0
  10. package/dist/modules/harnesses/adapters.d.mts +7 -0
  11. package/dist/modules/harnesses/adapters.mjs +74 -0
  12. package/dist/modules/harnesses/adapters.mjs.map +7 -0
  13. package/dist/modules/harnesses/claude-code.d.mts +14 -0
  14. package/dist/modules/harnesses/claude-code.mjs +79 -0
  15. package/dist/modules/harnesses/claude-code.mjs.map +7 -0
  16. package/dist/modules/harnesses/codex.d.mts +12 -0
  17. package/dist/modules/harnesses/codex.mjs +90 -0
  18. package/dist/modules/harnesses/codex.mjs.map +7 -0
  19. package/dist/modules/harnesses/config-fields.d.mts +98 -57
  20. package/dist/modules/harnesses/config-fields.mjs +58 -35
  21. package/dist/modules/harnesses/config-fields.mjs.map +3 -3
  22. package/dist/modules/harnesses/definitions.d.mts +3 -0
  23. package/dist/modules/harnesses/definitions.mjs +21 -0
  24. package/dist/modules/harnesses/definitions.mjs.map +7 -0
  25. package/dist/modules/harnesses/fidelity.d.mts +1 -1
  26. package/dist/modules/harnesses/fidelity.mjs +17 -14
  27. package/dist/modules/harnesses/fidelity.mjs.map +2 -2
  28. package/dist/modules/harnesses/final.d.mts +12 -0
  29. package/dist/modules/harnesses/final.mjs +70 -0
  30. package/dist/modules/harnesses/final.mjs.map +7 -0
  31. package/dist/modules/harnesses/index.d.mts +13 -12
  32. package/dist/modules/harnesses/index.mjs +86 -45
  33. package/dist/modules/harnesses/index.mjs.map +3 -3
  34. package/dist/modules/harnesses/names.d.mts +43 -0
  35. package/dist/modules/harnesses/names.mjs +59 -0
  36. package/dist/modules/harnesses/names.mjs.map +7 -0
  37. package/dist/modules/harnesses/nanocode-claude.d.mts +18 -0
  38. package/dist/modules/harnesses/nanocode-claude.mjs +101 -0
  39. package/dist/modules/harnesses/nanocode-claude.mjs.map +7 -0
  40. package/dist/modules/harnesses/nanocode-codex.d.mts +13 -0
  41. package/dist/modules/harnesses/nanocode-codex.mjs +64 -0
  42. package/dist/modules/harnesses/nanocode-codex.mjs.map +7 -0
  43. package/dist/modules/harnesses/pi.d.mts +12 -0
  44. package/dist/modules/harnesses/pi.mjs +71 -0
  45. package/dist/modules/harnesses/pi.mjs.map +7 -0
  46. package/dist/modules/integrations.d.mts +9 -0
  47. package/dist/modules/integrations.mjs +29 -0
  48. package/dist/modules/integrations.mjs.map +7 -0
  49. package/dist/modules/provider/general.bundle.d.mts +1 -0
  50. package/dist/modules/provider/general.bundle.mjs +5 -0
  51. package/dist/modules/provider/general.bundle.mjs.map +7 -0
  52. package/dist/modules/provider/general.d.mts +11 -0
  53. package/dist/modules/provider/general.mjs +130 -0
  54. package/dist/modules/provider/general.mjs.map +7 -0
  55. package/dist/modules/provider/index.d.mts +3 -0
  56. package/dist/modules/provider/index.mjs +13 -0
  57. package/dist/modules/provider/index.mjs.map +7 -0
  58. package/dist/modules/sandboxes/access.d.mts +34 -0
  59. package/dist/modules/sandboxes/access.mjs +15 -0
  60. package/dist/modules/sandboxes/access.mjs.map +7 -0
  61. package/dist/modules/sandboxes/computer.d.mts +24 -51
  62. package/dist/modules/sandboxes/computer.mjs +523 -888
  63. package/dist/modules/sandboxes/computer.mjs.map +3 -3
  64. package/dist/modules/sandboxes/computers-api.d.mts +3 -2
  65. package/dist/modules/sandboxes/computers-api.mjs +2 -4
  66. package/dist/modules/sandboxes/computers-api.mjs.map +2 -2
  67. package/dist/modules/sandboxes/device-api.d.mts +4 -3
  68. package/dist/modules/sandboxes/device-api.mjs +2 -4
  69. package/dist/modules/sandboxes/device-api.mjs.map +2 -2
  70. package/dist/modules/sandboxes/device.d.mts +6 -6
  71. package/dist/modules/sandboxes/device.mjs +126 -121
  72. package/dist/modules/sandboxes/device.mjs.map +3 -3
  73. package/dist/modules/sandboxes/egress.d.mts +10 -9
  74. package/dist/modules/sandboxes/egress.mjs +73 -56
  75. package/dist/modules/sandboxes/egress.mjs.map +2 -2
  76. package/dist/modules/sandboxes/environment.d.mts +35 -269
  77. package/dist/modules/sandboxes/environment.mjs +27 -104
  78. package/dist/modules/sandboxes/environment.mjs.map +3 -3
  79. package/dist/modules/sandboxes/index.d.mts +9 -69
  80. package/dist/modules/sandboxes/index.mjs +35 -95
  81. package/dist/modules/sandboxes/index.mjs.map +3 -3
  82. package/dist/modules/sandboxes/local.d.mts +28 -0
  83. package/dist/modules/sandboxes/local.mjs +499 -0
  84. package/dist/modules/sandboxes/local.mjs.map +7 -0
  85. package/dist/modules/sandboxes/session.d.mts +0 -3
  86. package/dist/modules/sandboxes/session.mjs +2 -22
  87. package/dist/modules/sandboxes/session.mjs.map +2 -2
  88. package/dist/modules/sandboxes/testing/fake-machine.mjs +0 -28
  89. package/dist/modules/sandboxes/testing/fake-machine.mjs.map +2 -2
  90. package/package.json +76 -104
  91. package/dist/modules/connections.d.mts +0 -11
  92. package/dist/modules/connections.mjs +0 -16
  93. package/dist/modules/connections.mjs.map +0 -7
  94. package/dist/modules/harnesses/acp-describe.d.mts +0 -20
  95. package/dist/modules/harnesses/acp-describe.mjs +0 -110
  96. package/dist/modules/harnesses/acp-describe.mjs.map +0 -7
  97. package/dist/modules/harnesses/local-stdio.d.mts +0 -47
  98. package/dist/modules/harnesses/local-stdio.mjs +0 -41
  99. package/dist/modules/harnesses/local-stdio.mjs.map +0 -7
  100. package/dist/modules/harnesses/remote-acp.d.mts +0 -76
  101. package/dist/modules/harnesses/remote-acp.mjs +0 -83
  102. package/dist/modules/harnesses/remote-acp.mjs.map +0 -7
  103. package/dist/modules/harnesses/remote-claude-code.d.mts +0 -88
  104. package/dist/modules/harnesses/remote-claude-code.mjs +0 -113
  105. package/dist/modules/harnesses/remote-claude-code.mjs.map +0 -7
  106. package/dist/modules/harnesses/remote-client-tls.d.mts +0 -35
  107. package/dist/modules/harnesses/remote-client-tls.mjs +0 -37
  108. package/dist/modules/harnesses/remote-client-tls.mjs.map +0 -7
  109. package/dist/modules/harnesses/remote-codex.d.mts +0 -98
  110. package/dist/modules/harnesses/remote-codex.mjs +0 -128
  111. package/dist/modules/harnesses/remote-codex.mjs.map +0 -7
  112. package/dist/modules/harnesses/remote-pi.d.mts +0 -78
  113. package/dist/modules/harnesses/remote-pi.mjs +0 -104
  114. package/dist/modules/harnesses/remote-pi.mjs.map +0 -7
  115. package/dist/modules/harnesses/remote-url.d.mts +0 -5
  116. package/dist/modules/harnesses/remote-url.mjs +0 -19
  117. package/dist/modules/harnesses/remote-url.mjs.map +0 -7
  118. package/dist/modules/harnesses/serverless-final.d.mts +0 -63
  119. package/dist/modules/harnesses/serverless-final.mjs +0 -88
  120. package/dist/modules/harnesses/serverless-final.mjs.map +0 -7
  121. package/dist/modules/harnesses/serverless-nanocode-claude.d.mts +0 -64
  122. package/dist/modules/harnesses/serverless-nanocode-claude.mjs +0 -105
  123. package/dist/modules/harnesses/serverless-nanocode-claude.mjs.map +0 -7
  124. package/dist/modules/harnesses/serverless-nanocode-codex.d.mts +0 -66
  125. package/dist/modules/harnesses/serverless-nanocode-codex.mjs +0 -113
  126. package/dist/modules/harnesses/serverless-nanocode-codex.mjs.map +0 -7
  127. package/dist/modules/harnesses/serverless-pi.d.mts +0 -64
  128. package/dist/modules/harnesses/serverless-pi.mjs +0 -98
  129. package/dist/modules/harnesses/serverless-pi.mjs.map +0 -7
  130. package/dist/modules/runtime/index.d.mts +0 -7
  131. package/dist/modules/runtime/index.mjs +0 -18
  132. package/dist/modules/runtime/index.mjs.map +0 -7
  133. package/dist/modules/runtime/local-stdio.d.mts +0 -10
  134. package/dist/modules/runtime/local-stdio.mjs +0 -106
  135. package/dist/modules/runtime/local-stdio.mjs.map +0 -7
  136. package/dist/modules/runtime/remote-acp.d.mts +0 -16
  137. package/dist/modules/runtime/remote-acp.mjs +0 -152
  138. package/dist/modules/runtime/remote-acp.mjs.map +0 -7
  139. package/dist/modules/runtime/remote-claude-code.d.mts +0 -5
  140. package/dist/modules/runtime/remote-claude-code.mjs +0 -47
  141. package/dist/modules/runtime/remote-claude-code.mjs.map +0 -7
  142. package/dist/modules/runtime/remote-codex.d.mts +0 -5
  143. package/dist/modules/runtime/remote-codex.mjs +0 -47
  144. package/dist/modules/runtime/remote-codex.mjs.map +0 -7
  145. package/dist/modules/runtime/remote-host.d.mts +0 -127
  146. package/dist/modules/runtime/remote-host.mjs +0 -387
  147. package/dist/modules/runtime/remote-host.mjs.map +0 -7
  148. package/dist/modules/runtime/remote-pi.d.mts +0 -5
  149. package/dist/modules/runtime/remote-pi.mjs +0 -44
  150. package/dist/modules/runtime/remote-pi.mjs.map +0 -7
  151. package/dist/modules/sandboxes/guide.d.mts +0 -35
  152. package/dist/modules/sandboxes/guide.mjs +0 -119
  153. package/dist/modules/sandboxes/guide.mjs.map +0 -7
  154. package/dist/modules/sandboxes/workspace-setup.d.mts +0 -42
  155. package/dist/modules/sandboxes/workspace-setup.mjs +0 -242
  156. package/dist/modules/sandboxes/workspace-setup.mjs.map +0 -7
  157. package/dist/modules/testing/harness.d.mts +0 -9
  158. package/dist/modules/testing/harness.mjs +0 -123
  159. package/dist/modules/testing/harness.mjs.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/session.ts"],
4
- "sourcesContent": ["import { SandboxAccess } from '@finalai/agent-provider';\nimport type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxAttachedProcessIface,\n SandboxAttachProcessOptionsIface,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk, splitChunks } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport {\n exitStatus,\n type SandboxTransportIface,\n type TransportOutputIface,\n type TransportOutputStreamIface,\n type TransportProcessIface,\n} from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n // What else a process ref must match beyond this session and the process's\n // boot, read when spawning and attaching (a Device's lease generation).\n processScope?: () => string;\n}\n\n// A durable process's ref: this session, the process and its boot, and the scope.\nconst PROCESS_REF_PREFIX = 'final-process.v1';\n\nconst encodeProcessRef = (parts: {\n session: string;\n process: TransportProcessIface;\n scope: string;\n}): string =>\n [PROCESS_REF_PREFIX, parts.session, parts.process.id, parts.process.bootId, parts.scope]\n .map(encodeURIComponent)\n .join(':');\n\nconst decodeProcessRef = (\n ref: string,\n): { session: string; process: TransportProcessIface; scope: string } | null => {\n const parts = ref.split(':');\n if (parts.length !== 5 || parts[0] !== PROCESS_REF_PREFIX) return null;\n try {\n const [session = '', id = '', bootId = '', scope = ''] = parts.slice(1).map(decodeURIComponent);\n return { session, process: { id, bootId }, scope };\n } catch {\n return null;\n }\n};\n\n// Where output read from `requested` starts: there, or later when the\n// backend no longer retains the bytes from there.\nconst outputStart = (chunk: TransportOutputStreamIface, requested: number): number =>\n Math.max(requested, chunk.nextOffset - chunk.data.byteLength);\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const kill =\n (process: TransportProcessIface) =>\n async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n\n // Polls a process's output from the given offsets (after `first`, output\n // already read from there) until it exits. Aborting `detach` stops polling\n // and fails the streams and the exit; the process is untouched.\n const followProcess = (args: {\n process: TransportProcessIface;\n stdoutOffset: number;\n stderrOffset: number;\n first?: TransportOutputIface;\n detach?: AbortSignal;\n }) => {\n const { process } = args;\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n void (async () => {\n let stdoutOffset = args.stdoutOffset;\n let stderrOffset = args.stderrOffset;\n let waitMs = transport.outputWaitMs;\n let pending = args.first;\n try {\n for (;;) {\n args.detach?.throwIfAborted();\n const output =\n pending ??\n (await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n signal: args.detach,\n }));\n pending = undefined;\n args.detach?.throwIfAborted();\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n }\n })();\n return { stdout: stdoutPush.stream, stderr: stderrPush.stream, exit, kill: kill(process) };\n };\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n // Durable only where processes outlive this client (`processGone`).\n const durable = options.durable === true && transport.processGone != null;\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const followed = followProcess({\n process,\n stdoutOffset: 0,\n stderrOffset: 0,\n detach: durable ? options.abortSignal : undefined,\n });\n if (!durable) {\n const onAbort = (): void => {\n void followed.kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n void followed.exit\n .catch(() => undefined)\n .finally(() => options.abortSignal?.removeEventListener('abort', onAbort));\n }\n\n // A detached durable handle neither writes to nor closes the process's stdin.\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n if (durable) options.abortSignal?.throwIfAborted();\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n // Forward input as it arrives: a stdin stream is often interactive.\n for await (const chunk of splitChunks(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n ref: durable\n ? encodeProcessRef({ session: args.id, process, scope: args.processScope?.() ?? '' })\n : null,\n stdout: followed.stdout,\n stderr: followed.stderr,\n write,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n // Finds a durable process again: null for a ref of another session or scope,\n // or a process the backend no longer knows.\n const attachProcess = async (\n options: SandboxAttachProcessOptionsIface,\n ): Promise<SandboxAttachedProcessIface | null> => {\n options.abortSignal?.throwIfAborted();\n const decoded = decodeProcessRef(options.ref);\n if (\n transport.processGone == null ||\n decoded == null ||\n decoded.session !== args.id ||\n decoded.scope !== (args.processScope?.() ?? '')\n )\n return null;\n const { process } = decoded;\n let first: TransportOutputIface;\n try {\n first = await transport.output({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n waitMs: 0,\n signal: options.abortSignal,\n });\n } catch (cause) {\n if (transport.processGone(cause)) return null;\n throw cause;\n }\n const followed = followProcess({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n first,\n detach: options.abortSignal,\n });\n return {\n ref: options.ref,\n stdoutOffset: outputStart(first.stdout, options.stdoutOffset),\n stderrOffset: outputStart(first.stderr, options.stderrOffset),\n stdout: followed.stdout,\n stderr: followed.stderr,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess({ ...options, durable: false }, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n if (transport.processGone != null) session.attachProcess = attachProcess;\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding is read-only');\n};\n\n// A read binding's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the lease the provider took.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n delete restricted.egress;\n delete restricted.attachProcess;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n\nconst fileWriteRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding runs processes but does not write files');\n};\n\n// An execute binding's view of a handle: reads and processes pass through; file\n// writes and lifecycle are refused.\nexport const executeOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: fileWriteRefusal,\n writeBinaryFile: fileWriteRefusal,\n writeTextFile: fileWriteRefusal,\n removePath: fileWriteRefusal,\n stop: fileWriteRefusal,\n destroy: fileWriteRefusal,\n };\n delete restricted.egress;\n return restricted;\n};\n\n// The view of a handle that a binding's access allows.\nexport const sessionForAccess = <S extends NetworkSandboxSessionIface>(\n session: S,\n access: SandboxAccess,\n): S =>\n access === SandboxAccess.Read\n ? readOnlySession(session)\n : access === SandboxAccess.Execute\n ? executeOnlySession(session)\n : session;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxAttachedProcessIface,\n SandboxAttachProcessOptionsIface,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk, splitChunks } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport {\n exitStatus,\n type SandboxTransportIface,\n type TransportOutputIface,\n type TransportOutputStreamIface,\n type TransportProcessIface,\n} from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n // What else a process ref must match beyond this session and the process's\n // boot, read when spawning and attaching (a Device's lease generation).\n processScope?: () => string;\n}\n\n// A durable process's ref: this session, the process and its boot, and the scope.\nconst PROCESS_REF_PREFIX = 'final-process.v1';\n\nconst encodeProcessRef = (parts: {\n session: string;\n process: TransportProcessIface;\n scope: string;\n}): string =>\n [PROCESS_REF_PREFIX, parts.session, parts.process.id, parts.process.bootId, parts.scope]\n .map(encodeURIComponent)\n .join(':');\n\nconst decodeProcessRef = (\n ref: string,\n): { session: string; process: TransportProcessIface; scope: string } | null => {\n const parts = ref.split(':');\n if (parts.length !== 5 || parts[0] !== PROCESS_REF_PREFIX) return null;\n try {\n const [session = '', id = '', bootId = '', scope = ''] = parts.slice(1).map(decodeURIComponent);\n return { session, process: { id, bootId }, scope };\n } catch {\n return null;\n }\n};\n\n// Where output read from `requested` starts: there, or later when the\n// backend no longer retains the bytes from there.\nconst outputStart = (chunk: TransportOutputStreamIface, requested: number): number =>\n Math.max(requested, chunk.nextOffset - chunk.data.byteLength);\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const kill =\n (process: TransportProcessIface) =>\n async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n\n // Polls a process's output from the given offsets (after `first`, output\n // already read from there) until it exits. Aborting `detach` stops polling\n // and fails the streams and the exit; the process is untouched.\n const followProcess = (args: {\n process: TransportProcessIface;\n stdoutOffset: number;\n stderrOffset: number;\n first?: TransportOutputIface;\n detach?: AbortSignal;\n }) => {\n const { process } = args;\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n void (async () => {\n let stdoutOffset = args.stdoutOffset;\n let stderrOffset = args.stderrOffset;\n let waitMs = transport.outputWaitMs;\n let pending = args.first;\n try {\n for (;;) {\n args.detach?.throwIfAborted();\n const output =\n pending ??\n (await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n signal: args.detach,\n }));\n pending = undefined;\n args.detach?.throwIfAborted();\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n }\n })();\n return { stdout: stdoutPush.stream, stderr: stderrPush.stream, exit, kill: kill(process) };\n };\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n // Durable only where processes outlive this client (`processGone`).\n const durable = options.durable === true && transport.processGone != null;\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const followed = followProcess({\n process,\n stdoutOffset: 0,\n stderrOffset: 0,\n detach: durable ? options.abortSignal : undefined,\n });\n if (!durable) {\n const onAbort = (): void => {\n void followed.kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n void followed.exit\n .catch(() => undefined)\n .finally(() => options.abortSignal?.removeEventListener('abort', onAbort));\n }\n\n // A detached durable handle neither writes to nor closes the process's stdin.\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n if (durable) options.abortSignal?.throwIfAborted();\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n // Forward input as it arrives: a stdin stream is often interactive.\n for await (const chunk of splitChunks(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n ref: durable\n ? encodeProcessRef({ session: args.id, process, scope: args.processScope?.() ?? '' })\n : null,\n stdout: followed.stdout,\n stderr: followed.stderr,\n write,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n // Finds a durable process again: null for a ref of another session or scope,\n // or a process the backend no longer knows.\n const attachProcess = async (\n options: SandboxAttachProcessOptionsIface,\n ): Promise<SandboxAttachedProcessIface | null> => {\n options.abortSignal?.throwIfAborted();\n const decoded = decodeProcessRef(options.ref);\n if (\n transport.processGone == null ||\n decoded == null ||\n decoded.session !== args.id ||\n decoded.scope !== (args.processScope?.() ?? '')\n )\n return null;\n const { process } = decoded;\n let first: TransportOutputIface;\n try {\n first = await transport.output({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n waitMs: 0,\n signal: options.abortSignal,\n });\n } catch (cause) {\n if (transport.processGone(cause)) return null;\n throw cause;\n }\n const followed = followProcess({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n first,\n detach: options.abortSignal,\n });\n return {\n ref: options.ref,\n stdoutOffset: outputStart(first.stdout, options.stdoutOffset),\n stderrOffset: outputStart(first.stderr, options.stderrOffset),\n stdout: followed.stdout,\n stderr: followed.stderr,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess({ ...options, durable: false }, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n if (transport.processGone != null) session.attachProcess = attachProcess;\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox handle is read-only');\n};\n\n// A passive viewer's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the backend the provider asked.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n delete restricted.egress;\n delete restricted.attachProcess;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["args"]
7
7
  }
@@ -3,7 +3,6 @@ import { SANDBOX_SEED_MARKER, SANDBOX_SEED_PROTOCOL } from "@finalai/agent-provi
3
3
  import { posix } from "node:path";
4
4
  import * as z from "zod";
5
5
  import { concatBytes } from "../bytes.mjs";
6
- import { GUIDE_COMMAND_PROTOCOL } from "../workspace-setup.mjs";
7
6
  import { quotedShellArguments } from "./quoted-shell-arguments.mjs";
8
7
  const unwrapCommand = (command) => {
9
8
  if (command.startsWith("bash -lc "))
@@ -36,33 +35,6 @@ const createFakeMachine = () => {
36
35
  };
37
36
  const builtin = (control) => {
38
37
  const script = control.exec.script;
39
- if (script.includes(GUIDE_COMMAND_PROTOCOL)) {
40
- const chunks = [];
41
- control.onStdin((data) => chunks.push(data));
42
- control.onEof(() => {
43
- const payload = z.object({ root: z.string(), files: z.record(z.string(), z.string()) }).parse(JSON.parse(new TextDecoder().decode(concatBytes(chunks))));
44
- if ([...links.keys()].some(
45
- (path) => payload.root === path || payload.root.startsWith(`${path}/`)
46
- )) {
47
- control.stderr("symlink command directory");
48
- control.exit(1);
49
- return;
50
- }
51
- for (const [name, content] of Object.entries(payload.files)) {
52
- const path = posix.join(payload.root, name);
53
- const existing = files.get(path);
54
- if (links.has(path) || existing != null && new TextDecoder().decode(existing) !== content) {
55
- control.stderr("guide command differs from its pinned source");
56
- control.exit(1);
57
- return;
58
- }
59
- mkdirp(payload.root);
60
- files.set(path, bytes(content));
61
- }
62
- control.exit(0);
63
- });
64
- return true;
65
- }
66
38
  if (script.includes(SANDBOX_SEED_PROTOCOL)) {
67
39
  const chunks = [];
68
40
  control.onStdin((data) => chunks.push(data));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sandboxes/testing/fake-machine.ts"],
4
- "sourcesContent": ["import { DURABLE_CONFORMANCE_SCRIPT } from '@finalai/agent-provider/conformance';\nimport { SANDBOX_SEED_MARKER, SANDBOX_SEED_PROTOCOL } from '@finalai/agent-provider/sandbox';\nimport { posix } from 'node:path';\nimport * as z from 'zod';\nimport { concatBytes } from \"../bytes.mjs\";\nimport { GUIDE_COMMAND_PROTOCOL } from \"../workspace-setup.mjs\";\nimport { quotedShellArguments } from \"./quoted-shell-arguments.mjs\";\n\n// An in-memory machine behind the fake Computers API, data plane and Device: a file\n// tree plus managed processes whose behaviour tests script by command.\n\nexport interface FakeExecIface {\n command: string;\n // The command with the provider's `bash -lc '\u2026'` / `exec '\u2026'` wrapper removed.\n script: string;\n cwd: string;\n env: Record<string, string>;\n}\n\nexport interface FakeProcessControlIface {\n readonly exec: FakeExecIface;\n stdout(text: string | Uint8Array): void;\n stderr(text: string | Uint8Array): void;\n exit(code: number, signal?: string | null): void;\n onStdin(listener: (data: Uint8Array) => void): void;\n onEof(listener: () => void): void;\n}\n\nexport interface FakeBehaviorIface {\n (process: FakeProcessControlIface): void;\n}\n\nexport interface FakeProcessIface {\n id: string;\n bootId: string;\n exec: FakeExecIface;\n stdout: Uint8Array;\n stderr: Uint8Array;\n exited: boolean;\n exitCode: number | null;\n signal: string | null;\n write(data: Uint8Array): void;\n eof(): void;\n terminate(signal?: string): void;\n // Resolves on the next change (output or exit), or after `ms`.\n changed(ms: number): Promise<void>;\n}\n\nexport interface FakeMachineIface {\n files: Map<string, Uint8Array>;\n dirs: Set<string>;\n // Symlink path \u2192 target path.\n links: Map<string, string>;\n execs: FakeExecIface[];\n processes: Map<string, FakeProcessIface>;\n // Tests register behaviours; the first whose predicate matches runs.\n on(match: (exec: FakeExecIface) => boolean, behavior: FakeBehaviorIface): void;\n exec(args: {\n id: string;\n command: string;\n cwd: string;\n env: Record<string, string>;\n }): FakeProcessIface;\n mkdirp(path: string): void;\n readText(path: string): string | null;\n}\n\n// Removes the session handle's `bash -lc '\u2026'` or `exec '\u2026' '\u2026'` wrapper.\nexport const unwrapCommand = (command: string): string => {\n if (command.startsWith('bash -lc '))\n return quotedShellArguments(command.slice('bash -lc '.length)).join(' ');\n if (command.startsWith('exec bash -lc '))\n return quotedShellArguments(command.slice('exec bash -lc '.length)).join(' ');\n if (command.startsWith('exec '))\n return quotedShellArguments(command.slice('exec '.length)).join(' ');\n return command;\n};\n\n// The first single-quoted argument after `marker` in a script.\nexport const quotedAfter = (script: string, marker: string): string | null => {\n const index = script.indexOf(marker);\n if (index < 0) return null;\n return quotedShellArguments(script.slice(index + marker.length))[0] ?? null;\n};\n\nconst bytes = (data: string | Uint8Array): Uint8Array =>\n data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n\nexport const createFakeMachine = (): FakeMachineIface => {\n const files = new Map<string, Uint8Array>();\n const dirs = new Set<string>(['/', '/workspaces', '/tmp']);\n const links = new Map<string, string>();\n const behaviors: { match: (exec: FakeExecIface) => boolean; behavior: FakeBehaviorIface }[] = [];\n const execs: FakeExecIface[] = [];\n const processes = new Map<string, FakeProcessIface>();\n\n const mkdirp = (path: string): void => {\n let current = posix.normalize(path);\n while (current !== '/' && !dirs.has(current)) {\n dirs.add(current);\n current = posix.dirname(current);\n }\n };\n\n // Built-in behaviour for the provider's own helper scripts.\n const builtin = (control: FakeProcessControlIface): boolean => {\n const script = control.exec.script;\n if (script.includes(GUIDE_COMMAND_PROTOCOL)) {\n const chunks: Uint8Array[] = [];\n control.onStdin((data) => chunks.push(data));\n control.onEof(() => {\n const payload = z\n .object({ root: z.string(), files: z.record(z.string(), z.string()) })\n .parse(JSON.parse(new TextDecoder().decode(concatBytes(chunks))));\n if (\n [...links.keys()].some(\n (path) => payload.root === path || payload.root.startsWith(`${path}/`),\n )\n ) {\n control.stderr('symlink command directory');\n control.exit(1);\n return;\n }\n for (const [name, content] of Object.entries(payload.files)) {\n const path = posix.join(payload.root, name);\n const existing = files.get(path);\n if (\n links.has(path) ||\n (existing != null && new TextDecoder().decode(existing) !== content)\n ) {\n control.stderr('guide command differs from its pinned source');\n control.exit(1);\n return;\n }\n mkdirp(payload.root);\n files.set(path, bytes(content));\n }\n control.exit(0);\n });\n return true;\n }\n if (script.includes(SANDBOX_SEED_PROTOCOL)) {\n const chunks: Uint8Array[] = [];\n control.onStdin((data) => chunks.push(data));\n control.onEof(() => {\n const payload = z\n .object({ root: z.string(), files: z.record(z.string(), z.string()) })\n .parse(JSON.parse(new TextDecoder().decode(concatBytes(chunks))));\n const marker = posix.join(payload.root, '.final', SANDBOX_SEED_MARKER);\n if (files.has(marker)) {\n control.exit(0);\n return;\n }\n for (const [path, content] of Object.entries(payload.files)) {\n const target = posix.join(payload.root, path);\n if (files.has(target)) continue;\n mkdirp(posix.dirname(target));\n files.set(target, bytes(content));\n }\n mkdirp(posix.dirname(marker));\n files.set(marker, bytes(SANDBOX_SEED_PROTOCOL));\n control.exit(0);\n });\n return true;\n }\n // The provider's helper scripts, matched by how they start.\n const leading = (marker: string): string | null =>\n script.startsWith(marker) ? quotedAfter(script, marker) : null;\n const statPath = leading('if [ ! -e ');\n if (statPath != null && script.includes('stat -c')) {\n // Like `stat` without -L: a symlink reports its own length.\n const link = links.get(statPath);\n if (link != null) control.stdout(`symbolic link|${link.length}|1700000000|777\\n`);\n else if (dirs.has(statPath)) control.stdout(`directory|4096|1700000000|755\\n`);\n else if (files.has(statPath))\n control.stdout(`regular file|${files.get(statPath)?.byteLength ?? 0}|1700000000|644\\n`);\n else control.stdout('missing\\n');\n control.exit(0);\n return true;\n }\n const listPath = leading('[ -d ');\n if (listPath != null && script.includes('find ')) {\n if (!dirs.has(listPath)) {\n control.stderr('Not a directory\\n');\n control.exit(2);\n return true;\n }\n const entries: string[] = [];\n for (const dir of dirs) {\n if (dir !== listPath && posix.dirname(dir) === listPath)\n entries.push(`d\\t4096\\t${posix.basename(dir)}\\0`);\n }\n for (const [path, content] of files) {\n if (posix.dirname(path) === listPath)\n entries.push(`f\\t${content.byteLength}\\t${posix.basename(path)}\\0`);\n }\n control.stdout(entries.join(''));\n control.exit(0);\n return true;\n }\n const mkdirPath = leading('mkdir -p -- ');\n if (mkdirPath != null) {\n mkdirp(mkdirPath);\n control.exit(0);\n return true;\n }\n const removePath = leading('if [ -d ');\n if (removePath != null && script.includes('rm')) {\n if (dirs.has(removePath)) {\n for (const dir of [...dirs])\n if (dir === removePath || dir.startsWith(`${removePath}/`)) dirs.delete(dir);\n for (const path of [...files.keys()])\n if (path.startsWith(`${removePath}/`)) files.delete(path);\n } else if (files.has(removePath)) {\n files.delete(removePath);\n } else if (!script.includes('-f')) {\n control.stderr(`rm: cannot remove: No such file or directory\\n`);\n control.exit(1);\n return true;\n }\n control.exit(0);\n return true;\n }\n if (script.includes('git clone')) {\n const destination = quotedAfter(script.slice(script.indexOf('git clone')), \"' \");\n if (destination != null) mkdirp(`${destination}/.git`);\n control.exit(0);\n return true;\n }\n // Enough of a shell for the conformance kit's process cases.\n if (script === 'cat') {\n control.onStdin((data) => control.stdout(data));\n control.onEof(() => control.exit(0));\n return true;\n }\n if (script.startsWith('sleep ')) return true;\n if (script === DURABLE_CONFORMANCE_SCRIPT) {\n control.stdout('one\\n');\n control.stderr('err-one\\n');\n setTimeout(() => {\n control.stdout('two\\n');\n control.stderr('err-two\\n');\n control.exit(7);\n }, 100);\n return true;\n }\n if (script === 'echo out; echo err >&2; exit 3') {\n control.stdout('out\\n');\n control.stderr('err\\n');\n control.exit(3);\n return true;\n }\n if (script.startsWith('printenv ')) {\n const name = script.slice('printenv '.length);\n const value = Object.hasOwn(control.exec.env, name) ? control.exec.env[name] : undefined;\n if (value != null) control.stdout(`${value}\\n`);\n control.exit(value == null ? 1 : 0);\n return true;\n }\n if (script === 'echo' || script.startsWith('echo ')) {\n control.stdout(`${script.slice('echo '.length)}\\n`);\n control.exit(0);\n return true;\n }\n return false;\n };\n\n const exec: FakeMachineIface['exec'] = (args) => {\n const record: FakeExecIface = {\n command: args.command,\n script: unwrapCommand(args.command),\n cwd: args.cwd,\n env: args.env,\n };\n execs.push(record);\n const stdinListeners: ((data: Uint8Array) => void)[] = [];\n const eofListeners: (() => void)[] = [];\n let waiters: (() => void)[] = [];\n const notify = (): void => {\n const pending = waiters;\n waiters = [];\n for (const wake of pending) wake();\n };\n const process: FakeProcessIface = {\n id: args.id,\n bootId: 'boot-1',\n exec: record,\n stdout: new Uint8Array(),\n stderr: new Uint8Array(),\n exited: false,\n exitCode: null,\n signal: null,\n write: (data) => {\n for (const listener of stdinListeners) listener(data);\n },\n eof: () => {\n for (const listener of eofListeners) listener();\n },\n terminate: (signal) => {\n if (process.exited) return;\n process.exited = true;\n process.signal = signal ?? 'SIGKILL';\n notify();\n },\n changed: (ms) =>\n new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n waiters.push(() => {\n clearTimeout(timer);\n resolve();\n });\n }),\n };\n const control: FakeProcessControlIface = {\n exec: record,\n stdout: (data) => {\n process.stdout = concatBytes([process.stdout, bytes(data)]);\n notify();\n },\n stderr: (data) => {\n process.stderr = concatBytes([process.stderr, bytes(data)]);\n notify();\n },\n exit: (code, signal = null) => {\n if (process.exited) return;\n process.exited = true;\n process.exitCode = signal == null ? code : null;\n process.signal = signal;\n notify();\n },\n onStdin: (listener) => stdinListeners.push(listener),\n onEof: (listener) => eofListeners.push(listener),\n };\n processes.set(args.id, process);\n const custom = behaviors.find((entry) => entry.match(record));\n if (custom != null) custom.behavior(control);\n else if (!builtin(control)) control.exit(0);\n return process;\n };\n\n return {\n files,\n dirs,\n links,\n execs,\n processes,\n on: (match, behavior) => behaviors.push({ match, behavior }),\n exec,\n mkdirp,\n readText: (path) => {\n const content = files.get(path);\n return content == null ? null : new TextDecoder().decode(content);\n },\n };\n};\n\n// Output from offsets, waiting up to `waitMs` (capped for fast tests) for news.\nexport const readFakeOutput = async (\n process: FakeProcessIface,\n offsets: { stdout: number; stderr: number; waitMs: number },\n): Promise<{ stdout: Uint8Array; stderr: Uint8Array; exited: boolean }> => {\n if (\n !process.exited &&\n process.stdout.byteLength <= offsets.stdout &&\n process.stderr.byteLength <= offsets.stderr &&\n offsets.waitMs > 0\n ) {\n await process.changed(Math.min(offsets.waitMs, 50));\n }\n return {\n stdout: process.stdout.subarray(offsets.stdout),\n stderr: process.stderr.subarray(offsets.stderr),\n exited: process.exited,\n };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { DURABLE_CONFORMANCE_SCRIPT } from '@finalai/agent-provider/conformance';\nimport { SANDBOX_SEED_MARKER, SANDBOX_SEED_PROTOCOL } from '@finalai/agent-provider/sandbox';\nimport { posix } from 'node:path';\nimport * as z from 'zod';\nimport { concatBytes } from \"../bytes.mjs\";\nimport { quotedShellArguments } from \"./quoted-shell-arguments.mjs\";\n\n// An in-memory machine behind the fake Computers API, data plane and Device: a file\n// tree plus managed processes whose behaviour tests script by command.\n\nexport interface FakeExecIface {\n command: string;\n // The command with the provider's `bash -lc '\u2026'` / `exec '\u2026'` wrapper removed.\n script: string;\n cwd: string;\n env: Record<string, string>;\n}\n\nexport interface FakeProcessControlIface {\n readonly exec: FakeExecIface;\n stdout(text: string | Uint8Array): void;\n stderr(text: string | Uint8Array): void;\n exit(code: number, signal?: string | null): void;\n onStdin(listener: (data: Uint8Array) => void): void;\n onEof(listener: () => void): void;\n}\n\nexport interface FakeBehaviorIface {\n (process: FakeProcessControlIface): void;\n}\n\nexport interface FakeProcessIface {\n id: string;\n bootId: string;\n exec: FakeExecIface;\n stdout: Uint8Array;\n stderr: Uint8Array;\n exited: boolean;\n exitCode: number | null;\n signal: string | null;\n write(data: Uint8Array): void;\n eof(): void;\n terminate(signal?: string): void;\n // Resolves on the next change (output or exit), or after `ms`.\n changed(ms: number): Promise<void>;\n}\n\nexport interface FakeMachineIface {\n files: Map<string, Uint8Array>;\n dirs: Set<string>;\n // Symlink path \u2192 target path.\n links: Map<string, string>;\n execs: FakeExecIface[];\n processes: Map<string, FakeProcessIface>;\n // Tests register behaviours; the first whose predicate matches runs.\n on(match: (exec: FakeExecIface) => boolean, behavior: FakeBehaviorIface): void;\n exec(args: {\n id: string;\n command: string;\n cwd: string;\n env: Record<string, string>;\n }): FakeProcessIface;\n mkdirp(path: string): void;\n readText(path: string): string | null;\n}\n\n// Removes the session handle's `bash -lc '\u2026'` or `exec '\u2026' '\u2026'` wrapper.\nexport const unwrapCommand = (command: string): string => {\n if (command.startsWith('bash -lc '))\n return quotedShellArguments(command.slice('bash -lc '.length)).join(' ');\n if (command.startsWith('exec bash -lc '))\n return quotedShellArguments(command.slice('exec bash -lc '.length)).join(' ');\n if (command.startsWith('exec '))\n return quotedShellArguments(command.slice('exec '.length)).join(' ');\n return command;\n};\n\n// The first single-quoted argument after `marker` in a script.\nexport const quotedAfter = (script: string, marker: string): string | null => {\n const index = script.indexOf(marker);\n if (index < 0) return null;\n return quotedShellArguments(script.slice(index + marker.length))[0] ?? null;\n};\n\nconst bytes = (data: string | Uint8Array): Uint8Array =>\n data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n\nexport const createFakeMachine = (): FakeMachineIface => {\n const files = new Map<string, Uint8Array>();\n const dirs = new Set<string>(['/', '/workspaces', '/tmp']);\n const links = new Map<string, string>();\n const behaviors: { match: (exec: FakeExecIface) => boolean; behavior: FakeBehaviorIface }[] = [];\n const execs: FakeExecIface[] = [];\n const processes = new Map<string, FakeProcessIface>();\n\n const mkdirp = (path: string): void => {\n let current = posix.normalize(path);\n while (current !== '/' && !dirs.has(current)) {\n dirs.add(current);\n current = posix.dirname(current);\n }\n };\n\n // Built-in behaviour for the provider's own helper scripts.\n const builtin = (control: FakeProcessControlIface): boolean => {\n const script = control.exec.script;\n if (script.includes(SANDBOX_SEED_PROTOCOL)) {\n const chunks: Uint8Array[] = [];\n control.onStdin((data) => chunks.push(data));\n control.onEof(() => {\n const payload = z\n .object({ root: z.string(), files: z.record(z.string(), z.string()) })\n .parse(JSON.parse(new TextDecoder().decode(concatBytes(chunks))));\n const marker = posix.join(payload.root, '.final', SANDBOX_SEED_MARKER);\n if (files.has(marker)) {\n control.exit(0);\n return;\n }\n for (const [path, content] of Object.entries(payload.files)) {\n const target = posix.join(payload.root, path);\n if (files.has(target)) continue;\n mkdirp(posix.dirname(target));\n files.set(target, bytes(content));\n }\n mkdirp(posix.dirname(marker));\n files.set(marker, bytes(SANDBOX_SEED_PROTOCOL));\n control.exit(0);\n });\n return true;\n }\n // The provider's helper scripts, matched by how they start.\n const leading = (marker: string): string | null =>\n script.startsWith(marker) ? quotedAfter(script, marker) : null;\n const statPath = leading('if [ ! -e ');\n if (statPath != null && script.includes('stat -c')) {\n // Like `stat` without -L: a symlink reports its own length.\n const link = links.get(statPath);\n if (link != null) control.stdout(`symbolic link|${link.length}|1700000000|777\\n`);\n else if (dirs.has(statPath)) control.stdout(`directory|4096|1700000000|755\\n`);\n else if (files.has(statPath))\n control.stdout(`regular file|${files.get(statPath)?.byteLength ?? 0}|1700000000|644\\n`);\n else control.stdout('missing\\n');\n control.exit(0);\n return true;\n }\n const listPath = leading('[ -d ');\n if (listPath != null && script.includes('find ')) {\n if (!dirs.has(listPath)) {\n control.stderr('Not a directory\\n');\n control.exit(2);\n return true;\n }\n const entries: string[] = [];\n for (const dir of dirs) {\n if (dir !== listPath && posix.dirname(dir) === listPath)\n entries.push(`d\\t4096\\t${posix.basename(dir)}\\0`);\n }\n for (const [path, content] of files) {\n if (posix.dirname(path) === listPath)\n entries.push(`f\\t${content.byteLength}\\t${posix.basename(path)}\\0`);\n }\n control.stdout(entries.join(''));\n control.exit(0);\n return true;\n }\n const mkdirPath = leading('mkdir -p -- ');\n if (mkdirPath != null) {\n mkdirp(mkdirPath);\n control.exit(0);\n return true;\n }\n const removePath = leading('if [ -d ');\n if (removePath != null && script.includes('rm')) {\n if (dirs.has(removePath)) {\n for (const dir of [...dirs])\n if (dir === removePath || dir.startsWith(`${removePath}/`)) dirs.delete(dir);\n for (const path of [...files.keys()])\n if (path.startsWith(`${removePath}/`)) files.delete(path);\n } else if (files.has(removePath)) {\n files.delete(removePath);\n } else if (!script.includes('-f')) {\n control.stderr(`rm: cannot remove: No such file or directory\\n`);\n control.exit(1);\n return true;\n }\n control.exit(0);\n return true;\n }\n if (script.includes('git clone')) {\n const destination = quotedAfter(script.slice(script.indexOf('git clone')), \"' \");\n if (destination != null) mkdirp(`${destination}/.git`);\n control.exit(0);\n return true;\n }\n // Enough of a shell for the conformance kit's process cases.\n if (script === 'cat') {\n control.onStdin((data) => control.stdout(data));\n control.onEof(() => control.exit(0));\n return true;\n }\n if (script.startsWith('sleep ')) return true;\n if (script === DURABLE_CONFORMANCE_SCRIPT) {\n control.stdout('one\\n');\n control.stderr('err-one\\n');\n setTimeout(() => {\n control.stdout('two\\n');\n control.stderr('err-two\\n');\n control.exit(7);\n }, 100);\n return true;\n }\n if (script === 'echo out; echo err >&2; exit 3') {\n control.stdout('out\\n');\n control.stderr('err\\n');\n control.exit(3);\n return true;\n }\n if (script.startsWith('printenv ')) {\n const name = script.slice('printenv '.length);\n const value = Object.hasOwn(control.exec.env, name) ? control.exec.env[name] : undefined;\n if (value != null) control.stdout(`${value}\\n`);\n control.exit(value == null ? 1 : 0);\n return true;\n }\n if (script === 'echo' || script.startsWith('echo ')) {\n control.stdout(`${script.slice('echo '.length)}\\n`);\n control.exit(0);\n return true;\n }\n return false;\n };\n\n const exec: FakeMachineIface['exec'] = (args) => {\n const record: FakeExecIface = {\n command: args.command,\n script: unwrapCommand(args.command),\n cwd: args.cwd,\n env: args.env,\n };\n execs.push(record);\n const stdinListeners: ((data: Uint8Array) => void)[] = [];\n const eofListeners: (() => void)[] = [];\n let waiters: (() => void)[] = [];\n const notify = (): void => {\n const pending = waiters;\n waiters = [];\n for (const wake of pending) wake();\n };\n const process: FakeProcessIface = {\n id: args.id,\n bootId: 'boot-1',\n exec: record,\n stdout: new Uint8Array(),\n stderr: new Uint8Array(),\n exited: false,\n exitCode: null,\n signal: null,\n write: (data) => {\n for (const listener of stdinListeners) listener(data);\n },\n eof: () => {\n for (const listener of eofListeners) listener();\n },\n terminate: (signal) => {\n if (process.exited) return;\n process.exited = true;\n process.signal = signal ?? 'SIGKILL';\n notify();\n },\n changed: (ms) =>\n new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n waiters.push(() => {\n clearTimeout(timer);\n resolve();\n });\n }),\n };\n const control: FakeProcessControlIface = {\n exec: record,\n stdout: (data) => {\n process.stdout = concatBytes([process.stdout, bytes(data)]);\n notify();\n },\n stderr: (data) => {\n process.stderr = concatBytes([process.stderr, bytes(data)]);\n notify();\n },\n exit: (code, signal = null) => {\n if (process.exited) return;\n process.exited = true;\n process.exitCode = signal == null ? code : null;\n process.signal = signal;\n notify();\n },\n onStdin: (listener) => stdinListeners.push(listener),\n onEof: (listener) => eofListeners.push(listener),\n };\n processes.set(args.id, process);\n const custom = behaviors.find((entry) => entry.match(record));\n if (custom != null) custom.behavior(control);\n else if (!builtin(control)) control.exit(0);\n return process;\n };\n\n return {\n files,\n dirs,\n links,\n execs,\n processes,\n on: (match, behavior) => behaviors.push({ match, behavior }),\n exec,\n mkdirp,\n readText: (path) => {\n const content = files.get(path);\n return content == null ? null : new TextDecoder().decode(content);\n },\n };\n};\n\n// Output from offsets, waiting up to `waitMs` (capped for fast tests) for news.\nexport const readFakeOutput = async (\n process: FakeProcessIface,\n offsets: { stdout: number; stderr: number; waitMs: number },\n): Promise<{ stdout: Uint8Array; stderr: Uint8Array; exited: boolean }> => {\n if (\n !process.exited &&\n process.stdout.byteLength <= offsets.stdout &&\n process.stderr.byteLength <= offsets.stderr &&\n offsets.waitMs > 0\n ) {\n await process.changed(Math.min(offsets.waitMs, 50));\n }\n return {\n stdout: process.stdout.subarray(offsets.stdout),\n stderr: process.stderr.subarray(offsets.stderr),\n exited: process.exited,\n };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@finalai/final-agent-provider",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
- "description": "Final provider helpers for harnesses, computer and device sandboxes, the Final room surface, and external provider channels.",
5
+ "description": "Final's harness and ACP adapter definitions and the general harness provider, computer, device and local sandbox providers, Final's MCP gateway integration, the Final room surface, and external provider channels.",
6
6
  "license": "Apache-2.0",
7
7
  "files": [
8
8
  "dist",
@@ -10,8 +10,7 @@
10
10
  "WORKSPACE-EGRESS.md",
11
11
  "LICENSE",
12
12
  "NOTICE",
13
- "HOSTING.md",
14
- "THIRD_PARTY_NOTICES.md"
13
+ "HOSTING.md"
15
14
  ],
16
15
  "type": "module",
17
16
  "sideEffects": false,
@@ -21,50 +20,60 @@
21
20
  "import": "./dist/modules/harnesses/index.mjs",
22
21
  "default": "./dist/modules/harnesses/index.mjs"
23
22
  },
24
- "./harnesses/serverless-final": {
25
- "types": "./dist/modules/harnesses/serverless-final.d.mts",
26
- "import": "./dist/modules/harnesses/serverless-final.mjs",
27
- "default": "./dist/modules/harnesses/serverless-final.mjs"
28
- },
29
- "./harnesses/serverless-pi": {
30
- "types": "./dist/modules/harnesses/serverless-pi.d.mts",
31
- "import": "./dist/modules/harnesses/serverless-pi.mjs",
32
- "default": "./dist/modules/harnesses/serverless-pi.mjs"
33
- },
34
- "./harnesses/serverless-nanocode-codex": {
35
- "types": "./dist/modules/harnesses/serverless-nanocode-codex.d.mts",
36
- "import": "./dist/modules/harnesses/serverless-nanocode-codex.mjs",
37
- "default": "./dist/modules/harnesses/serverless-nanocode-codex.mjs"
38
- },
39
- "./harnesses/serverless-nanocode-claude": {
40
- "types": "./dist/modules/harnesses/serverless-nanocode-claude.d.mts",
41
- "import": "./dist/modules/harnesses/serverless-nanocode-claude.mjs",
42
- "default": "./dist/modules/harnesses/serverless-nanocode-claude.mjs"
43
- },
44
- "./harnesses/remote-claude-code": {
45
- "types": "./dist/modules/harnesses/remote-claude-code.d.mts",
46
- "import": "./dist/modules/harnesses/remote-claude-code.mjs",
47
- "default": "./dist/modules/harnesses/remote-claude-code.mjs"
48
- },
49
- "./harnesses/remote-codex": {
50
- "types": "./dist/modules/harnesses/remote-codex.d.mts",
51
- "import": "./dist/modules/harnesses/remote-codex.mjs",
52
- "default": "./dist/modules/harnesses/remote-codex.mjs"
53
- },
54
- "./harnesses/remote-pi": {
55
- "types": "./dist/modules/harnesses/remote-pi.d.mts",
56
- "import": "./dist/modules/harnesses/remote-pi.mjs",
57
- "default": "./dist/modules/harnesses/remote-pi.mjs"
58
- },
59
- "./harnesses/remote-acp": {
60
- "types": "./dist/modules/harnesses/remote-acp.d.mts",
61
- "import": "./dist/modules/harnesses/remote-acp.mjs",
62
- "default": "./dist/modules/harnesses/remote-acp.mjs"
63
- },
64
- "./harnesses/local-stdio": {
65
- "types": "./dist/modules/harnesses/local-stdio.d.mts",
66
- "import": "./dist/modules/harnesses/local-stdio.mjs",
67
- "default": "./dist/modules/harnesses/local-stdio.mjs"
23
+ "./harnesses/final": {
24
+ "types": "./dist/modules/harnesses/final.d.mts",
25
+ "import": "./dist/modules/harnesses/final.mjs",
26
+ "default": "./dist/modules/harnesses/final.mjs"
27
+ },
28
+ "./harnesses/pi": {
29
+ "types": "./dist/modules/harnesses/pi.d.mts",
30
+ "import": "./dist/modules/harnesses/pi.mjs",
31
+ "default": "./dist/modules/harnesses/pi.mjs"
32
+ },
33
+ "./harnesses/nanocode-claude": {
34
+ "types": "./dist/modules/harnesses/nanocode-claude.d.mts",
35
+ "import": "./dist/modules/harnesses/nanocode-claude.mjs",
36
+ "default": "./dist/modules/harnesses/nanocode-claude.mjs"
37
+ },
38
+ "./harnesses/nanocode-codex": {
39
+ "types": "./dist/modules/harnesses/nanocode-codex.d.mts",
40
+ "import": "./dist/modules/harnesses/nanocode-codex.mjs",
41
+ "default": "./dist/modules/harnesses/nanocode-codex.mjs"
42
+ },
43
+ "./harnesses/claude-code": {
44
+ "types": "./dist/modules/harnesses/claude-code.d.mts",
45
+ "import": "./dist/modules/harnesses/claude-code.mjs",
46
+ "default": "./dist/modules/harnesses/claude-code.mjs"
47
+ },
48
+ "./harnesses/codex": {
49
+ "types": "./dist/modules/harnesses/codex.d.mts",
50
+ "import": "./dist/modules/harnesses/codex.mjs",
51
+ "default": "./dist/modules/harnesses/codex.mjs"
52
+ },
53
+ "./harnesses/adapters": {
54
+ "types": "./dist/modules/harnesses/adapters.d.mts",
55
+ "import": "./dist/modules/harnesses/adapters.mjs",
56
+ "default": "./dist/modules/harnesses/adapters.mjs"
57
+ },
58
+ "./harnesses/definitions": {
59
+ "types": "./dist/modules/harnesses/definitions.d.mts",
60
+ "import": "./dist/modules/harnesses/definitions.mjs",
61
+ "default": "./dist/modules/harnesses/definitions.mjs"
62
+ },
63
+ "./provider": {
64
+ "types": "./dist/modules/provider/index.d.mts",
65
+ "import": "./dist/modules/provider/index.mjs",
66
+ "default": "./dist/modules/provider/index.mjs"
67
+ },
68
+ "./provider/general": {
69
+ "types": "./dist/modules/provider/general.d.mts",
70
+ "import": "./dist/modules/provider/general.mjs",
71
+ "default": "./dist/modules/provider/general.mjs"
72
+ },
73
+ "./catalog": {
74
+ "types": "./dist/modules/catalog.d.mts",
75
+ "import": "./dist/modules/catalog.mjs",
76
+ "default": "./dist/modules/catalog.mjs"
68
77
  },
69
78
  "./harnesses/fidelity": {
70
79
  "types": "./dist/modules/harnesses/fidelity.d.mts",
@@ -86,6 +95,16 @@
86
95
  "import": "./dist/modules/sandboxes/device.mjs",
87
96
  "default": "./dist/modules/sandboxes/device.mjs"
88
97
  },
98
+ "./sandboxes/local": {
99
+ "types": "./dist/modules/sandboxes/local.d.mts",
100
+ "import": "./dist/modules/sandboxes/local.mjs",
101
+ "default": "./dist/modules/sandboxes/local.mjs"
102
+ },
103
+ "./sandboxes/access": {
104
+ "types": "./dist/modules/sandboxes/access.d.mts",
105
+ "import": "./dist/modules/sandboxes/access.mjs",
106
+ "default": "./dist/modules/sandboxes/access.mjs"
107
+ },
89
108
  "./channels": {
90
109
  "types": "./dist/modules/channels/index.d.mts",
91
110
  "import": "./dist/modules/channels/index.mjs",
@@ -137,61 +156,11 @@
137
156
  "import": "./dist/modules/sandboxes/testing/quoted-shell-arguments.mjs",
138
157
  "default": "./dist/modules/sandboxes/testing/quoted-shell-arguments.mjs"
139
158
  },
140
- "./runtime/local-stdio": {
141
- "types": "./dist/modules/runtime/local-stdio.d.mts",
142
- "import": "./dist/modules/runtime/local-stdio.mjs",
143
- "default": "./dist/modules/runtime/local-stdio.mjs"
144
- },
145
- "./runtime/remote-acp": {
146
- "types": "./dist/modules/runtime/remote-acp.d.mts",
147
- "import": "./dist/modules/runtime/remote-acp.mjs",
148
- "default": "./dist/modules/runtime/remote-acp.mjs"
149
- },
150
- "./runtime/remote-claude-code": {
151
- "types": "./dist/modules/runtime/remote-claude-code.d.mts",
152
- "import": "./dist/modules/runtime/remote-claude-code.mjs",
153
- "default": "./dist/modules/runtime/remote-claude-code.mjs"
154
- },
155
- "./runtime/remote-codex": {
156
- "types": "./dist/modules/runtime/remote-codex.d.mts",
157
- "import": "./dist/modules/runtime/remote-codex.mjs",
158
- "default": "./dist/modules/runtime/remote-codex.mjs"
159
- },
160
- "./runtime/remote-pi": {
161
- "types": "./dist/modules/runtime/remote-pi.d.mts",
162
- "import": "./dist/modules/runtime/remote-pi.mjs",
163
- "default": "./dist/modules/runtime/remote-pi.mjs"
164
- },
165
- "./runtime/remote-host": {
166
- "types": "./dist/modules/runtime/remote-host.d.mts",
167
- "import": "./dist/modules/runtime/remote-host.mjs",
168
- "default": "./dist/modules/runtime/remote-host.mjs"
169
- },
170
- "./harnesses/remote-url": {
171
- "types": "./dist/modules/harnesses/remote-url.d.mts",
172
- "import": "./dist/modules/harnesses/remote-url.mjs",
173
- "default": "./dist/modules/harnesses/remote-url.mjs"
174
- },
175
- "./runtime": {
176
- "types": "./dist/modules/runtime/index.d.mts",
177
- "import": "./dist/modules/runtime/index.mjs",
178
- "default": "./dist/modules/runtime/index.mjs"
179
- },
180
- "./testing/harness": {
181
- "types": "./dist/modules/testing/harness.d.mts",
182
- "import": "./dist/modules/testing/harness.mjs",
183
- "default": "./dist/modules/testing/harness.mjs"
184
- },
185
159
  "./testing/fake-platform": {
186
160
  "types": "./dist/modules/channels/fake-platform.d.mts",
187
161
  "import": "./dist/modules/channels/fake-platform.mjs",
188
162
  "default": "./dist/modules/channels/fake-platform.mjs"
189
163
  },
190
- "./connections": {
191
- "types": "./dist/modules/connections.d.mts",
192
- "import": "./dist/modules/connections.mjs",
193
- "default": "./dist/modules/connections.mjs"
194
- },
195
164
  "./sandboxes/egress": {
196
165
  "types": "./dist/modules/sandboxes/egress.d.mts",
197
166
  "import": "./dist/modules/sandboxes/egress.mjs",
@@ -201,6 +170,11 @@
201
170
  "types": "./dist/modules/sandboxes/egress-bootstrap.d.mts",
202
171
  "import": "./dist/modules/sandboxes/egress-bootstrap.mjs",
203
172
  "default": "./dist/modules/sandboxes/egress-bootstrap.mjs"
173
+ },
174
+ "./integrations": {
175
+ "types": "./dist/modules/integrations.d.mts",
176
+ "import": "./dist/modules/integrations.mjs",
177
+ "default": "./dist/modules/integrations.mjs"
204
178
  }
205
179
  },
206
180
  "publishConfig": {
@@ -209,14 +183,12 @@
209
183
  },
210
184
  "dependencies": {
211
185
  "@agentclientprotocol/sdk": "1.8.0",
212
- "@finalai/acp-session": "0.1.12",
213
- "@finalai/agent-protocol": "0.8.0",
214
- "@finalai/agent-provider": "0.9.0",
186
+ "@finalai/acp-session": "0.2.0",
187
+ "@finalai/agent-protocol": "0.9.0",
188
+ "@finalai/agent-provider": "0.10.0",
215
189
  "@finalai/computers": "0.3.1",
216
- "@finalai/websockets": "0.1.7",
217
- "ws": "^8.21.3",
218
190
  "zod": "4.6.6",
219
- "@finalai/agent-definition": "0.8.0"
191
+ "@finalai/agent-definition": "0.9.0"
220
192
  },
221
193
  "engines": {
222
194
  "node": ">=26"
@@ -1,11 +0,0 @@
1
- import { type DynamicSentinelIface, type HostedConnectionDefinitionIface, type McpClientConnectionDefinitionIface } from '@finalai/agent-definition/authoring';
2
- export type FinalConnectionDefinitionIface = Omit<McpClientConnectionDefinitionIface, 'auth'>;
3
- export interface FinalHostedConnectionDefinitionIface extends Omit<HostedConnectionDefinitionIface, 'binding'> {
4
- readonly binding?: string;
5
- }
6
- export declare function defineFinalConnection<TConnection extends FinalConnectionDefinitionIface>(definition: TConnection): TConnection & {
7
- readonly auth: {
8
- readonly kind: 'final-session';
9
- };
10
- };
11
- export declare function defineFinalConnection(definition?: FinalHostedConnectionDefinitionIface): DynamicSentinelIface<McpClientConnectionDefinitionIface>;
@@ -1,16 +0,0 @@
1
- import {
2
- defineMcpClientConnection,
3
- defineHostedConnection
4
- } from "@finalai/agent-definition/authoring";
5
- function defineFinalConnection(definition = {}) {
6
- if ("url" in definition)
7
- return defineMcpClientConnection({ ...definition, auth: { kind: "final-session" } });
8
- return defineHostedConnection({
9
- ...definition,
10
- binding: definition.binding ?? "final"
11
- });
12
- }
13
- export {
14
- defineFinalConnection
15
- };
16
- //# sourceMappingURL=connections.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/connections.ts"],
4
- "sourcesContent": ["import {\n defineMcpClientConnection,\n defineHostedConnection,\n type DynamicSentinelIface,\n type HostedConnectionDefinitionIface,\n type McpClientConnectionDefinitionIface,\n} from '@finalai/agent-definition/authoring';\n\nexport type FinalConnectionDefinitionIface = Omit<McpClientConnectionDefinitionIface, 'auth'>;\n\nexport interface FinalHostedConnectionDefinitionIface extends Omit<\n HostedConnectionDefinitionIface,\n 'binding'\n> {\n readonly binding?: string;\n}\n\n// `connections/final.ts`: Final's MCP server as an ordinary connection. The\n// session service's broker resolves `final-session` auth to a grant scoped to\n// the calling session, which Final's MCP server runs the tools as.\nexport function defineFinalConnection<TConnection extends FinalConnectionDefinitionIface>(\n definition: TConnection,\n): TConnection & { readonly auth: { readonly kind: 'final-session' } };\nexport function defineFinalConnection(\n definition?: FinalHostedConnectionDefinitionIface,\n): DynamicSentinelIface<McpClientConnectionDefinitionIface>;\nexport function defineFinalConnection(\n definition: FinalConnectionDefinitionIface | FinalHostedConnectionDefinitionIface = {},\n): McpClientConnectionDefinitionIface | DynamicSentinelIface<McpClientConnectionDefinitionIface> {\n if ('url' in definition)\n return defineMcpClientConnection({ ...definition, auth: { kind: 'final-session' } });\n return defineHostedConnection({\n ...definition,\n binding: definition.binding ?? 'final',\n });\n}\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAoBA,SAAS,sBACd,aAAoF,CAAC,GACU;AAC/F,MAAI,SAAS;AACX,WAAO,0BAA0B,EAAE,GAAG,YAAY,MAAM,EAAE,MAAM,gBAAgB,EAAE,CAAC;AACrF,SAAO,uBAAuB;AAAA,IAC5B,GAAG;AAAA,IACH,SAAS,WAAW,WAAW;AAAA,EACjC,CAAC;AACH;",
6
- "names": []
7
- }
@@ -1,20 +0,0 @@
1
- import { type InitializeResponse, type Stream } from '@agentclientprotocol/sdk/experimental/v2';
2
- import { type AcpTransport, type HarnessDescriptionIface, type JsonSchema } from '@finalai/agent-provider';
3
- export declare const FINAL_CLIENT_INFO: {
4
- name: string;
5
- version: string;
6
- };
7
- export declare const DEFAULT_CONNECT_TIMEOUT_MS = 10000;
8
- export declare const describeFromInitialize: (args: {
9
- response: InitializeResponse;
10
- transports: AcpTransport[];
11
- configSchema: JsonSchema;
12
- }) => HarnessDescriptionIface;
13
- export declare const unprobedDescription: (args: {
14
- transports: AcpTransport[];
15
- configSchema: JsonSchema;
16
- }) => HarnessDescriptionIface;
17
- export declare const initializeOver: (args: {
18
- stream: Stream;
19
- timeoutMs: number;
20
- }) => Promise<InitializeResponse>;