@finalai/final-agent-provider 0.7.0 → 0.8.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.
package/README.md CHANGED
@@ -31,6 +31,25 @@ The `modelZod(ids)` and `modelJson(ids, defaultId)` helpers retain explicit rest
31
31
 
32
32
  SDK 0.2.0 removes `@finalai/agents/models` and `@finalai/final-agent-provider/harnesses/models`, including their model arrays, defaults, model-ID unions and pricing helpers. Use string model references and the installed platform’s harness description for current candidates and defaults. Pricing belongs to the hosting platform. The protocol-level `ModelVendor` enum remains available from `@finalai/final-agent-provider/harnesses`.
33
33
 
34
+ ## Durable processes
35
+
36
+ The `computer` and `device` sandboxes offer durable processes
37
+ (`SandboxCapability.DurableProcesses`: `spawn({ durable: true })` and `attachProcess`) on
38
+ write and execute bindings. A ref names the sandbox, the process and its boot (and, on a
39
+ Device, the lease generation), so a ref from another sandbox, boot or generation attaches
40
+ to nothing. A dropped handle stops polling and never terminates the process; `timeoutMs`
41
+ is enforced by the computer or Device itself.
42
+
43
+ - Computers: managed processes run in the computer and are found by id and boot until it
44
+ boots again (a pause and resume keeps them; a stop, or a wake that boots it, does not)
45
+ or is deleted. The guest keeps only the first 8 MiB of each stream; later output is
46
+ not retained.
47
+ - Devices: lease processes end with the lease generation (released, expired or
48
+ superseded); attaching afterwards returns null. The Device keeps the most recent 1 MiB
49
+ of each stream, so an attached stream may start later than asked (`stdoutOffset` and
50
+ `stderrOffset` say where). A process whose output was read to the end after it exited
51
+ may be retired, and then attaches to nothing.
52
+
34
53
  ## Workspace Device egress
35
54
 
36
55
  `/sandboxes/egress` supplies provider-neutral Linux TCP/UDP/DNS routing through approved Final Devices. Hosts compose `createWorkspaceDeviceNetworking({ api, needed })` through the generic provider `networking` option. They supply stable logical workspace identity, durable networking registration, the current actor, and the raw privileged sandbox session. Preserve the direct policy before boot fencing; restore it on Disable. Configure and Disable ask for consent by default.
@@ -4,6 +4,7 @@ export declare const decodeBase64: (value: string) => Uint8Array;
4
4
  export declare const concatBytes: (chunks: readonly Uint8Array[]) => Uint8Array;
5
5
  export declare const collectStream: (stream: ReadableStream<Uint8Array>) => Promise<Uint8Array>;
6
6
  export declare const rechunk: (stream: ReadableStream<Uint8Array>, size: number) => AsyncGenerator<Uint8Array>;
7
+ export declare const splitChunks: (stream: ReadableStream<Uint8Array>, size: number) => AsyncGenerator<Uint8Array>;
7
8
  export declare const errorMessage: (cause: unknown) => string;
8
9
  export declare const isNotFoundMessage: (message: string) => boolean;
9
10
  export declare const sleep: (ms: number, signal?: AbortSignal) => Promise<void>;
@@ -50,6 +50,11 @@ const rechunk = async function* (stream, size) {
50
50
  }
51
51
  if (pendingBytes > 0) yield concatBytes(pending);
52
52
  };
53
+ const splitChunks = async function* (stream, size) {
54
+ for await (const chunk of stream)
55
+ for (let offset = 0; offset < chunk.byteLength; offset += size)
56
+ yield chunk.subarray(offset, offset + size);
57
+ };
53
58
  const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
54
59
  const isNotFoundMessage = (message) => /no such file|not found|does not exist|os error 2\b|ENOENT/i.test(message);
