@finalai/final-agent-provider 0.1.4 → 0.2.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 (42) hide show
  1. package/HOSTING.md +49 -9
  2. package/README.md +10 -0
  3. package/dist/modules/harnesses/config-fields.d.mts +3 -2
  4. package/dist/modules/harnesses/config-fields.mjs +16 -3
  5. package/dist/modules/harnesses/config-fields.mjs.map +3 -3
  6. package/dist/modules/harnesses/index.d.mts +1 -1
  7. package/dist/modules/harnesses/index.mjs +2 -1
  8. package/dist/modules/harnesses/index.mjs.map +2 -2
  9. package/dist/modules/harnesses/model-reference.d.mts +6 -0
  10. package/dist/modules/harnesses/model-reference.mjs +12 -0
  11. package/dist/modules/harnesses/model-reference.mjs.map +7 -0
  12. package/dist/modules/harnesses/remote-claude-code.mjs +2 -2
  13. package/dist/modules/harnesses/remote-claude-code.mjs.map +2 -2
  14. package/dist/modules/harnesses/remote-codex.mjs +2 -2
  15. package/dist/modules/harnesses/remote-codex.mjs.map +2 -2
  16. package/dist/modules/harnesses/remote-pi.mjs +2 -2
  17. package/dist/modules/harnesses/remote-pi.mjs.map +2 -2
  18. package/dist/modules/harnesses/serverless-final.d.mts +2 -3
  19. package/dist/modules/harnesses/serverless-final.mjs +4 -9
  20. package/dist/modules/harnesses/serverless-final.mjs.map +2 -2
  21. package/dist/modules/harnesses/serverless-nanocode-claude.d.mts +2 -3
  22. package/dist/modules/harnesses/serverless-nanocode-claude.mjs +4 -9
  23. package/dist/modules/harnesses/serverless-nanocode-claude.mjs.map +2 -2
  24. package/dist/modules/harnesses/serverless-nanocode-codex.d.mts +2 -3
  25. package/dist/modules/harnesses/serverless-nanocode-codex.mjs +4 -9
  26. package/dist/modules/harnesses/serverless-nanocode-codex.mjs.map +2 -2
  27. package/dist/modules/harnesses/serverless-pi.d.mts +2 -3
  28. package/dist/modules/harnesses/serverless-pi.mjs +4 -4
  29. package/dist/modules/harnesses/serverless-pi.mjs.map +2 -2
  30. package/dist/modules/sandboxes/computer.mjs +21 -14
  31. package/dist/modules/sandboxes/computer.mjs.map +2 -2
  32. package/dist/modules/sandboxes/device.mjs +1 -1
  33. package/dist/modules/sandboxes/device.mjs.map +2 -2
  34. package/dist/modules/sandboxes/session.d.mts +1 -1
  35. package/dist/modules/sandboxes/session.mjs +1 -1
  36. package/dist/modules/sandboxes/session.mjs.map +2 -2
  37. package/dist/modules/sandboxes/testing/fake-machine.mjs +8 -0
  38. package/dist/modules/sandboxes/testing/fake-machine.mjs.map +2 -2
  39. package/package.json +3 -8
  40. package/dist/modules/harnesses/models.d.mts +0 -281
  41. package/dist/modules/harnesses/models.mjs +0 -234
  42. package/dist/modules/harnesses/models.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 SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport { exitStatus, type SandboxTransportIface, type TransportProcessIface } from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env.\n baseEnv: () => Record<string, string>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n}\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...args.baseEnv(), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n const { stream: stdout } = stdoutPush;\n const { stream: stderr } = stderrPush;\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n\n const kill = async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n const onAbort = (): void => {\n void kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n\n void (async () => {\n let stdoutOffset = 0;\n let stderrOffset = 0;\n let waitMs = transport.outputWaitMs;\n try {\n for (;;) {\n const output = await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n });\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n } finally {\n options.abortSignal?.removeEventListener('abort', onAbort);\n }\n })();\n\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n for await (const chunk of rechunk(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n stdout,\n stderr,\n write,\n wait: () => exit,\n kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess(options, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding is read-only');\n};\n\n// A read binding's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the lease the provider took.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n\nconst fileWriteRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding runs processes but does not write files');\n};\n\n// An execute binding's view of a handle: reads and processes pass through; file\n// writes and lifecycle are refused.\nexport const executeOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => ({\n ...session,\n writeFile: fileWriteRefusal,\n writeBinaryFile: fileWriteRefusal,\n writeTextFile: fileWriteRefusal,\n removePath: fileWriteRefusal,\n stop: fileWriteRefusal,\n destroy: fileWriteRefusal,\n});\n\n// The view of a handle that a binding's access allows.\nexport const sessionForAccess = <S extends NetworkSandboxSessionIface>(\n session: S,\n access: SandboxAccess,\n): S =>\n access === SandboxAccess.Read\n ? readOnlySession(session)\n : access === SandboxAccess.Execute\n ? executeOnlySession(session)\n : session;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { SandboxAccess } from '@finalai/agent-provider';\nimport type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport { exitStatus, type SandboxTransportIface, type TransportProcessIface } from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n}\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n const { stream: stdout } = stdoutPush;\n const { stream: stderr } = stderrPush;\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n\n const kill = async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n const onAbort = (): void => {\n void kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n\n void (async () => {\n let stdoutOffset = 0;\n let stderrOffset = 0;\n let waitMs = transport.outputWaitMs;\n try {\n for (;;) {\n const output = await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n });\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n } finally {\n options.abortSignal?.removeEventListener('abort', onAbort);\n }\n })();\n\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n for await (const chunk of rechunk(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n stdout,\n stderr,\n write,\n wait: () => exit,\n kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess(options, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding is read-only');\n};\n\n// A read binding's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the lease the provider took.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n\nconst fileWriteRefusal = async (): Promise<never> => {\n throw new Error('this sandbox binding runs processes but does not write files');\n};\n\n// An execute binding's view of a handle: reads and processes pass through; file\n// writes and lifecycle are refused.\nexport const executeOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => ({\n ...session,\n writeFile: fileWriteRefusal,\n writeBinaryFile: fileWriteRefusal,\n writeTextFile: fileWriteRefusal,\n removePath: fileWriteRefusal,\n stop: fileWriteRefusal,\n destroy: fileWriteRefusal,\n});\n\n// The view of a handle that a binding's access allows.\nexport const sessionForAccess = <S extends NetworkSandboxSessionIface>(\n session: S,\n access: SandboxAccess,\n): S =>\n access === SandboxAccess.Read\n ? readOnlySession(session)\n : access === SandboxAccess.Execute\n ? executeOnlySession(session)\n : session;\n"],
5
+ "mappings": "AAAA,SAAS,qBAAqB;AAU9B,SAAS,0BAA0B,wBAAwB;AAC3D,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,eAAe,cAAc,mBAAmB,eAAe;AACxE,SAAS,wBAAyD;AAClE,SAAS,mBAA2C;AACpD,SAAS,kBAA0E;AA8BnF,MAAM,cAAc,MAAmB,IAAI,YAAY,OAAO;AAY9D,MAAM,aAAa,MAAuB;AACxC,QAAM,SAAgC,CAAC;AACvC,QAAM,SAAS,IAAI,eAA2B;AAAA,IAC5C,OAAO,CAAC,eAAe;AACrB,aAAO,aAAa;AAAA,IACtB;AAAA,EACF,CAAC;AACD,SAAO,EAAE,QAAQ,YAAY,OAAO,WAAW;AACjD;AAEA,MAAM,cAAc,CAClB,MACA,UACe;AAAA,EACf;AAAA,EACA,MAAM,KAAK;AAAA,EACX,MAAM,KAAK;AAAA,EACX,YAAY,KAAK,gBAAgB,OAAO,OAAO,IAAI,KAAK,KAAK,YAAY,EAAE,YAAY;AAAA,EACvF,MAAM,KAAK;AACb;AAEO,MAAM,yBAAyB,CACpC,SAC+B;AAC/B,QAAM,EAAE,UAAU,IAAI;AACtB,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,cAAc,KAAK,YAAY;AACrC,QAAM,cAAc,CAAC,SAAyB,MAAM,QAAQ,KAAK,eAAe,IAAI;AAEpF,QAAM,eAAe,OACnB,SACA,eACiC;AACjC,YAAQ,aAAa,eAAe;AACpC,UAAM,UAAiC,MAAM,UAAU,KAAK;AAAA,MAC1D,IAAI,KAAK,WAAW;AAAA,MACpB,SAAS,YAAY,OAAO;AAAA,MAC5B,KAAK,YAAY,QAAQ,OAAO,KAAK,aAAa;AAAA,MAClD,KAAK,EAAE,GAAI,MAAM,KAAK,QAAQ,GAAI,GAAG,QAAQ,IAAI;AAAA,MACjD,WAAW,QAAQ,aAAa;AAAA,MAChC,QAAQ,QAAQ;AAAA,IAClB,CAAC;AACD,UAAM,aAAa,WAAW;AAC9B,UAAM,aAAa,WAAW;AAC9B,UAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,UAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,QAAI,aAAoD,MAAM;AAC9D,QAAI,WAAmC,MAAM;AAC7C,UAAM,OAAO,IAAI,QAA8B,CAAC,SAAS,WAAW;AAClE,mBAAa;AACb,iBAAW;AAAA,IACb,CAAC;AAED,SAAK,MAAM,MAAM,MAAS;AAE1B,UAAM,OAAO,OAAO,WAAmC;AACrD,YAAM,UAAU;AAAA,QACd,UAAU,QAAQ,WAAW,YAAY,EAAE,SAAS,WAAW,KAAK,IAAI,EAAE,SAAS,OAAO;AAAA,MAC5F;AAAA,IACF;AACA,UAAM,UAAU,MAAY;AAC1B,WAAK,KAAK,EAAE,MAAM,MAAM,MAAS;AAAA,IACnC;AACA,YAAQ,aAAa,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACtE,QAAI,QAAQ,aAAa,YAAY,KAAM,SAAQ;AAEnD,UAAM,YAAY;AAChB,UAAI,eAAe;AACnB,UAAI,eAAe;AACnB,UAAI,SAAS,UAAU;AACvB,UAAI;AACF,mBAAS;AACP,gBAAM,SAAS,MAAM,UAAU,OAAO;AAAA,YACpC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AACD,cAAI,OAAO,OAAO,KAAK,aAAa,EAAG,YAAW,YAAY,QAAQ,OAAO,OAAO,IAAI;AACxF,cAAI,OAAO,OAAO,KAAK,aAAa,EAAG,YAAW,YAAY,QAAQ,OAAO,OAAO,IAAI;AACxF,gBAAM,WACJ,OAAO,OAAO,eAAe,gBAAgB,OAAO,OAAO,eAAe;AAC5E,yBAAe,OAAO,OAAO;AAC7B,yBAAe,OAAO,OAAO;AAC7B,cAAI,OAAO,UAAU,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAC3D,uBAAW,YAAY,MAAM;AAC7B,uBAAW,YAAY,MAAM;AAC7B,uBAAW,EAAE,UAAU,WAAW,OAAO,UAAU,OAAO,UAAU,EAAE,CAAC;AACvE;AAAA,UACF;AAEA,mBAAS,OAAO,UAAU,WAAW,IAAI,UAAU;AAAA,QACrD;AAAA,MACF,SAAS,OAAO;AACd,cAAM,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACtE,mBAAW,YAAY,MAAM,KAAK;AAClC,mBAAW,YAAY,MAAM,KAAK;AAClC,iBAAS,KAAK;AAAA,MAChB,UAAE;AACA,gBAAQ,aAAa,oBAAoB,SAAS,OAAO;AAAA,MAC3D;AAAA,IACF,GAAG;AAEH,UAAM,QAAQ,OAAO,MAA2B,iBAAqC;AACnF,YAAM,QAAQ,gBAAgB,aAAa,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAC/E,UAAI,MAAM,aAAa,EAAG,OAAM,UAAU,MAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AACxE,UAAI,cAAc,QAAQ,KAAM,OAAM,UAAU,MAAM,EAAE,SAAS,KAAK,KAAK,CAAC;AAAA,IAC9E;AAEA,UAAM,QAAQ,QAAQ;AACtB,QAAI,iBAAiB,gBAAgB;AACnC,YAAM,YAAY;AAChB,yBAAiB,SAAS,QAAQ,OAAO,KAAK,IAAI,EAAG,OAAM,MAAM,KAAK;AACtE,cAAM,MAAM,IAAI,WAAW,GAAG,EAAE,KAAK,KAAK,CAAC;AAAA,MAC7C,GAAG,EAAE,MAAM,MAAM,MAAS;AAAA,IAC5B,WAAW,SAAS,MAAM;AACxB,YAAM,MAAM,OAAO,EAAE,KAAK,KAAK,CAAC;AAAA,IAClC,WAAW,YAAY;AACrB,YAAM,UAAU,MAAM,EAAE,SAAS,KAAK,KAAK,CAAC;AAAA,IAC9C;AAEA,WAAO;AAAA,MACL,KAAK,QAAQ;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OACjB,MACA,WAC+C;AAC/C,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,OAAO,MAAM,UAAU,KAAK,EAAE,MAAM,UAAU,OAAO,CAAC;AAC5D,QAAI,QAAQ,KAAM,QAAO;AACzB,QAAI,KAAK,SAAS,iBAAiB,UAAW,OAAM,IAAI,MAAM,GAAG,QAAQ,iBAAiB;AAG1F,QAAI,SAAS;AACb,QAAI,OAAO;AACX,WAAO,IAAI,eAA2B;AAAA,MACpC,MAAM,OAAO,eAAe;AAC1B,YAAI,MAAM;AACR,qBAAW,MAAM;AACjB;AAAA,QACF;AACA,cAAM,QAAQ,MAAM,UAAU,UAAU;AAAA,UACtC,MAAM;AAAA,UACN;AAAA,UACA,QAAQ,UAAU;AAAA,UAClB;AAAA,QACF,CAAC;AACD,eAAO,MAAM,OAAO,MAAM,MAAM,eAAe;AAC/C,kBAAU,MAAM,MAAM;AACtB,YAAI,MAAM,MAAM,aAAa,EAAG,YAAW,QAAQ,MAAM,KAAK;AAC9D,YAAI,KAAM,YAAW,MAAM;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,cAAc,OAClB,MACA,SACA,WACkB;AAClB,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,UAAU,gBAAgB,EAAE,MAAM,MAAM,QAAQ,QAAQ,GAAG,OAAO,CAAC;AACzE,QAAI,SAAS;AACb,qBAAiB,SAAS,QAAQ,SAAS,UAAU,cAAc,GAAG;AACpE,YAAM,UAAU,WAAW,EAAE,MAAM,UAAU,QAAQ,OAAO,OAAO,OAAO,CAAC;AAC3E,gBAAU,MAAM;AAAA,IAClB;AACA,QAAI,WAAW;AACb,YAAM,UAAU,WAAW,EAAE,MAAM,UAAU,QAAQ,GAAG,OAAO,IAAI,WAAW,GAAG,OAAO,CAAC;AAAA,EAC7F;AAEA,QAAM,cAAc,CAAC,UACnB,IAAI,eAA2B;AAAA,IAC7B,OAAO,CAAC,eAAe;AACrB,UAAI,MAAM,aAAa,EAAG,YAAW,QAAQ,KAAK;AAClD,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF,CAAC;AAEH,QAAM,UAAsC;AAAA,IAC1C,IAAI,KAAK;AAAA,IACT,aAAa,KAAK;AAAA,IAClB,yBAAyB,KAAK;AAAA,IAC9B,OAAO,KAAK,QAAQ;AAAA,IACpB;AAAA,IACA,UAAU,OAAO,EAAE,MAAM,YAAY,MAAM,WAAW,MAAM,WAAW;AAAA,IACvE,gBAAgB,OAAO,EAAE,MAAM,YAAY,MAAM;AAC/C,YAAM,SAAS,MAAM,WAAW,MAAM,WAAW;AACjD,aAAO,UAAU,OAAO,OAAO,cAAc,MAAM;AAAA,IACrD;AAAA,IACA,cAAc,OAAO,YAAY;AAC/B,YAAM,SAAS,MAAM,WAAW,QAAQ,MAAM,QAAQ,WAAW;AACjE,aAAO,UAAU,OAAO,OAAO,mBAAmB,QAAQ,OAAO;AAAA,IACnE;AAAA,IACA,WAAW,OAAO,EAAE,MAAM,SAAS,YAAY,MAAM,YAAY,MAAM,SAAS,WAAW;AAAA,IAC3F,iBAAiB,OAAO,EAAE,MAAM,SAAS,YAAY,MACnD,YAAY,MAAM,YAAY,OAAO,GAAG,WAAW;AAAA,IACrD,eAAe,OAAO,EAAE,MAAM,SAAS,UAAU,YAAY,MAC3D,YAAY,MAAM,YAAY,kBAAkB,SAAS,QAAQ,CAAC,GAAG,WAAW;AAAA,IAClF,OAAO,CAAC,YAAY,aAAa,SAAS,KAAK;AAAA,IAC/C,KAAK,OAAO,YAA4C;AACtD,YAAM,UAAU,MAAM,aAAa,SAAS,IAAI;AAChD,YAAM,CAAC,QAAQ,QAAQ,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC/C,cAAc,QAAQ,MAAM;AAAA,QAC5B,cAAc,QAAQ,MAAM;AAAA,QAC5B,QAAQ,KAAK;AAAA,MACf,CAAC;AACD,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,QAAQ,YAAY,EAAE,OAAO,MAAM;AAAA,QACnC,QAAQ,YAAY,EAAE,OAAO,MAAM;AAAA,MACrC;AAAA,IACF;AAAA,IACA,MAAM,OAAO,EAAE,MAAM,YAAY,MAAM;AACrC,YAAM,WAAW,YAAY,IAAI;AACjC,YAAM,OAAO,MAAM,UAAU,KAAK,EAAE,MAAM,UAAU,QAAQ,YAAY,CAAC;AACzE,aAAO,QAAQ,OAAO,OAAO,YAAY,UAAU,IAAI;AAAA,IACzD;AAAA,IACA,SAAS,OAAO,EAAE,MAAM,YAAY,MAAgC;AAClE,YAAM,WAAW,YAAY,IAAI;AACjC,YAAM,UAAU,MAAM,UAAU,QAAQ,EAAE,MAAM,UAAU,QAAQ,YAAY,CAAC;AAC/E,aAAO,QAAQ,IAAI,CAAC,WAAW;AAAA,QAC7B,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM,KAAK,UAAU,MAAM,IAAI;AAAA,QACrC,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,MACd,EAAE;AAAA,IACJ;AAAA,IACA,YAAY,OAAO,EAAE,MAAM,WAAW,OAAO,YAAY,MAAM;AAC7D,YAAM,WAAW,YAAY,IAAI;AACjC,UAAI;AACF,cAAM,UAAU,OAAO;AAAA,UACrB,MAAM;AAAA,UACN,WAAW,cAAc;AAAA,UACzB,OAAO,UAAU;AAAA,UACjB,QAAQ;AAAA,QACV,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YAAI,UAAU,QAAQ,kBAAkB,aAAa,KAAK,CAAC,EAAG;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB,CAAC,YAAY,KAAK,QAAQ,gBAAgB,OAAO;AAAA,IAClE,YAAY,OAAO,aAAa,MAAM,KAAK,QAAQ,gBAAgB,OAAO,GAAG;AAAA,IAC7E,MAAM,MAAM,KAAK,QAAQ,KAAK;AAAA,IAC9B,SAAS,MAAM,KAAK,QAAQ,QAAQ;AAAA,EACtC;AACA,SAAO,EAAE,GAAG,SAAS,oBAAoB,yBAAyB,OAAO,EAAE;AAC7E;AAEA,MAAM,kBAAkB,YAA4B;AAClD,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAIO,MAAM,kBAAkB,CAAuC,YAAkB;AACtF,QAAM,aAAgB;AAAA,IACpB,GAAG;AAAA,IACH,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,OAAO;AAAA,IACP,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACA,MAAI,QAAQ,oBAAoB,KAAM,YAAW,mBAAmB;AACpE,QAAM,SAAS,QAAQ;AACvB,MAAI,UAAU;AACZ,eAAW,SAAS,OAAO,YAAY;AACrC,UAAI,SAAS,aAAa,MAAO,QAAO,gBAAgB;AACxD,aAAO,OAAO,KAAK,SAAS,OAAO;AAAA,IACrC;AACF,SAAO;AACT;AAEA,MAAM,mBAAmB,YAA4B;AACnD,QAAM,IAAI,MAAM,8DAA8D;AAChF;AAIO,MAAM,qBAAqB,CAAuC,aAAmB;AAAA,EAC1F,GAAG;AAAA,EACH,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,SAAS;AACX;AAGO,MAAM,mBAAmB,CAC9B,SACA,WAEA,WAAW,cAAc,OACrB,gBAAgB,OAAO,IACvB,WAAW,cAAc,UACvB,mBAAmB,OAAO,IAC1B;",
6
6
  "names": []
7
7
  }
@@ -161,6 +161,14 @@ const createFakeMachine = () => {
161
161
  control.exit(3);
162
162
  return true;
163
163
  }
164
+ if (script.startsWith("printenv ")) {
165
+ const name = script.slice("printenv ".length);
166
+ const value = Object.hasOwn(control.exec.env, name) ? control.exec.env[name] : void 0;
167
+ if (value != null) control.stdout(`${value}
168
+ `);
169
+ control.exit(value == null ? 1 : 0);
170
+ return true;
171
+ }
164
172
  if (script === "echo" || script.startsWith("echo ")) {
165
173
  control.stdout(`${script.slice("echo ".length)}
166
174
  `);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sandboxes/testing/fake-machine.ts"],
4
- "sourcesContent": ["import { 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 === '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 === '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 { 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 === '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,6 +1,6 @@
1
1
  {
2
2
  "name": "@finalai/final-agent-provider",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "Final's provider package: serverless, remote and local harnesses; the computer and device sandboxes; the messaging, schedule and event channels.",
6
6
  "license": "Apache-2.0",
@@ -111,11 +111,6 @@
111
111
  "default": "./dist/modules/channels/agent-events.mjs"
112
112
  },
113
113
  "./package.json": "./package.json",
114
- "./harnesses/models": {
115
- "types": "./dist/modules/harnesses/models.d.mts",
116
- "import": "./dist/modules/harnesses/models.mjs",
117
- "default": "./dist/modules/harnesses/models.mjs"
118
- },
119
114
  "./channel-factories": {
120
115
  "types": "./dist/modules/channel-factories.d.mts",
121
116
  "import": "./dist/modules/channel-factories.mjs",
@@ -215,12 +210,12 @@
215
210
  "@agentclientprotocol/sdk": "1.8.0",
216
211
  "@finalai/acp-session": "0.1.4",
217
212
  "@finalai/agent-protocol": "0.1.4",
218
- "@finalai/agent-provider": "0.1.4",
213
+ "@finalai/agent-provider": "0.1.6",
219
214
  "@finalai/computers": "0.1.4",
220
215
  "@finalai/websockets": "0.1.4",
221
216
  "ws": "^8.21.3",
222
217
  "zod": "4.6.5",
223
- "@finalai/agent-definition": "0.1.4"
218
+ "@finalai/agent-definition": "0.1.5"
224
219
  },
225
220
  "engines": {
226
221
  "node": ">=26"
@@ -1,281 +0,0 @@
1
- export declare enum ModelVendor {
2
- OpenAI = "openai",
3
- Anthropic = "anthropic",
4
- OpenRouter = "openrouter"
5
- }
6
- export interface ModelPriceIface {
7
- effectiveFrom: string;
8
- inputUsdPerMillion: number;
9
- outputUsdPerMillion: number;
10
- cachedInputUsdPerMillion: number;
11
- cacheWriteUsdPerMillion: number;
12
- }
13
- export interface HarnessModelIface {
14
- id: string;
15
- vendor: ModelVendor;
16
- label: string;
17
- vendorModelId?: string;
18
- prices?: readonly ModelPriceIface[];
19
- }
20
- export declare const FINAL_HARNESS_MODELS: readonly [{
21
- readonly id: "deepseek-v4.1-flash";
22
- readonly vendor: ModelVendor.OpenRouter;
23
- readonly label: "DeepSeek V4.1 Flash";
24
- readonly vendorModelId: "deepseek/deepseek-v4.1-flash";
25
- readonly prices: readonly [{
26
- readonly effectiveFrom: "2026-10-02T00:00:00Z";
27
- readonly inputUsdPerMillion: 0.22;
28
- readonly outputUsdPerMillion: 0.66;
29
- readonly cachedInputUsdPerMillion: 0.007;
30
- readonly cacheWriteUsdPerMillion: 0;
31
- }];
32
- }, {
33
- readonly id: "final-claude-opus-5.5";
34
- readonly vendor: ModelVendor.OpenRouter;
35
- readonly label: "Opus 5.5";
36
- readonly vendorModelId: "anthropic/claude-opus-5.5";
37
- readonly prices: readonly [{
38
- readonly effectiveFrom: "2026-10-02T00:00:00Z";
39
- readonly inputUsdPerMillion: 4;
40
- readonly outputUsdPerMillion: 20;
41
- readonly cachedInputUsdPerMillion: 0.2;
42
- readonly cacheWriteUsdPerMillion: 5;
43
- }];
44
- }, {
45
- readonly id: "final-gpt-6.1-sol";
46
- readonly vendor: ModelVendor.OpenRouter;
47
- readonly label: "GPT 6.1 Sol";
48
- readonly vendorModelId: "openai/gpt-6.1-sol";
49
- readonly prices: readonly [{
50
- readonly effectiveFrom: "2026-10-02T00:00:00Z";
51
- readonly inputUsdPerMillion: 2;
52
- readonly outputUsdPerMillion: 10;
53
- readonly cachedInputUsdPerMillion: 0.1;
54
- readonly cacheWriteUsdPerMillion: 2.5;
55
- }];
56
- }];
57
- export declare const CODEX_RESPONSES_LITE_MODELS: readonly [{
58
- readonly id: "gpt-6-sol";
59
- readonly vendor: ModelVendor.OpenAI;
60
- readonly label: "GPT 6 Sol";
61
- readonly prices: readonly [ModelPriceIface];
62
- }, {
63
- readonly id: "gpt-6.1-sol";
64
- readonly vendor: ModelVendor.OpenAI;
65
- readonly label: "GPT 6.1 Sol";
66
- readonly prices: readonly [ModelPriceIface];
67
- }, {
68
- readonly id: "gpt-6-luna";
69
- readonly vendor: ModelVendor.OpenAI;
70
- readonly label: "GPT 6 Luna";
71
- readonly prices: readonly [ModelPriceIface];
72
- }, {
73
- readonly id: "gpt-6-astra";
74
- readonly vendor: ModelVendor.OpenAI;
75
- readonly label: "GPT 6 Astra";
76
- readonly prices: readonly [ModelPriceIface];
77
- }, {
78
- readonly id: "gpt-5.6-sol";
79
- readonly vendor: ModelVendor.OpenAI;
80
- readonly label: "GPT 5.6 Sol";
81
- readonly prices: readonly [ModelPriceIface];
82
- }, {
83
- readonly id: "gpt-5.6-terra";
84
- readonly vendor: ModelVendor.OpenAI;
85
- readonly label: "GPT 5.6 Terra";
86
- readonly prices: readonly [ModelPriceIface];
87
- }, {
88
- readonly id: "gpt-5.6-luna";
89
- readonly vendor: ModelVendor.OpenAI;
90
- readonly label: "GPT 5.6 Luna";
91
- readonly prices: readonly [ModelPriceIface];
92
- }];
93
- export declare const CODEX_CLI_MODELS: readonly [{
94
- readonly id: "gpt-6-sol";
95
- readonly vendor: ModelVendor.OpenAI;
96
- readonly label: "GPT 6 Sol";
97
- readonly prices: readonly [ModelPriceIface];
98
- }, {
99
- readonly id: "gpt-6.1-sol";
100
- readonly vendor: ModelVendor.OpenAI;
101
- readonly label: "GPT 6.1 Sol";
102
- readonly prices: readonly [ModelPriceIface];
103
- }, {
104
- readonly id: "gpt-6-luna";
105
- readonly vendor: ModelVendor.OpenAI;
106
- readonly label: "GPT 6 Luna";
107
- readonly prices: readonly [ModelPriceIface];
108
- }, {
109
- readonly id: "gpt-6-astra";
110
- readonly vendor: ModelVendor.OpenAI;
111
- readonly label: "GPT 6 Astra";
112
- readonly prices: readonly [ModelPriceIface];
113
- }, {
114
- readonly id: "gpt-5.6-sol";
115
- readonly vendor: ModelVendor.OpenAI;
116
- readonly label: "GPT 5.6 Sol";
117
- readonly prices: readonly [ModelPriceIface];
118
- }, {
119
- readonly id: "gpt-5.6-terra";
120
- readonly vendor: ModelVendor.OpenAI;
121
- readonly label: "GPT 5.6 Terra";
122
- readonly prices: readonly [ModelPriceIface];
123
- }, {
124
- readonly id: "gpt-5.6-luna";
125
- readonly vendor: ModelVendor.OpenAI;
126
- readonly label: "GPT 5.6 Luna";
127
- readonly prices: readonly [ModelPriceIface];
128
- }, {
129
- readonly id: "gpt-5.5";
130
- readonly vendor: ModelVendor.OpenAI;
131
- readonly label: "GPT 5.5";
132
- readonly prices: readonly [ModelPriceIface];
133
- }, {
134
- readonly id: "gpt-5.4";
135
- readonly vendor: ModelVendor.OpenAI;
136
- readonly label: "GPT 5.4";
137
- readonly prices: readonly [ModelPriceIface];
138
- }, {
139
- readonly id: "gpt-5.4-mini";
140
- readonly vendor: ModelVendor.OpenAI;
141
- readonly label: "GPT 5.4 Mini";
142
- readonly prices: readonly [ModelPriceIface];
143
- }, {
144
- readonly id: "gpt-5.3-codex-spark";
145
- readonly vendor: ModelVendor.OpenAI;
146
- readonly label: "GPT 5.3 Codex Spark";
147
- }];
148
- export declare const CLAUDE_MODELS: readonly [{
149
- readonly id: "claude-opus-5-5";
150
- readonly vendor: ModelVendor.Anthropic;
151
- readonly label: "Opus 5.5";
152
- readonly prices: readonly [ModelPriceIface];
153
- }, {
154
- readonly id: "claude-opus-5";
155
- readonly vendor: ModelVendor.Anthropic;
156
- readonly label: "Opus 5";
157
- readonly prices: readonly [ModelPriceIface];
158
- }, {
159
- readonly id: "claude-fable-5";
160
- readonly vendor: ModelVendor.Anthropic;
161
- readonly label: "Fable 5";
162
- readonly prices: readonly [ModelPriceIface];
163
- }, {
164
- readonly id: "claude-sonnet-5";
165
- readonly vendor: ModelVendor.Anthropic;
166
- readonly label: "Sonnet 5";
167
- readonly prices: readonly [ModelPriceIface];
168
- }, {
169
- readonly id: "claude-haiku-4-5";
170
- readonly vendor: ModelVendor.Anthropic;
171
- readonly label: "Haiku 4.5";
172
- readonly prices: readonly [ModelPriceIface];
173
- }];
174
- export declare const PI_MODELS: readonly [{
175
- readonly id: "deepseek-v4.1-flash";
176
- readonly vendor: ModelVendor.OpenRouter;
177
- readonly label: "DeepSeek V4.1 Flash";
178
- readonly vendorModelId: "deepseek/deepseek-v4.1-flash";
179
- readonly prices: readonly [{
180
- readonly effectiveFrom: "2026-10-02T00:00:00Z";
181
- readonly inputUsdPerMillion: 0.22;
182
- readonly outputUsdPerMillion: 0.66;
183
- readonly cachedInputUsdPerMillion: 0.007;
184
- readonly cacheWriteUsdPerMillion: 0;
185
- }];
186
- }, ...({
187
- readonly id: "gpt-6-sol";
188
- readonly vendor: ModelVendor.OpenAI;
189
- readonly label: "GPT 6 Sol";
190
- readonly prices: readonly [ModelPriceIface];
191
- } | {
192
- readonly id: "gpt-6.1-sol";
193
- readonly vendor: ModelVendor.OpenAI;
194
- readonly label: "GPT 6.1 Sol";
195
- readonly prices: readonly [ModelPriceIface];
196
- } | {
197
- readonly id: "gpt-6-luna";
198
- readonly vendor: ModelVendor.OpenAI;
199
- readonly label: "GPT 6 Luna";
200
- readonly prices: readonly [ModelPriceIface];
201
- } | {
202
- readonly id: "gpt-6-astra";
203
- readonly vendor: ModelVendor.OpenAI;
204
- readonly label: "GPT 6 Astra";
205
- readonly prices: readonly [ModelPriceIface];
206
- } | {
207
- readonly id: "gpt-5.6-sol";
208
- readonly vendor: ModelVendor.OpenAI;
209
- readonly label: "GPT 5.6 Sol";
210
- readonly prices: readonly [ModelPriceIface];
211
- } | {
212
- readonly id: "gpt-5.6-terra";
213
- readonly vendor: ModelVendor.OpenAI;
214
- readonly label: "GPT 5.6 Terra";
215
- readonly prices: readonly [ModelPriceIface];
216
- } | {
217
- readonly id: "gpt-5.6-luna";
218
- readonly vendor: ModelVendor.OpenAI;
219
- readonly label: "GPT 5.6 Luna";
220
- readonly prices: readonly [ModelPriceIface];
221
- } | {
222
- readonly id: "gpt-5.5";
223
- readonly vendor: ModelVendor.OpenAI;
224
- readonly label: "GPT 5.5";
225
- readonly prices: readonly [ModelPriceIface];
226
- } | {
227
- readonly id: "gpt-5.4";
228
- readonly vendor: ModelVendor.OpenAI;
229
- readonly label: "GPT 5.4";
230
- readonly prices: readonly [ModelPriceIface];
231
- } | {
232
- readonly id: "gpt-5.4-mini";
233
- readonly vendor: ModelVendor.OpenAI;
234
- readonly label: "GPT 5.4 Mini";
235
- readonly prices: readonly [ModelPriceIface];
236
- })[], {
237
- readonly id: "claude-opus-5-5";
238
- readonly vendor: ModelVendor.Anthropic;
239
- readonly label: "Opus 5.5";
240
- readonly prices: readonly [ModelPriceIface];
241
- }, {
242
- readonly id: "claude-opus-5";
243
- readonly vendor: ModelVendor.Anthropic;
244
- readonly label: "Opus 5";
245
- readonly prices: readonly [ModelPriceIface];
246
- }, {
247
- readonly id: "claude-fable-5";
248
- readonly vendor: ModelVendor.Anthropic;
249
- readonly label: "Fable 5";
250
- readonly prices: readonly [ModelPriceIface];
251
- }, {
252
- readonly id: "claude-sonnet-5";
253
- readonly vendor: ModelVendor.Anthropic;
254
- readonly label: "Sonnet 5";
255
- readonly prices: readonly [ModelPriceIface];
256
- }, {
257
- readonly id: "claude-haiku-4-5";
258
- readonly vendor: ModelVendor.Anthropic;
259
- readonly label: "Haiku 4.5";
260
- readonly prices: readonly [ModelPriceIface];
261
- }];
262
- export type FinalHarnessModelId = (typeof FINAL_HARNESS_MODELS)[number]['id'];
263
- export type CodexResponsesLiteModelId = (typeof CODEX_RESPONSES_LITE_MODELS)[number]['id'];
264
- export type CodexCliModelId = (typeof CODEX_CLI_MODELS)[number]['id'];
265
- export type ClaudeModelId = (typeof CLAUDE_MODELS)[number]['id'];
266
- export type PiModelId = (typeof PI_MODELS)[number]['id'];
267
- export declare const DEFAULT_FINAL_HARNESS_MODEL: FinalHarnessModelId;
268
- export declare const DEFAULT_PI_MODEL: PiModelId;
269
- export declare const DEFAULT_CODEX_MODEL: CodexResponsesLiteModelId;
270
- export declare const DEFAULT_CLAUDE_MODEL: ClaudeModelId;
271
- export declare const modelIds: (models: readonly HarnessModelIface[]) => string[];
272
- export declare const modelVendor: (models: readonly HarnessModelIface[], id: string) => ModelVendor | null;
273
- export declare const vendorModelRef: (models: readonly HarnessModelIface[], id: string) => string;
274
- export declare const vendorsOf: (models: readonly HarnessModelIface[]) => ModelVendor[];
275
- export declare const CATALOG_MODELS: readonly HarnessModelIface[];
276
- export declare const modelPriceAt: (args: {
277
- vendor: string;
278
- model: string;
279
- at: Date;
280
- models?: readonly HarnessModelIface[];
281
- }) => ModelPriceIface | null;