@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
@@ -27,12 +27,7 @@ import {
27
27
  skillsJson,
28
28
  skillsZod
29
29
  } from "./config-fields.mjs";
30
- import {
31
- CLAUDE_MODELS,
32
- DEFAULT_CLAUDE_MODEL,
33
- modelIds,
34
- vendorsOf
35
- } from "./models.mjs";
30
+ import { ModelVendor } from "./model-reference.mjs";
36
31
  const SPECIFIER = "@finalai/final-agent-provider/harnesses/serverless-nanocode-claude";
37
32
  const CLAUDE_REASONING_LEVELS = [
38
33
  ReasoningLevel.Low,
@@ -48,7 +43,7 @@ const NANOCODE_CLAUDE_BASE_TOOLS = {
48
43
  [BaseCapability.Files]: { provision: BaseToolProvision.Bound, nativeTools: ["Read", "Write"] }
49
44
  };
50
45
  const serverlessNanocodeClaudeConfigSchema = z.strictObject({
51
- model: modelZod(modelIds(CLAUDE_MODELS)).default(DEFAULT_CLAUDE_MODEL),
46
+ model: modelZod().optional(),
52
47
  reasoning: reasoningZod(CLAUDE_REASONING_LEVELS).optional(),
53
48
  credentials: credentialsZod(),
54
49
  permissionMode: z.nativeEnum(ClaudePermissionMode).default(ClaudePermissionMode.Default),
@@ -59,7 +54,7 @@ const SERVERLESS_NANOCODE_CLAUDE_CONFIG_JSON_SCHEMA = configObjectJson({
59
54
  required: ["credentials"],
60
55
  title: "Claude on nanocode (serverless)",
61
56
  properties: {
62
- model: modelJson(modelIds(CLAUDE_MODELS), DEFAULT_CLAUDE_MODEL),
57
+ model: modelJson(),
63
58
  reasoning: reasoningJson(CLAUDE_REASONING_LEVELS),
64
59
  credentials: credentialsJson(),
65
60
  permissionMode: permissionModeJson(
@@ -80,7 +75,7 @@ const SERVERLESS_NANOCODE_CLAUDE_DESCRIPTION = {
80
75
  consumes: [SandboxWire.HandleRpc],
81
76
  // Subscriptions are the Claude setup token, used as a bearer.
82
77
  inference: {
83
- vendors: vendorsOf(CLAUDE_MODELS),
78
+ vendors: [ModelVendor.Anthropic],
84
79
  kinds: [
85
80
  InferenceCredentialKind.Subscription,
86
81
  InferenceCredentialKind.ApiKey,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/harnesses/serverless-nanocode-claude.ts"],
4
- "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n ClaudePermissionMode,\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport {\n CLAUDE_MODELS,\n DEFAULT_CLAUDE_MODEL,\n modelIds,\n vendorsOf,\n type ClaudeModelId,\n} from \"./models.mjs\";\n\n// nanocode's Claude engine in the nanocode Durable Object script.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-nanocode-claude';\n\nexport const CLAUDE_REASONING_LEVELS = [\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n ReasoningLevel.Max,\n] as const;\n\nexport const NANOCODE_CLAUDE_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['Bash', 'BashOutput'],\n },\n [BaseCapability.Files]: { provision: BaseToolProvision.Bound, nativeTools: ['Read', 'Write'] },\n};\n\nexport const serverlessNanocodeClaudeConfigSchema = z.strictObject({\n model: modelZod(modelIds(CLAUDE_MODELS)).default(DEFAULT_CLAUDE_MODEL),\n reasoning: reasoningZod(CLAUDE_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n permissionMode: z.nativeEnum(ClaudePermissionMode).default(ClaudePermissionMode.Default),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessNanocodeClaudeConfigIface = z.output<\n typeof serverlessNanocodeClaudeConfigSchema\n>;\n\nexport const SERVERLESS_NANOCODE_CLAUDE_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Claude on nanocode (serverless)',\n properties: {\n model: modelJson(modelIds(CLAUDE_MODELS), DEFAULT_CLAUDE_MODEL),\n reasoning: reasoningJson(CLAUDE_REASONING_LEVELS),\n credentials: credentialsJson(),\n permissionMode: permissionModeJson(\n Object.values(ClaudePermissionMode),\n ClaudePermissionMode.Default,\n ),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_NANOCODE_CLAUDE_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_NANOCODE_CLAUDE_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: NANOCODE_CLAUDE_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n // Subscriptions are the Claude setup token, used as a bearer.\n inference: {\n vendors: vendorsOf(CLAUDE_MODELS),\n kinds: [\n InferenceCredentialKind.Subscription,\n InferenceCredentialKind.ApiKey,\n InferenceCredentialKind.Platform,\n ],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers nanocode/claude.test.ts \"queues a prompt that arrives\n // while a turn runs\"): running, idle, running, idle. Open approvals are asked again\n // with new ids after a lost invocation, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Queue,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessNanocodeClaudeConfigInputIface {\n model?: ClaudeModelId;\n reasoning?:\n | (typeof CLAUDE_REASONING_LEVELS)[number]\n | `${(typeof CLAUDE_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n permissionMode?: ClaudePermissionMode | `${ClaudePermissionMode}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessNanocodeClaude = (\n config: ServerlessNanocodeClaudeConfigInputIface,\n): HarnessBindingOutputIface => harnessBinding(SPECIFIER, config);\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAIA,MAAM,YAAY;AAElB,MAAM,0BAA0B;AAAA,EACrC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAEO,MAAM,6BAAmE;AAAA,EAC9E,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,QAAQ,YAAY;AAAA,EACpC;AAAA,EACA,CAAC,eAAe,KAAK,GAAG,EAAE,WAAW,kBAAkB,OAAO,aAAa,CAAC,QAAQ,OAAO,EAAE;AAC/F;AAEO,MAAM,uCAAuC,EAAE,aAAa;AAAA,EACjE,OAAO,SAAS,SAAS,aAAa,CAAC,EAAE,QAAQ,oBAAoB;AAAA,EACrE,WAAW,aAAa,uBAAuB,EAAE,SAAS;AAAA,EAC1D,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,oBAAoB,EAAE,QAAQ,qBAAqB,OAAO;AAAA,EACvF,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAMM,MAAM,gDAA4D,iBAAiB;AAAA,EACxF,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU,SAAS,aAAa,GAAG,oBAAoB;AAAA,IAC9D,WAAW,cAAc,uBAAuB;AAAA,IAChD,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB;AAAA,MACd,OAAO,OAAO,oBAAoB;AAAA,MAClC,qBAAqB;AAAA,IACvB;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,yCAAkE;AAAA,EAC7E,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA;AAAA,EAEhC,WAAW;AAAA,IACT,SAAS,UAAU,aAAa;AAAA,IAChC,OAAO;AAAA,MACL,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAaO,MAAM,2BAA2B,CACtC,WAC8B,eAAe,WAAW,MAAM;",
4
+ "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n ClaudePermissionMode,\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport { ModelVendor } from \"./model-reference.mjs\";\n\n// nanocode's Claude engine in the nanocode Durable Object script.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-nanocode-claude';\n\nexport const CLAUDE_REASONING_LEVELS = [\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n ReasoningLevel.Max,\n] as const;\n\nexport const NANOCODE_CLAUDE_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['Bash', 'BashOutput'],\n },\n [BaseCapability.Files]: { provision: BaseToolProvision.Bound, nativeTools: ['Read', 'Write'] },\n};\n\nexport const serverlessNanocodeClaudeConfigSchema = z.strictObject({\n model: modelZod().optional(),\n reasoning: reasoningZod(CLAUDE_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n permissionMode: z.nativeEnum(ClaudePermissionMode).default(ClaudePermissionMode.Default),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessNanocodeClaudeConfigIface = z.output<\n typeof serverlessNanocodeClaudeConfigSchema\n>;\n\nexport const SERVERLESS_NANOCODE_CLAUDE_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Claude on nanocode (serverless)',\n properties: {\n model: modelJson(),\n reasoning: reasoningJson(CLAUDE_REASONING_LEVELS),\n credentials: credentialsJson(),\n permissionMode: permissionModeJson(\n Object.values(ClaudePermissionMode),\n ClaudePermissionMode.Default,\n ),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_NANOCODE_CLAUDE_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_NANOCODE_CLAUDE_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: NANOCODE_CLAUDE_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n // Subscriptions are the Claude setup token, used as a bearer.\n inference: {\n vendors: [ModelVendor.Anthropic],\n kinds: [\n InferenceCredentialKind.Subscription,\n InferenceCredentialKind.ApiKey,\n InferenceCredentialKind.Platform,\n ],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers nanocode/claude.test.ts \"queues a prompt that arrives\n // while a turn runs\"): running, idle, running, idle. Open approvals are asked again\n // with new ids after a lost invocation, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Queue,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessNanocodeClaudeConfigInputIface {\n model?: string;\n reasoning?:\n | (typeof CLAUDE_REASONING_LEVELS)[number]\n | `${(typeof CLAUDE_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n permissionMode?: ClaudePermissionMode | `${ClaudePermissionMode}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessNanocodeClaude = (\n config: ServerlessNanocodeClaudeConfigInputIface,\n): HarnessBindingOutputIface => harnessBinding(SPECIFIER, config);\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,mBAAmB;AAIrB,MAAM,YAAY;AAElB,MAAM,0BAA0B;AAAA,EACrC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAEO,MAAM,6BAAmE;AAAA,EAC9E,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,QAAQ,YAAY;AAAA,EACpC;AAAA,EACA,CAAC,eAAe,KAAK,GAAG,EAAE,WAAW,kBAAkB,OAAO,aAAa,CAAC,QAAQ,OAAO,EAAE;AAC/F;AAEO,MAAM,uCAAuC,EAAE,aAAa;AAAA,EACjE,OAAO,SAAS,EAAE,SAAS;AAAA,EAC3B,WAAW,aAAa,uBAAuB,EAAE,SAAS;AAAA,EAC1D,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,oBAAoB,EAAE,QAAQ,qBAAqB,OAAO;AAAA,EACvF,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAMM,MAAM,gDAA4D,iBAAiB;AAAA,EACxF,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU;AAAA,IACjB,WAAW,cAAc,uBAAuB;AAAA,IAChD,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB;AAAA,MACd,OAAO,OAAO,oBAAoB;AAAA,MAClC,qBAAqB;AAAA,IACvB;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,yCAAkE;AAAA,EAC7E,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA;AAAA,EAEhC,WAAW;AAAA,IACT,SAAS,CAAC,YAAY,SAAS;AAAA,IAC/B,OAAO;AAAA,MACL,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAaO,MAAM,2BAA2B,CACtC,WAC8B,eAAe,WAAW,MAAM;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,11 @@
1
1
  import { type HarnessDescriptionIface, type JsonSchema } from '@finalai/agent-provider';
2
2
  import * as z from 'zod';
3
3
  import { CodexApprovalPolicy, ReasoningLevel, type CredentialsInput, type HarnessBindingOutputIface, type InstructionInput, type SkillInput } from "./config-fields.mjs";
4
- import { type CodexResponsesLiteModelId } from "./models.mjs";
5
4
  export declare const SPECIFIER = "@finalai/final-agent-provider/harnesses/serverless-nanocode-codex";
6
5
  export declare const CODEX_REASONING_LEVELS: readonly [ReasoningLevel.Low, ReasoningLevel.Medium, ReasoningLevel.High, ReasoningLevel.Max];
7
6
  export declare const CODEX_BASE_TOOLS: HarnessDescriptionIface['baseTools'];
8
7
  export declare const serverlessNanocodeCodexConfigSchema: z.ZodObject<{
9
- model: z.ZodDefault<z.ZodString>;
8
+ model: z.ZodOptional<z.ZodString>;
10
9
  reasoning: z.ZodOptional<z.ZodEnum<typeof ReasoningLevel>>;
11
10
  credentials: z.ZodObject<{
12
11
  payer: z.ZodEnum<typeof import("@finalai/agent-provider").CredentialPayer>;
@@ -55,7 +54,7 @@ export type ServerlessNanocodeCodexConfigIface = z.output<typeof serverlessNanoc
55
54
  export declare const SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA: JsonSchema;
56
55
  export declare const SERVERLESS_NANOCODE_CODEX_DESCRIPTION: HarnessDescriptionIface;
57
56
  export interface ServerlessNanocodeCodexConfigInputIface {
58
- model?: CodexResponsesLiteModelId;
57
+ model?: string;
59
58
  reasoning?: (typeof CODEX_REASONING_LEVELS)[number] | `${(typeof CODEX_REASONING_LEVELS)[number]}`;
60
59
  credentials: CredentialsInput;
61
60
  approvalPolicy?: CodexApprovalPolicy | `${CodexApprovalPolicy}`;
@@ -27,12 +27,7 @@ import {
27
27
  skillsJson,
28
28
  skillsZod
29
29
  } from "./config-fields.mjs";
30
- import {
31
- CODEX_RESPONSES_LITE_MODELS,
32
- DEFAULT_CODEX_MODEL,
33
- modelIds,
34
- vendorsOf
35
- } from "./models.mjs";
30
+ import { ModelVendor } from "./model-reference.mjs";
36
31
  const SPECIFIER = "@finalai/final-agent-provider/harnesses/serverless-nanocode-codex";
37
32
  const CODEX_REASONING_LEVELS = [
38
33
  ReasoningLevel.Low,
@@ -51,7 +46,7 @@ const CODEX_BASE_TOOLS = {
51
46
  }
52
47
  };
53
48
  const serverlessNanocodeCodexConfigSchema = z.strictObject({
54
- model: modelZod(modelIds(CODEX_RESPONSES_LITE_MODELS)).default(DEFAULT_CODEX_MODEL),
49
+ model: modelZod().optional(),
55
50
  reasoning: reasoningZod(CODEX_REASONING_LEVELS).optional(),
56
51
  credentials: credentialsZod(),
57
52
  approvalPolicy: z.nativeEnum(CodexApprovalPolicy).default(CodexApprovalPolicy.OnRequest),
@@ -62,7 +57,7 @@ const SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA = configObjectJson({
62
57
  required: ["credentials"],
63
58
  title: "Codex on nanocode (serverless)",
64
59
  properties: {
65
- model: modelJson(modelIds(CODEX_RESPONSES_LITE_MODELS), DEFAULT_CODEX_MODEL),
60
+ model: modelJson(),
66
61
  reasoning: reasoningJson(CODEX_REASONING_LEVELS),
67
62
  credentials: credentialsJson(),
68
63
  approvalPolicy: permissionModeJson(
@@ -82,7 +77,7 @@ const SERVERLESS_NANOCODE_CODEX_DESCRIPTION = {
82
77
  baseTools: CODEX_BASE_TOOLS,
83
78
  consumes: [SandboxWire.HandleRpc],
84
79
  inference: {
85
- vendors: vendorsOf(CODEX_RESPONSES_LITE_MODELS),
80
+ vendors: [ModelVendor.OpenAI],
86
81
  kinds: [
87
82
  InferenceCredentialKind.Subscription,
88
83
  InferenceCredentialKind.ApiKey,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/harnesses/serverless-nanocode-codex.ts"],
4
- "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n CodexApprovalPolicy,\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport {\n CODEX_RESPONSES_LITE_MODELS,\n DEFAULT_CODEX_MODEL,\n modelIds,\n vendorsOf,\n type CodexResponsesLiteModelId,\n} from \"./models.mjs\";\n\n// nanocode's Codex engine (Rust \u2192 wasm) in the nanocode Durable Object script.\n// Responses Lite models only; ChatGPT subscriptions go through the session\n// service relay because chatgpt.com blocks Workers egress.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-nanocode-codex';\n\n// The final://schemas/reasoning fragment has no xhigh/ultra yet; nanocode's\n// policies accept the rest.\nexport const CODEX_REASONING_LEVELS = [\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n ReasoningLevel.Max,\n] as const;\n\nexport const CODEX_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['exec_command', 'write_stdin'],\n },\n [BaseCapability.Files]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['apply_patch', 'view_image'],\n },\n};\n\nexport const serverlessNanocodeCodexConfigSchema = z.strictObject({\n model: modelZod(modelIds(CODEX_RESPONSES_LITE_MODELS)).default(DEFAULT_CODEX_MODEL),\n reasoning: reasoningZod(CODEX_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n approvalPolicy: z.nativeEnum(CodexApprovalPolicy).default(CodexApprovalPolicy.OnRequest),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessNanocodeCodexConfigIface = z.output<\n typeof serverlessNanocodeCodexConfigSchema\n>;\n\nexport const SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Codex on nanocode (serverless)',\n properties: {\n model: modelJson(modelIds(CODEX_RESPONSES_LITE_MODELS), DEFAULT_CODEX_MODEL),\n reasoning: reasoningJson(CODEX_REASONING_LEVELS),\n credentials: credentialsJson(),\n approvalPolicy: permissionModeJson(\n Object.values(CodexApprovalPolicy),\n CodexApprovalPolicy.OnRequest,\n ),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_NANOCODE_CODEX_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: CODEX_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n inference: {\n vendors: vendorsOf(CODEX_RESPONSES_LITE_MODELS),\n kinds: [\n InferenceCredentialKind.Subscription,\n InferenceCredentialKind.ApiKey,\n InferenceCredentialKind.Platform,\n ],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers nanocode/codex.test.ts \"steers a prompt that arrives\n // while the turn runs into it\"); open approvals are asked again with new ids after a\n // lost invocation, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Inject,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessNanocodeCodexConfigInputIface {\n model?: CodexResponsesLiteModelId;\n reasoning?:\n | (typeof CODEX_REASONING_LEVELS)[number]\n | `${(typeof CODEX_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n approvalPolicy?: CodexApprovalPolicy | `${CodexApprovalPolicy}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessNanocodeCodex = (\n config: ServerlessNanocodeCodexConfigInputIface,\n): HarnessBindingOutputIface => harnessBinding(SPECIFIER, config);\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAMA,MAAM,YAAY;AAIlB,MAAM,yBAAyB;AAAA,EACpC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAEO,MAAM,mBAAyD;AAAA,EACpE,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,gBAAgB,aAAa;AAAA,EAC7C;AAAA,EACA,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,eAAe,YAAY;AAAA,EAC3C;AACF;AAEO,MAAM,sCAAsC,EAAE,aAAa;AAAA,EAChE,OAAO,SAAS,SAAS,2BAA2B,CAAC,EAAE,QAAQ,mBAAmB;AAAA,EAClF,WAAW,aAAa,sBAAsB,EAAE,SAAS;AAAA,EACzD,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,mBAAmB,EAAE,QAAQ,oBAAoB,SAAS;AAAA,EACvF,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAMM,MAAM,+CAA2D,iBAAiB;AAAA,EACvF,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU,SAAS,2BAA2B,GAAG,mBAAmB;AAAA,IAC3E,WAAW,cAAc,sBAAsB;AAAA,IAC/C,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB;AAAA,MACd,OAAO,OAAO,mBAAmB;AAAA,MACjC,oBAAoB;AAAA,IACtB;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,wCAAiE;AAAA,EAC5E,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA,EAChC,WAAW;AAAA,IACT,SAAS,UAAU,2BAA2B;AAAA,IAC9C,OAAO;AAAA,MACL,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAaO,MAAM,0BAA0B,CACrC,WAC8B,eAAe,WAAW,MAAM;",
4
+ "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n CodexApprovalPolicy,\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport { ModelVendor } from \"./model-reference.mjs\";\n\n// nanocode's Codex engine (Rust \u2192 wasm) in the nanocode Durable Object script.\n// Responses Lite models only; ChatGPT subscriptions go through the session\n// service relay because chatgpt.com blocks Workers egress.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-nanocode-codex';\n\n// The final://schemas/reasoning fragment has no xhigh/ultra yet; nanocode's\n// policies accept the rest.\nexport const CODEX_REASONING_LEVELS = [\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n ReasoningLevel.Max,\n] as const;\n\nexport const CODEX_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['exec_command', 'write_stdin'],\n },\n [BaseCapability.Files]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['apply_patch', 'view_image'],\n },\n};\n\nexport const serverlessNanocodeCodexConfigSchema = z.strictObject({\n model: modelZod().optional(),\n reasoning: reasoningZod(CODEX_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n approvalPolicy: z.nativeEnum(CodexApprovalPolicy).default(CodexApprovalPolicy.OnRequest),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessNanocodeCodexConfigIface = z.output<\n typeof serverlessNanocodeCodexConfigSchema\n>;\n\nexport const SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Codex on nanocode (serverless)',\n properties: {\n model: modelJson(),\n reasoning: reasoningJson(CODEX_REASONING_LEVELS),\n credentials: credentialsJson(),\n approvalPolicy: permissionModeJson(\n Object.values(CodexApprovalPolicy),\n CodexApprovalPolicy.OnRequest,\n ),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_NANOCODE_CODEX_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_NANOCODE_CODEX_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: CODEX_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n inference: {\n vendors: [ModelVendor.OpenAI],\n kinds: [\n InferenceCredentialKind.Subscription,\n InferenceCredentialKind.ApiKey,\n InferenceCredentialKind.Platform,\n ],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers nanocode/codex.test.ts \"steers a prompt that arrives\n // while the turn runs into it\"); open approvals are asked again with new ids after a\n // lost invocation, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Inject,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessNanocodeCodexConfigInputIface {\n model?: string;\n reasoning?:\n | (typeof CODEX_REASONING_LEVELS)[number]\n | `${(typeof CODEX_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n approvalPolicy?: CodexApprovalPolicy | `${CodexApprovalPolicy}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessNanocodeCodex = (\n config: ServerlessNanocodeCodexConfigInputIface,\n): HarnessBindingOutputIface => harnessBinding(SPECIFIER, config);\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,mBAAmB;AAMrB,MAAM,YAAY;AAIlB,MAAM,yBAAyB;AAAA,EACpC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAEO,MAAM,mBAAyD;AAAA,EACpE,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,gBAAgB,aAAa;AAAA,EAC7C;AAAA,EACA,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,eAAe,YAAY;AAAA,EAC3C;AACF;AAEO,MAAM,sCAAsC,EAAE,aAAa;AAAA,EAChE,OAAO,SAAS,EAAE,SAAS;AAAA,EAC3B,WAAW,aAAa,sBAAsB,EAAE,SAAS;AAAA,EACzD,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,mBAAmB,EAAE,QAAQ,oBAAoB,SAAS;AAAA,EACvF,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAMM,MAAM,+CAA2D,iBAAiB;AAAA,EACvF,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU;AAAA,IACjB,WAAW,cAAc,sBAAsB;AAAA,IAC/C,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB;AAAA,MACd,OAAO,OAAO,mBAAmB;AAAA,MACjC,oBAAoB;AAAA,IACtB;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,wCAAiE;AAAA,EAC5E,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA,EAChC,WAAW;AAAA,IACT,SAAS,CAAC,YAAY,MAAM;AAAA,IAC5B,OAAO;AAAA,MACL,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAaO,MAAM,0BAA0B,CACrC,WAC8B,eAAe,WAAW,MAAM;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,11 @@
1
1
  import { type HarnessDescriptionIface, type JsonSchema } from '@finalai/agent-provider';
2
2
  import * as z from 'zod';
3
3
  import { PiPermissionMode, ReasoningLevel, type CredentialsInput, type HarnessBindingOutputIface, type InstructionInput, type SkillInput } from "./config-fields.mjs";
4
- import { type PiModelId } from "./models.mjs";
5
4
  export declare const SPECIFIER = "@finalai/final-agent-provider/harnesses/serverless-pi";
6
5
  export declare const PI_REASONING_LEVELS: readonly [ReasoningLevel.None, ReasoningLevel.Minimal, ReasoningLevel.Low, ReasoningLevel.Medium, ReasoningLevel.High];
7
6
  export declare const PI_BASE_TOOLS: HarnessDescriptionIface['baseTools'];
8
7
  export declare const serverlessPiConfigSchema: z.ZodObject<{
9
- model: z.ZodDefault<z.ZodString>;
8
+ model: z.ZodOptional<z.ZodString>;
10
9
  reasoning: z.ZodOptional<z.ZodEnum<typeof ReasoningLevel>>;
11
10
  credentials: z.ZodObject<{
12
11
  payer: z.ZodEnum<typeof import("@finalai/agent-provider").CredentialPayer>;
@@ -55,7 +54,7 @@ export type ServerlessPiConfigIface = z.output<typeof serverlessPiConfigSchema>;
55
54
  export declare const SERVERLESS_PI_CONFIG_JSON_SCHEMA: JsonSchema;
56
55
  export declare const SERVERLESS_PI_DESCRIPTION: HarnessDescriptionIface;
57
56
  export interface ServerlessPiConfigInputIface {
58
- model?: PiModelId;
57
+ model?: string;
59
58
  reasoning?: (typeof PI_REASONING_LEVELS)[number] | `${(typeof PI_REASONING_LEVELS)[number]}`;
60
59
  credentials: CredentialsInput;
61
60
  permissionMode?: PiPermissionMode | `${PiPermissionMode}`;
@@ -27,7 +27,7 @@ import {
27
27
  skillsJson,
28
28
  skillsZod
29
29
  } from "./config-fields.mjs";
30
- import { DEFAULT_PI_MODEL, modelIds, PI_MODELS, vendorsOf } from "./models.mjs";
30
+ import { ModelVendor } from "./model-reference.mjs";
31
31
  const SPECIFIER = "@finalai/final-agent-provider/harnesses/serverless-pi";
32
32
  const PI_REASONING_LEVELS = [
33
33
  ReasoningLevel.None,
@@ -44,7 +44,7 @@ const PI_BASE_TOOLS = {
44
44
  }
45
45
  };
46
46
  const serverlessPiConfigSchema = z.strictObject({
47
- model: modelZod(modelIds(PI_MODELS)).default(DEFAULT_PI_MODEL),
47
+ model: modelZod().optional(),
48
48
  reasoning: reasoningZod(PI_REASONING_LEVELS).optional(),
49
49
  credentials: credentialsZod(),
50
50
  permissionMode: z.nativeEnum(PiPermissionMode).default(PiPermissionMode.Ask),
@@ -55,7 +55,7 @@ const SERVERLESS_PI_CONFIG_JSON_SCHEMA = configObjectJson({
55
55
  required: ["credentials"],
56
56
  title: "Pi (serverless)",
57
57
  properties: {
58
- model: modelJson(modelIds(PI_MODELS), DEFAULT_PI_MODEL),
58
+ model: modelJson(),
59
59
  reasoning: reasoningJson(PI_REASONING_LEVELS),
60
60
  credentials: credentialsJson(),
61
61
  permissionMode: permissionModeJson(Object.values(PiPermissionMode), PiPermissionMode.Ask),
@@ -72,7 +72,7 @@ const SERVERLESS_PI_DESCRIPTION = {
72
72
  baseTools: PI_BASE_TOOLS,
73
73
  consumes: [SandboxWire.HandleRpc],
74
74
  inference: {
75
- vendors: vendorsOf(PI_MODELS),
75
+ vendors: [ModelVendor.OpenRouter, ModelVendor.OpenAI, ModelVendor.Anthropic],
76
76
  kinds: [InferenceCredentialKind.ApiKey, InferenceCredentialKind.Platform],
77
77
  delivery: CredentialDelivery.PerRequest
78
78
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/harnesses/serverless-pi.ts"],
4
- "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n PiPermissionMode,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport { DEFAULT_PI_MODEL, modelIds, PI_MODELS, vendorsOf, type PiModelId } from \"./models.mjs\";\n\n// Pi (pi-mono) in a Durable Object per session in agent-harness-workers.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-pi';\n\nexport const PI_REASONING_LEVELS = [\n ReasoningLevel.None,\n ReasoningLevel.Minimal,\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n] as const;\n\n// Pi's native tools, all executed on the bound target's handle.\nexport const PI_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: { provision: BaseToolProvision.Bound, nativeTools: ['bash'] },\n [BaseCapability.Files]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['read', 'write', 'edit', 'grep', 'find', 'ls'],\n },\n};\n\nexport const serverlessPiConfigSchema = z.strictObject({\n model: modelZod(modelIds(PI_MODELS)).default(DEFAULT_PI_MODEL),\n reasoning: reasoningZod(PI_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n permissionMode: z.nativeEnum(PiPermissionMode).default(PiPermissionMode.Ask),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessPiConfigIface = z.output<typeof serverlessPiConfigSchema>;\n\nexport const SERVERLESS_PI_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Pi (serverless)',\n properties: {\n model: modelJson(modelIds(PI_MODELS), DEFAULT_PI_MODEL),\n reasoning: reasoningJson(PI_REASONING_LEVELS),\n credentials: credentialsJson(),\n permissionMode: permissionModeJson(Object.values(PiPermissionMode), PiPermissionMode.Ask),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_PI_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_PI_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: PI_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n inference: {\n vendors: vendorsOf(PI_MODELS),\n kinds: [InferenceCredentialKind.ApiKey, InferenceCredentialKind.Platform],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers pi/engine.test.ts \"injects a prompt accepted while\n // running into the running work\"): a steer joins the running run. Across a lost\n // invocation an open ask is not re-raised with its id, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Inject,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessPiConfigInputIface {\n model?: PiModelId;\n reasoning?: (typeof PI_REASONING_LEVELS)[number] | `${(typeof PI_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n permissionMode?: PiPermissionMode | `${PiPermissionMode}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessPi = (config: ServerlessPiConfigInputIface): HarnessBindingOutputIface =>\n harnessBinding(SPECIFIER, config);\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,kBAAkB,UAAU,WAAW,iBAAiC;AAI1E,MAAM,YAAY;AAElB,MAAM,sBAAsB;AAAA,EACjC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAGO,MAAM,gBAAsD;AAAA,EACjE,CAAC,eAAe,KAAK,GAAG,EAAE,WAAW,kBAAkB,OAAO,aAAa,CAAC,MAAM,EAAE;AAAA,EACpF,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,IAAI;AAAA,EAC7D;AACF;AAEO,MAAM,2BAA2B,EAAE,aAAa;AAAA,EACrD,OAAO,SAAS,SAAS,SAAS,CAAC,EAAE,QAAQ,gBAAgB;AAAA,EAC7D,WAAW,aAAa,mBAAmB,EAAE,SAAS;AAAA,EACtD,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,gBAAgB,EAAE,QAAQ,iBAAiB,GAAG;AAAA,EAC3E,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAIM,MAAM,mCAA+C,iBAAiB;AAAA,EAC3E,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU,SAAS,SAAS,GAAG,gBAAgB;AAAA,IACtD,WAAW,cAAc,mBAAmB;AAAA,IAC5C,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB,mBAAmB,OAAO,OAAO,gBAAgB,GAAG,iBAAiB,GAAG;AAAA,IACxF,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,4BAAqD;AAAA,EAChE,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA,EAChC,WAAW;AAAA,IACT,SAAS,UAAU,SAAS;AAAA,IAC5B,OAAO,CAAC,wBAAwB,QAAQ,wBAAwB,QAAQ;AAAA,IACxE,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAWO,MAAM,eAAe,CAAC,WAC3B,eAAe,WAAW,MAAM;",
4
+ "sourcesContent": ["import {\n AcpTransport,\n BaseCapability,\n BaseToolProvision,\n CredentialDelivery,\n HarnessTrustClass,\n InferenceCredentialKind,\n McpTransportKind,\n PromptWhileRunning,\n SandboxWire,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n configObjectJson,\n credentialsJson,\n credentialsZod,\n harnessBinding,\n instructionsJson,\n instructionsZod,\n modelJson,\n modelZod,\n permissionModeJson,\n PiPermissionMode,\n reasoningJson,\n ReasoningLevel,\n reasoningZod,\n skillsJson,\n skillsZod,\n type CredentialsInput,\n type HarnessBindingOutputIface,\n type InstructionInput,\n type SkillInput,\n} from \"./config-fields.mjs\";\nimport { ModelVendor } from \"./model-reference.mjs\";\n\n// Pi (pi-mono) in a Durable Object per session in agent-harness-workers.\n\nexport const SPECIFIER = '@finalai/final-agent-provider/harnesses/serverless-pi';\n\nexport const PI_REASONING_LEVELS = [\n ReasoningLevel.None,\n ReasoningLevel.Minimal,\n ReasoningLevel.Low,\n ReasoningLevel.Medium,\n ReasoningLevel.High,\n] as const;\n\n// Pi's native tools, all executed on the bound target's handle.\nexport const PI_BASE_TOOLS: HarnessDescriptionIface['baseTools'] = {\n [BaseCapability.Shell]: { provision: BaseToolProvision.Bound, nativeTools: ['bash'] },\n [BaseCapability.Files]: {\n provision: BaseToolProvision.Bound,\n nativeTools: ['read', 'write', 'edit', 'grep', 'find', 'ls'],\n },\n};\n\nexport const serverlessPiConfigSchema = z.strictObject({\n model: modelZod().optional(),\n reasoning: reasoningZod(PI_REASONING_LEVELS).optional(),\n credentials: credentialsZod(),\n permissionMode: z.nativeEnum(PiPermissionMode).default(PiPermissionMode.Ask),\n instructions: instructionsZod(),\n skills: skillsZod(),\n});\n\nexport type ServerlessPiConfigIface = z.output<typeof serverlessPiConfigSchema>;\n\nexport const SERVERLESS_PI_CONFIG_JSON_SCHEMA: JsonSchema = configObjectJson({\n required: ['credentials'],\n title: 'Pi (serverless)',\n properties: {\n model: modelJson(),\n reasoning: reasoningJson(PI_REASONING_LEVELS),\n credentials: credentialsJson(),\n permissionMode: permissionModeJson(Object.values(PiPermissionMode), PiPermissionMode.Ask),\n instructions: instructionsJson(),\n skills: skillsJson(),\n },\n});\n\nexport const SERVERLESS_PI_DESCRIPTION: HarnessDescriptionIface = {\n configSchema: SERVERLESS_PI_CONFIG_JSON_SCHEMA,\n acp: {\n transports: [AcpTransport.Relay, AcpTransport.Ws],\n mcp: [McpTransportKind.Acp, McpTransportKind.Http],\n },\n baseTools: PI_BASE_TOOLS,\n consumes: [SandboxWire.HandleRpc],\n inference: {\n vendors: [ModelVendor.OpenRouter, ModelVendor.OpenAI, ModelVendor.Anthropic],\n kinds: [InferenceCredentialKind.ApiKey, InferenceCredentialKind.Platform],\n delivery: CredentialDelivery.PerRequest,\n },\n // Final runs these on its own Workers.\n trust: HarnessTrustClass.FirstParty,\n supports: { observe: true, resumeReplay: true, fork: false, authorMeta: true },\n // Measured (agent-harness-workers pi/engine.test.ts \"injects a prompt accepted while\n // running into the running work\"): a steer joins the running run. Across a lost\n // invocation an open ask is not re-raised with its id, so no disconnect survival yet.\n promptWhileRunning: PromptWhileRunning.Inject,\n sessionSurvivesDisconnect: false,\n};\n\nexport interface ServerlessPiConfigInputIface {\n model?: string;\n reasoning?: (typeof PI_REASONING_LEVELS)[number] | `${(typeof PI_REASONING_LEVELS)[number]}`;\n credentials: CredentialsInput;\n permissionMode?: PiPermissionMode | `${PiPermissionMode}`;\n instructions?: InstructionInput[];\n skills?: SkillInput[];\n}\n\nexport const serverlessPi = (config: ServerlessPiConfigInputIface): HarnessBindingOutputIface =>\n harnessBinding(SPECIFIER, config);\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,mBAAmB;AAIrB,MAAM,YAAY;AAElB,MAAM,sBAAsB;AAAA,EACjC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;AAGO,MAAM,gBAAsD;AAAA,EACjE,CAAC,eAAe,KAAK,GAAG,EAAE,WAAW,kBAAkB,OAAO,aAAa,CAAC,MAAM,EAAE;AAAA,EACpF,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,WAAW,kBAAkB;AAAA,IAC7B,aAAa,CAAC,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,IAAI;AAAA,EAC7D;AACF;AAEO,MAAM,2BAA2B,EAAE,aAAa;AAAA,EACrD,OAAO,SAAS,EAAE,SAAS;AAAA,EAC3B,WAAW,aAAa,mBAAmB,EAAE,SAAS;AAAA,EACtD,aAAa,eAAe;AAAA,EAC5B,gBAAgB,EAAE,WAAW,gBAAgB,EAAE,QAAQ,iBAAiB,GAAG;AAAA,EAC3E,cAAc,gBAAgB;AAAA,EAC9B,QAAQ,UAAU;AACpB,CAAC;AAIM,MAAM,mCAA+C,iBAAiB;AAAA,EAC3E,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO;AAAA,EACP,YAAY;AAAA,IACV,OAAO,UAAU;AAAA,IACjB,WAAW,cAAc,mBAAmB;AAAA,IAC5C,aAAa,gBAAgB;AAAA,IAC7B,gBAAgB,mBAAmB,OAAO,OAAO,gBAAgB,GAAG,iBAAiB,GAAG;AAAA,IACxF,cAAc,iBAAiB;AAAA,IAC/B,QAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEM,MAAM,4BAAqD;AAAA,EAChE,cAAc;AAAA,EACd,KAAK;AAAA,IACH,YAAY,CAAC,aAAa,OAAO,aAAa,EAAE;AAAA,IAChD,KAAK,CAAC,iBAAiB,KAAK,iBAAiB,IAAI;AAAA,EACnD;AAAA,EACA,WAAW;AAAA,EACX,UAAU,CAAC,YAAY,SAAS;AAAA,EAChC,WAAW;AAAA,IACT,SAAS,CAAC,YAAY,YAAY,YAAY,QAAQ,YAAY,SAAS;AAAA,IAC3E,OAAO,CAAC,wBAAwB,QAAQ,wBAAwB,QAAQ;AAAA,IACxE,UAAU,mBAAmB;AAAA,EAC/B;AAAA;AAAA,EAEA,OAAO,kBAAkB;AAAA,EACzB,UAAU,EAAE,SAAS,MAAM,cAAc,MAAM,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAAA;AAAA,EAI7E,oBAAoB,mBAAmB;AAAA,EACvC,2BAA2B;AAC7B;AAWO,MAAM,eAAe,CAAC,WAC3B,eAAe,WAAW,MAAM;",
6
6
  "names": []
7
7
  }
@@ -8,6 +8,8 @@ import {
8
8
  import {
9
9
  defineSandboxProvider,
10
10
  materializeSandboxSeeds,
11
+ PLATFORM_ENVIRONMENT_NAMES,
12
+ platformProcessEnvironment,
11
13
  PortProtocol,
12
14
  SandboxCapability,
13
15
  sandboxSeedArtifact,
@@ -15,7 +17,9 @@ import {
15
17
  sandboxSeedFiles,
16
18
  sandboxSeedFilesForStart,
17
19
  sandboxSeedIdentity,
18
- SandboxWorkspace
20
+ SandboxWorkspace,
21
+ withPlatformEgressHosts,
22
+ writePlatformFiles
19
23
  } from "@finalai/agent-provider/sandbox";
20
24
  import {
21
25
  ComputerBaseState,
@@ -95,6 +99,7 @@ const computerStateSchema = z.object({
95
99
  });
96
100
  const computerSandboxError = (code, message) => Object.assign(new Error(message), { name: "ComputerSandboxError", code });
97
101
  const RESERVED_ENV = /* @__PURE__ */ new Set([
102
+ ...PLATFORM_ENVIRONMENT_NAMES,
98
103
  "DISPLAY",
99
104
  "XDG_RUNTIME_DIR",
100
105
  "PATH",
@@ -129,11 +134,11 @@ const CAPTURE_SCRUBBED_PATHS = [
129
134
  "/home/user/.ssh"
130
135
  ];
131
136
  const BUILDER_IDLE_TIMEOUT_SECONDS = 2 * 60 * 60;
132
- const egressFor = (spec) => {
133
- const policy = spec.parameters.networkPolicy;
137
+ const egressFor = (ctx, requested) => {
138
+ const policy = withPlatformEgressHosts(ctx, requested);
134
139
  if (policy.mode === NetworkPolicy.AllowAll) return { egress: ComputerEgressPolicy.Internet };
135
140
  if (policy.mode === NetworkPolicy.DenyAll) return { egress: ComputerEgressPolicy.None };
136
- return { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow };
141
+ return { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow ?? [] };
137
142
  };
138
143
  const LINEAGE_PREFIX = "lineage:";
139
144
  const portOf = (url) => {
@@ -246,7 +251,7 @@ const createComputerSandboxProvider = (config) => {
246
251
  ${commandHelp}`}`,
247
252
  workspaceRoot: WORKSPACE_ROOT,
248
253
  transport,
249
- baseEnv: () => args.env,
254
+ baseEnv: args.env,
250
255
  randomUuid,
251
256
  network: {
252
257
  ports,
@@ -344,8 +349,7 @@ ${commandHelp}`}`,
344
349
  setNetworkPolicy: async (policy) => {
345
350
  if (args.access === SandboxAccess.Read)
346
351
  throw new Error("this sandbox binding is read-only");
347
- const network = policy.mode === NetworkPolicy.AllowAll ? { egress: ComputerEgressPolicy.Internet } : policy.mode === NetworkPolicy.DenyAll ? { egress: ComputerEgressPolicy.None } : { egress: ComputerEgressPolicy.Allowlist, allow: policy.allow ?? [] };
348
- await client.setNetworkPolicy(info.id, network);
352
+ await client.setNetworkPolicy(info.id, egressFor(args.ctx, policy));
349
353
  },
350
354
  describe: () => description,
351
355
  capabilities
@@ -397,7 +401,7 @@ ${commandHelp}`}`,
397
401
  description: `setup of ${args.info.name}`,
398
402
  workspaceRoot: WORKSPACE_ROOT,
399
403
  transport,
400
- baseEnv: () => args.env,
404
+ baseEnv: args.env,
401
405
  randomUuid,
402
406
  network: {
403
407
  ports: [],
@@ -471,7 +475,7 @@ ${commandHelp}`}`,
471
475
  );
472
476
  ctx.log?.(`building computer base ${key} on ${builder.name}`);
473
477
  try {
474
- const sandbox = setupSession({ client, info: builder, env: {} }).sandbox;
478
+ const sandbox = setupSession({ client, info: builder, env: async () => ({}) }).sandbox;
475
479
  const prepared = await sandbox.run({
476
480
  command: "/bin/sh",
477
481
  args: ["-c", `mkdir -p ${BUILD_ROOT}
@@ -569,7 +573,8 @@ ${step.run}`,
569
573
  sandbox: args.setup.sandbox,
570
574
  transport: args.setup.transport,
571
575
  template: args.spec.template,
572
- env: args.env,
576
+ // Services run for the computer's life, with the platform's values as they are now.
577
+ env: await args.env(),
573
578
  randomUuid,
574
579
  log
575
580
  });
@@ -675,7 +680,7 @@ ${step.run}`,
675
680
  start: async (ctx, openOptions, rawArtifact) => {
676
681
  const access = computerOpenOptionsSchema.parse(openOptions ?? {}).access;
677
682
  const spec = await resolve(ctx.guides);
678
- const egress = egressFor(spec);
683
+ const egress = egressFor(ctx, spec.parameters.networkPolicy);
679
684
  const artifact = computerArtifactSchema.safeParse(rawArtifact);
680
685
  if (!artifact.success) {
681
686
  throw computerSandboxError(
@@ -690,7 +695,7 @@ ${step.run}`,
690
695
  `computer base ${artifact.data.key} was prepared without its build steps; prepare it again`
691
696
  );
692
697
  }
693
- const env = await loadVariables(ctx, spec);
698
+ const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));
694
699
  const client = clientFor(ctx.session.organizationId);
695
700
  const workspace = spec.parameters.workspace;
696
701
  const name = workspace === ComputerWorkspacePolicy.Conversation && ctx.session.conversationId != null ? `ac-${(await sha256Hex(`${ctx.session.conversationId}:${ctx.session.target}`)).slice(0, 24)}` : `ab-${compactId(ctx.session.bindingId)}`;
@@ -734,6 +739,7 @@ ${step.run}`,
734
739
  log("computer_sandbox.started", { computerId: info.id, reused: existing != null });
735
740
  try {
736
741
  const setup = setupSession({ client, info, env });
742
+ await writePlatformFiles(ctx, setup.sandbox);
737
743
  await mountRepositories({
738
744
  sandbox: setup.sandbox,
739
745
  repositories: spec.parameters.repositories,
@@ -791,7 +797,7 @@ ${step.run}`,
791
797
  "computer is not running for passive access"
792
798
  );
793
799
  const spec = await resolve(ctx.guides);
794
- const env = await loadVariables(ctx, spec);
800
+ const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));
795
801
  return (await buildHandle({ ctx, client, info, spec, access: state.access, env })).handle;
796
802
  },
797
803
  resume: async (ctx, _artifact, rawState) => {
@@ -805,8 +811,9 @@ ${step.run}`,
805
811
  if (info.state === ComputerState.Paused) await client.action(info.id, "resume");
806
812
  else if (rebooted) await client.action(info.id, "start");
807
813
  const spec = await resolve(ctx.guides);
808
- const env = await loadVariables(ctx, spec);
814
+ const env = platformProcessEnvironment(ctx, await loadVariables(ctx, spec));
809
815
  const setup = setupSession({ client, info, env });
816
+ await writePlatformFiles(ctx, setup.sandbox);
810
817
  await installGuideCommands({ sandbox: setup.sandbox, template: spec.template });
811
818
  if (rebooted) await startServicesFor({ setup, spec, env });
812
819
  const { handle } = await buildHandle({