@openai/agents-extensions 0.8.5 → 0.9.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 (213) hide show
  1. package/dist/metadata.js +2 -2
  2. package/dist/metadata.mjs +2 -2
  3. package/dist/sandbox/blaxel/index.d.ts +2 -0
  4. package/dist/sandbox/blaxel/index.js +19 -0
  5. package/dist/sandbox/blaxel/index.js.map +1 -0
  6. package/dist/sandbox/blaxel/index.mjs +3 -0
  7. package/dist/sandbox/blaxel/index.mjs.map +1 -0
  8. package/dist/sandbox/blaxel/mounts.d.ts +101 -0
  9. package/dist/sandbox/blaxel/mounts.js +542 -0
  10. package/dist/sandbox/blaxel/mounts.js.map +1 -0
  11. package/dist/sandbox/blaxel/mounts.mjs +529 -0
  12. package/dist/sandbox/blaxel/mounts.mjs.map +1 -0
  13. package/dist/sandbox/blaxel/sandbox.d.ts +155 -0
  14. package/dist/sandbox/blaxel/sandbox.js +1110 -0
  15. package/dist/sandbox/blaxel/sandbox.js.map +1 -0
  16. package/dist/sandbox/blaxel/sandbox.mjs +1072 -0
  17. package/dist/sandbox/blaxel/sandbox.mjs.map +1 -0
  18. package/dist/sandbox/cloudflare/index.d.ts +2 -0
  19. package/dist/sandbox/cloudflare/index.js +19 -0
  20. package/dist/sandbox/cloudflare/index.js.map +1 -0
  21. package/dist/sandbox/cloudflare/index.mjs +3 -0
  22. package/dist/sandbox/cloudflare/index.mjs.map +1 -0
  23. package/dist/sandbox/cloudflare/mounts.d.ts +28 -0
  24. package/dist/sandbox/cloudflare/mounts.js +150 -0
  25. package/dist/sandbox/cloudflare/mounts.js.map +1 -0
  26. package/dist/sandbox/cloudflare/mounts.mjs +143 -0
  27. package/dist/sandbox/cloudflare/mounts.mjs.map +1 -0
  28. package/dist/sandbox/cloudflare/sandbox.d.ts +91 -0
  29. package/dist/sandbox/cloudflare/sandbox.js +1163 -0
  30. package/dist/sandbox/cloudflare/sandbox.js.map +1 -0
  31. package/dist/sandbox/cloudflare/sandbox.mjs +1125 -0
  32. package/dist/sandbox/cloudflare/sandbox.mjs.map +1 -0
  33. package/dist/sandbox/daytona/index.d.ts +2 -0
  34. package/dist/sandbox/daytona/index.js +19 -0
  35. package/dist/sandbox/daytona/index.js.map +1 -0
  36. package/dist/sandbox/daytona/index.mjs +3 -0
  37. package/dist/sandbox/daytona/index.mjs.map +1 -0
  38. package/dist/sandbox/daytona/mounts.d.ts +11 -0
  39. package/dist/sandbox/daytona/mounts.js +17 -0
  40. package/dist/sandbox/daytona/mounts.js.map +1 -0
  41. package/dist/sandbox/daytona/mounts.mjs +12 -0
  42. package/dist/sandbox/daytona/mounts.mjs.map +1 -0
  43. package/dist/sandbox/daytona/sandbox.d.ts +160 -0
  44. package/dist/sandbox/daytona/sandbox.js +938 -0
  45. package/dist/sandbox/daytona/sandbox.js.map +1 -0
  46. package/dist/sandbox/daytona/sandbox.mjs +900 -0
  47. package/dist/sandbox/daytona/sandbox.mjs.map +1 -0
  48. package/dist/sandbox/e2b/index.d.ts +2 -0
  49. package/dist/sandbox/e2b/index.js +19 -0
  50. package/dist/sandbox/e2b/index.js.map +1 -0
  51. package/dist/sandbox/e2b/index.mjs +3 -0
  52. package/dist/sandbox/e2b/index.mjs.map +1 -0
  53. package/dist/sandbox/e2b/mounts.d.ts +11 -0
  54. package/dist/sandbox/e2b/mounts.js +17 -0
  55. package/dist/sandbox/e2b/mounts.js.map +1 -0
  56. package/dist/sandbox/e2b/mounts.mjs +12 -0
  57. package/dist/sandbox/e2b/mounts.mjs.map +1 -0
  58. package/dist/sandbox/e2b/sandbox.d.ts +169 -0
  59. package/dist/sandbox/e2b/sandbox.js +829 -0
  60. package/dist/sandbox/e2b/sandbox.js.map +1 -0
  61. package/dist/sandbox/e2b/sandbox.mjs +791 -0
  62. package/dist/sandbox/e2b/sandbox.mjs.map +1 -0
  63. package/dist/sandbox/modal/index.d.ts +2 -0
  64. package/dist/sandbox/modal/index.js +19 -0
  65. package/dist/sandbox/modal/index.js.map +1 -0
  66. package/dist/sandbox/modal/index.mjs +3 -0
  67. package/dist/sandbox/modal/index.mjs.map +1 -0
  68. package/dist/sandbox/modal/mounts.d.ts +24 -0
  69. package/dist/sandbox/modal/mounts.js +194 -0
  70. package/dist/sandbox/modal/mounts.js.map +1 -0
  71. package/dist/sandbox/modal/mounts.mjs +188 -0
  72. package/dist/sandbox/modal/mounts.mjs.map +1 -0
  73. package/dist/sandbox/modal/sandbox.d.ts +220 -0
  74. package/dist/sandbox/modal/sandbox.js +1621 -0
  75. package/dist/sandbox/modal/sandbox.js.map +1 -0
  76. package/dist/sandbox/modal/sandbox.mjs +1581 -0
  77. package/dist/sandbox/modal/sandbox.mjs.map +1 -0
  78. package/dist/sandbox/runloop/index.d.ts +2 -0
  79. package/dist/sandbox/runloop/index.js +19 -0
  80. package/dist/sandbox/runloop/index.js.map +1 -0
  81. package/dist/sandbox/runloop/index.mjs +3 -0
  82. package/dist/sandbox/runloop/index.mjs.map +1 -0
  83. package/dist/sandbox/runloop/mounts.d.ts +11 -0
  84. package/dist/sandbox/runloop/mounts.js +17 -0
  85. package/dist/sandbox/runloop/mounts.js.map +1 -0
  86. package/dist/sandbox/runloop/mounts.mjs +12 -0
  87. package/dist/sandbox/runloop/mounts.mjs.map +1 -0
  88. package/dist/sandbox/runloop/sandbox.d.ts +266 -0
  89. package/dist/sandbox/runloop/sandbox.js +1390 -0
  90. package/dist/sandbox/runloop/sandbox.js.map +1 -0
  91. package/dist/sandbox/runloop/sandbox.mjs +1346 -0
  92. package/dist/sandbox/runloop/sandbox.mjs.map +1 -0
  93. package/dist/sandbox/shared/archive.d.ts +34 -0
  94. package/dist/sandbox/shared/archive.js +397 -0
  95. package/dist/sandbox/shared/archive.js.map +1 -0
  96. package/dist/sandbox/shared/archive.mjs +389 -0
  97. package/dist/sandbox/shared/archive.mjs.map +1 -0
  98. package/dist/sandbox/shared/editor.d.ts +17 -0
  99. package/dist/sandbox/shared/editor.js +65 -0
  100. package/dist/sandbox/shared/editor.js.map +1 -0
  101. package/dist/sandbox/shared/editor.mjs +61 -0
  102. package/dist/sandbox/shared/editor.mjs.map +1 -0
  103. package/dist/sandbox/shared/environment.d.ts +1 -0
  104. package/dist/sandbox/shared/environment.js +13 -0
  105. package/dist/sandbox/shared/environment.js.map +1 -0
  106. package/dist/sandbox/shared/environment.mjs +2 -0
  107. package/dist/sandbox/shared/environment.mjs.map +1 -0
  108. package/dist/sandbox/shared/git.d.ts +4 -0
  109. package/dist/sandbox/shared/git.js +20 -0
  110. package/dist/sandbox/shared/git.js.map +1 -0
  111. package/dist/sandbox/shared/git.mjs +17 -0
  112. package/dist/sandbox/shared/git.mjs.map +1 -0
  113. package/dist/sandbox/shared/inContainerMounts.d.ts +40 -0
  114. package/dist/sandbox/shared/inContainerMounts.js +670 -0
  115. package/dist/sandbox/shared/inContainerMounts.js.map +1 -0
  116. package/dist/sandbox/shared/inContainerMounts.mjs +662 -0
  117. package/dist/sandbox/shared/inContainerMounts.mjs.map +1 -0
  118. package/dist/sandbox/shared/index.d.ts +23 -0
  119. package/dist/sandbox/shared/index.js +112 -0
  120. package/dist/sandbox/shared/index.js.map +1 -0
  121. package/dist/sandbox/shared/index.mjs +18 -0
  122. package/dist/sandbox/shared/index.mjs.map +1 -0
  123. package/dist/sandbox/shared/localSources.d.ts +8 -0
  124. package/dist/sandbox/shared/localSources.js +378 -0
  125. package/dist/sandbox/shared/localSources.js.map +1 -0
  126. package/dist/sandbox/shared/localSources.mjs +372 -0
  127. package/dist/sandbox/shared/localSources.mjs.map +1 -0
  128. package/dist/sandbox/shared/manifest.d.ts +38 -0
  129. package/dist/sandbox/shared/manifest.js +254 -0
  130. package/dist/sandbox/shared/manifest.js.map +1 -0
  131. package/dist/sandbox/shared/manifest.mjs +233 -0
  132. package/dist/sandbox/shared/manifest.mjs.map +1 -0
  133. package/dist/sandbox/shared/media.d.ts +1 -0
  134. package/dist/sandbox/shared/media.js +10 -0
  135. package/dist/sandbox/shared/media.js.map +1 -0
  136. package/dist/sandbox/shared/media.mjs +2 -0
  137. package/dist/sandbox/shared/media.mjs.map +1 -0
  138. package/dist/sandbox/shared/metadata.d.ts +7 -0
  139. package/dist/sandbox/shared/metadata.js +87 -0
  140. package/dist/sandbox/shared/metadata.js.map +1 -0
  141. package/dist/sandbox/shared/metadata.mjs +81 -0
  142. package/dist/sandbox/shared/metadata.mjs.map +1 -0
  143. package/dist/sandbox/shared/output.d.ts +1 -0
  144. package/dist/sandbox/shared/output.js +8 -0
  145. package/dist/sandbox/shared/output.js.map +1 -0
  146. package/dist/sandbox/shared/output.mjs +2 -0
  147. package/dist/sandbox/shared/output.mjs.map +1 -0
  148. package/dist/sandbox/shared/paths.d.ts +27 -0
  149. package/dist/sandbox/shared/paths.js +245 -0
  150. package/dist/sandbox/shared/paths.js.map +1 -0
  151. package/dist/sandbox/shared/paths.mjs +236 -0
  152. package/dist/sandbox/shared/paths.mjs.map +1 -0
  153. package/dist/sandbox/shared/ports.d.ts +14 -0
  154. package/dist/sandbox/shared/ports.js +75 -0
  155. package/dist/sandbox/shared/ports.js.map +1 -0
  156. package/dist/sandbox/shared/ports.mjs +69 -0
  157. package/dist/sandbox/shared/ports.mjs.map +1 -0
  158. package/dist/sandbox/shared/process.d.ts +16 -0
  159. package/dist/sandbox/shared/process.js +90 -0
  160. package/dist/sandbox/shared/process.js.map +1 -0
  161. package/dist/sandbox/shared/process.mjs +86 -0
  162. package/dist/sandbox/shared/process.mjs.map +1 -0
  163. package/dist/sandbox/shared/pty.d.ts +81 -0
  164. package/dist/sandbox/shared/pty.js +382 -0
  165. package/dist/sandbox/shared/pty.js.map +1 -0
  166. package/dist/sandbox/shared/pty.mjs +335 -0
  167. package/dist/sandbox/shared/pty.mjs.map +1 -0
  168. package/dist/sandbox/shared/runAs.d.ts +46 -0
  169. package/dist/sandbox/shared/runAs.js +149 -0
  170. package/dist/sandbox/shared/runAs.js.map +1 -0
  171. package/dist/sandbox/shared/runAs.mjs +141 -0
  172. package/dist/sandbox/shared/runAs.mjs.map +1 -0
  173. package/dist/sandbox/shared/session.d.ts +16 -0
  174. package/dist/sandbox/shared/session.js +138 -0
  175. package/dist/sandbox/shared/session.js.map +1 -0
  176. package/dist/sandbox/shared/session.mjs +128 -0
  177. package/dist/sandbox/shared/session.mjs.map +1 -0
  178. package/dist/sandbox/shared/sessionBase.d.ts +90 -0
  179. package/dist/sandbox/shared/sessionBase.js +446 -0
  180. package/dist/sandbox/shared/sessionBase.js.map +1 -0
  181. package/dist/sandbox/shared/sessionBase.mjs +442 -0
  182. package/dist/sandbox/shared/sessionBase.mjs.map +1 -0
  183. package/dist/sandbox/shared/sessionState.d.ts +7 -0
  184. package/dist/sandbox/shared/sessionState.js +35 -0
  185. package/dist/sandbox/shared/sessionState.js.map +1 -0
  186. package/dist/sandbox/shared/sessionState.mjs +31 -0
  187. package/dist/sandbox/shared/sessionState.mjs.map +1 -0
  188. package/dist/sandbox/shared/snapshots.d.ts +9 -0
  189. package/dist/sandbox/shared/snapshots.js +62 -0
  190. package/dist/sandbox/shared/snapshots.js.map +1 -0
  191. package/dist/sandbox/shared/snapshots.mjs +57 -0
  192. package/dist/sandbox/shared/snapshots.mjs.map +1 -0
  193. package/dist/sandbox/shared/typeGuards.d.ts +10 -0
  194. package/dist/sandbox/shared/typeGuards.js +50 -0
  195. package/dist/sandbox/shared/typeGuards.js.map +1 -0
  196. package/dist/sandbox/shared/typeGuards.mjs +38 -0
  197. package/dist/sandbox/shared/typeGuards.mjs.map +1 -0
  198. package/dist/sandbox/shared/types.d.ts +24 -0
  199. package/dist/sandbox/shared/types.js +3 -0
  200. package/dist/sandbox/shared/types.js.map +1 -0
  201. package/dist/sandbox/shared/types.mjs +2 -0
  202. package/dist/sandbox/shared/types.mjs.map +1 -0
  203. package/dist/sandbox/vercel/index.d.ts +1 -0
  204. package/dist/sandbox/vercel/index.js +18 -0
  205. package/dist/sandbox/vercel/index.js.map +1 -0
  206. package/dist/sandbox/vercel/index.mjs +2 -0
  207. package/dist/sandbox/vercel/index.mjs.map +1 -0
  208. package/dist/sandbox/vercel/sandbox.d.ts +135 -0
  209. package/dist/sandbox/vercel/sandbox.js +1001 -0
  210. package/dist/sandbox/vercel/sandbox.js.map +1 -0
  211. package/dist/sandbox/vercel/sandbox.mjs +963 -0
  212. package/dist/sandbox/vercel/sandbox.mjs.map +1 -0
  213. package/package.json +108 -4
