@finalai/final-agent-provider 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/HOSTING.md +334 -245
  2. package/README.md +126 -40
  3. package/WORKSPACE-EGRESS.md +11 -11
  4. package/dist/modules/catalog.d.mts +9 -0
  5. package/dist/modules/catalog.mjs +21 -0
  6. package/dist/modules/catalog.mjs.map +7 -0
  7. package/dist/modules/channels/projection.mjs +15 -8
  8. package/dist/modules/channels/projection.mjs.map +2 -2
  9. package/dist/modules/harnesses/acp-agent.d.mts +4 -0
  10. package/dist/modules/harnesses/acp-agent.mjs +35 -0
  11. package/dist/modules/harnesses/acp-agent.mjs.map +7 -0
  12. package/dist/modules/harnesses/adapters.d.mts +7 -0
  13. package/dist/modules/harnesses/adapters.mjs +74 -0
  14. package/dist/modules/harnesses/adapters.mjs.map +7 -0
  15. package/dist/modules/harnesses/claude-code.d.mts +14 -0
  16. package/dist/modules/harnesses/claude-code.mjs +79 -0
  17. package/dist/modules/harnesses/claude-code.mjs.map +7 -0
  18. package/dist/modules/harnesses/codex.d.mts +12 -0
  19. package/dist/modules/harnesses/codex.mjs +90 -0
  20. package/dist/modules/harnesses/codex.mjs.map +7 -0
  21. package/dist/modules/harnesses/config-fields.d.mts +98 -57
  22. package/dist/modules/harnesses/config-fields.mjs +58 -35
  23. package/dist/modules/harnesses/config-fields.mjs.map +3 -3
  24. package/dist/modules/harnesses/definitions.d.mts +3 -0
  25. package/dist/modules/harnesses/definitions.mjs +21 -0
  26. package/dist/modules/harnesses/definitions.mjs.map +7 -0
  27. package/dist/modules/harnesses/fidelity.d.mts +1 -1
  28. package/dist/modules/harnesses/fidelity.mjs +19 -16
  29. package/dist/modules/harnesses/fidelity.mjs.map +2 -2
  30. package/dist/modules/harnesses/final.d.mts +12 -0
  31. package/dist/modules/harnesses/final.mjs +70 -0
  32. package/dist/modules/harnesses/final.mjs.map +7 -0
  33. package/dist/modules/harnesses/index.d.mts +13 -12
  34. package/dist/modules/harnesses/index.mjs +86 -45
  35. package/dist/modules/harnesses/index.mjs.map +3 -3
  36. package/dist/modules/harnesses/names.d.mts +43 -0
  37. package/dist/modules/harnesses/names.mjs +59 -0
  38. package/dist/modules/harnesses/names.mjs.map +7 -0
  39. package/dist/modules/harnesses/nanocode-claude.d.mts +18 -0
  40. package/dist/modules/harnesses/nanocode-claude.mjs +101 -0
  41. package/dist/modules/harnesses/nanocode-claude.mjs.map +7 -0
  42. package/dist/modules/harnesses/nanocode-codex.d.mts +13 -0
  43. package/dist/modules/harnesses/nanocode-codex.mjs +64 -0
  44. package/dist/modules/harnesses/nanocode-codex.mjs.map +7 -0
  45. package/dist/modules/harnesses/pi.d.mts +12 -0
  46. package/dist/modules/harnesses/pi.mjs +71 -0
  47. package/dist/modules/harnesses/pi.mjs.map +7 -0
  48. package/dist/modules/integrations.d.mts +9 -0
  49. package/dist/modules/integrations.mjs +29 -0
  50. package/dist/modules/integrations.mjs.map +7 -0
  51. package/dist/modules/provider/general.bundle.d.mts +1 -0
  52. package/dist/modules/provider/general.bundle.mjs +5 -0
  53. package/dist/modules/provider/general.bundle.mjs.map +7 -0
  54. package/dist/modules/provider/general.d.mts +11 -0
  55. package/dist/modules/provider/general.mjs +130 -0
  56. package/dist/modules/provider/general.mjs.map +7 -0
  57. package/dist/modules/provider/index.d.mts +3 -0
  58. package/dist/modules/provider/index.mjs +13 -0
  59. package/dist/modules/provider/index.mjs.map +7 -0
  60. package/dist/modules/sandboxes/access.d.mts +34 -0
  61. package/dist/modules/sandboxes/access.mjs +15 -0
  62. package/dist/modules/sandboxes/access.mjs.map +7 -0
  63. package/dist/modules/sandboxes/computer.d.mts +24 -51
  64. package/dist/modules/sandboxes/computer.mjs +523 -888
  65. package/dist/modules/sandboxes/computer.mjs.map +3 -3
  66. package/dist/modules/sandboxes/computers-api.d.mts +3 -2
  67. package/dist/modules/sandboxes/computers-api.mjs +2 -4
  68. package/dist/modules/sandboxes/computers-api.mjs.map +2 -2
  69. package/dist/modules/sandboxes/device-api.d.mts +4 -3
  70. package/dist/modules/sandboxes/device-api.mjs +2 -4
  71. package/dist/modules/sandboxes/device-api.mjs.map +2 -2
  72. package/dist/modules/sandboxes/device.d.mts +6 -6
  73. package/dist/modules/sandboxes/device.mjs +126 -121
  74. package/dist/modules/sandboxes/device.mjs.map +3 -3
  75. package/dist/modules/sandboxes/egress.d.mts +10 -9
  76. package/dist/modules/sandboxes/egress.mjs +73 -56
  77. package/dist/modules/sandboxes/egress.mjs.map +2 -2
  78. package/dist/modules/sandboxes/environment.d.mts +35 -269
  79. package/dist/modules/sandboxes/environment.mjs +27 -104
  80. package/dist/modules/sandboxes/environment.mjs.map +3 -3
  81. package/dist/modules/sandboxes/index.d.mts +9 -69
  82. package/dist/modules/sandboxes/index.mjs +35 -95
  83. package/dist/modules/sandboxes/index.mjs.map +3 -3
  84. package/dist/modules/sandboxes/local.d.mts +28 -0
  85. package/dist/modules/sandboxes/local.mjs +499 -0
  86. package/dist/modules/sandboxes/local.mjs.map +7 -0
  87. package/dist/modules/sandboxes/session.d.mts +0 -3
  88. package/dist/modules/sandboxes/session.mjs +2 -22
  89. package/dist/modules/sandboxes/session.mjs.map +2 -2
  90. package/dist/modules/sandboxes/testing/fake-machine.mjs +0 -28
  91. package/dist/modules/sandboxes/testing/fake-machine.mjs.map +2 -2
  92. package/package.json +76 -104
  93. package/dist/modules/connections.d.mts +0 -11
  94. package/dist/modules/connections.mjs +0 -16
  95. package/dist/modules/connections.mjs.map +0 -7
  96. package/dist/modules/harnesses/acp-describe.d.mts +0 -20
  97. package/dist/modules/harnesses/acp-describe.mjs +0 -110
  98. package/dist/modules/harnesses/acp-describe.mjs.map +0 -7
  99. package/dist/modules/harnesses/local-stdio.d.mts +0 -47
  100. package/dist/modules/harnesses/local-stdio.mjs +0 -41
  101. package/dist/modules/harnesses/local-stdio.mjs.map +0 -7
  102. package/dist/modules/harnesses/remote-acp.d.mts +0 -76
  103. package/dist/modules/harnesses/remote-acp.mjs +0 -83
  104. package/dist/modules/harnesses/remote-acp.mjs.map +0 -7
  105. package/dist/modules/harnesses/remote-claude-code.d.mts +0 -88
  106. package/dist/modules/harnesses/remote-claude-code.mjs +0 -113
  107. package/dist/modules/harnesses/remote-claude-code.mjs.map +0 -7
  108. package/dist/modules/harnesses/remote-client-tls.d.mts +0 -35
  109. package/dist/modules/harnesses/remote-client-tls.mjs +0 -37
  110. package/dist/modules/harnesses/remote-client-tls.mjs.map +0 -7
  111. package/dist/modules/harnesses/remote-codex.d.mts +0 -98
  112. package/dist/modules/harnesses/remote-codex.mjs +0 -128
  113. package/dist/modules/harnesses/remote-codex.mjs.map +0 -7
  114. package/dist/modules/harnesses/remote-pi.d.mts +0 -78
  115. package/dist/modules/harnesses/remote-pi.mjs +0 -104
  116. package/dist/modules/harnesses/remote-pi.mjs.map +0 -7
  117. package/dist/modules/harnesses/remote-url.d.mts +0 -5
  118. package/dist/modules/harnesses/remote-url.mjs +0 -19
  119. package/dist/modules/harnesses/remote-url.mjs.map +0 -7
  120. package/dist/modules/harnesses/serverless-final.d.mts +0 -63
  121. package/dist/modules/harnesses/serverless-final.mjs +0 -88
  122. package/dist/modules/harnesses/serverless-final.mjs.map +0 -7
  123. package/dist/modules/harnesses/serverless-nanocode-claude.d.mts +0 -64
  124. package/dist/modules/harnesses/serverless-nanocode-claude.mjs +0 -105
  125. package/dist/modules/harnesses/serverless-nanocode-claude.mjs.map +0 -7
  126. package/dist/modules/harnesses/serverless-nanocode-codex.d.mts +0 -66
  127. package/dist/modules/harnesses/serverless-nanocode-codex.mjs +0 -113
  128. package/dist/modules/harnesses/serverless-nanocode-codex.mjs.map +0 -7
  129. package/dist/modules/harnesses/serverless-pi.d.mts +0 -64
  130. package/dist/modules/harnesses/serverless-pi.mjs +0 -98
  131. package/dist/modules/harnesses/serverless-pi.mjs.map +0 -7
  132. package/dist/modules/runtime/index.d.mts +0 -7
  133. package/dist/modules/runtime/index.mjs +0 -18
  134. package/dist/modules/runtime/index.mjs.map +0 -7
  135. package/dist/modules/runtime/local-stdio.d.mts +0 -10
  136. package/dist/modules/runtime/local-stdio.mjs +0 -106
  137. package/dist/modules/runtime/local-stdio.mjs.map +0 -7
  138. package/dist/modules/runtime/remote-acp.d.mts +0 -16
  139. package/dist/modules/runtime/remote-acp.mjs +0 -152
  140. package/dist/modules/runtime/remote-acp.mjs.map +0 -7
  141. package/dist/modules/runtime/remote-claude-code.d.mts +0 -5
  142. package/dist/modules/runtime/remote-claude-code.mjs +0 -47
  143. package/dist/modules/runtime/remote-claude-code.mjs.map +0 -7
  144. package/dist/modules/runtime/remote-codex.d.mts +0 -5
  145. package/dist/modules/runtime/remote-codex.mjs +0 -47
  146. package/dist/modules/runtime/remote-codex.mjs.map +0 -7
  147. package/dist/modules/runtime/remote-host.d.mts +0 -127
  148. package/dist/modules/runtime/remote-host.mjs +0 -387
  149. package/dist/modules/runtime/remote-host.mjs.map +0 -7
  150. package/dist/modules/runtime/remote-pi.d.mts +0 -5
  151. package/dist/modules/runtime/remote-pi.mjs +0 -44
  152. package/dist/modules/runtime/remote-pi.mjs.map +0 -7
  153. package/dist/modules/sandboxes/guide.d.mts +0 -35
  154. package/dist/modules/sandboxes/guide.mjs +0 -119
  155. package/dist/modules/sandboxes/guide.mjs.map +0 -7
  156. package/dist/modules/sandboxes/workspace-setup.d.mts +0 -42
  157. package/dist/modules/sandboxes/workspace-setup.mjs +0 -242
  158. package/dist/modules/sandboxes/workspace-setup.mjs.map +0 -7
  159. package/dist/modules/testing/harness.d.mts +0 -9
  160. package/dist/modules/testing/harness.mjs +0 -123
  161. package/dist/modules/testing/harness.mjs.map +0 -7