55
60
  const sleep = (ms, signal) => new Promise((resolve, reject) => {
@@ -91,6 +96,7 @@ export {
91
96
  isNotFoundMessage,
92
97
  rechunk,
93
98
  sha256Hex,
94
- sleep
99
+ sleep,
100
+ splitChunks
95
101
  };
96
102
  //# sourceMappingURL=bytes.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/bytes.ts"],
4
- "sourcesContent": ["import type { JsonValue } from '@finalai/agent-provider';\n\n// Byte and stream helpers shared by the transports and the session handle.\n\nexport const encodeBase64 = (bytes: Uint8Array): string => {\n let binary = '';\n for (let index = 0; index < bytes.length; index += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(index, index + 0x8000));\n }\n return btoa(binary);\n};\n\nexport const decodeBase64 = (value: string): Uint8Array => {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);\n return bytes;\n};\n\nexport const concatBytes = (chunks: readonly Uint8Array[]): Uint8Array => {\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const joined = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n joined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return joined;\n};\n\nexport const collectStream = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n for (;;) {\n const next = await reader.read();\n if (next.done) break;\n chunks.push(next.value);\n }\n return concatBytes(chunks);\n};\n\n// Re-chunks a byte stream into pieces of exactly `size` bytes (the last may be shorter).\nexport const rechunk = async function* (\n stream: ReadableStream<Uint8Array>,\n size: number,\n): AsyncGenerator<Uint8Array> {\n const reader = stream.getReader();\n let pending: Uint8Array[] = [];\n let pendingBytes = 0;\n for (;;) {\n const next = await reader.read();\n if (next.done) break;\n pending.push(next.value);\n pendingBytes += next.value.byteLength;\n while (pendingBytes >= size) {\n const joined = concatBytes(pending);\n yield joined.subarray(0, size);\n const rest = joined.subarray(size);\n pending = rest.byteLength > 0 ? [rest] : [];\n pendingBytes = rest.byteLength;\n }\n }\n if (pendingBytes > 0) yield concatBytes(pending);\n};\n\nexport const errorMessage = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\nexport const isNotFoundMessage = (message: string): boolean =>\n /no such file|not found|does not exist|os error 2\\b|ENOENT/i.test(message);\n\nexport const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n if (signal?.aborted === true) {\n reject(signal.reason);\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n\nexport const sha256Hex = async (text: string): Promise<string> => {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n};\n\n// Sorted-key JSON, so equal inputs hash equally regardless of key order.\nexport const canonicalJson = (value: JsonValue): string => {\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;\n if (value instanceof Object) {\n const entries = Object.entries(value).sort(([left], [right]) =>\n left < right ? -1 : left > right ? 1 : 0,\n );\n return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`).join(',')}}`;\n }\n return JSON.stringify(value);\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { JsonValue } from '@finalai/agent-provider';\n\n// Byte and stream helpers shared by the transports and the session handle.\n\nexport const encodeBase64 = (bytes: Uint8Array): string => {\n let binary = '';\n for (let index = 0; index < bytes.length; index += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(index, index + 0x8000));\n }\n return btoa(binary);\n};\n\nexport const decodeBase64 = (value: string): Uint8Array => {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);\n return bytes;\n};\n\nexport const concatBytes = (chunks: readonly Uint8Array[]): Uint8Array => {\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const joined = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n joined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return joined;\n};\n\nexport const collectStream = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n for (;;) {\n const next = await reader.read();\n if (next.done) break;\n chunks.push(next.value);\n }\n return concatBytes(chunks);\n};\n\n// Re-chunks a byte stream into pieces of exactly `size` bytes (the last may be shorter).\nexport const rechunk = async function* (\n stream: ReadableStream<Uint8Array>,\n size: number,\n): AsyncGenerator<Uint8Array> {\n const reader = stream.getReader();\n let pending: Uint8Array[] = [];\n let pendingBytes = 0;\n for (;;) {\n const next = await reader.read();\n if (next.done) break;\n pending.push(next.value);\n pendingBytes += next.value.byteLength;\n while (pendingBytes >= size) {\n const joined = concatBytes(pending);\n yield joined.subarray(0, size);\n const rest = joined.subarray(size);\n pending = rest.byteLength > 0 ? [rest] : [];\n pendingBytes = rest.byteLength;\n }\n }\n if (pendingBytes > 0) yield concatBytes(pending);\n};\n\n// Passes each chunk on as soon as it arrives, split into pieces of at most\n// `size` bytes; never waits to fill a piece (interactive input).\nexport const splitChunks = async function* (\n stream: ReadableStream<Uint8Array>,\n size: number,\n): AsyncGenerator<Uint8Array> {\n for await (const chunk of stream)\n for (let offset = 0; offset < chunk.byteLength; offset += size)\n yield chunk.subarray(offset, offset + size);\n};\n\nexport const errorMessage = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\nexport const isNotFoundMessage = (message: string): boolean =>\n /no such file|not found|does not exist|os error 2\\b|ENOENT/i.test(message);\n\nexport const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n if (signal?.aborted === true) {\n reject(signal.reason);\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n\nexport const sha256Hex = async (text: string): Promise<string> => {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n};\n\n// Sorted-key JSON, so equal inputs hash equally regardless of key order.\nexport const canonicalJson = (value: JsonValue): string => {\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;\n if (value instanceof Object) {\n const entries = Object.entries(value).sort(([left], [right]) =>\n left < right ? -1 : left > right ? 1 : 0,\n );\n return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`).join(',')}}`;\n }\n return JSON.stringify(value);\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,7 +6,7 @@ import {
6
6
  processInspectionPageSchema,
7
7
  processInspectionRequestSchema
8
8
  } from "@finalai/agent-protocol/process-inspection";
9
- import { err, ok } from "@finalai/computers";
9
+ import { ComputerState, err, ok } from "@finalai/computers";
10
10
  import * as z from "zod";
11
11
  const outputStreamSchema = z.object({ dataB64: z.string(), offset: z.number(), eof: z.boolean() });
12
12
  const outputSchema = z.object({ stdout: outputStreamSchema, stderr: outputStreamSchema });
@@ -18,8 +18,10 @@ const inspectComputerProcesses = async (args) => {
18
18
  if (request.operation === ProcessInspectionOperation.Available) {
19
19
  const response2 = await args.transport.request({ method: "GET", path: args.computerPath });
20
20
  if (!response2.ok) return response2;
21
- const parsed = z.object({ computer: z.object({ state: z.string() }) }).safeParse(response2.data);
22
- return parsed.success ? ok({ available: parsed.data.computer.state === "running" }) : err("unexpected computer response shape");
21
+ const parsed = z.object({ computer: z.object({ state: z.union([z.number().int(), z.string()]) }) }).safeParse(response2.data);
22
+ return parsed.success ? ok({
23
+ available: parsed.data.computer.state === ComputerState.Running || parsed.data.computer.state === "running"
24
+ }) : err("unexpected computer response shape");
23
25
  }
24
26
  const path = args.computerPath + "/processes";
25
27
  const pagination = {};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/computer-processes.ts"],
4
- "sourcesContent": ["import {\n inspectedProcessMemberSchema,\n inspectedProcessSchema,\n processInspectionDetailSchema,\n ProcessInspectionOperation,\n processInspectionPageSchema,\n processInspectionRequestSchema,\n type ProcessInspectionRequestIface,\n type ProcessInspectionResultIface,\n} from '@finalai/agent-protocol/process-inspection';\nimport type { TransportIface } from '@finalai/computers';\nimport { err, ok, type ResultIface } from '@finalai/computers';\nimport * as z from 'zod';\n\nconst outputStreamSchema = z.object({ dataB64: z.string(), offset: z.number(), eof: z.boolean() });\nconst outputSchema = z.object({ stdout: outputStreamSchema, stderr: outputStreamSchema });\nconst decode = (value: string) =>\n new TextDecoder().decode(Uint8Array.from(atob(value), (byte) => byte.charCodeAt(0)));\n\nexport const inspectComputerProcesses = async (args: {\n transport: Pick<TransportIface, 'request'>;\n computerPath: string;\n request: ProcessInspectionRequestIface;\n}): Promise<ResultIface<ProcessInspectionResultIface>> => {\n const input = processInspectionRequestSchema.safeParse(args.request);\n if (!input.success) return err(input.error.message);\n const request = input.data;\n if (request.operation === ProcessInspectionOperation.Available) {\n const response = await args.transport.request({ method: 'GET', path: args.computerPath });\n if (!response.ok) return response;\n const parsed = z.object({ computer: z.object({ state: z.string() }) }).safeParse(response.data);\n return parsed.success\n ? ok({ available: parsed.data.computer.state === 'running' })\n : err('unexpected computer response shape');\n }\n const path = args.computerPath + '/processes';\n const pagination: NonNullable<Parameters<TransportIface['request']>[0]['query']> = {};\n if ('limit' in request && request.limit != null) pagination.limit = String(request.limit);\n if ('cursor' in request && request.cursor != null) pagination.cursor = request.cursor;\n if (request.operation === ProcessInspectionOperation.List) {\n const response = await args.transport.request({\n method: 'GET',\n path,\n query: { ...pagination, includeSystem: 'false' },\n });\n if (!response.ok) return response;\n const parsed = processInspectionPageSchema.safeParse(response.data);\n return parsed.success ? ok(parsed.data) : err('unexpected process inventory response shape');\n }\n const processPath = path + '/' + encodeURIComponent(request.processId);\n if (request.operation === ProcessInspectionOperation.Stop) {\n const response = await args.transport.request({\n method: 'POST',\n path: processPath + '/terminate',\n jsonBody: { bootId: request.bootId },\n });\n return response.ok ? ok({ stopped: true }) : response;\n }\n const detail = await args.transport.request({\n method: 'GET',\n path: processPath,\n query: { bootId: request.bootId, ...pagination },\n });\n if (!detail.ok) return detail;\n const process = z\n .object({\n process: inspectedProcessSchema,\n descendants: z.array(inspectedProcessMemberSchema),\n nextCursor: z.string().nullable(),\n })\n .safeParse(detail.data);\n if (!process.success) return err('unexpected process detail response shape');\n const response = await args.transport.request({\n method: 'GET',\n path: processPath + '/output',\n query: { bootId: request.bootId, stdoutOffset: '0', stderrOffset: '0', waitMs: '0' },\n });\n if (!response.ok) return response;\n const output = outputSchema.safeParse(response.data);\n if (!output.success) return err('unexpected process output response shape');\n try {\n return ok(\n processInspectionDetailSchema.parse({\n ...process.data,\n logs: {\n stdout: decode(output.data.stdout.dataB64),\n stderr: decode(output.data.stderr.dataB64),\n stdoutTruncated: output.data.stdout.offset > 0 || !output.data.stdout.eof,\n stderrTruncated: output.data.stderr.offset > 0 || !output.data.stderr.eof,\n },\n }),\n );\n } catch {\n return err('invalid process output encoding');\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n inspectedProcessMemberSchema,\n inspectedProcessSchema,\n processInspectionDetailSchema,\n ProcessInspectionOperation,\n processInspectionPageSchema,\n processInspectionRequestSchema,\n type ProcessInspectionRequestIface,\n type ProcessInspectionResultIface,\n} from '@finalai/agent-protocol/process-inspection';\nimport type { TransportIface } from '@finalai/computers';\nimport { ComputerState, err, ok, type ResultIface } from '@finalai/computers';\nimport * as z from 'zod';\n\nconst outputStreamSchema = z.object({ dataB64: z.string(), offset: z.number(), eof: z.boolean() });\nconst outputSchema = z.object({ stdout: outputStreamSchema, stderr: outputStreamSchema });\nconst decode = (value: string) =>\n new TextDecoder().decode(Uint8Array.from(atob(value), (byte) => byte.charCodeAt(0)));\n\nexport const inspectComputerProcesses = async (args: {\n transport: Pick<TransportIface, 'request'>;\n computerPath: string;\n request: ProcessInspectionRequestIface;\n}): Promise<ResultIface<ProcessInspectionResultIface>> => {\n const input = processInspectionRequestSchema.safeParse(args.request);\n if (!input.success) return err(input.error.message);\n const request = input.data;\n if (request.operation === ProcessInspectionOperation.Available) {\n const response = await args.transport.request({ method: 'GET', path: args.computerPath });\n if (!response.ok) return response;\n // Keep the previously accepted string form alongside the SDK's numeric state.\n const parsed = z\n .object({ computer: z.object({ state: z.union([z.number().int(), z.string()]) }) })\n .safeParse(response.data);\n return parsed.success\n ? ok({\n available:\n parsed.data.computer.state === ComputerState.Running ||\n parsed.data.computer.state === 'running',\n })\n : err('unexpected computer response shape');\n }\n const path = args.computerPath + '/processes';\n const pagination: NonNullable<Parameters<TransportIface['request']>[0]['query']> = {};\n if ('limit' in request && request.limit != null) pagination.limit = String(request.limit);\n if ('cursor' in request && request.cursor != null) pagination.cursor = request.cursor;\n if (request.operation === ProcessInspectionOperation.List) {\n const response = await args.transport.request({\n method: 'GET',\n path,\n query: { ...pagination, includeSystem: 'false' },\n });\n if (!response.ok) return response;\n const parsed = processInspectionPageSchema.safeParse(response.data);\n return parsed.success ? ok(parsed.data) : err('unexpected process inventory response shape');\n }\n const processPath = path + '/' + encodeURIComponent(request.processId);\n if (request.operation === ProcessInspectionOperation.Stop) {\n const response = await args.transport.request({\n method: 'POST',\n path: processPath + '/terminate',\n jsonBody: { bootId: request.bootId },\n });\n return response.ok ? ok({ stopped: true }) : response;\n }\n const detail = await args.transport.request({\n method: 'GET',\n path: processPath,\n query: { bootId: request.bootId, ...pagination },\n });\n if (!detail.ok) return detail;\n const process = z\n .object({\n process: inspectedProcessSchema,\n descendants: z.array(inspectedProcessMemberSchema),\n nextCursor: z.string().nullable(),\n })\n .safeParse(detail.data);\n if (!process.success) return err('unexpected process detail response shape');\n const response = await args.transport.request({\n method: 'GET',\n path: processPath + '/output',\n query: { bootId: request.bootId, stdoutOffset: '0', stderrOffset: '0', waitMs: '0' },\n });\n if (!response.ok) return response;\n const output = outputSchema.safeParse(response.data);\n if (!output.success) return err('unexpected process output response shape');\n try {\n return ok(\n processInspectionDetailSchema.parse({\n ...process.data,\n logs: {\n stdout: decode(output.data.stdout.dataB64),\n stderr: decode(output.data.stderr.dataB64),\n stdoutTruncated: output.data.stdout.offset > 0 || !output.data.stdout.eof,\n stderrTruncated: output.data.stderr.offset > 0 || !output.data.stderr.eof,\n },\n }),\n );\n } catch {\n return err('invalid process output encoding');\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["response"]
7
7
  }
@@ -425,7 +425,11 @@ ${commandHelp}`}`,
425
425
  if (screenAvailable) capabilities.push(SandboxCapability.Screen);
426
426
  if (computerUse != null) capabilities.push(SandboxCapability.ComputerUse);
427
427
  if (args.access !== SandboxAccess.Read)
428
- capabilities.push(SandboxCapability.Process, SandboxCapability.NetworkPolicy);
428
+ capabilities.push(
429
+ SandboxCapability.Process,
430
+ SandboxCapability.DurableProcesses,
431
+ SandboxCapability.NetworkPolicy
432
+ );
429
433
  if (args.access === SandboxAccess.Write && args.networking != null)
430
434
  capabilities.push(...config.networking?.capabilities ?? []);
431
435
  const description = {