@@ -0,0 +1,1346 @@
1
+ import { UserError } from '@openai/agents-core';
2
+ import { SandboxConfigurationError, SandboxProviderError, SandboxUnsupportedFeatureError, normalizeSandboxClientCreateArgs, } from '@openai/agents-core/sandbox';
3
+ import { posix as pathPosix } from 'node:path';
4
+ import { assertCoreSnapshotUnsupported, assertTarWorkspacePersistence, assertResumeRecreateAllowed, assertRunAsUnsupported, assertSandboxManifestMetadataSupported, SANDBOX_MANIFEST_METADATA_SUPPORT, closeRemoteSessionOnManifestError, cloneManifestWithRoot, decodeNativeSnapshotRef, assertShellEnvironmentName, deserializeRemoteSandboxSessionStateValues, encodeNativeSnapshotRef, materializeEnvironment, serializeRemoteSandboxSessionState, shellQuote, isRecord, readOptionalNumber, readOptionalNumberArray, readOptionalRecord, readOptionalString, readOptionalStringRecord, readString, withProviderError, withSandboxSpan, RemoteSandboxSessionBase, } from "../shared/index.mjs";
5
+ import { mountRcloneCloudBucket, rclonePatternFromMountStrategy, unmountRcloneMount, } from "../shared/inContainerMounts.mjs";
6
+ import { isRunloopCloudBucketMountEntry } from "./mounts.mjs";
7
+ export const DEFAULT_RUNLOOP_WORKSPACE_ROOT = '/home/user';
8
+ export const DEFAULT_RUNLOOP_ROOT_WORKSPACE_ROOT = '/root';
9
+ const UNKNOWN_RUNLOOP_EXIT_CODE = 1;
10
+ const DEFAULT_RUNLOOP_TUNNEL_PARAMS = {
11
+ auth_mode: 'open',
12
+ http_keep_alive: true,
13
+ wake_on_http: false,
14
+ };
15
+ export class RunloopPlatformBlueprintsClient {
16
+ sdk;
17
+ constructor(sdk) {
18
+ this.sdk = sdk;
19
+ }
20
+ async list(params = {}) {
21
+ return await callRunloopPlatformMethod('blueprint.list', this.sdk.blueprint?.list, params);
22
+ }
23
+ async listPublic(params = {}) {
24
+ return await callRunloopPlatformMethod('api.blueprints.listPublic', this.sdk.api?.blueprints?.listPublic, params);
25
+ }
26
+ get(blueprintId) {
27
+ return callRunloopPlatformGetter('blueprint.fromId', this.sdk.blueprint?.fromId, blueprintId);
28
+ }
29
+ async logs(blueprintId, params = {}) {
30
+ return await callRunloopPlatformMethod('api.blueprints.logs', this.sdk.api?.blueprints?.logs, blueprintId, params);
31
+ }
32
+ async create(params = {}) {
33
+ return await callRunloopPlatformMethod('blueprint.create', this.sdk.blueprint?.create, params);
34
+ }
35
+ async awaitBuildComplete(blueprintId, params = {}) {
36
+ return await callRunloopPlatformMethod('api.blueprints.awaitBuildComplete', this.sdk.api?.blueprints?.awaitBuildComplete, blueprintId, params);
37
+ }
38
+ async delete(blueprintId, params = {}) {
39
+ return await callRunloopPlatformMethod('blueprint.delete', bindRunloopMethod(this.get(blueprintId), 'delete'), params);
40
+ }
41
+ }
42
+ export class RunloopPlatformBenchmarksClient {
43
+ sdk;
44
+ constructor(sdk) {
45
+ this.sdk = sdk;
46
+ }
47
+ async list(params = {}) {
48
+ return await callRunloopPlatformMethod('benchmark.list', this.sdk.benchmark?.list, params);
49
+ }
50
+ async listPublic(params = {}) {
51
+ return await callRunloopPlatformMethod('api.benchmarks.listPublic', this.sdk.api?.benchmarks?.listPublic, params);
52
+ }
53
+ get(benchmarkId) {
54
+ if (this.sdk.benchmark?.retrieve) {
55
+ return callRunloopPlatformMethod('benchmark.retrieve', this.sdk.benchmark.retrieve, benchmarkId);
56
+ }
57
+ return this.getBenchmarkFacade(benchmarkId);
58
+ }
59
+ async create(params = {}) {
60
+ return await callRunloopPlatformMethod('benchmark.create', this.sdk.benchmark?.create, params);
61
+ }
62
+ async update(benchmarkId, params = {}) {
63
+ if (this.sdk.benchmark?.update) {
64
+ return await callRunloopPlatformMethod('benchmark.update', this.sdk.benchmark.update, benchmarkId, params);
65
+ }
66
+ return await callRunloopPlatformMethod('benchmark.update', bindRunloopMethod(this.getBenchmarkFacade(benchmarkId), 'update'), params);
67
+ }
68
+ async definitions(benchmarkId, params = {}) {
69
+ return await callRunloopPlatformMethod('api.benchmarks.definitions', this.sdk.api?.benchmarks?.definitions, benchmarkId, params);
70
+ }
71
+ async startRun(benchmarkId, params = {}) {
72
+ if (this.sdk.benchmark?.startRun) {
73
+ return await callRunloopPlatformMethod('benchmark.startRun', this.sdk.benchmark.startRun, {
74
+ ...params,
75
+ benchmark_id: benchmarkId,
76
+ });
77
+ }
78
+ return await callRunloopPlatformMethod('benchmark.startRun', bindRunloopMethod(this.getBenchmarkFacade(benchmarkId), 'startRun'), params);
79
+ }
80
+ async updateScenarios(benchmarkId, params = {}) {
81
+ return await callRunloopPlatformMethod('api.benchmarks.updateScenarios', this.sdk.api?.benchmarks?.updateScenarios, benchmarkId, params);
82
+ }
83
+ getBenchmarkFacade(benchmarkId) {
84
+ return callRunloopPlatformGetter('benchmark.fromId', this.sdk.benchmark?.fromId, benchmarkId);
85
+ }
86
+ }
87
+ export class RunloopPlatformSecretsClient {
88
+ sdk;
89
+ constructor(sdk) {
90
+ this.sdk = sdk;
91
+ }
92
+ async create(params) {
93
+ return await callRunloopPlatformMethod('secret.create', this.sdk.secret?.create, params);
94
+ }
95
+ async list(params = {}) {
96
+ return await callRunloopPlatformMethod('secret.list', this.sdk.secret
97
+ ?.list, params);
98
+ }
99
+ async get(name, params = {}) {
100
+ return await callRunloopPlatformMethod('api.secrets.retrieve', this.sdk.api?.secrets?.retrieve, name, params);
101
+ }
102
+ async update(params) {
103
+ return await callRunloopPlatformMethod('secret.update', this.sdk.secret?.update, params.name, { value: params.value });
104
+ }
105
+ async delete(name, params = {}) {
106
+ return await callRunloopPlatformMethod('secret.delete', this.sdk.secret
107
+ ?.delete, name, params);
108
+ }
109
+ }
110
+ export class RunloopPlatformNetworkPoliciesClient {
111
+ sdk;
112
+ constructor(sdk) {
113
+ this.sdk = sdk;
114
+ }
115
+ async create(params = {}) {
116
+ return await callRunloopPlatformMethod('networkPolicy.create', this.sdk.networkPolicy?.create, params);
117
+ }
118
+ async list(params = {}) {
119
+ return await callRunloopPlatformMethod('networkPolicy.list', this.sdk.networkPolicy?.list, params);
120
+ }
121
+ get(networkPolicyId) {
122
+ return callRunloopPlatformGetter('networkPolicy.fromId', this.sdk.networkPolicy?.fromId, networkPolicyId);
123
+ }
124
+ async update(networkPolicyId, params = {}) {
125
+ return await callRunloopPlatformMethod('networkPolicy.update', bindRunloopMethod(this.get(networkPolicyId), 'update'), params);
126
+ }
127
+ async delete(networkPolicyId, params = {}) {
128
+ return await callRunloopPlatformMethod('networkPolicy.delete', bindRunloopMethod(this.get(networkPolicyId), 'delete'), params);
129
+ }
130
+ }
131
+ export class RunloopPlatformAxonsClient {
132
+ sdk;
133
+ constructor(sdk) {
134
+ this.sdk = sdk;
135
+ }
136
+ async create(params = {}) {
137
+ return await callRunloopPlatformMethod('axon.create', this.sdk.axon?.create, params);
138
+ }
139
+ async list(params = {}) {
140
+ return await callRunloopPlatformMethod('axon.list', this.sdk.axon?.list, params);
141
+ }
142
+ get(axonId) {
143
+ return callRunloopPlatformGetter('axon.fromId', this.sdk.axon?.fromId, axonId);
144
+ }
145
+ async publish(axonId, params = {}) {
146
+ return await callRunloopPlatformMethod('axon.publish', bindRunloopMethod(this.get(axonId), 'publish'), params);
147
+ }
148
+ async querySql(axonId, params = {}) {
149
+ const axon = this.get(axonId);
150
+ return await callRunloopPlatformMethod('axon.sql.query', bindRunloopMethod(axon.sql, 'query'), params);
151
+ }
152
+ async batchSql(axonId, params = {}) {
153
+ const axon = this.get(axonId);
154
+ return await callRunloopPlatformMethod('axon.sql.batch', bindRunloopMethod(axon.sql, 'batch'), params);
155
+ }
156
+ }
157
+ export class RunloopPlatformClient {
158
+ sdk;
159
+ constructor(sdk) {
160
+ this.sdk = sdk;
161
+ }
162
+ get blueprints() {
163
+ return new RunloopPlatformBlueprintsClient(this.sdk);
164
+ }
165
+ get benchmarks() {
166
+ return new RunloopPlatformBenchmarksClient(this.sdk);
167
+ }
168
+ get secrets() {
169
+ return new RunloopPlatformSecretsClient(this.sdk);
170
+ }
171
+ get networkPolicies() {
172
+ return new RunloopPlatformNetworkPoliciesClient(this.sdk);
173
+ }
174
+ get axons() {
175
+ return new RunloopPlatformAxonsClient(this.sdk);
176
+ }
177
+ }
178
+ export class RunloopSandboxSession extends RemoteSandboxSessionBase {
179
+ sdk;
180
+ devbox;
181
+ activeMountPaths = new Set();
182
+ constructor(args) {
183
+ super({
184
+ state: args.state,
185
+ options: {
186
+ providerName: 'RunloopSandboxClient',
187
+ providerId: 'runloop',
188
+ concurrencyLimits: args.concurrencyLimits,
189
+ },
190
+ });
191
+ this.sdk = args.sdk;
192
+ this.devbox = args.devbox;
193
+ }
194
+ supportsPty() {
195
+ return false;
196
+ }
197
+ exposedPortSource() {
198
+ return 'tunnel URL';
199
+ }
200
+ async resolveRemoteExposedPort(port) {
201
+ return await this.ensureTunnelUrl(port);
202
+ }
203
+ resolveManifestForApply(manifest) {
204
+ return resolveRunloopManifestRoot(manifest, this.state.userParameters, true);
205
+ }
206
+ async beforeApplyManifest(manifest) {
207
+ await this.ensureManifestRoot(manifest.root);
208
+ }
209
+ async persistWorkspace() {
210
+ const snapshot = await this.persistWorkspaceViaNativeSnapshot();
211
+ if (snapshot) {
212
+ return snapshot;
213
+ }
214
+ assertTarWorkspacePersistence('RunloopSandboxClient', 'tar');
215
+ return await this.persistWorkspaceTar();
216
+ }
217
+ async hydrateWorkspace(data) {
218
+ const snapshotRef = decodeNativeSnapshotRef(data);
219
+ if (snapshotRef?.provider === 'runloop') {
220
+ await this.replaceDevboxFromSnapshot(snapshotRef.snapshotId);
221
+ return;
222
+ }
223
+ assertTarWorkspacePersistence('RunloopSandboxClient', 'tar');
224
+ await this.hydrateWorkspaceTar(data);
225
+ }
226
+ async close() {
227
+ if (this.state.pauseOnExit) {
228
+ await withSandboxSpan('sandbox.stop', {
229
+ backend_id: 'runloop',
230
+ devbox_id: this.state.devboxId,
231
+ }, async () => {
232
+ await this.devbox.suspend(runloopRequestOptions(this.state.timeouts?.suspendTimeoutMs));
233
+ });
234
+ return;
235
+ }
236
+ await withSandboxSpan('sandbox.shutdown', {
237
+ backend_id: 'runloop',
238
+ devbox_id: this.state.devboxId,
239
+ }, async () => {
240
+ await this.unmountActiveMounts();
241
+ await this.devbox.shutdown(runloopRequestOptions(this.state.timeouts?.cleanupTimeoutMs));
242
+ });
243
+ }
244
+ async shutdown() {
245
+ await this.close();
246
+ }
247
+ async delete() {
248
+ await withSandboxSpan('sandbox.shutdown', {
249
+ backend_id: 'runloop',
250
+ devbox_id: this.state.devboxId,
251
+ }, async () => {
252
+ await this.unmountActiveMounts();
253
+ await this.devbox.shutdown(runloopRequestOptions(this.state.timeouts?.cleanupTimeoutMs));
254
+ });
255
+ }
256
+ async persistWorkspaceViaNativeSnapshot() {
257
+ if (this.nativeSnapshotRequiresTarFallback()) {
258
+ return undefined;
259
+ }
260
+ if (!this.devbox.snapshotDisk) {
261
+ return undefined;
262
+ }
263
+ let snapshot;
264
+ try {
265
+ const snapshotOptions = runloopLongPollOptions(this.state.timeouts?.snapshotTimeoutMs);
266
+ const snapshotParams = {
267
+ name: `sandbox-${this.state.devboxId}`,
268
+ metadata: {
269
+ openai_agents_devbox_id: this.state.devboxId,
270
+ },
271
+ };
272
+ snapshot = snapshotOptions
273
+ ? await this.devbox.snapshotDisk(snapshotParams, snapshotOptions)
274
+ : await this.devbox.snapshotDisk(snapshotParams);
275
+ }
276
+ catch (error) {
277
+ throw new SandboxProviderError('RunloopSandboxClient failed to create a native disk snapshot.', {
278
+ provider: 'runloop',
279
+ devboxId: this.state.devboxId,
280
+ cause: error instanceof Error ? error.message : String(error),
281
+ });
282
+ }
283
+ if (!snapshot.id) {
284
+ throw new SandboxProviderError('RunloopSandboxClient native disk snapshot did not return a snapshot id.', {
285
+ provider: 'runloop',
286
+ devboxId: this.state.devboxId,
287
+ });
288
+ }
289
+ return encodeNativeSnapshotRef({
290
+ provider: 'runloop',
291
+ snapshotId: snapshot.id,
292
+ });
293
+ }
294
+ nativeSnapshotRequiresTarFallback() {
295
+ return this.state.manifest.ephemeralPersistencePaths().size > 0;
296
+ }
297
+ async replaceDevboxFromSnapshot(snapshotId) {
298
+ if (!this.sdk.devbox.createFromSnapshot) {
299
+ throw new SandboxProviderError('RunloopSandboxClient native snapshot restore requires createFromSnapshot(snapshotId).', {
300
+ provider: 'runloop',
301
+ snapshotId,
302
+ });
303
+ }
304
+ const previousDevbox = this.devbox;
305
+ const previousActiveMountPaths = new Set(this.activeMountPaths);
306
+ let devbox;
307
+ try {
308
+ devbox = await this.sdk.devbox.createFromSnapshot(snapshotId, createRunloopParams(this.state, this.state.environment, {
309
+ includeBlueprint: false,
310
+ includeSecrets: false,
311
+ }), createRunloopOptions(this.state));
312
+ }
313
+ catch (error) {
314
+ throw new SandboxProviderError('RunloopSandboxClient failed to restore a native disk snapshot.', {
315
+ provider: 'runloop',
316
+ snapshotId,
317
+ cause: error instanceof Error ? error.message : String(error),
318
+ });
319
+ }
320
+ const previousDevboxId = this.state.devboxId;
321
+ this.devbox = devbox;
322
+ this.state.devboxId = devbox.id;
323
+ this.activeMountPaths.clear();
324
+ invalidateRunloopRuntimeCaches(this.state);
325
+ try {
326
+ await rematerializeRunloopManifestMounts(this, this.state.manifest);
327
+ }
328
+ catch (error) {
329
+ let replacementCleanupCause;
330
+ try {
331
+ await this.unmountActiveMounts();
332
+ }
333
+ catch (unmountError) {
334
+ replacementCleanupCause = errorMessage(unmountError);
335
+ }
336
+ try {
337
+ await devbox.shutdown();
338
+ }
339
+ catch (shutdownError) {
340
+ replacementCleanupCause = replacementCleanupCause
341
+ ? `${replacementCleanupCause}; ${errorMessage(shutdownError)}`
342
+ : errorMessage(shutdownError);
343
+ }
344
+ this.devbox = previousDevbox;
345
+ this.state.devboxId = previousDevboxId;
346
+ this.activeMountPaths.clear();
347
+ for (const mountPath of previousActiveMountPaths) {
348
+ this.activeMountPaths.add(mountPath);
349
+ }
350
+ invalidateRunloopRuntimeCaches(this.state);
351
+ throw new SandboxProviderError('RunloopSandboxClient native snapshot restore failed while rematerializing mounts.', {
352
+ provider: 'runloop',
353
+ devboxId: previousDevboxId,
354
+ replacementDevboxId: devbox.id,
355
+ snapshotId,
356
+ cause: errorMessage(error),
357
+ ...(replacementCleanupCause ? { replacementCleanupCause } : {}),
358
+ });
359
+ }
360
+ try {
361
+ await previousDevbox.shutdown();
362
+ }
363
+ catch (error) {
364
+ let replacementShutdownCause;
365
+ try {
366
+ await this.unmountActiveMounts();
367
+ }
368
+ catch (unmountError) {
369
+ replacementShutdownCause = errorMessage(unmountError);
370
+ }
371
+ try {
372
+ await devbox.shutdown();
373
+ }
374
+ catch (replacementShutdownError) {
375
+ replacementShutdownCause = replacementShutdownCause
376
+ ? `${replacementShutdownCause}; ${errorMessage(replacementShutdownError)}`
377
+ : errorMessage(replacementShutdownError);
378
+ }
379
+ this.devbox = previousDevbox;
380
+ this.state.devboxId = previousDevboxId;
381
+ this.activeMountPaths.clear();
382
+ for (const mountPath of previousActiveMountPaths) {
383
+ this.activeMountPaths.add(mountPath);
384
+ }
385
+ invalidateRunloopRuntimeCaches(this.state);
386
+ throw new SandboxProviderError('RunloopSandboxClient native snapshot restore created a replacement devbox, but shutting down the previous devbox failed.', {
387
+ provider: 'runloop',
388
+ devboxId: previousDevbox.id,
389
+ replacementDevboxId: devbox.id,
390
+ snapshotId,
391
+ cause: errorMessage(error),
392
+ ...(replacementShutdownCause ? { replacementShutdownCause } : {}),
393
+ });
394
+ }
395
+ }
396
+ manifestMetadataSupport() {
397
+ return SANDBOX_MANIFEST_METADATA_SUPPORT;
398
+ }
399
+ manifestMaterializationOptions() {
400
+ return {
401
+ materializeMount: this.materializeMountEntry.bind(this),
402
+ };
403
+ }
404
+ assertExecRunAs(_runAs) {
405
+ void _runAs;
406
+ }
407
+ assertFilesystemRunAs(_runAs) {
408
+ assertRunAsUnsupported('RunloopSandboxClient', _runAs);
409
+ }
410
+ async materializeMountEntry(absolutePath, entry) {
411
+ if (!isRunloopCloudBucketMountEntry(entry)) {
412
+ throw new SandboxUnsupportedFeatureError('RunloopSandboxClient only supports RunloopCloudBucketMountStrategy mount entries.', {
413
+ provider: 'runloop',
414
+ feature: 'entry.mountStrategy',
415
+ path: absolutePath,
416
+ mountType: entry.type,
417
+ strategyType: entry.mountStrategy?.type,
418
+ });
419
+ }
420
+ const mountPath = await this.resolveRemotePath(entry.mountPath ?? absolutePath, { forWrite: true });
421
+ await mountRcloneCloudBucket({
422
+ providerName: 'RunloopSandboxClient',
423
+ providerId: 'runloop',
424
+ strategyType: 'runloop_cloud_bucket',
425
+ entry,
426
+ mountPath,
427
+ pattern: rclonePatternFromMountStrategy(entry.mountStrategy),
428
+ runCommand: this.mountCommandRunner(),
429
+ writeFile: this.writeRemoteFile.bind(this),
430
+ packageManagers: ['apt'],
431
+ installRcloneViaScript: true,
432
+ });
433
+ this.activeMountPaths.add(mountPath);
434
+ }
435
+ async rematerializeManifestMounts(manifest) {
436
+ for (const { absolutePath, entry, } of manifest.mountTargetsForMaterialization()) {
437
+ await this.materializeMountEntry(absolutePath, structuredClone(entry));
438
+ }
439
+ }
440
+ async cleanupAfterFailedResume() {
441
+ await this.unmountActiveMounts().catch(() => { });
442
+ if (this.state.pauseOnExit) {
443
+ await this.devbox
444
+ .suspend(runloopRequestOptions(this.state.timeouts?.suspendTimeoutMs))
445
+ .catch(() => { });
446
+ return;
447
+ }
448
+ await this.devbox
449
+ .shutdown(runloopRequestOptions(this.state.timeouts?.cleanupTimeoutMs))
450
+ .catch(() => { });
451
+ }
452
+ async ensureCurrentManifestRoot() {
453
+ await this.ensureManifestRoot(this.state.manifest.root);
454
+ }
455
+ async unmountActiveMounts() {
456
+ for (const mountPath of [...this.activeMountPaths].reverse()) {
457
+ await unmountRcloneMount({
458
+ providerName: 'RunloopSandboxClient',
459
+ providerId: 'runloop',
460
+ mountPath,
461
+ runCommand: this.mountCommandRunner(),
462
+ }).catch(() => { });
463
+ this.activeMountPaths.delete(mountPath);
464
+ }
465
+ }
466
+ mountCommandRunner() {
467
+ return async (command, options = {}) => {
468
+ const result = await this.execShellWithEnvironment(command, undefined, options.timeoutMs ?? this.state.timeouts?.fastOperationTimeoutMs, mountCommandEnvironment(this.state.environment, options.user, this.state.userParameters), options.user);
469
+ return {
470
+ status: runloopExitStatus(result),
471
+ stdout: await result.stdout(),
472
+ stderr: await result.stderr(),
473
+ };
474
+ };
475
+ }
476
+ async ensureManifestRoot(root) {
477
+ const home = effectiveRunloopHome(this.state.userParameters);
478
+ const rootParent = root === home ? root : pathPosix.dirname(root);
479
+ const result = await this.execShellInWorkdir([
480
+ `home_real=$(cd -- ${shellQuote(home)} && pwd -P)`,
481
+ `root_ancestor=${shellQuote(rootParent)}`,
482
+ 'while [ ! -e "$root_ancestor" ]; do parent=$(dirname -- "$root_ancestor"); [ "$parent" = "$root_ancestor" ] && break; root_ancestor="$parent"; done',
483
+ 'ancestor_real=$(cd -- "$root_ancestor" && pwd -P)',
484
+ `printf 'OPENAI_AGENTS_REALPATH_HOME=%s\\nOPENAI_AGENTS_REALPATH_ANCESTOR=%s\\n' "$home_real" "$ancestor_real"`,
485
+ 'case "$ancestor_real" in "$home_real"|"$home_real"/*) ancestor_confined=1 ;; *) ancestor_confined=0 ;; esac',
486
+ `if [ "$home_real" = / ] || [ "$ancestor_confined" != 1 ]; then printf 'OPENAI_AGENTS_REALPATH_ROOT=%s\\n' ''; exit 0; fi`,
487
+ `mkdir -p -- ${shellQuote(root)}`,
488
+ `root_real=$(cd -- ${shellQuote(root)} && pwd -P)`,
489
+ `printf 'OPENAI_AGENTS_REALPATH_ROOT=%s\\n' "$root_real"`,
490
+ ].join(' && '), home, this.state.timeouts?.fastOperationTimeoutMs, {});
491
+ if (!runloopSucceeded(result)) {
492
+ throw new SandboxProviderError('RunloopSandboxClient failed to prepare the workspace root.', {
493
+ provider: 'runloop',
494
+ root,
495
+ exitCode: runloopExitStatus(result),
496
+ stderr: await result.stderr(),
497
+ });
498
+ }
499
+ assertRunloopManifestRootRealPath(root, home, await result.stdout());
500
+ }
501
+ async execShellWithEnvironment(command, workdir, timeoutMs, environment, user) {
502
+ return await this.execShellInWorkdir(command, this.resolveWorkdir(workdir), timeoutMs, environment, user);
503
+ }
504
+ async execShellInWorkdir(command, workdir, timeoutMs, environment, user) {
505
+ const shellCommand = buildShellCommand(command, environment, workdir, user, this.state.userParameters);
506
+ const params = {
507
+ last_n: '2000',
508
+ };
509
+ const options = runloopLongPollOptions(timeoutMs);
510
+ return options
511
+ ? await this.devbox.cmd.exec(shellCommand, params, options)
512
+ : await this.devbox.cmd.exec(shellCommand, params);
513
+ }
514
+ async runRemoteCommand(command, options) {
515
+ const result = await this.execShellInWorkdir(command, options.workdir, options.timeoutMs ?? this.timeoutForCommand(options), remoteCommandEnvironment(this.state.environment, options), options.runAs);
516
+ return {
517
+ status: runloopExitStatus(result),
518
+ stdout: await result.stdout(),
519
+ stderr: await result.stderr(),
520
+ };
521
+ }
522
+ async mkdirRemote(path) {
523
+ const result = await this.runRemoteCommand(`mkdir -p -- ${shellQuote(path)}`, {
524
+ kind: 'manifest',
525
+ workdir: this.state.manifest.root,
526
+ timeoutMs: this.state.timeouts?.fastOperationTimeoutMs,
527
+ });
528
+ this.assertRemoteCommandSucceeded(result, 'create directory', path);
529
+ }
530
+ async readRemoteText(path) {
531
+ return await this.devbox.file.read({
532
+ file_path: path,
533
+ });
534
+ }
535
+ async readRemoteFile(path) {
536
+ const downloadOptions = runloopRequestOptions(this.state.timeouts?.fileDownloadTimeoutMs);
537
+ const response = downloadOptions
538
+ ? await this.devbox.file.download({ path }, downloadOptions)
539
+ : await this.devbox.file.download({ path });
540
+ if (response.buffer) {
541
+ return Uint8Array.from(await response.buffer());
542
+ }
543
+ return new Uint8Array(await response.arrayBuffer());
544
+ }
545
+ async writeRemoteFile(path, content) {
546
+ const uploadOptions = runloopRequestOptions(this.state.timeouts?.fileUploadTimeoutMs);
547
+ const uploadParams = {
548
+ path,
549
+ file: new File([typeof content === 'string' ? content : Uint8Array.from(content)], basename(path)),
550
+ };
551
+ if (uploadOptions) {
552
+ await this.devbox.file.upload(uploadParams, uploadOptions);
553
+ }
554
+ else {
555
+ await this.devbox.file.upload(uploadParams);
556
+ }
557
+ }
558
+ async deleteRemotePath(path) {
559
+ const result = await this.runRemoteCommand(`rm -f -- ${shellQuote(path)}`, {
560
+ kind: 'manifest',
561
+ workdir: this.state.manifest.root,
562
+ timeoutMs: this.state.timeouts?.fastOperationTimeoutMs,
563
+ });
564
+ this.assertRemoteCommandSucceeded(result, 'delete path', path);
565
+ }
566
+ assertRemoteCommandSucceeded(result, operation, path) {
567
+ if (result.status === 0) {
568
+ return;
569
+ }
570
+ throw new SandboxProviderError(`RunloopSandboxClient failed to ${operation}.`, {
571
+ provider: 'runloop',
572
+ operation,
573
+ devboxId: this.state.devboxId,
574
+ path,
575
+ exitCode: result.status,
576
+ stdout: result.stdout ?? '',
577
+ stderr: result.stderr ?? '',
578
+ });
579
+ }
580
+ timeoutForCommand(options) {
581
+ if (options.kind === 'exec') {
582
+ return this.state.timeouts?.execTimeoutMs;
583
+ }
584
+ if (options.kind === 'running') {
585
+ return this.state.timeouts?.keepAliveTimeoutMs;
586
+ }
587
+ if (options.kind === 'archive') {
588
+ return this.state.timeouts?.snapshotTimeoutMs;
589
+ }
590
+ if (options.kind === 'path' || options.kind === 'manifest') {
591
+ return this.state.timeouts?.fastOperationTimeoutMs;
592
+ }
593
+ return undefined;
594
+ }
595
+ async ensureTunnelUrl(port) {
596
+ const existingUrl = await this.getTunnelUrl(port);
597
+ if (existingUrl) {
598
+ return existingUrl;
599
+ }
600
+ if (!this.devbox.net?.enableTunnel) {
601
+ throw new SandboxProviderError('RunloopSandboxClient exposed port resolution requires a Runloop tunnel API.', {
602
+ provider: 'runloop',
603
+ port,
604
+ });
605
+ }
606
+ try {
607
+ const tunnelOptions = runloopRequestOptions(this.state.timeouts?.fastOperationTimeoutMs);
608
+ const tunnelParams = runloopTunnelEnableParams(this.state.tunnel);
609
+ if (!tunnelParams) {
610
+ throw new SandboxProviderError(`RunloopSandboxClient cannot enable a tunnel for exposed port ${port} because tunnel is disabled.`, {
611
+ provider: 'runloop',
612
+ port,
613
+ });
614
+ }
615
+ if (tunnelOptions) {
616
+ await this.devbox.net.enableTunnel(tunnelParams, tunnelOptions);
617
+ }
618
+ else {
619
+ await this.devbox.net.enableTunnel(tunnelParams);
620
+ }
621
+ }
622
+ catch (error) {
623
+ throw new SandboxProviderError(`RunloopSandboxClient failed to enable a tunnel for exposed port ${port}.`, {
624
+ provider: 'runloop',
625
+ port,
626
+ cause: error instanceof Error ? error.message : String(error),
627
+ });
628
+ }
629
+ const enabledUrl = await this.getTunnelUrl(port);
630
+ if (!enabledUrl) {
631
+ throw new SandboxProviderError(`RunloopSandboxClient did not return a tunnel URL for exposed port ${port}.`, {
632
+ provider: 'runloop',
633
+ port,
634
+ });
635
+ }
636
+ return enabledUrl;
637
+ }
638
+ async getTunnelUrl(port) {
639
+ if (!this.devbox.getTunnelUrl) {
640
+ throw new SandboxProviderError('RunloopSandboxClient exposed port resolution requires getTunnelUrl(port).', {
641
+ provider: 'runloop',
642
+ port,
643
+ });
644
+ }
645
+ try {
646
+ const tunnelOptions = runloopRequestOptions(this.state.timeouts?.fastOperationTimeoutMs);
647
+ const url = tunnelOptions
648
+ ? await this.devbox.getTunnelUrl(port, tunnelOptions)
649
+ : await this.devbox.getTunnelUrl(port);
650
+ return typeof url === 'string' && url ? url : undefined;
651
+ }
652
+ catch {
653
+ return undefined;
654
+ }
655
+ }
656
+ }
657
+ /**
658
+ * @see {@link https://docs.runloop.ai/docs/devboxes/overview | Devbox overview}.
659
+ * @see {@link https://docs.runloop.ai/docs/devboxes/start-stop | Devbox lifecycle}.
660
+ * @see {@link https://runloopai.github.io/api-client-ts/stable/classes/sdk.DevboxOps.html | TypeScript SDK Devbox reference}.
661
+ */
662
+ export class RunloopSandboxClient {
663
+ backendId = 'runloop';
664
+ options;
665
+ constructor(options = {}) {
666
+ this.options = options;
667
+ }
668
+ async platform() {
669
+ return new RunloopPlatformClient(await createRunloopClient(this.options));
670
+ }
671
+ async create(args, manifestOptions) {
672
+ const createArgs = normalizeSandboxClientCreateArgs(args, manifestOptions);
673
+ assertCoreSnapshotUnsupported('RunloopSandboxClient', createArgs.snapshot);
674
+ const resolvedOptions = {
675
+ ...this.options,
676
+ ...createArgs.options,
677
+ };
678
+ const timeouts = resolveRunloopTimeouts(resolvedOptions);
679
+ const manifest = resolveRunloopManifestRoot(createArgs.manifest, resolvedOptions.userParameters, false);
680
+ assertSandboxManifestMetadataSupported('RunloopSandboxClient', manifest, SANDBOX_MANIFEST_METADATA_SUPPORT);
681
+ const sdk = await createRunloopClient(resolvedOptions);
682
+ return await withSandboxSpan('sandbox.start', {
683
+ backend_id: this.backendId,
684
+ }, async () => {
685
+ const environment = await materializeEnvironment(manifest, resolvedOptions.env);
686
+ const createParams = {
687
+ environment_variables: environment,
688
+ };
689
+ const createBlueprintId = resolvedOptions.blueprintName
690
+ ? undefined
691
+ : resolvedOptions.blueprintId;
692
+ for (const key of [
693
+ 'blueprintId',
694
+ 'name',
695
+ 'exposedPorts',
696
+ 'tunnel',
697
+ 'gateways',
698
+ 'mcp',
699
+ 'metadata',
700
+ ]) {
701
+ const value = key === 'blueprintId' ? createBlueprintId : resolvedOptions[key];
702
+ if (value !== undefined) {
703
+ createParams[toSnakeCase(key)] = value;
704
+ }
705
+ }
706
+ if (resolvedOptions.userParameters ||
707
+ resolvedOptions.launchParameters) {
708
+ createParams.launch_parameters = {
709
+ ...(resolvedOptions.launchParameters ?? {}),
710
+ user_parameters: resolvedOptions.userParameters,
711
+ };
712
+ }
713
+ const createOptions = runloopLongPollOptions(timeouts.createTimeoutMs);
714
+ const secretRefs = resolvedOptions.secretRefs ??
715
+ (await upsertRunloopManagedSecrets(sdk, resolvedOptions.managedSecrets, runloopRequestOptions(timeouts.fastOperationTimeoutMs) ??
716
+ createOptions));
717
+ const persistedSecretRefs = Object.keys(secretRefs).length > 0 ? secretRefs : undefined;
718
+ if (persistedSecretRefs) {
719
+ createParams.secrets = persistedSecretRefs;
720
+ }
721
+ const devbox = await withProviderError('RunloopSandboxClient', 'runloop', 'create devbox', async () => resolvedOptions.blueprintName
722
+ ? await sdk.devbox.createFromBlueprintName(resolvedOptions.blueprintName, createParams, createOptions)
723
+ : await sdk.devbox.create(createParams, createOptions), {
724
+ blueprintName: resolvedOptions.blueprintName,
725
+ blueprintId: createBlueprintId,
726
+ });
727
+ const session = new RunloopSandboxSession({
728
+ sdk,
729
+ devbox,
730
+ concurrencyLimits: createArgs.concurrencyLimits,
731
+ state: {
732
+ manifest,
733
+ devboxId: devbox.id,
734
+ blueprintName: resolvedOptions.blueprintName,
735
+ blueprintId: createBlueprintId,
736
+ name: resolvedOptions.name,
737
+ launchParameters: resolvedOptions.launchParameters,
738
+ configuredExposedPorts: resolvedOptions.exposedPorts,
739
+ tunnel: resolvedOptions.tunnel,
740
+ gateways: resolvedOptions.gateways,
741
+ mcp: resolvedOptions.mcp,
742
+ metadata: resolvedOptions.metadata,
743
+ secretRefs: persistedSecretRefs,
744
+ pauseOnExit: resolvedOptions.pauseOnExit ?? false,
745
+ userParameters: resolvedOptions.userParameters,
746
+ environment,
747
+ baseUrl: resolvedOptions.baseUrl,
748
+ createTimeoutMs: timeouts.createTimeoutMs,
749
+ timeouts,
750
+ },
751
+ });
752
+ try {
753
+ await session.applyManifest(manifest);
754
+ }
755
+ catch (error) {
756
+ session.state.pauseOnExit = false;
757
+ await closeRemoteSessionOnManifestError('Runloop', session, error);
758
+ }
759
+ return session;
760
+ });
761
+ }
762
+ async serializeSessionState(state) {
763
+ const { managedSecrets: _managedSecrets, ...serializableState } = state;
764
+ return serializeRemoteSandboxSessionState(serializableState);
765
+ }
766
+ canPersistOwnedSessionState(state) {
767
+ return state.pauseOnExit;
768
+ }
769
+ async deserializeSessionState(state) {
770
+ const baseState = deserializeRemoteSandboxSessionStateValues(state, this.options.env);
771
+ const { managedSecrets: _managedSecrets, ...rest } = state;
772
+ return {
773
+ ...rest,
774
+ ...baseState,
775
+ devboxId: readString(state, 'devboxId'),
776
+ blueprintName: readOptionalString(state, 'blueprintName'),
777
+ blueprintId: readOptionalString(state, 'blueprintId'),
778
+ name: readOptionalString(state, 'name'),
779
+ launchParameters: readOptionalRecord(state.launchParameters),
780
+ configuredExposedPorts: readOptionalNumberArray(state.configuredExposedPorts),
781
+ tunnel: typeof state.tunnel === 'boolean' || isRecord(state.tunnel)
782
+ ? state.tunnel
783
+ : undefined,
784
+ gateways: readOptionalRecord(state.gateways),
785
+ mcp: readOptionalRecord(state.mcp),
786
+ metadata: readOptionalStringRecord(state.metadata),
787
+ secretRefs: readOptionalStringRecord(state.secretRefs),
788
+ pauseOnExit: Boolean(state.pauseOnExit),
789
+ userParameters: typeof state.userParameters === 'object' && state.userParameters
790
+ ? state.userParameters
791
+ : undefined,
792
+ baseUrl: readOptionalString(state, 'baseUrl'),
793
+ createTimeoutMs: readOptionalNumber(state, 'createTimeoutMs'),
794
+ timeouts: resolveRunloopTimeouts({
795
+ createTimeoutMs: readOptionalNumber(state, 'createTimeoutMs'),
796
+ timeouts: isRecord(state.timeouts)
797
+ ? state.timeouts
798
+ : undefined,
799
+ }),
800
+ };
801
+ }
802
+ async resume(state) {
803
+ const resumeState = {
804
+ ...state,
805
+ baseUrl: this.options.baseUrl,
806
+ launchParameters: this.options.launchParameters,
807
+ userParameters: this.options.userParameters,
808
+ manifest: resolveRunloopManifestRoot(state.manifest, this.options.userParameters, true),
809
+ };
810
+ const sdk = await createRunloopClient(this.options);
811
+ try {
812
+ const devbox = sdk.devbox.fromId(resumeState.devboxId);
813
+ if (resumeState.pauseOnExit) {
814
+ await devbox.resume(runloopLongPollOptions(resumeState.timeouts?.resumeTimeoutMs));
815
+ }
816
+ invalidateRunloopRuntimeCaches(resumeState);
817
+ const session = new RunloopSandboxSession({
818
+ state: resumeState,
819
+ sdk,
820
+ devbox,
821
+ });
822
+ try {
823
+ await session.ensureCurrentManifestRoot();
824
+ await rematerializeRunloopManifestMounts(session, resumeState.manifest);
825
+ }
826
+ catch (error) {
827
+ await session.cleanupAfterFailedResume();
828
+ throw error;
829
+ }
830
+ return session;
831
+ }
832
+ catch (error) {
833
+ assertResumeRecreateAllowed(error, {
834
+ providerName: 'RunloopSandboxClient',
835
+ provider: 'runloop',
836
+ details: { devboxId: resumeState.devboxId },
837
+ });
838
+ assertRunloopResumeRecreateSecretRefsTrusted(resumeState, this.options);
839
+ const recreateOptions = {
840
+ blueprintName: this.options.blueprintName,
841
+ blueprintId: this.options.blueprintId,
842
+ name: resumeState.name,
843
+ launchParameters: this.options.launchParameters,
844
+ exposedPorts: resumeState.configuredExposedPorts,
845
+ tunnel: resumeState.tunnel,
846
+ gateways: resumeState.gateways,
847
+ mcp: resumeState.mcp,
848
+ metadata: resumeState.metadata,
849
+ managedSecrets: this.options.managedSecrets,
850
+ pauseOnExit: resumeState.pauseOnExit,
851
+ userParameters: this.options.userParameters,
852
+ env: this.options.env,
853
+ baseUrl: this.options.baseUrl,
854
+ createTimeoutMs: resumeState.createTimeoutMs,
855
+ timeouts: resumeState.timeouts,
856
+ };
857
+ return await this.create(resumeState.manifest, recreateOptions);
858
+ }
859
+ }
860
+ }
861
+ async function createRunloopClient(options) {
862
+ try {
863
+ const { RunloopSDK } = await import('@runloop/api-client');
864
+ return adaptRunloopClient(new RunloopSDK({
865
+ ...(options.apiKey ? { bearerToken: options.apiKey } : {}),
866
+ ...(options.baseUrl ? { baseURL: options.baseUrl } : {}),
867
+ }));
868
+ }
869
+ catch (error) {
870
+ throw new UserError(`Runloop sandbox support requires the optional \`@runloop/api-client\` package. Install it before using Runloop-backed sandbox examples. ${error.message}`);
871
+ }
872
+ }
873
+ function adaptRunloopClient(sdk) {
874
+ const createFromSnapshot = bindRunloopMethod(sdk.devbox, 'createFromSnapshot');
875
+ const secretList = bindRunloopMethod(sdk.secret, 'list');
876
+ const secretDelete = bindRunloopMethod(sdk.secret, 'delete');
877
+ return {
878
+ devbox: {
879
+ create: async (params, options) => adaptRunloopDevbox(await sdk.devbox.create(params, options)),
880
+ createFromBlueprintName: async (blueprintName, params, options) => adaptRunloopDevbox(await sdk.devbox.createFromBlueprintName(blueprintName, params, options)),
881
+ ...(createFromSnapshot
882
+ ? {
883
+ createFromSnapshot: async (snapshotId, params, options) => adaptRunloopDevbox((await createFromSnapshot(snapshotId, params, options))),
884
+ }
885
+ : {}),
886
+ fromId: (id) => adaptRunloopDevbox(sdk.devbox.fromId(id)),
887
+ },
888
+ secret: {
889
+ create: async (...args) => {
890
+ const [params, options] = args;
891
+ const createParams = params;
892
+ return args.length > 1
893
+ ? await sdk.secret.create(createParams, options)
894
+ : await sdk.secret.create(createParams);
895
+ },
896
+ update: async (...args) => {
897
+ const [secret, params, options] = args;
898
+ const updateParams = params;
899
+ return args.length > 2
900
+ ? await sdk.secret.update(secret, updateParams, options)
901
+ : await sdk.secret.update(secret, updateParams);
902
+ },
903
+ ...(secretList
904
+ ? {
905
+ list: async (...args) => {
906
+ const [params, options] = args;
907
+ return args.length > 1
908
+ ? await secretList(params, options)
909
+ : await secretList(params);
910
+ },
911
+ }
912
+ : {}),
913
+ ...(secretDelete
914
+ ? {
915
+ delete: async (...args) => {
916
+ const [secret, params, options] = args;
917
+ return args.length > 2
918
+ ? await secretDelete(secret, params, options)
919
+ : await secretDelete(secret, params);
920
+ },
921
+ }
922
+ : {}),
923
+ },
924
+ blueprint: adaptRunloopPlatformResource(sdk.blueprint),
925
+ benchmark: adaptRunloopBenchmarkResource(sdk),
926
+ networkPolicy: adaptRunloopPlatformResource(sdk.networkPolicy),
927
+ axon: adaptRunloopPlatformResource(sdk.axon),
928
+ api: adaptRunloopApi(sdk),
929
+ };
930
+ }
931
+ function adaptRunloopDevbox(devbox) {
932
+ const enableTunnel = bindRunloopMethod(devbox.net, 'enableTunnel');
933
+ const getTunnelUrl = bindRunloopMethod(devbox, 'getTunnelUrl');
934
+ const snapshotDisk = bindRunloopMethod(devbox, 'snapshotDisk');
935
+ return {
936
+ id: devbox.id,
937
+ cmd: {
938
+ exec: async (...args) => {
939
+ const [command, params, options] = args;
940
+ if (args.length > 2) {
941
+ return await devbox.cmd.exec(command, params, options);
942
+ }
943
+ return args.length > 1
944
+ ? await devbox.cmd.exec(command, params)
945
+ : await devbox.cmd.exec(command);
946
+ },
947
+ },
948
+ file: {
949
+ read: async (params, options) => await devbox.file.read(params, options),
950
+ write: async (params, options) => await devbox.file.write({
951
+ file_path: params.path,
952
+ contents: params.contents,
953
+ }, options),
954
+ download: async (params, options) => await devbox.file.download(params, options),
955
+ upload: async (params, options) => {
956
+ const uploadParams = params;
957
+ return options
958
+ ? await devbox.file.upload(uploadParams, options)
959
+ : await devbox.file.upload(uploadParams);
960
+ },
961
+ },
962
+ ...(enableTunnel
963
+ ? {
964
+ net: {
965
+ enableTunnel: async (params, options) => options
966
+ ? await enableTunnel(params, options)
967
+ : await enableTunnel(params),
968
+ },
969
+ }
970
+ : {}),
971
+ ...(getTunnelUrl
972
+ ? {
973
+ getTunnelUrl: async (port, options) => (options
974
+ ? await getTunnelUrl(port, options)
975
+ : await getTunnelUrl(port)),
976
+ }
977
+ : {}),
978
+ ...(snapshotDisk
979
+ ? {
980
+ snapshotDisk: async (params, options) => (options
981
+ ? await snapshotDisk(params, options)
982
+ : await snapshotDisk(params)),
983
+ }
984
+ : {}),
985
+ resume: async (options) => await devbox.resume(options),
986
+ suspend: async (options) => await devbox.suspend(options),
987
+ shutdown: async (options) => await devbox.shutdown(options),
988
+ };
989
+ }
990
+ function adaptRunloopPlatformResource(resource) {
991
+ if (!isRecord(resource)) {
992
+ return undefined;
993
+ }
994
+ const fromId = resource.fromId;
995
+ return {
996
+ create: bindRunloopMethod(resource, 'create'),
997
+ list: bindRunloopMethod(resource, 'list'),
998
+ fromId: typeof fromId === 'function'
999
+ ? (id) => fromId.call(resource, id)
1000
+ : undefined,
1001
+ };
1002
+ }
1003
+ function adaptRunloopBenchmarkResource(sdk) {
1004
+ const apiBenchmarks = sdk.api
1005
+ ?.benchmarks;
1006
+ const apiResource = adaptRunloopApiBenchmarkResource(apiBenchmarks);
1007
+ if (apiResource) {
1008
+ return apiResource;
1009
+ }
1010
+ return adaptRunloopPlatformResource(sdk.benchmark);
1011
+ }
1012
+ function adaptRunloopApiBenchmarkResource(resource) {
1013
+ if (!isRecord(resource)) {
1014
+ return undefined;
1015
+ }
1016
+ const adapted = {
1017
+ create: bindRunloopMethod(resource, 'create'),
1018
+ list: bindRunloopMethod(resource, 'list'),
1019
+ retrieve: bindRunloopMethod(resource, 'retrieve'),
1020
+ update: bindRunloopMethod(resource, 'update'),
1021
+ startRun: bindRunloopMethod(resource, 'startRun'),
1022
+ };
1023
+ return Object.values(adapted).some((value) => typeof value === 'function')
1024
+ ? adapted
1025
+ : undefined;
1026
+ }
1027
+ function adaptRunloopApi(sdk) {
1028
+ const apiClient = sdk.api;
1029
+ if (!isRecord(apiClient)) {
1030
+ return {};
1031
+ }
1032
+ const api = {};
1033
+ const blueprintsResource = apiClient.blueprints;
1034
+ const benchmarksResource = apiClient.benchmarks;
1035
+ const secretsResource = apiClient.secrets;
1036
+ const blueprints = runloopApiResource({
1037
+ listPublic: bindRunloopMethod(blueprintsResource, 'listPublic'),
1038
+ logs: bindRunloopMethod(blueprintsResource, 'logs'),
1039
+ awaitBuildComplete: bindRunloopMethod(blueprintsResource, 'awaitBuildComplete'),
1040
+ });
1041
+ if (Object.keys(blueprints).length > 0) {
1042
+ api.blueprints = blueprints;
1043
+ }
1044
+ const benchmarks = runloopApiResource({
1045
+ listPublic: bindRunloopMethod(benchmarksResource, 'listPublic'),
1046
+ definitions: bindRunloopMethod(benchmarksResource, 'definitions'),
1047
+ updateScenarios: bindRunloopMethod(benchmarksResource, 'updateScenarios'),
1048
+ });
1049
+ if (Object.keys(benchmarks).length > 0) {
1050
+ api.benchmarks = benchmarks;
1051
+ }
1052
+ const secrets = runloopApiResource({
1053
+ retrieve: bindRunloopMethod(secretsResource, 'retrieve'),
1054
+ });
1055
+ if (Object.keys(secrets).length > 0) {
1056
+ api.secrets = secrets;
1057
+ }
1058
+ return api;
1059
+ }
1060
+ function runloopApiResource(methods) {
1061
+ return Object.fromEntries(Object.entries(methods).filter((entry) => typeof entry[1] === 'function'));
1062
+ }
1063
+ function bindRunloopMethod(target, methodName) {
1064
+ if (!isRecord(target)) {
1065
+ return undefined;
1066
+ }
1067
+ const method = target[methodName];
1068
+ return typeof method === 'function'
1069
+ ? method.bind(target)
1070
+ : undefined;
1071
+ }
1072
+ async function upsertRunloopManagedSecrets(sdk, managedSecrets, options) {
1073
+ if (!managedSecrets || Object.keys(managedSecrets).length === 0) {
1074
+ return {};
1075
+ }
1076
+ if (!sdk.secret?.create || !sdk.secret.update) {
1077
+ throw new SandboxProviderError('RunloopSandboxClient managedSecrets require the Runloop SDK secret API.', {
1078
+ provider: 'runloop',
1079
+ });
1080
+ }
1081
+ const refs = {};
1082
+ for (const [name, value] of Object.entries(managedSecrets).sort(([left], [right]) => left.localeCompare(right))) {
1083
+ try {
1084
+ await sdk.secret.create({ name, value }, options);
1085
+ }
1086
+ catch (error) {
1087
+ if (!isRunloopConflictError(error)) {
1088
+ throw new SandboxProviderError(`RunloopSandboxClient failed to create managed secret ${name}.`, {
1089
+ provider: 'runloop',
1090
+ secretName: name,
1091
+ cause: formatRunloopSecretErrorCause(error, value),
1092
+ });
1093
+ }
1094
+ try {
1095
+ await sdk.secret.update(name, { value }, options);
1096
+ }
1097
+ catch (updateError) {
1098
+ throw new SandboxProviderError(`RunloopSandboxClient failed to update managed secret ${name}.`, {
1099
+ provider: 'runloop',
1100
+ secretName: name,
1101
+ cause: formatRunloopSecretErrorCause(updateError, value),
1102
+ });
1103
+ }
1104
+ }
1105
+ refs[name] = name;
1106
+ }
1107
+ return refs;
1108
+ }
1109
+ function isRunloopConflictError(error) {
1110
+ if (!isRecord(error)) {
1111
+ return false;
1112
+ }
1113
+ const status = error.status ?? error.statusCode;
1114
+ if (status === 409 || status === '409') {
1115
+ return true;
1116
+ }
1117
+ const code = error.code;
1118
+ if (code === 409 || code === '409') {
1119
+ return true;
1120
+ }
1121
+ const text = `${String(error.name ?? '')} ${String(error.message ?? '')}`;
1122
+ return /\b(conflict|already exists)\b/iu.test(text);
1123
+ }
1124
+ function formatRunloopSecretErrorCause(error, secretValue) {
1125
+ const message = error instanceof Error ? error.message : String(error);
1126
+ return secretValue ? message.split(secretValue).join('[redacted]') : message;
1127
+ }
1128
+ function errorMessage(error) {
1129
+ return error instanceof Error ? error.message : String(error);
1130
+ }
1131
+ async function callRunloopPlatformMethod(methodName, method, ...args) {
1132
+ if (!method) {
1133
+ throw new SandboxUnsupportedFeatureError(`Runloop platform method ${methodName} is not available in the installed Runloop SDK.`, {
1134
+ provider: 'runloop',
1135
+ feature: `platform.${methodName}`,
1136
+ });
1137
+ }
1138
+ return await withProviderError('RunloopSandboxClient', 'runloop', `call platform method ${methodName}`, async () => await method(...args));
1139
+ }
1140
+ function callRunloopPlatformGetter(methodName, method, id) {
1141
+ if (!method) {
1142
+ throw new SandboxUnsupportedFeatureError(`Runloop platform method ${methodName} is not available in the installed Runloop SDK.`, {
1143
+ provider: 'runloop',
1144
+ feature: `platform.${methodName}`,
1145
+ });
1146
+ }
1147
+ try {
1148
+ return method(id);
1149
+ }
1150
+ catch (error) {
1151
+ if (error instanceof UserError) {
1152
+ throw error;
1153
+ }
1154
+ throw new SandboxProviderError(`RunloopSandboxClient failed to call platform method ${methodName}.`, {
1155
+ provider: 'runloop',
1156
+ operation: `call platform method ${methodName}`,
1157
+ cause: error instanceof Error ? error.message : String(error),
1158
+ });
1159
+ }
1160
+ }
1161
+ function createRunloopParams(state, environment, options = {}) {
1162
+ const createParams = {
1163
+ environment_variables: environment,
1164
+ };
1165
+ const includeBlueprint = options.includeBlueprint ?? true;
1166
+ const includeSecrets = options.includeSecrets ?? true;
1167
+ const values = {
1168
+ blueprintId: includeBlueprint ? state.blueprintId : undefined,
1169
+ name: state.name,
1170
+ exposedPorts: state.configuredExposedPorts,
1171
+ tunnel: state.tunnel,
1172
+ gateways: state.gateways,
1173
+ mcp: state.mcp,
1174
+ metadata: state.metadata,
1175
+ secrets: includeSecrets ? state.secretRefs : undefined,
1176
+ };
1177
+ for (const [key, value] of Object.entries(values)) {
1178
+ if (value !== undefined) {
1179
+ createParams[toSnakeCase(key)] = value;
1180
+ }
1181
+ }
1182
+ if (state.userParameters || state.launchParameters) {
1183
+ createParams.launch_parameters = {
1184
+ ...(state.launchParameters ?? {}),
1185
+ user_parameters: state.userParameters,
1186
+ };
1187
+ }
1188
+ return createParams;
1189
+ }
1190
+ function resolveRunloopManifestRoot(manifest, userParameters, preserveDefaultRoot) {
1191
+ const effectiveHome = effectiveRunloopHome(userParameters);
1192
+ const resolvedManifest = !preserveDefaultRoot && manifest.root === '/workspace'
1193
+ ? cloneManifestWithRoot(manifest, effectiveHome)
1194
+ : manifest;
1195
+ validateRunloopManifestRoot(resolvedManifest, effectiveHome);
1196
+ return resolvedManifest;
1197
+ }
1198
+ function effectiveRunloopHome(userParameters) {
1199
+ if (!userParameters) {
1200
+ return DEFAULT_RUNLOOP_WORKSPACE_ROOT;
1201
+ }
1202
+ validateRunloopUsername(userParameters.username);
1203
+ if (userParameters.username === 'root' && userParameters.uid === 0) {
1204
+ return DEFAULT_RUNLOOP_ROOT_WORKSPACE_ROOT;
1205
+ }
1206
+ return `/home/${userParameters.username}`;
1207
+ }
1208
+ function validateRunloopUsername(username) {
1209
+ if (username.length > 0 &&
1210
+ username !== '.' &&
1211
+ !username.includes('/') &&
1212
+ !username.includes('..') &&
1213
+ !username.includes('\0')) {
1214
+ return;
1215
+ }
1216
+ throw new SandboxConfigurationError('RunloopSandboxClient userParameters.username must be non-empty and must not contain "/", "..", or NUL bytes.', {
1217
+ provider: 'runloop',
1218
+ username,
1219
+ });
1220
+ }
1221
+ function validateRunloopManifestRoot(manifest, home) {
1222
+ const root = pathPosix.normalize(manifest.root);
1223
+ if (root === home || root.startsWith(`${home}/`)) {
1224
+ return;
1225
+ }
1226
+ throw new SandboxConfigurationError(`RunloopSandboxClient requires manifest.root to be the effective Runloop home (${home}) or a subdirectory of it.`, {
1227
+ provider: 'runloop',
1228
+ root: manifest.root,
1229
+ effectiveHome: home,
1230
+ });
1231
+ }
1232
+ function assertRunloopManifestRootRealPath(root, home, stdout) {
1233
+ const values = new Map(stdout
1234
+ .trim()
1235
+ .split(/\r?\n/u)
1236
+ .map((line) => line.match(/^(OPENAI_AGENTS_REALPATH_(?:ANCESTOR|HOME|ROOT))=(.*)$/u))
1237
+ .filter((match) => match !== null)
1238
+ .map((match) => [match[1], pathPosix.normalize(match[2] ?? '')]));
1239
+ const realHome = values.get('OPENAI_AGENTS_REALPATH_HOME');
1240
+ const realAncestor = values.get('OPENAI_AGENTS_REALPATH_ANCESTOR');
1241
+ const realRoot = values.get('OPENAI_AGENTS_REALPATH_ROOT');
1242
+ const normalizedHome = pathPosix.normalize(home);
1243
+ const realHomeIsConfined = realHome &&
1244
+ realHome !== '/' &&
1245
+ (realHome === normalizedHome || realHome.startsWith(`${normalizedHome}/`));
1246
+ const realAncestorIsConfined = realHome &&
1247
+ realAncestor &&
1248
+ (realAncestor === realHome || realAncestor.startsWith(`${realHome}/`));
1249
+ const realRootIsConfined = realHome &&
1250
+ realRoot &&
1251
+ (realRoot === realHome || realRoot.startsWith(`${realHome}/`));
1252
+ if (realHomeIsConfined && realAncestorIsConfined && realRootIsConfined) {
1253
+ return;
1254
+ }
1255
+ throw new SandboxConfigurationError(`RunloopSandboxClient requires manifest.root to resolve to the effective Runloop home (${home}) or a subdirectory of it.`, {
1256
+ provider: 'runloop',
1257
+ root,
1258
+ effectiveHome: home,
1259
+ resolvedRoot: realRoot,
1260
+ resolvedHome: realHome,
1261
+ resolvedAncestor: realAncestor,
1262
+ });
1263
+ }
1264
+ function createRunloopOptions(state) {
1265
+ return runloopLongPollOptions(state.timeouts?.createTimeoutMs ?? state.createTimeoutMs);
1266
+ }
1267
+ function resolveRunloopTimeouts(options) {
1268
+ return {
1269
+ ...options.timeouts,
1270
+ createTimeoutMs: options.timeouts?.createTimeoutMs ?? options.createTimeoutMs,
1271
+ fastOperationTimeoutMs: options.timeouts?.fastOperationTimeoutMs ?? options.createTimeoutMs,
1272
+ };
1273
+ }
1274
+ function runloopRequestOptions(timeoutMs) {
1275
+ return typeof timeoutMs === 'number' ? { timeout: timeoutMs } : undefined;
1276
+ }
1277
+ function runloopLongPollOptions(timeoutMs) {
1278
+ return typeof timeoutMs === 'number'
1279
+ ? { timeout: timeoutMs, longPoll: { timeoutMs } }
1280
+ : undefined;
1281
+ }
1282
+ function runloopTunnelEnableParams(tunnel) {
1283
+ if (tunnel === false) {
1284
+ return undefined;
1285
+ }
1286
+ if (isRecord(tunnel)) {
1287
+ return {
1288
+ ...DEFAULT_RUNLOOP_TUNNEL_PARAMS,
1289
+ ...tunnel,
1290
+ };
1291
+ }
1292
+ return { ...DEFAULT_RUNLOOP_TUNNEL_PARAMS };
1293
+ }
1294
+ function runloopExitStatus(result) {
1295
+ return result.exitCode ?? UNKNOWN_RUNLOOP_EXIT_CODE;
1296
+ }
1297
+ function runloopSucceeded(result) {
1298
+ return result.exitCode === 0;
1299
+ }
1300
+ function invalidateRunloopRuntimeCaches(state) {
1301
+ delete state.exposedPorts;
1302
+ }
1303
+ function remoteCommandEnvironment(environment, options) {
1304
+ return options.kind === 'exec' ? environment : {};
1305
+ }
1306
+ function assertRunloopResumeRecreateSecretRefsTrusted(state, options) {
1307
+ if (!state.secretRefs || Object.keys(state.secretRefs).length === 0) {
1308
+ return;
1309
+ }
1310
+ if (options.managedSecrets &&
1311
+ Object.keys(options.managedSecrets).length > 0) {
1312
+ return;
1313
+ }
1314
+ throw new UserError('RunloopSandboxClient cannot recreate a missing devbox with persisted secretRefs. Configure managedSecrets on the client to recreate secrets from trusted input.');
1315
+ }
1316
+ async function rematerializeRunloopManifestMounts(session, manifest) {
1317
+ await session.rematerializeManifestMounts(manifest);
1318
+ }
1319
+ function mountCommandEnvironment(environment, user, userParameters) {
1320
+ const effectiveUser = user ?? effectiveRunloopUsername(userParameters);
1321
+ return effectiveUser === 'root' ? {} : environment;
1322
+ }
1323
+ function buildShellCommand(command, environment, cwd, user, userParameters) {
1324
+ const exports = Object.entries(environment).map(([key, value]) => {
1325
+ assertShellEnvironmentName(key);
1326
+ return `export ${key}=${shellQuote(value)}`;
1327
+ });
1328
+ const shellCommand = [`cd ${shellQuote(cwd)}`, ...exports, command].join(' && ');
1329
+ return runloopShellCommandForUser(shellCommand, user, userParameters);
1330
+ }
1331
+ function runloopShellCommandForUser(command, user, userParameters) {
1332
+ if (!user || user === effectiveRunloopUsername(userParameters)) {
1333
+ return command;
1334
+ }
1335
+ return `sudo -n -u ${shellQuote(user)} -- sh -lc ${shellQuote(command)}`;
1336
+ }
1337
+ function effectiveRunloopUsername(userParameters) {
1338
+ return userParameters?.username ?? 'user';
1339
+ }
1340
+ function toSnakeCase(value) {
1341
+ return value.replace(/[A-Z]/gu, (match) => `_${match.toLowerCase()}`);
1342
+ }
1343
+ function basename(path) {
1344
+ return path.split('/').pop() || 'file';
1345
+ }
1346
+ //# sourceMappingURL=sandbox.mjs.map