@@ -1,119 +0,0 @@
1
- import {
2
- NetworkPolicy
3
- } from "@finalai/agent-provider";
4
- import { canonicalJson, sha256Hex } from "./bytes.mjs";
5
- import {
6
- computerParametersSchema,
7
- computerTemplateSchema,
8
- ComputerWorkspacePolicy
9
- } from "./environment.mjs";
10
- const ARTIFACT_KEY_VERSION = 1;
11
- const PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION = 2;
12
- const DEFAULT_COMPUTER_IMAGE = "lineage:sandbox";
13
- const computerNeedsBuild = (inputs) => inputs.template.build.steps.length > 0 || inputs.template.build.verify.length > 0;
14
- const computeComputerArtifactKey = async (inputs) => {
15
- if (!computerNeedsBuild(inputs)) {
16
- const hex2 = await sha256Hex(canonicalJson({ v: ARTIFACT_KEY_VERSION, image: inputs.image }));
17
- return `img-${hex2.slice(0, 16)}`;
18
- }
19
- const hex = await sha256Hex(
20
- canonicalJson({
21
- v: ARTIFACT_KEY_VERSION,
22
- image: inputs.image,
23
- build: inputs.template.build,
24
- diskGb: inputs.diskGb
25
- })
26
- );
27
- return `pa-g${hex.slice(0, 16)}-c${PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION}`;
28
- };
29
- const toNetworkPolicy = (option) => {
30
- if (option == null) return void 0;
31
- if (option instanceof Object) return { mode: option.mode, allow: option.allow };
32
- return { mode: option, allow: [] };
33
- };
34
- const mergeComputerParameters = (base, override) => {
35
- const repositories = /* @__PURE__ */ new Map();
36
- for (const repository of [...base.repositories ?? [], ...override.repositories ?? []]) {
37
- repositories.set(repository.alias, repository);
38
- }
39
- return {
40
- repositories: [...repositories.values()],
41
- variables: [.../* @__PURE__ */ new Set([...base.variables ?? [], ...override.variables ?? []])],
42
- workspace: override.workspace ?? base.workspace ?? ComputerWorkspacePolicy.Session,
43
- networkPolicy: toNetworkPolicy(override.networkPolicy) ?? toNetworkPolicy(base.networkPolicy) ?? { mode: NetworkPolicy.AllowAll, allow: [] },
44
- env: { ...base.env, ...override.env }
45
- };
46
- };
47
- const fromVersion = (version, override) => {
48
- const template = computerTemplateSchema.safeParse(version.templateConfig);
49
- if (!template.success) {
50
- throw new Error(
51
- `computer setup guide ${version.slug} v${version.number} has an invalid template`
52
- );
53
- }
54
- const defaults = computerParametersSchema.safeParse(version.defaultParameters);
55
- if (!defaults.success) {
56
- throw new Error(
57
- `computer setup guide ${version.slug} v${version.number} has invalid default parameters`
58
- );
59
- }
60
- return {
61
- image: version.image,
62
- template: template.data,
63
- parameters: mergeComputerParameters(defaults.data, override),
64
- guide: {
65
- guideId: version.guideId,
66
- versionId: version.versionId,
67
- slug: version.slug,
68
- title: version.title,
69
- number: version.number,
70
- preparedArtifact: version.preparedArtifact
71
- },
72
- instructionsMarkdown: version.instructionsMarkdown
73
- };
74
- };
75
- const imageOnly = (image, override) => ({
76
- image,
77
- template: computerTemplateSchema.parse({}),
78
- parameters: mergeComputerParameters({ workspace: ComputerWorkspacePolicy.Ephemeral }, override),
79
- guide: null,
80
- instructionsMarkdown: null
81
- });
82
- const resolveComputerSpec = async (args) => {
83
- const { options } = args;
84
- if ("guide" in options) {
85
- const version = await args.guides.get({
86
- ref: options.guide.ref,
87
- version: options.guide.version
88
- });
89
- if (version == null) {
90
- throw new Error(
91
- `computer setup guide ${options.guide.ref}@${options.guide.version} was not found`
92
- );
93
- }
94
- return fromVersion(version, options.parameters);
95
- }
96
- if ("inline" in options) {
97
- return {
98
- image: options.inline.image,
99
- template: options.inline.template,
100
- parameters: mergeComputerParameters(
101
- { repositories: options.inline.repositories, variables: options.inline.variables },
102
- options.parameters
103
- ),
104
- guide: null,
105
- instructionsMarkdown: null
106
- };
107
- }
108
- if ("image" in options) return imageOnly(options.image, options.parameters);
109
- const fallback = await args.guides.default();
110
- return fallback == null ? imageOnly(args.defaultImage, options.parameters) : fromVersion(fallback, options.parameters);
111
- };
112
- export {
113
- DEFAULT_COMPUTER_IMAGE,
114
- computeComputerArtifactKey,
115
- computerNeedsBuild,
116
- mergeComputerParameters,
117
- resolveComputerSpec
118
- };
119
- //# sourceMappingURL=guide.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/sandboxes/guide.ts"],
4
- "sourcesContent": ["import {\n NetworkPolicy,\n type SandboxGuidesIface,\n type SandboxGuideVersionIface,\n} from '@finalai/agent-provider';\nimport { canonicalJson, sha256Hex } from \"./bytes.mjs\";\nimport {\n computerParametersSchema,\n computerTemplateSchema,\n ComputerWorkspacePolicy,\n type ComputerEnvironmentOptions,\n type ComputerNetworkPolicyOption,\n type ComputerParametersIface,\n type ComputerRepositoryIface,\n type ComputerTemplateIface,\n} from \"./environment.mjs\";\n\n// Computer setup guides: resolving a reference (or an inline guide) into the\n// build-time inputs that define the base and the start-time inputs applied per\n// computer.\n\n// One saved version (agent.computer_setup_guide_versions), as the platform\n// serves it to every provider through the contract's `guides` reader.\nexport type ComputerGuideVersionIface = SandboxGuideVersionIface;\n\nexport interface ResolvedNetworkPolicyIface {\n mode: NetworkPolicy;\n allow: string[];\n}\n\nexport interface ResolvedComputerParametersIface {\n repositories: ComputerRepositoryIface[];\n variables: string[];\n workspace: ComputerWorkspacePolicy;\n networkPolicy: ResolvedNetworkPolicyIface;\n env: Record<string, string>;\n}\n\nexport interface ResolvedComputerSpecIface {\n image: string;\n template: ComputerTemplateIface;\n parameters: ResolvedComputerParametersIface;\n guide: Pick<\n ComputerGuideVersionIface,\n 'guideId' | 'versionId' | 'slug' | 'title' | 'number' | 'preparedArtifact'\n > | null;\n instructionsMarkdown: string | null;\n}\n\n// Bumped when the meaning of the build inputs changes (forces rebuilds).\nconst ARTIFACT_KEY_VERSION = 1;\n// Part of a built base's key; bumping it rebuilds every guide's base.\nconst PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION = 2;\nexport const DEFAULT_COMPUTER_IMAGE = 'lineage:sandbox';\n\nexport interface ComputerBuildInputsIface {\n image: string;\n template: ComputerTemplateIface;\n diskGb: number | null;\n}\n\n// Build steps and verify steps are the only build-time inputs besides the image.\nexport const computerNeedsBuild = (inputs: Pick<ComputerBuildInputsIface, 'template'>): boolean =>\n inputs.template.build.steps.length > 0 || inputs.template.build.verify.length > 0;\n\n// The base's identity: a hash of the build-time inputs only (no guide id, no\n// start-time inputs), so identical guides share one base. B6 stores the same key in\n// computer_setup_guide_versions.build_artifact_key.\nexport const computeComputerArtifactKey = async (\n inputs: ComputerBuildInputsIface,\n): Promise<string> => {\n if (!computerNeedsBuild(inputs)) {\n const hex = await sha256Hex(canonicalJson({ v: ARTIFACT_KEY_VERSION, image: inputs.image }));\n return `img-${hex.slice(0, 16)}`;\n }\n const hex = await sha256Hex(\n canonicalJson({\n v: ARTIFACT_KEY_VERSION,\n image: inputs.image,\n build: inputs.template.build,\n diskGb: inputs.diskGb,\n }),\n );\n return `pa-g${hex.slice(0, 16)}-c${PROJECT_ARTIFACT_CAPTURE_PROTOCOL_VERSION}`;\n};\n\nconst toNetworkPolicy = (\n option: ComputerNetworkPolicyOption | undefined,\n): ResolvedNetworkPolicyIface | undefined => {\n if (option == null) return undefined;\n if (option instanceof Object) return { mode: option.mode, allow: option.allow };\n return { mode: option, allow: [] };\n};\n\n// Saved defaults overridden by the binding: repositories merge by alias, variables\n// union by name, env merges by key, scalars replace.\nexport const mergeComputerParameters = (\n base: ComputerParametersIface,\n override: ComputerParametersIface,\n): ResolvedComputerParametersIface => {\n const repositories = new Map<string, ComputerRepositoryIface>();\n for (const repository of [...(base.repositories ?? []), ...(override.repositories ?? [])]) {\n repositories.set(repository.alias, repository);\n }\n return {\n repositories: [...repositories.values()],\n variables: [...new Set([...(base.variables ?? []), ...(override.variables ?? [])])],\n workspace: override.workspace ?? base.workspace ?? ComputerWorkspacePolicy.Session,\n networkPolicy: toNetworkPolicy(override.networkPolicy) ??\n toNetworkPolicy(base.networkPolicy) ?? { mode: NetworkPolicy.AllowAll, allow: [] },\n env: { ...base.env, ...override.env },\n };\n};\n\nconst fromVersion = (\n version: ComputerGuideVersionIface,\n override: ComputerParametersIface,\n): ResolvedComputerSpecIface => {\n const template = computerTemplateSchema.safeParse(version.templateConfig);\n if (!template.success) {\n throw new Error(\n `computer setup guide ${version.slug} v${version.number} has an invalid template`,\n );\n }\n const defaults = computerParametersSchema.safeParse(version.defaultParameters);\n if (!defaults.success) {\n throw new Error(\n `computer setup guide ${version.slug} v${version.number} has invalid default parameters`,\n );\n }\n return {\n image: version.image,\n template: template.data,\n parameters: mergeComputerParameters(defaults.data, override),\n guide: {\n guideId: version.guideId,\n versionId: version.versionId,\n slug: version.slug,\n title: version.title,\n number: version.number,\n preparedArtifact: version.preparedArtifact,\n },\n instructionsMarkdown: version.instructionsMarkdown,\n };\n};\n\nconst imageOnly = (\n image: string,\n override: ComputerParametersIface,\n): ResolvedComputerSpecIface => ({\n image,\n template: computerTemplateSchema.parse({}),\n parameters: mergeComputerParameters({ workspace: ComputerWorkspacePolicy.Ephemeral }, override),\n guide: null,\n instructionsMarkdown: null,\n});\n\n// Guides come from the contract's `guides` reader (the session's organization).\nexport const resolveComputerSpec = async (args: {\n options: ComputerEnvironmentOptions;\n guides: SandboxGuidesIface;\n defaultImage: string;\n}): Promise<ResolvedComputerSpecIface> => {\n const { options } = args;\n if ('guide' in options) {\n const version = await args.guides.get({\n ref: options.guide.ref,\n version: options.guide.version,\n });\n if (version == null) {\n throw new Error(\n `computer setup guide ${options.guide.ref}@${options.guide.version} was not found`,\n );\n }\n return fromVersion(version, options.parameters);\n }\n if ('inline' in options) {\n return {\n image: options.inline.image,\n template: options.inline.template,\n parameters: mergeComputerParameters(\n { repositories: options.inline.repositories, variables: options.inline.variables },\n options.parameters,\n ),\n guide: null,\n instructionsMarkdown: null,\n };\n }\n if ('image' in options) return imageOnly(options.image, options.parameters);\n const fallback = await args.guides.default();\n return fallback == null\n ? imageOnly(args.defaultImage, options.parameters)\n : fromVersion(fallback, options.parameters);\n};\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,OAGK;AACP,SAAS,eAAe,iBAAiB;AACzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAmCP,MAAM,uBAAuB;AAE7B,MAAM,4CAA4C;AAC3C,MAAM,yBAAyB;AAS/B,MAAM,qBAAqB,CAAC,WACjC,OAAO,SAAS,MAAM,MAAM,SAAS,KAAK,OAAO,SAAS,MAAM,OAAO,SAAS;AAK3E,MAAM,6BAA6B,OACxC,WACoB;AACpB,MAAI,CAAC,mBAAmB,MAAM,GAAG;AAC/B,UAAMA,OAAM,MAAM,UAAU,cAAc,EAAE,GAAG,sBAAsB,OAAO,OAAO,MAAM,CAAC,CAAC;AAC3F,WAAO,OAAOA,KAAI,MAAM,GAAG,EAAE,CAAC;AAAA,EAChC;AACA,QAAM,MAAM,MAAM;AAAA,IAChB,cAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO,OAAO;AAAA,MACd,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AACA,SAAO,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK,yCAAyC;AAC9E;AAEA,MAAM,kBAAkB,CACtB,WAC2C;AAC3C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,kBAAkB,OAAQ,QAAO,EAAE,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM;AAC9E,SAAO,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE;AACnC;AAIO,MAAM,0BAA0B,CACrC,MACA,aACoC;AACpC,QAAM,eAAe,oBAAI,IAAqC;AAC9D,aAAW,cAAc,CAAC,GAAI,KAAK,gBAAgB,CAAC,GAAI,GAAI,SAAS,gBAAgB,CAAC,CAAE,GAAG;AACzF,iBAAa,IAAI,WAAW,OAAO,UAAU;AAAA,EAC/C;AACA,SAAO;AAAA,IACL,cAAc,CAAC,GAAG,aAAa,OAAO,CAAC;AAAA,IACvC,WAAW,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAI,KAAK,aAAa,CAAC,GAAI,GAAI,SAAS,aAAa,CAAC,CAAE,CAAC,CAAC;AAAA,IAClF,WAAW,SAAS,aAAa,KAAK,aAAa,wBAAwB;AAAA,IAC3E,eAAe,gBAAgB,SAAS,aAAa,KACnD,gBAAgB,KAAK,aAAa,KAAK,EAAE,MAAM,cAAc,UAAU,OAAO,CAAC,EAAE;AAAA,IACnF,KAAK,EAAE,GAAG,KAAK,KAAK,GAAG,SAAS,IAAI;AAAA,EACtC;AACF;AAEA,MAAM,cAAc,CAClB,SACA,aAC8B;AAC9B,QAAM,WAAW,uBAAuB,UAAU,QAAQ,cAAc;AACxE,MAAI,CAAC,SAAS,SAAS;AACrB,UAAM,IAAI;AAAA,MACR,wBAAwB,QAAQ,IAAI,KAAK,QAAQ,MAAM;AAAA,IACzD;AAAA,EACF;AACA,QAAM,WAAW,yBAAyB,UAAU,QAAQ,iBAAiB;AAC7E,MAAI,CAAC,SAAS,SAAS;AACrB,UAAM,IAAI;AAAA,MACR,wBAAwB,QAAQ,IAAI,KAAK,QAAQ,MAAM;AAAA,IACzD;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,UAAU,SAAS;AAAA,IACnB,YAAY,wBAAwB,SAAS,MAAM,QAAQ;AAAA,IAC3D,OAAO;AAAA,MACL,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,MAChB,kBAAkB,QAAQ;AAAA,IAC5B;AAAA,IACA,sBAAsB,QAAQ;AAAA,EAChC;AACF;AAEA,MAAM,YAAY,CAChB,OACA,cAC+B;AAAA,EAC/B;AAAA,EACA,UAAU,uBAAuB,MAAM,CAAC,CAAC;AAAA,EACzC,YAAY,wBAAwB,EAAE,WAAW,wBAAwB,UAAU,GAAG,QAAQ;AAAA,EAC9F,OAAO;AAAA,EACP,sBAAsB;AACxB;AAGO,MAAM,sBAAsB,OAAO,SAIA;AACxC,QAAM,EAAE,QAAQ,IAAI;AACpB,MAAI,WAAW,SAAS;AACtB,UAAM,UAAU,MAAM,KAAK,OAAO,IAAI;AAAA,MACpC,KAAK,QAAQ,MAAM;AAAA,MACnB,SAAS,QAAQ,MAAM;AAAA,IACzB,CAAC;AACD,QAAI,WAAW,MAAM;AACnB,YAAM,IAAI;AAAA,QACR,wBAAwB,QAAQ,MAAM,GAAG,IAAI,QAAQ,MAAM,OAAO;AAAA,MACpE;AAAA,IACF;AACA,WAAO,YAAY,SAAS,QAAQ,UAAU;AAAA,EAChD;AACA,MAAI,YAAY,SAAS;AACvB,WAAO;AAAA,MACL,OAAO,QAAQ,OAAO;AAAA,MACtB,UAAU,QAAQ,OAAO;AAAA,MACzB,YAAY;AAAA,QACV,EAAE,cAAc,QAAQ,OAAO,cAAc,WAAW,QAAQ,OAAO,UAAU;AAAA,QACjF,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,sBAAsB;AAAA,IACxB;AAAA,EACF;AACA,MAAI,WAAW,QAAS,QAAO,UAAU,QAAQ,OAAO,QAAQ,UAAU;AAC1E,QAAM,WAAW,MAAM,KAAK,OAAO,QAAQ;AAC3C,SAAO,YAAY,OACf,UAAU,KAAK,cAAc,QAAQ,UAAU,IAC/C,YAAY,UAAU,QAAQ,UAAU;AAC9C;",
6
- "names": ["hex"]
7
- }
@@ -1,42 +0,0 @@
1
- import type { NetworkSandboxSessionIface, SandboxRepositoriesIface, SandboxRepositoryCloneSourceIface } from '@finalai/agent-provider/sandbox';
2
- import { type ComputerRepositoryIface, type ComputerTemplateIface } from "./environment.mjs";
3
- import type { SandboxTransportIface } from "./transport.mjs";
4
- export declare const WORKSPACE_ROOT = "/workspaces";
5
- export interface GuideCommandIface {
6
- name: string;
7
- path: string;
8
- description: string | null;
9
- cwd: string;
10
- timeoutMs: number;
11
- }
12
- export declare const guideCommands: (template: ComputerTemplateIface) => Promise<GuideCommandIface[]>;
13
- export declare const GUIDE_COMMAND_PROTOCOL = "guide-command-v1";
14
- export declare const installGuideCommands: (args: {
15
- sandbox: Pick<NetworkSandboxSessionIface, "run">;
16
- template: ComputerTemplateIface;
17
- }) => Promise<void>;
18
- export type RepositoryCloneSourceIface = SandboxRepositoryCloneSourceIface;
19
- export interface SetupLogIface {
20
- (message: string, fields?: Record<string, string | number | boolean | null>): void;
21
- }
22
- export declare const repositoryPath: (alias: string) => string;
23
- export declare const mountRepositories: (args: {
24
- sandbox: NetworkSandboxSessionIface;
25
- repositories: ComputerRepositoryIface[];
26
- resolver: SandboxRepositoriesIface;
27
- log: SetupLogIface;
28
- }) => Promise<void>;
29
- export declare const runWorkspaceSetup: (args: {
30
- sandbox: NetworkSandboxSessionIface;
31
- template: ComputerTemplateIface;
32
- repositories: ComputerRepositoryIface[];
33
- log: SetupLogIface;
34
- }) => Promise<string | null>;
35
- export declare const startServices: (args: {
36
- sandbox: NetworkSandboxSessionIface;
37
- transport: SandboxTransportIface;
38
- template: ComputerTemplateIface;
39
- env: Record<string, string>;
40
- randomUuid: () => string;
41
- log: SetupLogIface;
42
- }) => Promise<string[]>;
@@ -1,242 +0,0 @@
1
- import { canonicalJson, sha256Hex } from "./bytes.mjs";
2
- import {
3
- TemplateWhenMissing
4
- } from "./environment.mjs";
5
- import { shellQuote } from "./paths.mjs";
6
- const WORKSPACE_ROOT = "/workspaces";
7
- const SETUP_MARKER_ROOT = "/workspaces/.final/setup";
8
- const guideCommands = async (template) => {
9
- const hash = await sha256Hex(canonicalJson(template.commands));
10
- return Object.entries(template.commands).map(([name, command]) => ({
11
- name,
12
- path: `${WORKSPACE_ROOT}/.final/commands/${hash}/${name}`,
13
- description: command.description,
14
- cwd: stepCwd(command.cwd),
15
- timeoutMs: command.timeoutMinutes * 6e4
16
- }));
17
- };
18
- const GUIDE_COMMAND_PROTOCOL = "guide-command-v1";
19
- const INSTALL_GUIDE_COMMANDS_SCRIPT = `# ${GUIDE_COMMAND_PROTOCOL}
20
- import json, os, stat, sys, uuid
21
- p = json.load(sys.stdin)
22
- flags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW
23
- root = os.open('/', flags)
24
- try:
25
- for part in p['root'].split('/'):
26
- if not part:
27
- continue
28
- if part in ('.', '..'):
29
- raise ValueError('invalid command root')
30
- try:
31
- os.mkdir(part, dir_fd=root)
32
- except FileExistsError:
33
- pass
34
- child = os.open(part, flags, dir_fd=root)
35
- os.close(root)
36
- root = child
37
- for name, content in p['files'].items():
38
- if '/' in name or name in ('.', '..'):
39
- raise ValueError('invalid command name')
40
- temporary = '.command-' + uuid.uuid4().hex
41
- try:
42
- fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o700, dir_fd=root)
43
- with os.fdopen(fd, 'wb') as f:
44
- f.write(content.encode('utf-8'))
45
- try:
46
- os.link(temporary, name, src_dir_fd=root, dst_dir_fd=root, follow_symlinks=False)
47
- except FileExistsError:
48
- fd = os.open(name, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=root)
49
- with os.fdopen(fd, 'rb') as f:
50
- if not stat.S_ISREG(os.fstat(f.fileno()).st_mode) or f.read(len(content.encode('utf-8')) + 1) != content.encode('utf-8'):
51
- raise ValueError('guide command differs from its pinned source')
52
- finally:
53
- os.unlink(temporary, dir_fd=root)
54
- finally:
55
- os.close(root)
56
- `;
57
- const installGuideCommands = async (args) => {
58
- const commands = await guideCommands(args.template);
59
- const first = commands[0];
60
- if (first == null) return;
61
- const files = {};
62
- for (const command of commands) {
63
- const source = args.template.commands[command.name];
64
- if (source == null) throw new Error("guide command source is missing");
65
- const missingExit = source.whenMissing === TemplateWhenMissing.Fail ? 1 : 0;
66
- files[command.name] = `#!/bin/bash
67
- set -eu
68
- if [ ! -d ${shellQuote(command.cwd)} ]; then
69
- printf '%s\\n' ${shellQuote(`guide command ${command.name}: missing ${command.cwd}`)} >&2
70
- exit ${missingExit}
71
- fi
72
- cd -- ${shellQuote(command.cwd)}
73
- exec timeout --signal=TERM --kill-after=10s ${source.timeoutMinutes * 60}s bash -c ${shellQuote(source.run)} ${shellQuote(command.name)} "$@"
74
- `;
75
- }
76
- const result = await args.sandbox.run({
77
- command: "python3",
78
- args: ["-c", INSTALL_GUIDE_COMMANDS_SCRIPT],
79
- cwd: "/",
80
- stdin: JSON.stringify({ root: first.path.slice(0, first.path.lastIndexOf("/")), files }),
81
- timeoutMs: 6e4
82
- });
83
- if (result.exitCode !== 0)
84
- throw new Error(`guide command installation failed: ${result.stderr.trim().slice(-2e3)}`);
85
- };
86
- const isGitUrl = (value) => /^(https?:\/\/|ssh:\/\/|git@)/.test(value);
87
- const repositoryPath = (alias) => `${WORKSPACE_ROOT}/${alias}`;
88
- const stepCwd = (cwd) => cwd === "." ? WORKSPACE_ROOT : repositoryPath(cwd);
89
- const runOrThrow = async (sandbox, label, options) => {
90
- const result = await sandbox.run(options);
91
- if (result.exitCode !== 0) {
92
- throw new Error(
93
- `${label} failed (exit ${result.exitCode}): ${result.stderr.trim().slice(-2e3)}`
94
- );
95
- }
96
- };
97
- const mountRepositories = async (args) => {
98
- for (const repository of args.repositories) {
99
- const destination = repositoryPath(repository.alias);
100
- if (await args.sandbox.stat({ path: `${destination}/.git` }) != null) {
101
- await runOrThrow(args.sandbox, `existing checkout ${repository.alias}`, {
102
- command: `git -C ${shellQuote(destination)} rev-parse --verify HEAD`,
103
- shell: true,
104
- cwd: "/",
105
- timeoutMs: 3e4
106
- });
107
- continue;
108
- }
109
- const source = await args.resolver.cloneSource({
110
- repository: repository.repository,
111
- ref: repository.ref
112
- }) ?? (isGitUrl(repository.repository) ? { url: repository.repository, ref: repository.ref, authorization: null } : null);
113
- if (source == null) {
114
- throw new Error(
115
- `repository ${repository.repository} (${repository.alias}) cannot be resolved to a clone source`
116
- );
117
- }
118
- const env = source.authorization == null ? {} : {
119
- GIT_CONFIG_COUNT: "1",
120
- GIT_CONFIG_KEY_0: "http.extraHeader",
121
- GIT_CONFIG_VALUE_0: `Authorization: ${source.authorization}`
122
- };
123
- const checkout = source.ref == null ? "" : ` && git -C ${shellQuote(destination)} checkout --quiet ${shellQuote(source.ref)}`;
124
- args.log("computer_sandbox.repository_clone", { alias: repository.alias });
125
- await runOrThrow(args.sandbox, `clone ${repository.alias}`, {
126
- command: `set -eu; mkdir -p ${WORKSPACE_ROOT}; git clone --quiet -- ${shellQuote(source.url)} ${shellQuote(destination)}${checkout} && git -C ${shellQuote(destination)} rev-parse --verify HEAD`,
127
- shell: true,
128
- cwd: "/",
129
- env: { GIT_TERMINAL_PROMPT: "0", ...env },
130
- timeoutMs: 20 * 6e4
131
- });
132
- }
133
- };
134
- const aliasMissing = async (sandbox, cwd) => cwd !== "." && await sandbox.stat({ path: repositoryPath(cwd) }) == null;
135
- const runWorkspaceSetup = async (args) => {
136
- const steps = args.template.workspace.setup;
137
- if (steps.length === 0) return null;
138
- const hash = (await sha256Hex(
139
- canonicalJson({
140
- steps,
141
- repositories: args.repositories.map((repository) => [
142
- repository.alias,
143
- repository.repository,
144
- repository.ref
145
- ])
146
- })
147
- )).slice(0, 24);
148
- const marker = `${SETUP_MARKER_ROOT}/${hash}`;
149
- if (await args.sandbox.stat({ path: marker }) != null) return hash;
150
- for (const [index, step] of steps.entries()) {
151
- if (await aliasMissing(args.sandbox, step.cwd)) {
152
- if (step.whenMissing === TemplateWhenMissing.Fail) {
153
- throw new Error(
154
- `workspace setup step ${index + 1} needs /workspaces/${step.cwd}, which is missing`
155
- );
156
- }
157
- continue;
158
- }
159
- args.log("computer_sandbox.setup_step", { index });
160
- try {
161
- await runOrThrow(args.sandbox, `workspace setup step ${index + 1}`, {
162
- command: `set -eu
163
- ${step.run}`,
164
- shell: true,
165
- cwd: stepCwd(step.cwd),
166
- timeoutMs: step.timeoutMinutes * 6e4
167
- });
168
- } catch (error) {
169
- if (step.required) throw error;
170
- args.log("computer_sandbox.setup_step_failed", { index, required: false });
171
- }
172
- }
173
- await args.sandbox.writeTextFile({ path: marker, content: (/* @__PURE__ */ new Date()).toISOString() });
174
- return hash;
175
- };
176
- const readyScript = (url, timeoutSeconds) => `
177
- end=$(( $(date +%s) + ${timeoutSeconds} ))
178
- while :; do
179
- code=$(curl -s -o /dev/null -w '%{http_code}' ${shellQuote(url)} || true)
180
- if [ "$code" -ge 200 ] 2>/dev/null && [ "$code" -lt 500 ]; then exit 0; fi
181
- if [ "$(date +%s)" -ge "$end" ]; then exit 1; fi
182
- sleep 2
183
- done`;
184
- const startServices = async (args) => {
185
- const started = [];
186
- for (const service of args.template.services) {
187
- if (await aliasMissing(args.sandbox, service.cwd)) {
188
- if (service.whenMissing === TemplateWhenMissing.Fail) {
189
- throw new Error(
190
- `service ${service.name} needs /workspaces/${service.cwd}, which is missing`
191
- );
192
- }
193
- continue;
194
- }
195
- await args.transport.exec({
196
- id: args.randomUuid(),
197
- command: `exec bash -lc ${shellQuote(service.run)}`,
198
- cwd: stepCwd(service.cwd),
199
- env: args.env,
200
- timeoutMs: null
201
- });
202
- started.push(service.name);
203
- args.log("computer_sandbox.service_started", { service: service.name });
204
- }
205
- await Promise.all(
206
- args.template.services.filter((service) => service.ready != null && started.includes(service.name)).map(async (service) => {
207
- const ready = service.ready;
208
- if (ready == null) return;
209
- const result = await args.sandbox.run({
210
- command: readyScript(ready.url, ready.timeoutSeconds),
211
- shell: true,
212
- cwd: "/",
213
- timeoutMs: (ready.timeoutSeconds + 30) * 1e3
214
- });
215
- if (result.exitCode === 0) {
216
- args.log("computer_sandbox.service_ready", { service: service.name });
217
- return;
218
- }
219
- if (service.required) {
220
- throw new Error(
221
- `service ${service.name} was not ready at ${ready.url} within ${ready.timeoutSeconds} s`
222
- );
223
- }
224
- args.log("computer_sandbox.service_ready_timeout", {
225
- service: service.name,
226
- required: false
227
- });
228
- })
229
- );
230
- return started;
231
- };
232
- export {
233
- GUIDE_COMMAND_PROTOCOL,
234
- WORKSPACE_ROOT,
235
- guideCommands,
236
- installGuideCommands,
237
- mountRepositories,
238
- repositoryPath,
239
- runWorkspaceSetup,
240
- startServices
241
- };
242
- //# sourceMappingURL=workspace-setup.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/sandboxes/workspace-setup.ts"],
4
- "sourcesContent": ["import type {\n NetworkSandboxSessionIface,\n SandboxRepositoriesIface,\n SandboxRepositoryCloneSourceIface,\n} from '@finalai/agent-provider/sandbox';\nimport { canonicalJson, sha256Hex } from \"./bytes.mjs\";\nimport {\n TemplateWhenMissing,\n type ComputerRepositoryIface,\n type ComputerTemplateIface,\n} from \"./environment.mjs\";\nimport { shellQuote } from \"./paths.mjs\";\nimport type { SandboxTransportIface } from \"./transport.mjs\";\n\n// Start-time inputs: repositories, named commands, setup once per workspace and services.\n\nexport const WORKSPACE_ROOT = '/workspaces';\nconst SETUP_MARKER_ROOT = '/workspaces/.final/setup';\n\nexport interface GuideCommandIface {\n name: string;\n path: string;\n description: string | null;\n cwd: string;\n timeoutMs: number;\n}\n\nexport const guideCommands = async (\n template: ComputerTemplateIface,\n): Promise<GuideCommandIface[]> => {\n const hash = await sha256Hex(canonicalJson(template.commands));\n return Object.entries(template.commands).map(([name, command]) => ({\n name,\n path: `${WORKSPACE_ROOT}/.final/commands/${hash}/${name}`,\n description: command.description,\n cwd: stepCwd(command.cwd),\n timeoutMs: command.timeoutMinutes * 60_000,\n }));\n};\n\n// Pin directories and publish complete scripts without following workspace symlinks.\nexport const GUIDE_COMMAND_PROTOCOL = 'guide-command-v1';\nconst INSTALL_GUIDE_COMMANDS_SCRIPT = `# ${GUIDE_COMMAND_PROTOCOL}\nimport json, os, stat, sys, uuid\np = json.load(sys.stdin)\nflags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW\nroot = os.open('/', flags)\ntry:\n for part in p['root'].split('/'):\n if not part:\n continue\n if part in ('.', '..'):\n raise ValueError('invalid command root')\n try:\n os.mkdir(part, dir_fd=root)\n except FileExistsError:\n pass\n child = os.open(part, flags, dir_fd=root)\n os.close(root)\n root = child\n for name, content in p['files'].items():\n if '/' in name or name in ('.', '..'):\n raise ValueError('invalid command name')\n temporary = '.command-' + uuid.uuid4().hex\n try:\n fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o700, dir_fd=root)\n with os.fdopen(fd, 'wb') as f:\n f.write(content.encode('utf-8'))\n try:\n os.link(temporary, name, src_dir_fd=root, dst_dir_fd=root, follow_symlinks=False)\n except FileExistsError:\n fd = os.open(name, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=root)\n with os.fdopen(fd, 'rb') as f:\n if not stat.S_ISREG(os.fstat(f.fileno()).st_mode) or f.read(len(content.encode('utf-8')) + 1) != content.encode('utf-8'):\n raise ValueError('guide command differs from its pinned source')\n finally:\n os.unlink(temporary, dir_fd=root)\nfinally:\n os.close(root)\n`;\n\nexport const installGuideCommands = async (args: {\n sandbox: Pick<NetworkSandboxSessionIface, 'run'>;\n template: ComputerTemplateIface;\n}): Promise<void> => {\n const commands = await guideCommands(args.template);\n const first = commands[0];\n if (first == null) return;\n const files: Record<string, string> = {};\n for (const command of commands) {\n const source = args.template.commands[command.name];\n if (source == null) throw new Error('guide command source is missing');\n const missingExit = source.whenMissing === TemplateWhenMissing.Fail ? 1 : 0;\n files[command.name] =\n `#!/bin/bash\\nset -eu\\nif [ ! -d ${shellQuote(command.cwd)} ]; then\\n printf '%s\\\\n' ${shellQuote(`guide command ${command.name}: missing ${command.cwd}`)} >&2\\n exit ${missingExit}\\nfi\\ncd -- ${shellQuote(command.cwd)}\\nexec timeout --signal=TERM --kill-after=10s ${source.timeoutMinutes * 60}s bash -c ${shellQuote(source.run)} ${shellQuote(command.name)} \"$@\"\\n`;\n }\n const result = await args.sandbox.run({\n command: 'python3',\n args: ['-c', INSTALL_GUIDE_COMMANDS_SCRIPT],\n cwd: '/',\n stdin: JSON.stringify({ root: first.path.slice(0, first.path.lastIndexOf('/')), files }),\n timeoutMs: 60_000,\n });\n if (result.exitCode !== 0)\n throw new Error(`guide command installation failed: ${result.stderr.trim().slice(-2000)}`);\n};\n\nexport type RepositoryCloneSourceIface = SandboxRepositoryCloneSourceIface;\n\nexport interface SetupLogIface {\n (message: string, fields?: Record<string, string | number | boolean | null>): void;\n}\n\nconst isGitUrl = (value: string): boolean => /^(https?:\\/\\/|ssh:\\/\\/|git@)/.test(value);\n\nexport const repositoryPath = (alias: string): string => `${WORKSPACE_ROOT}/${alias}`;\n\nconst stepCwd = (cwd: string): string => (cwd === '.' ? WORKSPACE_ROOT : repositoryPath(cwd));\n\nconst runOrThrow = async (\n sandbox: Pick<NetworkSandboxSessionIface, 'run'>,\n label: string,\n options: Parameters<NetworkSandboxSessionIface['run']>[0],\n): Promise<void> => {\n const result = await sandbox.run(options);\n if (result.exitCode !== 0) {\n throw new Error(\n `${label} failed (exit ${result.exitCode}): ${result.stderr.trim().slice(-2000)}`,\n );\n }\n};\n\nexport const mountRepositories = async (args: {\n sandbox: NetworkSandboxSessionIface;\n repositories: ComputerRepositoryIface[];\n // The contract's repository credentials (the start context's `repositories`).\n resolver: SandboxRepositoriesIface;\n log: SetupLogIface;\n}): Promise<void> => {\n for (const repository of args.repositories) {\n const destination = repositoryPath(repository.alias);\n if ((await args.sandbox.stat({ path: `${destination}/.git` })) != null) {\n await runOrThrow(args.sandbox, `existing checkout ${repository.alias}`, {\n command: `git -C ${shellQuote(destination)} rev-parse --verify HEAD`,\n shell: true,\n cwd: '/',\n timeoutMs: 30_000,\n });\n continue;\n }\n const source =\n (await args.resolver.cloneSource({\n repository: repository.repository,\n ref: repository.ref,\n })) ??\n (isGitUrl(repository.repository)\n ? { url: repository.repository, ref: repository.ref, authorization: null }\n : null);\n if (source == null) {\n throw new Error(\n `repository ${repository.repository} (${repository.alias}) cannot be resolved to a clone source`,\n );\n }\n // GIT_CONFIG_* applies the header for this process only.\n const env: Record<string, string> =\n source.authorization == null\n ? {}\n : {\n GIT_CONFIG_COUNT: '1',\n GIT_CONFIG_KEY_0: 'http.extraHeader',\n GIT_CONFIG_VALUE_0: `Authorization: ${source.authorization}`,\n };\n const checkout =\n source.ref == null\n ? ''\n : ` && git -C ${shellQuote(destination)} checkout --quiet ${shellQuote(source.ref)}`;\n args.log('computer_sandbox.repository_clone', { alias: repository.alias });\n await runOrThrow(args.sandbox, `clone ${repository.alias}`, {\n command: `set -eu; mkdir -p ${WORKSPACE_ROOT}; git clone --quiet -- ${shellQuote(source.url)} ${shellQuote(destination)}${checkout} && git -C ${shellQuote(destination)} rev-parse --verify HEAD`,\n shell: true,\n cwd: '/',\n env: { GIT_TERMINAL_PROMPT: '0', ...env },\n timeoutMs: 20 * 60_000,\n });\n }\n};\n\nconst aliasMissing = async (sandbox: NetworkSandboxSessionIface, cwd: string): Promise<boolean> =>\n cwd !== '.' && (await sandbox.stat({ path: repositoryPath(cwd) })) == null;\n\nexport const runWorkspaceSetup = async (args: {\n sandbox: NetworkSandboxSessionIface;\n template: ComputerTemplateIface;\n repositories: ComputerRepositoryIface[];\n log: SetupLogIface;\n}): Promise<string | null> => {\n const steps = args.template.workspace.setup;\n if (steps.length === 0) return null;\n const hash = (\n await sha256Hex(\n canonicalJson({\n steps,\n repositories: args.repositories.map((repository) => [\n repository.alias,\n repository.repository,\n repository.ref,\n ]),\n }),\n )\n ).slice(0, 24);\n const marker = `${SETUP_MARKER_ROOT}/${hash}`;\n if ((await args.sandbox.stat({ path: marker })) != null) return hash;\n for (const [index, step] of steps.entries()) {\n if (await aliasMissing(args.sandbox, step.cwd)) {\n if (step.whenMissing === TemplateWhenMissing.Fail) {\n throw new Error(\n `workspace setup step ${index + 1} needs /workspaces/${step.cwd}, which is missing`,\n );\n }\n continue;\n }\n args.log('computer_sandbox.setup_step', { index });\n try {\n await runOrThrow(args.sandbox, `workspace setup step ${index + 1}`, {\n command: `set -eu\\n${step.run}`,\n shell: true,\n cwd: stepCwd(step.cwd),\n timeoutMs: step.timeoutMinutes * 60_000,\n });\n } catch (error) {\n if (step.required) throw error;\n args.log('computer_sandbox.setup_step_failed', { index, required: false });\n }\n }\n await args.sandbox.writeTextFile({ path: marker, content: new Date().toISOString() });\n return hash;\n};\n\nconst readyScript = (url: string, timeoutSeconds: number): string => `\nend=$(( $(date +%s) + ${timeoutSeconds} ))\nwhile :; do\n code=$(curl -s -o /dev/null -w '%{http_code}' ${shellQuote(url)} || true)\n if [ \"$code\" -ge 200 ] 2>/dev/null && [ \"$code\" -lt 500 ]; then exit 0; fi\n if [ \"$(date +%s)\" -ge \"$end\" ]; then exit 1; fi\n sleep 2\ndone`;\n\n// Starts each service as a managed process (not followed, so nothing polls its\n// output) and waits for the required ones to answer their ready check.\nexport const startServices = async (args: {\n sandbox: NetworkSandboxSessionIface;\n transport: SandboxTransportIface;\n template: ComputerTemplateIface;\n env: Record<string, string>;\n randomUuid: () => string;\n log: SetupLogIface;\n}): Promise<string[]> => {\n const started: string[] = [];\n for (const service of args.template.services) {\n if (await aliasMissing(args.sandbox, service.cwd)) {\n if (service.whenMissing === TemplateWhenMissing.Fail) {\n throw new Error(\n `service ${service.name} needs /workspaces/${service.cwd}, which is missing`,\n );\n }\n continue;\n }\n await args.transport.exec({\n id: args.randomUuid(),\n command: `exec bash -lc ${shellQuote(service.run)}`,\n cwd: stepCwd(service.cwd),\n env: args.env,\n timeoutMs: null,\n });\n started.push(service.name);\n args.log('computer_sandbox.service_started', { service: service.name });\n }\n await Promise.all(\n args.template.services\n .filter((service) => service.ready != null && started.includes(service.name))\n .map(async (service) => {\n const ready = service.ready;\n if (ready == null) return;\n const result = await args.sandbox.run({\n command: readyScript(ready.url, ready.timeoutSeconds),\n shell: true,\n cwd: '/',\n timeoutMs: (ready.timeoutSeconds + 30) * 1000,\n });\n if (result.exitCode === 0) {\n args.log('computer_sandbox.service_ready', { service: service.name });\n return;\n }\n if (service.required) {\n throw new Error(\n `service ${service.name} was not ready at ${ready.url} within ${ready.timeoutSeconds} s`,\n );\n }\n args.log('computer_sandbox.service_ready_timeout', {\n service: service.name,\n required: false,\n });\n }),\n );\n return started;\n};\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,9 +0,0 @@
1
- import { type OpenHarnessSessionArgsIface, type ResolvedAgentManifestIface, type SandboxTargetEndpointIface } from '@finalai/agent-provider';
2
- export declare const SESSION_ID = "0192f7a0-0000-7000-8000-000000000001";
3
- export declare const HARNESS_SESSION_ID = "0192f7a0-0000-7000-8000-0000000000aa";
4
- export declare const EXPIRES_AT = "2026-10-10T00:15:00.000Z";
5
- export declare const computerEndpoint: SandboxTargetEndpointIface;
6
- export declare const deviceEndpoint: SandboxTargetEndpointIface;
7
- export declare const resolvedManifest: () => ResolvedAgentManifestIface;
8
- export declare const openArgs: (config: unknown, secrets?: Record<string, string>) => OpenHarnessSessionArgsIface;
9
- export declare const idSequence: (prefix: string) => (() => string);
@@ -1,123 +0,0 @@
1
- import {
2
- BaseCapability,
3
- CredentialRoute,
4
- credentials,
5
- jsonObjectSchema,
6
- MANIFEST_VERSION,
7
- packageRef,
8
- ToolApproval
9
- } from "@finalai/agent-provider";
10
- const SESSION_ID = "0192f7a0-0000-7000-8000-000000000001";
11
- const HARNESS_SESSION_ID = "0192f7a0-0000-7000-8000-0000000000aa";
12
- const EXPIRES_AT = "2026-10-10T00:15:00.000Z";
13
- const computerEndpoint = {
14
- target: "computer",
15
- bindingId: "0192f7a0-0000-7000-8000-0000000000c1",
16
- capabilities: ["shell", "files", "process"],
17
- rpc: { url: "wss://agent-session.test/sandboxes/b/c1", token: "rpc-c1", expiresAt: EXPIRES_AT },
18
- mcp: {
19
- url: "https://agent-session.test/sandboxes/b/c1/mcp",
20
- token: "mcp-c1",
21
- expiresAt: EXPIRES_AT
22
- }
23
- };
24
- const deviceEndpoint = {
25
- target: "device",
26
- bindingId: "0192f7a0-0000-7000-8000-0000000000d1",
27
- capabilities: ["computerUse"],
28
- rpc: null,
29
- mcp: {
30
- url: "https://agent-session.test/sandboxes/b/d1/mcp",
31
- token: "mcp-d1",
32
- expiresAt: EXPIRES_AT
33
- }
34
- };
35
- const resolvedManifest = () => ({
36
- version: MANIFEST_VERSION,
37
- identity: { name: "Release Scout", description: null },
38
- harness: {
39
- harness: packageRef("@finalai/final-agent-provider/harnesses/serverless-pi"),
40
- config: {}
41
- },
42
- mcpServers: [],
43
- sandboxes: {},
44
- tools: {
45
- base: {
46
- shell: { target: "computer" },
47
- files: { target: "computer" },
48
- computerUse: { target: "device" }
49
- }
50
- },
51
- secrets: [],
52
- toolPolicy: {
53
- shell: ToolApproval.Ask,
54
- "files.write": ToolApproval.Ask,
55
- create_issue: ToolApproval.Allow
56
- },
57
- channels: [],
58
- hooks: [],
59
- schedules: [],
60
- bundle: null
61
- });
62
- const openArgs = (config, secrets = {}) => ({
63
- harnessSessionId: "0192f7a0-0000-7000-8000-0000000000a1",
64
- session: {
65
- sessionId: SESSION_ID,
66
- organizationId: "0192f7a0-0000-7000-8000-0000000000o1",
67
- definitionId: "0192f7a0-0000-7000-8000-0000000000e1",
68
- revisionId: "0192f7a0-0000-7000-8000-0000000000r1",
69
- sessionServiceUrl: "https://agent-session.test"
70
- },
71
- config: {
72
- credentials: credentials.chain({
73
- payer: "organization",
74
- tryInOrder: [credentials.apiKey({ owner: "organization" }), credentials.platform()]
75
- }),
76
- ...jsonObjectSchema.parse(config)
77
- },
78
- manifest: resolvedManifest(),
79
- mcpServers: [],
80
- baseTools: {
81
- [BaseCapability.Shell]: computerEndpoint,
82
- [BaseCapability.Files]: computerEndpoint,
83
- [BaseCapability.ComputerUse]: deviceEndpoint
84
- },
85
- sandboxes: { computer: computerEndpoint, device: deviceEndpoint },
86
- credentials: {
87
- brokerUrl: "https://credentials.example.com/provider",
88
- grants: [
89
- { route: CredentialRoute.Model, token: "grant-model", expiresAt: EXPIRES_AT },
90
- { route: CredentialRoute.Mcp, token: "grant-mcp", expiresAt: EXPIRES_AT }
91
- ],
92
- atOpen: null,
93
- refresh: {
94
- url: "https://credentials.example.com/provider/refresh",
95
- token: "grant-model",
96
- harnessSessionId: "0192f7a0-0000-7000-8000-0000000000a1",
97
- expiresAt: EXPIRES_AT
98
- }
99
- },
100
- secrets: { get: async (name) => secrets[name] ?? null },
101
- trace: {
102
- traceparent: "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
103
- tracestate: null
104
- }
105
- });
106
- const idSequence = (prefix) => {
107
- let next = 0;
108
- return () => {
109
- next += 1;
110
- return `${prefix}-7000-8000-${String(next).padStart(12, "0")}`;
111
- };
112
- };
113
- export {
114
- EXPIRES_AT,
115
- HARNESS_SESSION_ID,
116
- SESSION_ID,
117
- computerEndpoint,
118
- deviceEndpoint,
119
- idSequence,
120
- openArgs,
121
- resolvedManifest
122
- };
123
- //# sourceMappingURL=harness.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/testing/harness.ts"],
4
- "sourcesContent": ["import {\n BaseCapability,\n CredentialRoute,\n credentials,\n jsonObjectSchema,\n MANIFEST_VERSION,\n packageRef,\n ToolApproval,\n type OpenHarnessSessionArgsIface,\n type ResolvedAgentManifestIface,\n type SandboxTargetEndpointIface,\n} from '@finalai/agent-provider';\n\n// Shared fixtures for the harness tests (no module mocks: fakes go in through\n// each factory's fetch/now/newId seams).\n\nexport const SESSION_ID = '0192f7a0-0000-7000-8000-000000000001';\nexport const HARNESS_SESSION_ID = '0192f7a0-0000-7000-8000-0000000000aa';\nexport const EXPIRES_AT = '2026-10-10T00:15:00.000Z';\n\nexport const computerEndpoint: SandboxTargetEndpointIface = {\n target: 'computer',\n bindingId: '0192f7a0-0000-7000-8000-0000000000c1',\n capabilities: ['shell', 'files', 'process'],\n rpc: { url: 'wss://agent-session.test/sandboxes/b/c1', token: 'rpc-c1', expiresAt: EXPIRES_AT },\n mcp: {\n url: 'https://agent-session.test/sandboxes/b/c1/mcp',\n token: 'mcp-c1',\n expiresAt: EXPIRES_AT,\n },\n};\n\nexport const deviceEndpoint: SandboxTargetEndpointIface = {\n target: 'device',\n bindingId: '0192f7a0-0000-7000-8000-0000000000d1',\n capabilities: ['computerUse'],\n rpc: null,\n mcp: {\n url: 'https://agent-session.test/sandboxes/b/d1/mcp',\n token: 'mcp-d1',\n expiresAt: EXPIRES_AT,\n },\n};\n\nexport const resolvedManifest = (): ResolvedAgentManifestIface => ({\n version: MANIFEST_VERSION,\n identity: { name: 'Release Scout', description: null },\n harness: {\n harness: packageRef('@finalai/final-agent-provider/harnesses/serverless-pi'),\n config: {},\n },\n mcpServers: [],\n sandboxes: {},\n tools: {\n base: {\n shell: { target: 'computer' },\n files: { target: 'computer' },\n computerUse: { target: 'device' },\n },\n },\n secrets: [],\n toolPolicy: {\n shell: ToolApproval.Ask,\n 'files.write': ToolApproval.Ask,\n create_issue: ToolApproval.Allow,\n },\n channels: [],\n hooks: [],\n schedules: [],\n bundle: null,\n});\n\nexport const openArgs = (\n config: unknown,\n secrets: Record<string, string> = {},\n): OpenHarnessSessionArgsIface => ({\n harnessSessionId: '0192f7a0-0000-7000-8000-0000000000a1',\n session: {\n sessionId: SESSION_ID,\n organizationId: '0192f7a0-0000-7000-8000-0000000000o1',\n definitionId: '0192f7a0-0000-7000-8000-0000000000e1',\n revisionId: '0192f7a0-0000-7000-8000-0000000000r1',\n sessionServiceUrl: 'https://agent-session.test',\n },\n config: {\n credentials: credentials.chain({\n payer: 'organization',\n tryInOrder: [credentials.apiKey({ owner: 'organization' }), credentials.platform()],\n }),\n ...jsonObjectSchema.parse(config),\n },\n manifest: resolvedManifest(),\n mcpServers: [],\n baseTools: {\n [BaseCapability.Shell]: computerEndpoint,\n [BaseCapability.Files]: computerEndpoint,\n [BaseCapability.ComputerUse]: deviceEndpoint,\n },\n sandboxes: { computer: computerEndpoint, device: deviceEndpoint },\n credentials: {\n brokerUrl: 'https://credentials.example.com/provider',\n grants: [\n { route: CredentialRoute.Model, token: 'grant-model', expiresAt: EXPIRES_AT },\n { route: CredentialRoute.Mcp, token: 'grant-mcp', expiresAt: EXPIRES_AT },\n ],\n atOpen: null,\n refresh: {\n url: 'https://credentials.example.com/provider/refresh',\n token: 'grant-model',\n harnessSessionId: '0192f7a0-0000-7000-8000-0000000000a1',\n expiresAt: EXPIRES_AT,\n },\n },\n secrets: { get: async (name) => secrets[name] ?? null },\n trace: {\n traceparent: '00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01',\n tracestate: null,\n },\n});\n\n// Monotonic ids so assertions can name them.\nexport const idSequence = (prefix: string): (() => string) => {\n let next = 0;\n return () => {\n next += 1;\n return `${prefix}-7000-8000-${String(next).padStart(12, '0')}`;\n };\n};\n"],
5
- "mappings": "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",
6
- "names": []
7
- }