openpond-sdk 0.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/index.js +2635 -0
  4. package/dist/index.js.map +7 -0
  5. package/dist/types/packages/cloud/src/api/core.d.ts +23 -0
  6. package/dist/types/packages/cloud/src/api/core.d.ts.map +1 -0
  7. package/dist/types/packages/cloud/src/api/vercel-protection.d.ts +2 -0
  8. package/dist/types/packages/cloud/src/api/vercel-protection.d.ts.map +1 -0
  9. package/dist/types/packages/cloud/src/hosted-chat.d.ts +163 -0
  10. package/dist/types/packages/cloud/src/hosted-chat.d.ts.map +1 -0
  11. package/dist/types/packages/cloud/src/sandbox/async-request-options.d.ts +3 -0
  12. package/dist/types/packages/cloud/src/sandbox/async-request-options.d.ts.map +1 -0
  13. package/dist/types/packages/cloud/src/sandbox/client-handles.d.ts +101 -0
  14. package/dist/types/packages/cloud/src/sandbox/client-handles.d.ts.map +1 -0
  15. package/dist/types/packages/cloud/src/sandbox/client.d.ts +327 -0
  16. package/dist/types/packages/cloud/src/sandbox/client.d.ts.map +1 -0
  17. package/dist/types/packages/cloud/src/sandbox/runtime-handle.d.ts +37 -0
  18. package/dist/types/packages/cloud/src/sandbox/runtime-handle.d.ts.map +1 -0
  19. package/dist/types/packages/cloud/src/sandbox/sandbox-instance-client.d.ts +73 -0
  20. package/dist/types/packages/cloud/src/sandbox/sandbox-instance-client.d.ts.map +1 -0
  21. package/dist/types/packages/cloud/src/sandbox/smoke.d.ts +4 -0
  22. package/dist/types/packages/cloud/src/sandbox/smoke.d.ts.map +1 -0
  23. package/dist/types/packages/cloud/src/sandbox/stream.d.ts +8 -0
  24. package/dist/types/packages/cloud/src/sandbox/stream.d.ts.map +1 -0
  25. package/dist/types/packages/cloud/src/sandbox/types/billing.d.ts +177 -0
  26. package/dist/types/packages/cloud/src/sandbox/types/billing.d.ts.map +1 -0
  27. package/dist/types/packages/cloud/src/sandbox/types/client.d.ts +104 -0
  28. package/dist/types/packages/cloud/src/sandbox/types/client.d.ts.map +1 -0
  29. package/dist/types/packages/cloud/src/sandbox/types/core.d.ts +141 -0
  30. package/dist/types/packages/cloud/src/sandbox/types/core.d.ts.map +1 -0
  31. package/dist/types/packages/cloud/src/sandbox/types/index.d.ts +15 -0
  32. package/dist/types/packages/cloud/src/sandbox/types/index.d.ts.map +1 -0
  33. package/dist/types/packages/cloud/src/sandbox/types/io.d.ts +241 -0
  34. package/dist/types/packages/cloud/src/sandbox/types/io.d.ts.map +1 -0
  35. package/dist/types/packages/cloud/src/sandbox/types/microsoft-teams-bot.d.ts +52 -0
  36. package/dist/types/packages/cloud/src/sandbox/types/microsoft-teams-bot.d.ts.map +1 -0
  37. package/dist/types/packages/cloud/src/sandbox/types/org-project-agent.d.ts +524 -0
  38. package/dist/types/packages/cloud/src/sandbox/types/org-project-agent.d.ts.map +1 -0
  39. package/dist/types/packages/cloud/src/sandbox/types/record.d.ts +54 -0
  40. package/dist/types/packages/cloud/src/sandbox/types/record.d.ts.map +1 -0
  41. package/dist/types/packages/cloud/src/sandbox/types/responses.d.ts +296 -0
  42. package/dist/types/packages/cloud/src/sandbox/types/responses.d.ts.map +1 -0
  43. package/dist/types/packages/cloud/src/sandbox/types/runtime-environments.d.ts +3 -0
  44. package/dist/types/packages/cloud/src/sandbox/types/runtime-environments.d.ts.map +1 -0
  45. package/dist/types/packages/cloud/src/sandbox/types/runtime-profiles.d.ts +16 -0
  46. package/dist/types/packages/cloud/src/sandbox/types/runtime-profiles.d.ts.map +1 -0
  47. package/dist/types/packages/cloud/src/sandbox/types/runtime.d.ts +153 -0
  48. package/dist/types/packages/cloud/src/sandbox/types/runtime.d.ts.map +1 -0
  49. package/dist/types/packages/cloud/src/sandbox/types/schedules.d.ts +142 -0
  50. package/dist/types/packages/cloud/src/sandbox/types/schedules.d.ts.map +1 -0
  51. package/dist/types/packages/cloud/src/sandbox/types/snapshots.d.ts +206 -0
  52. package/dist/types/packages/cloud/src/sandbox/types/snapshots.d.ts.map +1 -0
  53. package/dist/types/packages/cloud/src/sandbox/types/workflow-modes.d.ts +2 -0
  54. package/dist/types/packages/cloud/src/sandbox/types/workflow-modes.d.ts.map +1 -0
  55. package/dist/types/packages/cloud/src/sandbox/types/workload-sources.d.ts +21 -0
  56. package/dist/types/packages/cloud/src/sandbox/types/workload-sources.d.ts.map +1 -0
  57. package/dist/types/packages/cloud/src/sandbox/url.d.ts +3 -0
  58. package/dist/types/packages/cloud/src/sandbox/url.d.ts.map +1 -0
  59. package/dist/types/packages/cloud/src/urls.d.ts +5 -0
  60. package/dist/types/packages/cloud/src/urls.d.ts.map +1 -0
  61. package/dist/types/packages/sdk/src/index.d.ts +17 -0
  62. package/dist/types/packages/sdk/src/index.d.ts.map +1 -0
  63. package/dist/types/packages/sdk/src/types.d.ts +11 -0
  64. package/dist/types/packages/sdk/src/types.d.ts.map +1 -0
  65. package/dist/types/packages/sdk/src/work.d.ts +71 -0
  66. package/dist/types/packages/sdk/src/work.d.ts.map +1 -0
  67. package/package.json +50 -0
package/dist/index.js ADDED
@@ -0,0 +1,2635 @@
1
+ // ../cloud/src/sandbox/client-handles.ts
2
+ function createSandboxRuntimeNamespace(client) {
3
+ return {
4
+ list: (input = {}) => client.listSandboxRuntimes(input),
5
+ create: (input) => client.createSandboxRuntime(input),
6
+ handle: (runtimeId, initial = null) => client.sandboxRuntime(runtimeId, initial),
7
+ get: (runtimeId) => client.getSandboxRuntime(runtimeId),
8
+ createSandbox: (runtimeId, input = {}, options = {}) => client.createSandboxRuntimeSandbox(runtimeId, input, options),
9
+ updateStatus: (runtimeId, input) => client.updateSandboxRuntimeStatus(runtimeId, input),
10
+ events: (runtimeId) => client.listSandboxRuntimeEvents(runtimeId),
11
+ event: (runtimeId, input) => client.emitSandboxRuntimeEvent(runtimeId, input),
12
+ checkpoint: (runtimeId, input = {}) => client.checkpointSandboxRuntime(runtimeId, input),
13
+ promote: (runtimeId, input, options = {}) => client.promoteSandboxRuntime(runtimeId, input, options),
14
+ preserveSource: (runtimeId, input = {}, options = {}) => client.preserveSandboxRuntimeSource(runtimeId, input, options)
15
+ };
16
+ }
17
+ function createSandboxNamespace(client) {
18
+ return {
19
+ list: (input = {}) => client.list(input),
20
+ create: (input) => client.create(input),
21
+ get: (sandboxId) => client.get(sandboxId),
22
+ pricing: () => client.pricing(),
23
+ costs: (input = {}) => client.costs(input)
24
+ };
25
+ }
26
+ function createSandboxProjectNamespace(client) {
27
+ return {
28
+ list: (input) => client.listProjects(input),
29
+ upsert: (input) => client.upsertProject(input),
30
+ upsertGitRemote: (input) => client.upsertProjectGitRemote(input),
31
+ get: (projectId, input) => client.getProject(projectId, input),
32
+ update: (projectId, input) => client.updateProject(projectId, input),
33
+ sync: (projectId, input) => client.syncProject(projectId, input),
34
+ ensureGitRemote: (projectId, input) => client.ensureProjectGitRemote(projectId, input),
35
+ getGitRemote: (projectId, input) => client.ensureProjectGitRemote(projectId, input),
36
+ git: (projectId, input) => client.ensureProjectGitRemote(projectId, input),
37
+ uploadSource: (projectId, input) => client.uploadProjectSource(projectId, input),
38
+ archive: (projectId, input) => client.archiveProject(projectId, input)
39
+ };
40
+ }
41
+ function createSandboxProfileNamespace(client) {
42
+ return {
43
+ get: (input) => client.getHostedProfile(input),
44
+ status: (input) => client.getHostedProfile(input),
45
+ ensureHosted: (input) => client.ensureHostedProfile(input),
46
+ push: (input) => client.pushHostedProfile(input)
47
+ };
48
+ }
49
+ function createSandboxAgentNamespace(client) {
50
+ return {
51
+ list: (input) => client.listAgents(input),
52
+ upsert: (input) => client.upsertAgent(input),
53
+ get: (agentId, input) => client.getAgent(agentId, input),
54
+ update: (agentId, input) => client.updateAgent(agentId, input),
55
+ archive: (agentId, input) => client.archiveAgent(agentId, input),
56
+ run: (agentId, input) => client.runAgent(agentId, input),
57
+ sourceDeployPlan: (agentId, input) => client.getAgentSourceDeployPlan(agentId, input),
58
+ manifestSnapshots: (agentId, input) => client.listAgentManifestSnapshots(agentId, input),
59
+ requestSourceChecks: (agentId, input) => client.requestAgentSourceChecks(agentId, input),
60
+ publishSource: (agentId, input) => client.publishAgentSource(agentId, input)
61
+ };
62
+ }
63
+
64
+ // ../cloud/src/sandbox/runtime-handle.ts
65
+ function createSandboxRuntimeHandle(client, runtimeId, initial = null) {
66
+ const currentSandbox = async (input = {}, options = {}) => {
67
+ const runtime = await client.getSandboxRuntime(runtimeId);
68
+ if (runtime.sandboxId) {
69
+ return client.get(runtime.sandboxId);
70
+ }
71
+ return client.createSandboxRuntimeSandbox(runtimeId, input, options).then((payload) => payload.sandbox);
72
+ };
73
+ const resume = async (input = {}, options = {}) => {
74
+ const runtime = await client.getSandboxRuntime(runtimeId);
75
+ if (!runtime.sandboxId) {
76
+ return client.createSandboxRuntimeSandbox(runtimeId, input, options).then((payload) => payload.sandbox);
77
+ }
78
+ const sandbox = await client.get(runtime.sandboxId);
79
+ if (sandbox.state === "stopped") {
80
+ return client.start(sandbox.id, options).then((payload) => payload.sandbox);
81
+ }
82
+ if (sandbox.state === "archived") {
83
+ return client.restore(sandbox.id).then((payload) => payload.sandbox);
84
+ }
85
+ if (sandbox.state === "deleted" || sandbox.state === "error") {
86
+ return client.createSandboxRuntimeSandbox(runtimeId, input, options).then((payload) => payload.sandbox);
87
+ }
88
+ return sandbox;
89
+ };
90
+ const checkpointHint = (input = {}) => client.emitSandboxRuntimeEvent(runtimeId, {
91
+ type: "workflow.checkpoint_hint",
92
+ summary: input.summary ?? input.reason ?? "Workflow checkpoint hint",
93
+ payload: {
94
+ ...input.payload,
95
+ reason: input.reason ?? null
96
+ },
97
+ artifactRefs: input.artifactRefs,
98
+ lifecycleHint: {
99
+ kind: "checkpoint",
100
+ reason: input.reason ?? null
101
+ }
102
+ });
103
+ const waitForUser = async (input = {}) => {
104
+ await client.emitSandboxRuntimeEvent(runtimeId, {
105
+ type: "workflow.waiting_for_user",
106
+ summary: input.summary ?? input.reason ?? "Waiting for user",
107
+ payload: {
108
+ ...input.payload,
109
+ reason: input.reason ?? null
110
+ },
111
+ lifecycleHint: {
112
+ kind: "waiting_for_user",
113
+ reason: input.reason ?? null
114
+ }
115
+ });
116
+ const current = await client.getSandboxRuntime(runtimeId);
117
+ if (current.status === "waiting_for_user") return current;
118
+ return client.updateSandboxRuntimeStatus(runtimeId, {
119
+ status: "waiting_for_user",
120
+ expectedVersion: current.version,
121
+ summary: input.summary ?? input.reason,
122
+ metadata: {
123
+ workflowWaitForUserReason: input.reason ?? null
124
+ }
125
+ });
126
+ };
127
+ const keepAlive = (input = {}) => {
128
+ const keepaliveUntil = runtimeKeepaliveUntilIso(input);
129
+ return client.emitSandboxRuntimeEvent(runtimeId, {
130
+ type: "workflow.keepalive",
131
+ summary: input.summary ?? input.reason ?? "Workflow keepalive",
132
+ payload: {
133
+ ...input.payload,
134
+ reason: input.reason ?? null,
135
+ keepaliveUntil
136
+ },
137
+ lifecycleHint: {
138
+ kind: "keepalive",
139
+ reason: input.reason ?? null,
140
+ keepaliveUntil
141
+ }
142
+ });
143
+ };
144
+ return {
145
+ id: runtimeId,
146
+ initial,
147
+ get: () => client.getSandboxRuntime(runtimeId),
148
+ sandbox: currentSandbox,
149
+ resume,
150
+ createSandbox: (input = {}, options = {}) => client.createSandboxRuntimeSandbox(runtimeId, input, options),
151
+ status: async (input) => {
152
+ if (typeof input !== "string") {
153
+ return client.updateSandboxRuntimeStatus(runtimeId, input);
154
+ }
155
+ const current = await client.getSandboxRuntime(runtimeId);
156
+ return client.updateSandboxRuntimeStatus(runtimeId, {
157
+ status: input,
158
+ expectedVersion: current.version
159
+ });
160
+ },
161
+ events: () => client.listSandboxRuntimeEvents(runtimeId),
162
+ event: (input) => client.emitSandboxRuntimeEvent(runtimeId, input),
163
+ recordCommit: (commitSha, input = {}) => client.emitSandboxRuntimeEvent(runtimeId, {
164
+ ...input,
165
+ type: input.type ?? "git.commit",
166
+ commitSha
167
+ }),
168
+ checkpointHint,
169
+ waitForUser,
170
+ keepAlive,
171
+ checkpoint: (input) => client.checkpointSandboxRuntime(runtimeId, input),
172
+ files: {
173
+ write: async (path, contents) => client.uploadFile((await resume()).id, path, contents),
174
+ read: async (path) => client.downloadFile((await resume()).id, path),
175
+ readResponse: async (input) => client.downloadFileResponse((await resume()).id, input),
176
+ list: async (input = {}) => client.listFiles((await resume()).id, input),
177
+ delete: async (path, input = {}) => client.deleteFile((await resume()).id, path, input),
178
+ search: async (input) => client.searchFiles((await resume()).id, input),
179
+ stat: async (path) => client.statFile((await resume()).id, path),
180
+ mkdir: async (input) => client.mkdir((await resume()).id, input),
181
+ move: async (input) => client.moveFile((await resume()).id, input)
182
+ },
183
+ commands: {
184
+ run: async (command) => client.exec(
185
+ (await resume()).id,
186
+ typeof command === "string" ? { command } : command
187
+ )
188
+ },
189
+ ports: {
190
+ expose: async (port) => client.openPort(
191
+ (await resume()).id,
192
+ typeof port === "number" ? { port } : port
193
+ )
194
+ },
195
+ promote: (input, options = {}) => client.promoteSandboxRuntime(runtimeId, input, options),
196
+ preserveSource: (input = {}, options = {}) => client.preserveSandboxRuntimeSource(runtimeId, input, options),
197
+ archive: async (expectedVersion) => {
198
+ const version = expectedVersion ?? (await client.getSandboxRuntime(runtimeId)).version;
199
+ return client.updateSandboxRuntimeStatus(runtimeId, {
200
+ status: "archived",
201
+ expectedVersion: version
202
+ });
203
+ }
204
+ };
205
+ }
206
+ function runtimeKeepaliveUntilIso(input) {
207
+ if (input?.until instanceof Date) {
208
+ return input.until.toISOString();
209
+ }
210
+ if (typeof input?.until === "string" && input.until.trim()) {
211
+ return new Date(input.until).toISOString();
212
+ }
213
+ const seconds = typeof input?.seconds === "number" && Number.isFinite(input.seconds) ? Math.max(1, Math.trunc(input.seconds)) : 60;
214
+ return new Date(Date.now() + seconds * 1e3).toISOString();
215
+ }
216
+
217
+ // ../cloud/src/sandbox/smoke.ts
218
+ async function runSandboxSmoke(client, options = {}) {
219
+ const runId = `openpond-code-smoke-${Date.now()}`;
220
+ const expectedExec = `openpond-code-exec-ok:${runId}`;
221
+ const expectedPreview = `openpond-code-preview-ok:${runId}`;
222
+ const expectedFile = `openpond-code-file-ok:${runId}`;
223
+ const previewPort = 4173;
224
+ let sandboxId = null;
225
+ let forkSandboxId = null;
226
+ let deleted = false;
227
+ let forkDeleted = false;
228
+ try {
229
+ const sandbox = await waitForCreateReady(
230
+ client,
231
+ await client.create(
232
+ {
233
+ repo: options.repo ?? "https://github.com/octocat/Hello-World",
234
+ resources: {
235
+ cpu: options.cpu ?? 1,
236
+ memoryGb: options.memoryGb ?? 1,
237
+ diskGb: options.diskGb ?? 8
238
+ },
239
+ budget: { maxUsd: options.budgetUsd ?? "0.05" },
240
+ quotas: {
241
+ maxSpendUsd: options.budgetUsd ?? "0.05",
242
+ maxDurationSeconds: 600,
243
+ idleTimeoutSeconds: 600,
244
+ maxOpenPorts: 2
245
+ },
246
+ metadata: {
247
+ runId,
248
+ source: "openpond-code-sandbox-smoke"
249
+ }
250
+ },
251
+ { async: true }
252
+ )
253
+ );
254
+ sandboxId = sandbox.id;
255
+ const expectedRuntimeDriver = options.expectedRuntimeDriver ?? "remote-firecracker";
256
+ if (sandbox.runtimeDriver !== expectedRuntimeDriver) {
257
+ throw new Error(
258
+ `expected ${expectedRuntimeDriver}, got ${sandbox.runtimeDriver}`
259
+ );
260
+ }
261
+ const expectedMppMode = options.expectedMppMode;
262
+ if (expectedMppMode && sandbox.reservation.mpp?.mode !== expectedMppMode) {
263
+ throw new Error(
264
+ `expected ${expectedMppMode} reservation, got ${sandbox.reservation.mpp?.mode ?? "none"}`
265
+ );
266
+ }
267
+ if (!expectedMppMode && !sandbox.reservation.mpp?.mode) {
268
+ throw new Error("expected sandbox reservation MPP metadata");
269
+ }
270
+ const exec = await client.exec(sandbox.id, {
271
+ command: [
272
+ `printf '${expectedExec}\\n'`,
273
+ "test -f README && printf 'repo-clone-ok\\n'",
274
+ "cat > server.cjs <<'EOF'",
275
+ "const { createServer } = require('node:http');",
276
+ `createServer((_request, response) => response.end('${expectedPreview}')).listen(${previewPort}, '0.0.0.0');`,
277
+ "EOF",
278
+ "nohup node server.cjs > server.log 2>&1 & sleep 1"
279
+ ].join("\n"),
280
+ timeoutSeconds: 120
281
+ });
282
+ if (exec.command.status !== "succeeded") {
283
+ throw new Error(`expected command success, got ${exec.command.status}`);
284
+ }
285
+ if (!exec.command.output.includes(expectedExec)) {
286
+ throw new Error("expected exec marker");
287
+ }
288
+ await client.uploadFile(
289
+ sandbox.id,
290
+ "openpond-code-smoke.txt",
291
+ expectedFile
292
+ );
293
+ const downloaded = await client.downloadFile(
294
+ sandbox.id,
295
+ "openpond-code-smoke.txt"
296
+ );
297
+ if (downloaded !== expectedFile) {
298
+ throw new Error("expected file roundtrip marker");
299
+ }
300
+ let snapshotId = null;
301
+ if (options.snapshot || options.fork) {
302
+ const snapshotResponse = await client.createSnapshot(sandbox.id, {
303
+ async: true,
304
+ name: `openpond-code-smoke-${runId}`,
305
+ replay: {
306
+ entrypoints: [
307
+ {
308
+ command: "cat openpond-code-smoke.txt",
309
+ name: "default"
310
+ }
311
+ ],
312
+ retention: {
313
+ class: "pinned"
314
+ },
315
+ safety: {
316
+ cleanup: "delete",
317
+ idleTimeoutSeconds: 600,
318
+ internetEgress: "block",
319
+ maxDurationSeconds: 600,
320
+ maxSpendUsd: options.budgetUsd ?? "0.05",
321
+ publicPreview: false
322
+ },
323
+ validation: {
324
+ commands: [
325
+ {
326
+ command: "test -f openpond-code-smoke.txt"
327
+ }
328
+ ]
329
+ }
330
+ }
331
+ });
332
+ const snapshot = snapshotResponse.snapshot ?? (await waitForSnapshotReady(
333
+ client,
334
+ sandbox.id,
335
+ snapshotResponse.snapshotJob?.snapshotId
336
+ )).snapshot;
337
+ snapshotId = snapshot.id;
338
+ if (snapshot.state !== "ready") {
339
+ throw new Error(`expected ready snapshot, got ${snapshot.state}`);
340
+ }
341
+ }
342
+ if (options.fork) {
343
+ if (!snapshotId) {
344
+ throw new Error("expected snapshot id before fork");
345
+ }
346
+ const forked = await waitForCreateReady(
347
+ client,
348
+ (await client.forkSnapshot(
349
+ snapshotId,
350
+ {
351
+ budget: { maxUsd: options.budgetUsd ?? "0.05" },
352
+ metadata: {
353
+ source: "openpond-code-sandbox-smoke-fork",
354
+ templateSnapshotId: snapshotId
355
+ }
356
+ },
357
+ { async: true }
358
+ )).sandbox
359
+ );
360
+ forkSandboxId = forked.id;
361
+ const forkExec = await client.exec(forked.id, {
362
+ command: "cat openpond-code-smoke.txt",
363
+ timeoutSeconds: 120
364
+ });
365
+ if (forkExec.command.status !== "succeeded") {
366
+ throw new Error(
367
+ `expected fork command success, got ${forkExec.command.status}`
368
+ );
369
+ }
370
+ if (!forkExec.command.output.includes(expectedFile)) {
371
+ throw new Error("expected fork snapshot marker");
372
+ }
373
+ if (!options.keep) {
374
+ await deleteSandboxForSmoke(client, forked.id);
375
+ forkDeleted = true;
376
+ }
377
+ }
378
+ let previewStatus = null;
379
+ if (options.preview !== false) {
380
+ const opened = await client.openPort(sandbox.id, {
381
+ label: "openpond-code-smoke",
382
+ port: previewPort
383
+ });
384
+ const preview = await fetch(opened.preview.url);
385
+ previewStatus = preview.status;
386
+ const body = await preview.text();
387
+ if (preview.status !== 200) {
388
+ throw new Error(`expected preview HTTP 200, got ${preview.status}`);
389
+ }
390
+ if (!body.includes(expectedPreview)) {
391
+ throw new Error("expected preview marker");
392
+ }
393
+ }
394
+ const { sandbox: readback, receipts } = await stopSandboxForSmoke(
395
+ client,
396
+ sandbox.id
397
+ );
398
+ if (!options.keep) {
399
+ await deleteSandboxForSmoke(client, sandbox.id);
400
+ deleted = true;
401
+ }
402
+ return {
403
+ deleted,
404
+ execOutput: exec.command.output.trim(),
405
+ fileRoundtrip: true,
406
+ forkSandboxId,
407
+ previewStatus,
408
+ receiptRefs: receipts.map((receipt) => receipt.mpp.receiptRef ?? null),
409
+ reservationRef: sandbox.reservation.mpp?.reservationRef ?? null,
410
+ runId,
411
+ sandboxId: sandbox.id,
412
+ snapshotId,
413
+ state: readback.state
414
+ };
415
+ } finally {
416
+ if (forkSandboxId && !options.keep && !forkDeleted) {
417
+ await cleanupSandboxBestEffort(client, forkSandboxId);
418
+ }
419
+ if (sandboxId && !options.keep && !deleted) {
420
+ await cleanupSandboxBestEffort(client, sandboxId);
421
+ }
422
+ }
423
+ }
424
+ async function stopSandboxForSmoke(client, sandboxId) {
425
+ try {
426
+ await client.stop(sandboxId);
427
+ } catch {
428
+ await client.stop(sandboxId, { async: true });
429
+ }
430
+ const sandbox = await waitForSandboxState(
431
+ client,
432
+ sandboxId,
433
+ /* @__PURE__ */ new Set(["stopped", "deleted"]),
434
+ "stop"
435
+ );
436
+ const receipts = await waitForReceipts(client, sandboxId);
437
+ if (receipts.length === 0) {
438
+ throw new Error("expected receipt readback");
439
+ }
440
+ return { sandbox, receipts };
441
+ }
442
+ async function deleteSandboxForSmoke(client, sandboxId) {
443
+ try {
444
+ const deleted = await client.delete(sandboxId);
445
+ if (deleted.state === "deleted") {
446
+ return deleted;
447
+ }
448
+ await client.delete(sandboxId, { async: true });
449
+ } catch {
450
+ await client.delete(sandboxId, { async: true });
451
+ }
452
+ return waitForSandboxState(
453
+ client,
454
+ sandboxId,
455
+ /* @__PURE__ */ new Set(["deleted"]),
456
+ "delete"
457
+ );
458
+ }
459
+ async function cleanupSandboxBestEffort(client, sandboxId) {
460
+ try {
461
+ await deleteSandboxForSmoke(client, sandboxId);
462
+ } catch {
463
+ await client.delete(sandboxId, { async: true }).catch(() => void 0);
464
+ }
465
+ }
466
+ async function waitForSandboxState(client, sandboxId, targetStates, operation) {
467
+ const timeoutMs = 5 * 6e4;
468
+ const pollMs = 3e3;
469
+ const deadline = Date.now() + timeoutMs;
470
+ let latest = await client.get(sandboxId);
471
+ while (Date.now() < deadline) {
472
+ if (targetStates.has(latest.state)) {
473
+ return latest;
474
+ }
475
+ if (latest.state === "error") {
476
+ throw new Error(`sandbox ${operation} failed: ${sandboxId}`);
477
+ }
478
+ await sleep(pollMs);
479
+ latest = await client.get(sandboxId);
480
+ }
481
+ throw new Error(
482
+ `sandbox ${operation} did not reach ${[...targetStates].join(
483
+ "/"
484
+ )} before timeout: ${sandboxId} (${latest.state})`
485
+ );
486
+ }
487
+ async function waitForReceipts(client, sandboxId) {
488
+ const timeoutMs = 2 * 6e4;
489
+ const pollMs = 3e3;
490
+ const deadline = Date.now() + timeoutMs;
491
+ let receipts = await client.receipts(sandboxId);
492
+ while (Date.now() < deadline) {
493
+ if (receipts.length > 0) {
494
+ return receipts;
495
+ }
496
+ await sleep(pollMs);
497
+ receipts = await client.receipts(sandboxId);
498
+ }
499
+ return receipts;
500
+ }
501
+ async function waitForCreateReady(client, sandbox) {
502
+ if (sandbox.state === "running" || sandbox.state === "stopped") {
503
+ return sandbox;
504
+ }
505
+ if (sandbox.state === "error") {
506
+ throw new Error(
507
+ `sandbox create failed: ${sandbox.id}
508
+ ${sandbox.logs.join("\n")}`
509
+ );
510
+ }
511
+ const timeoutMs = 12 * 6e4;
512
+ const pollMs = 3e3;
513
+ const deadline = Date.now() + timeoutMs;
514
+ let latest = sandbox;
515
+ while (Date.now() < deadline) {
516
+ await sleep(pollMs);
517
+ latest = await client.get(sandbox.id);
518
+ if (latest.state === "running" || latest.state === "stopped") {
519
+ return latest;
520
+ }
521
+ if (latest.state === "error") {
522
+ throw new Error(
523
+ `sandbox create failed: ${latest.id}
524
+ ${latest.logs.join("\n")}`
525
+ );
526
+ }
527
+ }
528
+ throw new Error(
529
+ `sandbox create did not reach running state before timeout: ${latest.id} (${latest.state})`
530
+ );
531
+ }
532
+ async function waitForSnapshotReady(client, sandboxId, snapshotId) {
533
+ if (!snapshotId) {
534
+ throw new Error("snapshot job did not return snapshot id");
535
+ }
536
+ const timeoutMs = 12 * 6e4;
537
+ const pollMs = 3e3;
538
+ const deadline = Date.now() + timeoutMs;
539
+ let latest = await client.get(sandboxId);
540
+ while (Date.now() < deadline) {
541
+ const snapshot = latest.snapshots?.find((item) => item.id === snapshotId);
542
+ if (snapshot?.state === "ready") {
543
+ return { sandbox: latest, snapshot };
544
+ }
545
+ const job = latest.snapshotJobs?.find(
546
+ (item) => item.snapshotId === snapshotId
547
+ );
548
+ if (job?.status === "failed") {
549
+ throw new Error(`snapshot job failed: ${job.error ?? snapshotId}`);
550
+ }
551
+ await sleep(pollMs);
552
+ latest = await client.get(sandboxId);
553
+ }
554
+ throw new Error(
555
+ `snapshot did not reach ready state before timeout: ${snapshotId}`
556
+ );
557
+ }
558
+ function sleep(ms) {
559
+ return new Promise((resolve) => setTimeout(resolve, ms));
560
+ }
561
+
562
+ // ../cloud/src/sandbox/async-request-options.ts
563
+ function asyncRequestHeaders(options = {}) {
564
+ return options.async || options.respondAsync ? { Prefer: "respond-async" } : void 0;
565
+ }
566
+
567
+ // ../cloud/src/api/vercel-protection.ts
568
+ var VERCEL_PROTECTION_BYPASS_HEADER = "x-vercel-protection-bypass";
569
+ function withVercelProtectionBypass(requestUrl, inputHeaders, env = typeof process === "undefined" ? {} : process.env) {
570
+ const headers = new Headers(inputHeaders);
571
+ const secret = env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();
572
+ if (!secret || !isOpenPondStagingUrl(requestUrl)) return headers;
573
+ headers.set(VERCEL_PROTECTION_BYPASS_HEADER, secret);
574
+ return headers;
575
+ }
576
+ function isOpenPondStagingUrl(requestUrl) {
577
+ try {
578
+ const hostname = new URL(requestUrl).hostname.toLowerCase();
579
+ return hostname === "staging.openpond.ai" || hostname === "staging-api.openpond.ai" || hostname.endsWith(".staging-api.openpond.ai");
580
+ } catch {
581
+ return false;
582
+ }
583
+ }
584
+
585
+ // ../cloud/src/api/core.ts
586
+ var DEFAULT_API_TIMEOUT_MS = 3e4;
587
+ var DEFAULT_API_RESPONSE_BYTES = 8 * 1024 * 1024;
588
+ var LONG_STREAM_API_OPTIONS = { timeoutMs: 15 * 60 * 1e3, maxResponseBytes: 64 * 1024 * 1024 };
589
+ var ApiTimeoutError = class extends Error {
590
+ constructor(timeoutMs, requestUrl) {
591
+ super(`API request timed out after ${timeoutMs}ms: ${requestUrl}`);
592
+ this.timeoutMs = timeoutMs;
593
+ this.requestUrl = requestUrl;
594
+ this.name = "ApiTimeoutError";
595
+ }
596
+ timeoutMs;
597
+ requestUrl;
598
+ code = "OPENPOND_API_TIMEOUT";
599
+ };
600
+ var ApiResponseTooLargeError = class extends Error {
601
+ constructor(maximumBytes, requestUrl) {
602
+ super(`API response exceeded ${maximumBytes} bytes: ${requestUrl}`);
603
+ this.maximumBytes = maximumBytes;
604
+ this.requestUrl = requestUrl;
605
+ this.name = "ApiResponseTooLargeError";
606
+ }
607
+ maximumBytes;
608
+ requestUrl;
609
+ code = "OPENPOND_API_RESPONSE_TOO_LARGE";
610
+ };
611
+ async function apiFetch(baseUrl, token, requestPath, options = {}) {
612
+ const { timeoutMs = DEFAULT_API_TIMEOUT_MS, maxResponseBytes = DEFAULT_API_RESPONSE_BYTES, ...init } = options;
613
+ const requestUrl = `${baseUrl}${requestPath}`;
614
+ const headers = withVercelProtectionBypass(requestUrl, init.headers);
615
+ headers.set("Content-Type", "application/json");
616
+ const apiKey = process.env.OPENPOND_API_KEY;
617
+ const trimmedToken = token?.trim() || "";
618
+ const tokenIsApiKey = trimmedToken.startsWith("opk_");
619
+ const effectiveApiKey = apiKey || (tokenIsApiKey ? trimmedToken : null);
620
+ if (effectiveApiKey && !headers.has("openpond-api-key")) headers.set("openpond-api-key", effectiveApiKey);
621
+ if (token) {
622
+ headers.set("Authorization", tokenIsApiKey ? `ApiKey ${trimmedToken}` : `Bearer ${token}`);
623
+ } else if (apiKey && !headers.has("Authorization")) {
624
+ headers.set("Authorization", `ApiKey ${apiKey}`);
625
+ }
626
+ const timeoutController = new AbortController();
627
+ const timeoutError = new ApiTimeoutError(timeoutMs, requestUrl);
628
+ const timer = timeoutMs > 0 ? setTimeout(() => timeoutController.abort(timeoutError), timeoutMs) : null;
629
+ timer?.unref?.();
630
+ const signal = composedSignal(init.signal, timeoutController.signal, timeoutMs);
631
+ const cleanup = () => {
632
+ if (timer) clearTimeout(timer);
633
+ };
634
+ try {
635
+ const response = await fetch(requestUrl, { ...init, headers, signal });
636
+ return boundedResponse(response, {
637
+ cleanup,
638
+ maximumBytes: maxResponseBytes,
639
+ requestUrl,
640
+ timeoutController,
641
+ timeoutError
642
+ });
643
+ } catch (error) {
644
+ cleanup();
645
+ if (timeoutController.signal.aborted) throw timeoutError;
646
+ throw error;
647
+ }
648
+ }
649
+ async function readApiJson(response, label) {
650
+ let payload;
651
+ try {
652
+ const text = await response.text();
653
+ payload = text ? JSON.parse(text) : {};
654
+ } catch (error) {
655
+ if (error instanceof ApiTimeoutError || error instanceof ApiResponseTooLargeError) throw error;
656
+ payload = {};
657
+ }
658
+ if (!response.ok) {
659
+ const message = typeof payload.message === "string" ? payload.message : typeof payload.error === "string" ? payload.error : "";
660
+ throw new Error(`${label} failed: ${response.status}${message ? ` ${message}` : ""}`);
661
+ }
662
+ return payload;
663
+ }
664
+ function boundedResponse(response, input) {
665
+ if (!response.body) {
666
+ input.cleanup();
667
+ return response;
668
+ }
669
+ const contentLength = Number(response.headers.get("content-length"));
670
+ if (input.maximumBytes > 0 && Number.isFinite(contentLength) && contentLength > input.maximumBytes) {
671
+ input.cleanup();
672
+ void response.body.cancel();
673
+ throw new ApiResponseTooLargeError(input.maximumBytes, input.requestUrl);
674
+ }
675
+ const reader = response.body.getReader();
676
+ let receivedBytes = 0;
677
+ const body = new ReadableStream({
678
+ async pull(controller) {
679
+ try {
680
+ const result = await reader.read();
681
+ if (result.done) {
682
+ input.cleanup();
683
+ controller.close();
684
+ return;
685
+ }
686
+ receivedBytes += result.value.byteLength;
687
+ if (input.maximumBytes > 0 && receivedBytes > input.maximumBytes) {
688
+ input.cleanup();
689
+ await reader.cancel();
690
+ controller.error(new ApiResponseTooLargeError(input.maximumBytes, input.requestUrl));
691
+ return;
692
+ }
693
+ controller.enqueue(result.value);
694
+ } catch (error) {
695
+ input.cleanup();
696
+ controller.error(input.timeoutController.signal.aborted ? input.timeoutError : error);
697
+ }
698
+ },
699
+ async cancel(reason) {
700
+ input.cleanup();
701
+ await reader.cancel(reason);
702
+ }
703
+ });
704
+ return new Response(body, {
705
+ headers: response.headers,
706
+ status: response.status,
707
+ statusText: response.statusText
708
+ });
709
+ }
710
+ function composedSignal(callerSignal, timeoutSignal, timeoutMs) {
711
+ if (timeoutMs <= 0) return callerSignal ?? void 0;
712
+ return callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
713
+ }
714
+
715
+ // ../cloud/src/urls.ts
716
+ var DEFAULT_OPENPOND_WEB_BASE_URL = "https://openpond.ai";
717
+ var DEFAULT_OPENPOND_API_BASE_URL = "https://api.openpond.ai";
718
+ var DEFAULT_OPENPOND_OPCHAT_API_BASE_URL = "https://api.openpond.ai/opchat/v1";
719
+
720
+ // ../cloud/src/sandbox/stream.ts
721
+ async function streamSandboxEventOutput(params) {
722
+ const response = await apiFetch(
723
+ params.sandboxApiUrl,
724
+ params.apiKey,
725
+ params.path,
726
+ { timeoutMs: 0, maxResponseBytes: 0 }
727
+ );
728
+ if (!response.body) {
729
+ return;
730
+ }
731
+ const reader = response.body.getReader();
732
+ const decoder = new TextDecoder();
733
+ let buffered = "";
734
+ try {
735
+ while (true) {
736
+ const { done, value } = await reader.read();
737
+ if (done) break;
738
+ buffered += decoder.decode(value, { stream: true });
739
+ let separatorIndex = buffered.indexOf("\n\n");
740
+ while (separatorIndex !== -1) {
741
+ const event = buffered.slice(0, separatorIndex);
742
+ buffered = buffered.slice(separatorIndex + 2);
743
+ const output = parseProcessOutputEvent(event);
744
+ if (output) process.stdout.write(output);
745
+ separatorIndex = buffered.indexOf("\n\n");
746
+ }
747
+ }
748
+ } finally {
749
+ reader.releaseLock();
750
+ }
751
+ }
752
+ function normalizePtyInput(input) {
753
+ if (typeof input === "string") {
754
+ return { dataBase64: Buffer.from(input, "utf-8").toString("base64") };
755
+ }
756
+ if (input instanceof Uint8Array) {
757
+ return { dataBase64: Buffer.from(input).toString("base64") };
758
+ }
759
+ return input;
760
+ }
761
+ function parseProcessOutputEvent(event) {
762
+ if (!event.includes("event: output")) {
763
+ return null;
764
+ }
765
+ const dataLines = event.split(/\r?\n/).filter((line) => line.startsWith("data: ")).map((line) => line.slice("data: ".length));
766
+ if (dataLines.length === 0) {
767
+ return null;
768
+ }
769
+ try {
770
+ const parsed = JSON.parse(dataLines.join("\n"));
771
+ return typeof parsed.output === "string" ? parsed.output : null;
772
+ } catch {
773
+ return null;
774
+ }
775
+ }
776
+
777
+ // ../cloud/src/sandbox/url.ts
778
+ function normalizeSandboxApiUrl(baseUrlOrApiUrl) {
779
+ const trimmed = baseUrlOrApiUrl.trim().replace(/\/$/, "");
780
+ if (!trimmed) {
781
+ throw new Error("sandbox API URL must be non-empty");
782
+ }
783
+ const url = new URL(trimmed);
784
+ const normalizedPath = url.pathname.replace(/\/$/, "");
785
+ if (normalizedPath.endsWith("/v1/sandboxes") || normalizedPath.endsWith("/api/sandboxes")) {
786
+ return `${url.origin}${normalizedPath}`;
787
+ }
788
+ if (normalizedPath.endsWith("/v1")) {
789
+ return `${url.origin}${normalizedPath}/sandboxes`;
790
+ }
791
+ if (isOpenPondHostedApiHost(url.hostname)) {
792
+ return `${url.origin}${normalizedPath}/v1/sandboxes`;
793
+ }
794
+ if (url.origin === DEFAULT_OPENPOND_WEB_BASE_URL) {
795
+ return `${DEFAULT_OPENPOND_API_BASE_URL}/v1/sandboxes`;
796
+ }
797
+ return `${url.origin}${normalizedPath}/api/sandboxes`;
798
+ }
799
+ function apiRootUrlFromSandboxApiUrl(sandboxApiUrl) {
800
+ const suffix = "/sandboxes";
801
+ if (!sandboxApiUrl.endsWith(suffix)) {
802
+ throw new Error("sandbox API URL must end with /sandboxes");
803
+ }
804
+ return sandboxApiUrl.slice(0, -suffix.length);
805
+ }
806
+ function isOpenPondHostedApiHost(hostname) {
807
+ return hostname === "api.openpond.ai" || hostname.startsWith("api") && hostname.endsWith(".openpond.ai");
808
+ }
809
+
810
+ // ../cloud/src/sandbox/sandbox-instance-client.ts
811
+ var OpenPondSandboxInstanceClient = class {
812
+ apiKey;
813
+ apiRootUrl;
814
+ sandboxApiUrl;
815
+ constructor(options) {
816
+ this.apiKey = options.apiKey;
817
+ this.sandboxApiUrl = normalizeSandboxApiUrl(
818
+ options.sandboxApiUrl ?? options.baseUrl ?? DEFAULT_OPENPOND_API_BASE_URL
819
+ );
820
+ this.apiRootUrl = apiRootUrlFromSandboxApiUrl(this.sandboxApiUrl);
821
+ }
822
+ create(input, options = {}) {
823
+ return this.request("", {
824
+ method: "POST",
825
+ headers: asyncRequestHeaders(options),
826
+ body: JSON.stringify(input)
827
+ }).then((payload) => payload.sandbox);
828
+ }
829
+ get(sandboxId) {
830
+ return this.request(
831
+ `/${encodeURIComponent(sandboxId)}`
832
+ ).then((payload) => payload.sandbox);
833
+ }
834
+ exec(sandboxId, input) {
835
+ return this.request(
836
+ `/${encodeURIComponent(sandboxId)}/exec`,
837
+ {
838
+ method: "POST",
839
+ body: JSON.stringify(input)
840
+ }
841
+ );
842
+ }
843
+ startProcess(sandboxId, input) {
844
+ return this.request(
845
+ `/${encodeURIComponent(sandboxId)}/processes`,
846
+ {
847
+ method: "POST",
848
+ body: JSON.stringify(input)
849
+ }
850
+ );
851
+ }
852
+ listProcesses(sandboxId) {
853
+ return this.request(
854
+ `/${encodeURIComponent(sandboxId)}/processes`
855
+ );
856
+ }
857
+ getProcess(sandboxId, processId, input = {}) {
858
+ const query = new URLSearchParams();
859
+ if (input.since !== void 0)
860
+ query.set("since", String(Math.max(0, input.since)));
861
+ return this.request(
862
+ `/${encodeURIComponent(sandboxId)}/processes/${encodeURIComponent(
863
+ processId
864
+ )}${query.size > 0 ? `?${query.toString()}` : ""}`
865
+ );
866
+ }
867
+ stopProcess(sandboxId, processId) {
868
+ return this.request(
869
+ `/${encodeURIComponent(sandboxId)}/processes/${encodeURIComponent(
870
+ processId
871
+ )}`,
872
+ {
873
+ method: "DELETE"
874
+ }
875
+ );
876
+ }
877
+ async streamProcessOutput(sandboxId, processId, input = {}) {
878
+ const query = new URLSearchParams();
879
+ if (input.since !== void 0)
880
+ query.set("since", String(Math.max(0, input.since)));
881
+ await streamSandboxEventOutput({
882
+ sandboxApiUrl: this.sandboxApiUrl,
883
+ apiKey: this.apiKey,
884
+ path: `/${encodeURIComponent(sandboxId)}/processes/${encodeURIComponent(
885
+ processId
886
+ )}/stream${query.size > 0 ? `?${query.toString()}` : ""}`
887
+ });
888
+ }
889
+ startPty(sandboxId, input = {}) {
890
+ return this.request(
891
+ `/${encodeURIComponent(sandboxId)}/pty`,
892
+ {
893
+ method: "POST",
894
+ body: JSON.stringify(input)
895
+ }
896
+ );
897
+ }
898
+ listPtys(sandboxId) {
899
+ return this.request(
900
+ `/${encodeURIComponent(sandboxId)}/pty`
901
+ );
902
+ }
903
+ getPty(sandboxId, ptyId, input = {}) {
904
+ const query = new URLSearchParams();
905
+ if (input.since !== void 0)
906
+ query.set("since", String(Math.max(0, input.since)));
907
+ return this.request(
908
+ `/${encodeURIComponent(sandboxId)}/pty/${encodeURIComponent(ptyId)}${query.size > 0 ? `?${query.toString()}` : ""}`
909
+ );
910
+ }
911
+ writePtyInput(sandboxId, ptyId, input) {
912
+ return this.request(
913
+ `/${encodeURIComponent(sandboxId)}/pty/${encodeURIComponent(
914
+ ptyId
915
+ )}/input`,
916
+ {
917
+ method: "POST",
918
+ body: JSON.stringify(normalizePtyInput(input))
919
+ }
920
+ );
921
+ }
922
+ stopPty(sandboxId, ptyId) {
923
+ return this.request(
924
+ `/${encodeURIComponent(sandboxId)}/pty/${encodeURIComponent(ptyId)}`,
925
+ {
926
+ method: "DELETE"
927
+ }
928
+ );
929
+ }
930
+ async streamPtyOutput(sandboxId, ptyId, input = {}) {
931
+ const query = new URLSearchParams();
932
+ if (input.since !== void 0)
933
+ query.set("since", String(Math.max(0, input.since)));
934
+ await streamSandboxEventOutput({
935
+ sandboxApiUrl: this.sandboxApiUrl,
936
+ apiKey: this.apiKey,
937
+ path: `/${encodeURIComponent(sandboxId)}/pty/${encodeURIComponent(
938
+ ptyId
939
+ )}/stream${query.size > 0 ? `?${query.toString()}` : ""}`
940
+ });
941
+ }
942
+ uploadFile(sandboxId, path, contents) {
943
+ return this.uploadFileBase64(
944
+ sandboxId,
945
+ path,
946
+ Buffer.from(contents, "utf-8").toString("base64")
947
+ );
948
+ }
949
+ uploadFileBase64(sandboxId, path, contentsBase64) {
950
+ return this.request(
951
+ `/${encodeURIComponent(sandboxId)}/files`,
952
+ {
953
+ method: "POST",
954
+ body: JSON.stringify({
955
+ path,
956
+ contentsBase64
957
+ })
958
+ }
959
+ );
960
+ }
961
+ async downloadFile(sandboxId, path) {
962
+ const payload = await this.downloadFileResponse(sandboxId, path);
963
+ return Buffer.from(payload.file.contentsBase64, "base64").toString("utf-8");
964
+ }
965
+ downloadFileResponse(sandboxId, input) {
966
+ const normalized = typeof input === "string" ? { path: input } : input;
967
+ const query = new URLSearchParams({ path: normalized.path });
968
+ if (normalized.offsetBytes !== void 0) {
969
+ query.set("offsetBytes", String(normalized.offsetBytes));
970
+ }
971
+ if (normalized.maxBytes !== void 0) {
972
+ query.set("maxBytes", String(normalized.maxBytes));
973
+ }
974
+ return this.request(
975
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`
976
+ );
977
+ }
978
+ listFiles(sandboxId, input = {}) {
979
+ const query = new URLSearchParams({ list: "1" });
980
+ if (input.path) query.set("path", input.path);
981
+ if (input.recursive !== void 0)
982
+ query.set("recursive", String(input.recursive));
983
+ if (input.maxEntries !== void 0)
984
+ query.set("maxEntries", String(input.maxEntries));
985
+ return this.request(
986
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`
987
+ );
988
+ }
989
+ deleteFile(sandboxId, path, input = {}) {
990
+ const query = new URLSearchParams({ path });
991
+ if (input.recursive !== void 0)
992
+ query.set("recursive", String(input.recursive));
993
+ return this.request(
994
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`,
995
+ {
996
+ method: "DELETE"
997
+ }
998
+ );
999
+ }
1000
+ statFile(sandboxId, path) {
1001
+ const query = new URLSearchParams({ stat: "1", path });
1002
+ return this.request(
1003
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`
1004
+ );
1005
+ }
1006
+ mkdir(sandboxId, input) {
1007
+ const normalized = typeof input === "string" ? { path: input } : input;
1008
+ const query = new URLSearchParams({ path: normalized.path });
1009
+ if (normalized.recursive !== void 0)
1010
+ query.set("recursive", String(normalized.recursive));
1011
+ return this.request(
1012
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`,
1013
+ {
1014
+ method: "PUT"
1015
+ }
1016
+ );
1017
+ }
1018
+ moveFile(sandboxId, input) {
1019
+ const query = new URLSearchParams({
1020
+ fromPath: input.fromPath,
1021
+ toPath: input.toPath
1022
+ });
1023
+ if (input.overwrite !== void 0)
1024
+ query.set("overwrite", String(input.overwrite));
1025
+ return this.request(
1026
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`,
1027
+ {
1028
+ method: "PATCH"
1029
+ }
1030
+ );
1031
+ }
1032
+ searchFiles(sandboxId, input) {
1033
+ const query = new URLSearchParams({
1034
+ search: "1",
1035
+ query: input.query
1036
+ });
1037
+ if (input.path) query.set("path", input.path);
1038
+ if (input.maxResults !== void 0)
1039
+ query.set("maxResults", String(input.maxResults));
1040
+ return this.request(
1041
+ `/${encodeURIComponent(sandboxId)}/files?${query.toString()}`
1042
+ );
1043
+ }
1044
+ openPort(sandboxId, input) {
1045
+ return this.request(
1046
+ `/${encodeURIComponent(sandboxId)}/ports`,
1047
+ {
1048
+ method: "POST",
1049
+ body: JSON.stringify(input)
1050
+ }
1051
+ );
1052
+ }
1053
+ createSnapshot(sandboxId, input) {
1054
+ return this.request(
1055
+ `/${encodeURIComponent(sandboxId)}/snapshots`,
1056
+ {
1057
+ method: "POST",
1058
+ body: JSON.stringify(input)
1059
+ }
1060
+ );
1061
+ }
1062
+ updateSnapshot(sandboxId, snapshotId, input) {
1063
+ return this.request(
1064
+ `/${encodeURIComponent(sandboxId)}/snapshots/${encodeURIComponent(
1065
+ snapshotId
1066
+ )}`,
1067
+ {
1068
+ method: "PATCH",
1069
+ body: JSON.stringify(input)
1070
+ }
1071
+ );
1072
+ }
1073
+ validateSnapshot(sandboxId, snapshotId, input = {}) {
1074
+ return this.request(
1075
+ `/${encodeURIComponent(sandboxId)}/snapshots/${encodeURIComponent(
1076
+ snapshotId
1077
+ )}/validate`,
1078
+ {
1079
+ method: "POST",
1080
+ body: JSON.stringify(input)
1081
+ }
1082
+ );
1083
+ }
1084
+ publishSnapshot(sandboxId, snapshotId) {
1085
+ return this.request(
1086
+ `/${encodeURIComponent(sandboxId)}/snapshots/${encodeURIComponent(
1087
+ snapshotId
1088
+ )}/publish`,
1089
+ {
1090
+ method: "POST"
1091
+ }
1092
+ );
1093
+ }
1094
+ fork(sandboxId, input = {}) {
1095
+ return this.request(
1096
+ `/${encodeURIComponent(sandboxId)}/fork`,
1097
+ {
1098
+ method: "POST",
1099
+ body: JSON.stringify(input)
1100
+ }
1101
+ );
1102
+ }
1103
+ stop(sandboxId, options = {}) {
1104
+ const query = new URLSearchParams();
1105
+ if (options.failOnUnpreservedChanges) {
1106
+ query.set("failOnUnpreservedChanges", "true");
1107
+ }
1108
+ return this.request(
1109
+ `/${encodeURIComponent(sandboxId)}/stop${query.size > 0 ? `?${query.toString()}` : ""}`,
1110
+ {
1111
+ method: "POST",
1112
+ headers: asyncRequestHeaders(options)
1113
+ }
1114
+ );
1115
+ }
1116
+ start(sandboxId, options = {}) {
1117
+ return this.request(
1118
+ `/${encodeURIComponent(sandboxId)}/start`,
1119
+ {
1120
+ method: "POST",
1121
+ headers: asyncRequestHeaders(options)
1122
+ }
1123
+ );
1124
+ }
1125
+ restore(sandboxId) {
1126
+ return this.request(
1127
+ `/${encodeURIComponent(sandboxId)}/restore`,
1128
+ {
1129
+ method: "POST"
1130
+ }
1131
+ );
1132
+ }
1133
+ delete(sandboxId, options = {}) {
1134
+ const query = new URLSearchParams();
1135
+ if (options.failOnUnpreservedChanges) {
1136
+ query.set("failOnUnpreservedChanges", "true");
1137
+ }
1138
+ return this.request(
1139
+ `/${encodeURIComponent(sandboxId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
1140
+ {
1141
+ method: "DELETE",
1142
+ headers: asyncRequestHeaders(options)
1143
+ }
1144
+ ).then((payload) => payload.sandbox);
1145
+ }
1146
+ receipts(sandboxId) {
1147
+ return this.request(
1148
+ `/${encodeURIComponent(sandboxId)}/receipts`
1149
+ ).then((payload) => payload.receipts);
1150
+ }
1151
+ logs(sandboxId) {
1152
+ return this.request(
1153
+ `/${encodeURIComponent(sandboxId)}/logs`
1154
+ ).then((payload) => payload.logs);
1155
+ }
1156
+ gitStatus(sandboxId) {
1157
+ return this.request(
1158
+ `/${encodeURIComponent(sandboxId)}/git/status`
1159
+ );
1160
+ }
1161
+ gitDiff(sandboxId, input = {}) {
1162
+ return this.request(
1163
+ `/${encodeURIComponent(sandboxId)}/git/diff`,
1164
+ {
1165
+ method: "POST",
1166
+ body: JSON.stringify(input)
1167
+ }
1168
+ );
1169
+ }
1170
+ gitExportPatch(sandboxId, input = {}) {
1171
+ return this.request(
1172
+ `/${encodeURIComponent(sandboxId)}/git/export-patch`,
1173
+ {
1174
+ method: "POST",
1175
+ body: JSON.stringify(input)
1176
+ }
1177
+ );
1178
+ }
1179
+ gitBranch(sandboxId, input) {
1180
+ return this.request(
1181
+ `/${encodeURIComponent(sandboxId)}/git/branch`,
1182
+ {
1183
+ method: "POST",
1184
+ body: JSON.stringify(input)
1185
+ }
1186
+ );
1187
+ }
1188
+ gitCommit(sandboxId, input) {
1189
+ return this.request(
1190
+ `/${encodeURIComponent(sandboxId)}/git/commit`,
1191
+ {
1192
+ method: "POST",
1193
+ body: JSON.stringify(input)
1194
+ }
1195
+ );
1196
+ }
1197
+ gitPull(sandboxId, input = {}) {
1198
+ return this.request(
1199
+ `/${encodeURIComponent(sandboxId)}/git/pull`,
1200
+ {
1201
+ method: "POST",
1202
+ body: JSON.stringify(input)
1203
+ }
1204
+ );
1205
+ }
1206
+ gitPush(sandboxId, input = {}) {
1207
+ return this.request(
1208
+ `/${encodeURIComponent(sandboxId)}/git/push`,
1209
+ {
1210
+ method: "POST",
1211
+ body: JSON.stringify(input)
1212
+ }
1213
+ );
1214
+ }
1215
+ billing(sandboxId) {
1216
+ return this.request(
1217
+ `/${encodeURIComponent(sandboxId)}/billing`
1218
+ );
1219
+ }
1220
+ pricing() {
1221
+ return this.request("/pricing");
1222
+ }
1223
+ costs(input = {}) {
1224
+ const query = new URLSearchParams();
1225
+ if (input.teamId) query.set("teamId", input.teamId);
1226
+ if (input.projectId) query.set("projectId", input.projectId);
1227
+ if (input.agentId) query.set("agentId", input.agentId);
1228
+ return this.request(
1229
+ `/costs${query.size > 0 ? `?${query.toString()}` : ""}`
1230
+ );
1231
+ }
1232
+ integrationLeases(sandboxId) {
1233
+ return this.request(
1234
+ `/${encodeURIComponent(sandboxId)}/integrations`
1235
+ );
1236
+ }
1237
+ attachIntegrationConnection(sandboxId, input) {
1238
+ return this.request(
1239
+ `/${encodeURIComponent(sandboxId)}/integrations`,
1240
+ {
1241
+ method: "POST",
1242
+ body: JSON.stringify(input)
1243
+ }
1244
+ );
1245
+ }
1246
+ removeIntegrationLease(sandboxId, leaseId) {
1247
+ return this.request(
1248
+ `/${encodeURIComponent(sandboxId)}/integrations`,
1249
+ {
1250
+ method: "DELETE",
1251
+ body: JSON.stringify({ leaseId })
1252
+ }
1253
+ );
1254
+ }
1255
+ async request(path, init = {}) {
1256
+ const response = await apiFetch(
1257
+ this.sandboxApiUrl,
1258
+ this.apiKey,
1259
+ path,
1260
+ init
1261
+ );
1262
+ return readApiJson(response, "Sandbox request");
1263
+ }
1264
+ async requestApiRoot(path, init = {}) {
1265
+ const response = await apiFetch(this.apiRootUrl, this.apiKey, path, init);
1266
+ return readApiJson(response, "OpenPond API request");
1267
+ }
1268
+ };
1269
+
1270
+ // ../cloud/src/sandbox/client.ts
1271
+ var OpenPondSandboxClient = class extends OpenPondSandboxInstanceClient {
1272
+ runtimes = createSandboxRuntimeNamespace(this);
1273
+ sandboxes = createSandboxNamespace(this);
1274
+ profile = createSandboxProfileNamespace(this);
1275
+ projects = createSandboxProjectNamespace(this);
1276
+ agents = createSandboxAgentNamespace(this);
1277
+ list(input = {}) {
1278
+ const query = new URLSearchParams();
1279
+ if (input.teamId) query.set("teamId", input.teamId);
1280
+ if (input.projectId) query.set("projectId", input.projectId);
1281
+ if (input.agentId) query.set("agentId", input.agentId);
1282
+ return this.request(
1283
+ query.size > 0 ? `?${query.toString()}` : ""
1284
+ ).then((payload) => payload.sandboxes);
1285
+ }
1286
+ listSecrets(input = {}) {
1287
+ const query = new URLSearchParams();
1288
+ if (input.teamId) query.set("teamId", input.teamId);
1289
+ return this.requestApiRoot(
1290
+ `/sandbox-secrets${query.size > 0 ? `?${query.toString()}` : ""}`
1291
+ ).then((payload) => payload.secrets);
1292
+ }
1293
+ getSecret(secretId, input = {}) {
1294
+ const query = new URLSearchParams();
1295
+ if (input.teamId) query.set("teamId", input.teamId);
1296
+ return this.requestApiRoot(
1297
+ `/sandbox-secrets/${encodeURIComponent(secretId)}${query.size > 0 ? `?${query.toString()}` : ""}`
1298
+ ).then((payload) => payload.secret);
1299
+ }
1300
+ createSecret(input) {
1301
+ return this.requestApiRoot("/sandbox-secrets", {
1302
+ method: "POST",
1303
+ body: JSON.stringify(input)
1304
+ }).then((payload) => payload.secret);
1305
+ }
1306
+ rotateSecret(secretId, input) {
1307
+ const query = new URLSearchParams();
1308
+ if (input.teamId) query.set("teamId", input.teamId);
1309
+ const { teamId: _teamId, ...body } = input;
1310
+ return this.requestApiRoot(
1311
+ `/sandbox-secrets/${encodeURIComponent(secretId)}/rotate${query.size > 0 ? `?${query.toString()}` : ""}`,
1312
+ {
1313
+ method: "POST",
1314
+ body: JSON.stringify(body)
1315
+ }
1316
+ ).then((payload) => payload.secret);
1317
+ }
1318
+ attachSecret(secretId, input) {
1319
+ const query = new URLSearchParams();
1320
+ if (input.teamId) query.set("teamId", input.teamId);
1321
+ const { teamId: _teamId, ...body } = input;
1322
+ return this.requestApiRoot(
1323
+ `/sandbox-secrets/${encodeURIComponent(secretId)}/attach${query.size > 0 ? `?${query.toString()}` : ""}`,
1324
+ {
1325
+ method: "POST",
1326
+ body: JSON.stringify(body)
1327
+ }
1328
+ ).then((payload) => payload.secret);
1329
+ }
1330
+ revokeSecret(secretId, input = {}) {
1331
+ const query = new URLSearchParams();
1332
+ if (input.teamId) query.set("teamId", input.teamId);
1333
+ return this.requestApiRoot(
1334
+ `/sandbox-secrets/${encodeURIComponent(secretId)}/revoke${query.size > 0 ? `?${query.toString()}` : ""}`,
1335
+ { method: "POST" }
1336
+ ).then((payload) => payload.secret);
1337
+ }
1338
+ deleteSecret(secretId, input = {}) {
1339
+ const query = new URLSearchParams();
1340
+ if (input.teamId) query.set("teamId", input.teamId);
1341
+ return this.requestApiRoot(
1342
+ `/sandbox-secrets/${encodeURIComponent(secretId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
1343
+ { method: "DELETE" }
1344
+ ).then((payload) => payload.secret);
1345
+ }
1346
+ snapshotCatalog(input = {}) {
1347
+ const query = new URLSearchParams();
1348
+ if (input.teamId) query.set("teamId", input.teamId);
1349
+ if (input.projectId) query.set("projectId", input.projectId);
1350
+ if (input.agentId) query.set("agentId", input.agentId);
1351
+ if (input.q) query.set("q", input.q);
1352
+ if (input.kind) query.set("kind", input.kind);
1353
+ if (input.replayState) query.set("replayState", input.replayState);
1354
+ if (input.visibility) query.set("visibility", input.visibility);
1355
+ if (input.tag) query.set("tag", input.tag);
1356
+ if (input.useCase) query.set("useCase", input.useCase);
1357
+ if (input.limit) query.set("limit", String(input.limit));
1358
+ return this.request(
1359
+ `/catalog/snapshots${query.size > 0 ? `?${query.toString()}` : ""}`
1360
+ );
1361
+ }
1362
+ listSandboxRuntimes(input = {}) {
1363
+ const query = new URLSearchParams();
1364
+ if (input.teamId) query.set("teamId", input.teamId);
1365
+ if (input.projectId) query.set("projectId", input.projectId);
1366
+ if (input.agentId) query.set("agentId", input.agentId);
1367
+ return this.requestApiRoot(
1368
+ `/runtimes${query.size > 0 ? `?${query.toString()}` : ""}`
1369
+ ).then((payload) => payload.runtimes);
1370
+ }
1371
+ listProjects(input) {
1372
+ const query = new URLSearchParams({ teamId: input.teamId });
1373
+ return this.requestApiRoot(
1374
+ `/projects?${query.toString()}`
1375
+ ).then((payload) => payload.projects);
1376
+ }
1377
+ upsertProject(input) {
1378
+ return this.requestApiRoot("/projects", {
1379
+ method: "POST",
1380
+ body: JSON.stringify(input)
1381
+ }).then((payload) => payload.project);
1382
+ }
1383
+ getHostedProfile(input) {
1384
+ const query = new URLSearchParams({ teamId: input.teamId });
1385
+ return this.requestApiRoot(
1386
+ `/profile?${query.toString()}`
1387
+ ).then((payload) => payload.profile);
1388
+ }
1389
+ ensureHostedProfile(input) {
1390
+ const query = new URLSearchParams({ teamId: input.teamId });
1391
+ return this.requestApiRoot(
1392
+ `/profile/ensure?${query.toString()}`,
1393
+ { method: "POST" }
1394
+ ).then((payload) => {
1395
+ if (!payload.profile) {
1396
+ throw new Error("hosted_profile_missing");
1397
+ }
1398
+ return payload.profile;
1399
+ });
1400
+ }
1401
+ pushHostedProfile(input) {
1402
+ const query = new URLSearchParams({ teamId: input.teamId });
1403
+ const { teamId: _teamId, ...body } = input;
1404
+ return this.requestApiRoot(
1405
+ `/profile/push?${query.toString()}`,
1406
+ {
1407
+ method: "POST",
1408
+ body: JSON.stringify(body)
1409
+ }
1410
+ );
1411
+ }
1412
+ async upsertProjectGitRemote(input) {
1413
+ const project = await this.upsertProject(input);
1414
+ return this.ensureProjectGitRemote(project.id, { teamId: input.teamId });
1415
+ }
1416
+ getProject(projectId, input) {
1417
+ const query = new URLSearchParams({ teamId: input.teamId });
1418
+ return this.requestApiRoot(
1419
+ `/projects/${encodeURIComponent(projectId)}?${query.toString()}`
1420
+ ).then((payload) => payload.project);
1421
+ }
1422
+ syncProject(projectId, input) {
1423
+ const query = new URLSearchParams({ teamId: input.teamId });
1424
+ return this.requestApiRoot(
1425
+ `/projects/${encodeURIComponent(projectId)}/sync?${query.toString()}`,
1426
+ { method: "POST" }
1427
+ ).then((payload) => payload.project);
1428
+ }
1429
+ ensureProjectGitRemote(projectId, input) {
1430
+ const query = new URLSearchParams({ teamId: input.teamId });
1431
+ return this.requestApiRoot(
1432
+ `/projects/${encodeURIComponent(projectId)}/git?${query.toString()}`,
1433
+ { method: "POST" }
1434
+ );
1435
+ }
1436
+ uploadProjectSource(projectId, input) {
1437
+ const query = new URLSearchParams({ teamId: input.teamId });
1438
+ const { teamId: _teamId, ...body } = input;
1439
+ return this.requestApiRoot(
1440
+ `/projects/${encodeURIComponent(projectId)}/source?${query.toString()}`,
1441
+ {
1442
+ method: "POST",
1443
+ body: JSON.stringify(body)
1444
+ }
1445
+ ).then((payload) => payload.project);
1446
+ }
1447
+ updateProject(projectId, input) {
1448
+ const query = new URLSearchParams({ teamId: input.teamId });
1449
+ const { teamId: _teamId, ...body } = input;
1450
+ return this.requestApiRoot(
1451
+ `/projects/${encodeURIComponent(projectId)}?${query.toString()}`,
1452
+ {
1453
+ method: "PATCH",
1454
+ body: JSON.stringify(body)
1455
+ }
1456
+ ).then((payload) => payload.project);
1457
+ }
1458
+ archiveProject(projectId, input) {
1459
+ const query = new URLSearchParams({ teamId: input.teamId });
1460
+ return this.requestApiRoot(
1461
+ `/projects/${encodeURIComponent(projectId)}?${query.toString()}`,
1462
+ { method: "DELETE" }
1463
+ ).then((payload) => payload.project);
1464
+ }
1465
+ listAgents(input) {
1466
+ const query = new URLSearchParams({ teamId: input.teamId });
1467
+ return this.requestApiRoot(
1468
+ `/agents?${query.toString()}`
1469
+ ).then((payload) => payload.agents);
1470
+ }
1471
+ upsertAgent(input) {
1472
+ return this.requestApiRoot("/agents", {
1473
+ method: "POST",
1474
+ body: JSON.stringify(input)
1475
+ }).then((payload) => payload.agent);
1476
+ }
1477
+ getAgent(agentId, input) {
1478
+ const query = new URLSearchParams({ teamId: input.teamId });
1479
+ return this.requestApiRoot(
1480
+ `/agents/${encodeURIComponent(agentId)}?${query.toString()}`
1481
+ ).then((payload) => payload.agent);
1482
+ }
1483
+ archiveAgent(agentId, input) {
1484
+ const query = new URLSearchParams({ teamId: input.teamId });
1485
+ return this.requestApiRoot(
1486
+ `/agents/${encodeURIComponent(agentId)}?${query.toString()}`,
1487
+ { method: "DELETE" }
1488
+ ).then((payload) => payload.agent);
1489
+ }
1490
+ updateAgent(agentId, input) {
1491
+ const query = new URLSearchParams({ teamId: input.teamId });
1492
+ const { teamId: _teamId, ...body } = input;
1493
+ return this.requestApiRoot(
1494
+ `/agents/${encodeURIComponent(agentId)}?${query.toString()}`,
1495
+ {
1496
+ method: "PATCH",
1497
+ body: JSON.stringify(body)
1498
+ }
1499
+ ).then((payload) => payload.agent);
1500
+ }
1501
+ runAgent(agentId, input) {
1502
+ return this.requestApiRoot(
1503
+ `/agents/${encodeURIComponent(agentId)}/run`,
1504
+ {
1505
+ method: "POST",
1506
+ headers: {
1507
+ Prefer: "respond-async"
1508
+ },
1509
+ body: JSON.stringify(input)
1510
+ }
1511
+ );
1512
+ }
1513
+ getAgentSourceDeployPlan(agentId, input) {
1514
+ const query = new URLSearchParams({ teamId: input.teamId });
1515
+ return this.requestApiRoot(
1516
+ `/agents/${encodeURIComponent(
1517
+ agentId
1518
+ )}/source/deploy-plan?${query.toString()}`
1519
+ ).then((payload) => payload.deployPlan);
1520
+ }
1521
+ listAgentManifestSnapshots(agentId, input) {
1522
+ const query = new URLSearchParams({ teamId: input.teamId });
1523
+ if (input.limit !== void 0) query.set("limit", String(input.limit));
1524
+ return this.requestApiRoot(
1525
+ `/agents/${encodeURIComponent(
1526
+ agentId
1527
+ )}/source/manifest-snapshots?${query.toString()}`
1528
+ ).then((payload) => payload.manifestSnapshots);
1529
+ }
1530
+ requestAgentSourceChecks(agentId, input) {
1531
+ const query = new URLSearchParams({ teamId: input.teamId });
1532
+ const { teamId: _teamId, ...body } = input;
1533
+ return this.requestApiRoot(
1534
+ `/agents/${encodeURIComponent(
1535
+ agentId
1536
+ )}/source/checks?${query.toString()}`,
1537
+ {
1538
+ method: "POST",
1539
+ body: JSON.stringify(body)
1540
+ }
1541
+ );
1542
+ }
1543
+ publishAgentSource(agentId, input) {
1544
+ const query = new URLSearchParams({ teamId: input.teamId });
1545
+ const { teamId: _teamId, ...body } = input;
1546
+ return this.requestApiRoot(
1547
+ `/agents/${encodeURIComponent(
1548
+ agentId
1549
+ )}/source/publish?${query.toString()}`,
1550
+ {
1551
+ method: "POST",
1552
+ body: JSON.stringify(body)
1553
+ }
1554
+ );
1555
+ }
1556
+ getMicrosoftTeamsBotOverview(input) {
1557
+ const query = new URLSearchParams({ teamId: input.teamId });
1558
+ return this.requestApiRoot(
1559
+ `/teams/bot/overview?${query.toString()}`
1560
+ );
1561
+ }
1562
+ bindMicrosoftTeamsBotConversation(input) {
1563
+ return this.requestApiRoot(
1564
+ "/teams/bot/bindings",
1565
+ {
1566
+ method: "POST",
1567
+ body: JSON.stringify(input)
1568
+ }
1569
+ );
1570
+ }
1571
+ rebindMicrosoftTeamsBotConversation(bindingId, input) {
1572
+ return this.requestApiRoot(
1573
+ `/teams/bot/bindings/${encodeURIComponent(bindingId)}`,
1574
+ {
1575
+ method: "PATCH",
1576
+ body: JSON.stringify(input)
1577
+ }
1578
+ );
1579
+ }
1580
+ unlinkMicrosoftTeamsBotConversation(input) {
1581
+ return this.requestApiRoot(
1582
+ `/teams/bot/bindings/${encodeURIComponent(input.bindingId)}`,
1583
+ {
1584
+ method: "DELETE",
1585
+ body: JSON.stringify({ teamId: input.teamId })
1586
+ }
1587
+ );
1588
+ }
1589
+ sendMicrosoftTeamsBotDiagnostic(input) {
1590
+ return this.requestApiRoot("/teams/bot/diagnostics", {
1591
+ method: "POST",
1592
+ body: JSON.stringify(input)
1593
+ });
1594
+ }
1595
+ sendMicrosoftTeamsBotDiagnosticRun(input) {
1596
+ return this.requestApiRoot(
1597
+ "/teams/bot/diagnostics/run",
1598
+ {
1599
+ method: "POST",
1600
+ body: JSON.stringify(input)
1601
+ }
1602
+ );
1603
+ }
1604
+ createSandboxRuntime(input) {
1605
+ return this.requestApiRoot("/runtimes", {
1606
+ method: "POST",
1607
+ body: JSON.stringify(input)
1608
+ }).then((payload) => payload.runtime);
1609
+ }
1610
+ sandboxRuntime(runtimeId, initial = null) {
1611
+ return createSandboxRuntimeHandle(this, runtimeId, initial);
1612
+ }
1613
+ getSandboxRuntime(runtimeId) {
1614
+ return this.requestApiRoot(
1615
+ `/runtimes/${encodeURIComponent(runtimeId)}`
1616
+ ).then((payload) => payload.runtime);
1617
+ }
1618
+ createSandboxRuntimeSandbox(runtimeId, input = {}, options = {}) {
1619
+ return this.requestApiRoot(
1620
+ `/runtimes/${encodeURIComponent(runtimeId)}/sandbox`,
1621
+ {
1622
+ method: "POST",
1623
+ headers: asyncRequestHeaders(options),
1624
+ body: JSON.stringify(input)
1625
+ }
1626
+ );
1627
+ }
1628
+ updateSandboxRuntimeStatus(runtimeId, input) {
1629
+ return this.requestApiRoot(
1630
+ `/runtimes/${encodeURIComponent(runtimeId)}/status`,
1631
+ {
1632
+ method: "PATCH",
1633
+ body: JSON.stringify(input)
1634
+ }
1635
+ ).then((payload) => payload.runtime);
1636
+ }
1637
+ listSandboxRuntimeEvents(runtimeId) {
1638
+ return this.requestApiRoot(
1639
+ `/runtimes/${encodeURIComponent(runtimeId)}/events`
1640
+ );
1641
+ }
1642
+ emitSandboxRuntimeEvent(runtimeId, input) {
1643
+ return this.requestApiRoot(
1644
+ `/runtimes/${encodeURIComponent(runtimeId)}/events`,
1645
+ {
1646
+ method: "POST",
1647
+ body: JSON.stringify(input)
1648
+ }
1649
+ );
1650
+ }
1651
+ checkpointSandboxRuntime(runtimeId, input) {
1652
+ return this.requestApiRoot(
1653
+ `/runtimes/${encodeURIComponent(runtimeId)}/checkpoints`,
1654
+ {
1655
+ method: "POST",
1656
+ body: JSON.stringify(input)
1657
+ }
1658
+ ).then((payload) => payload.runtime);
1659
+ }
1660
+ promoteSandboxRuntime(runtimeId, input, options = {}) {
1661
+ const query = new URLSearchParams();
1662
+ if (options.teamId) query.set("teamId", options.teamId);
1663
+ return this.requestApiRoot(
1664
+ `/runtimes/${encodeURIComponent(runtimeId)}/promote${query.size > 0 ? `?${query.toString()}` : ""}`,
1665
+ {
1666
+ method: "POST",
1667
+ body: JSON.stringify(input)
1668
+ }
1669
+ );
1670
+ }
1671
+ preserveSandboxRuntimeSource(runtimeId, input = {}, options = {}) {
1672
+ const query = new URLSearchParams();
1673
+ if (options.teamId) query.set("teamId", options.teamId);
1674
+ return this.requestApiRoot(
1675
+ `/runtimes/${encodeURIComponent(runtimeId)}/preserve-source${query.size > 0 ? `?${query.toString()}` : ""}`,
1676
+ {
1677
+ method: "POST",
1678
+ body: JSON.stringify(input)
1679
+ }
1680
+ );
1681
+ }
1682
+ forkSnapshot(snapshotId, input = {}, options = {}) {
1683
+ const query = new URLSearchParams();
1684
+ if (input.teamId) query.set("teamId", input.teamId);
1685
+ if (input.projectId) query.set("projectId", input.projectId);
1686
+ if (options.async) query.set("async", "1");
1687
+ const { teamId: _teamId, projectId: _projectId, ...body } = input;
1688
+ return this.request(
1689
+ `/catalog/snapshots/${encodeURIComponent(snapshotId)}/fork${query.size > 0 ? `?${query.toString()}` : ""}`,
1690
+ {
1691
+ method: "POST",
1692
+ headers: options.async ? { Prefer: "respond-async" } : void 0,
1693
+ body: JSON.stringify({
1694
+ ...body,
1695
+ snapshotId
1696
+ })
1697
+ }
1698
+ );
1699
+ }
1700
+ templates(input = {}) {
1701
+ const query = new URLSearchParams();
1702
+ if (input.teamId) query.set("teamId", input.teamId);
1703
+ if (input.projectId) query.set("projectId", input.projectId);
1704
+ if (input.q) query.set("q", input.q);
1705
+ if (input.name) query.set("name", input.name);
1706
+ if (input.version) query.set("version", input.version);
1707
+ if (input.visibility) query.set("visibility", input.visibility);
1708
+ if (input.tag) query.set("tag", input.tag);
1709
+ if (input.useCase) query.set("useCase", input.useCase);
1710
+ if (input.limit) query.set("limit", String(input.limit));
1711
+ return this.request(
1712
+ `/templates${query.size > 0 ? `?${query.toString()}` : ""}`
1713
+ );
1714
+ }
1715
+ publishedSnapshots(input = {}) {
1716
+ const query = new URLSearchParams();
1717
+ if (input.teamId) query.set("teamId", input.teamId);
1718
+ if (input.projectId) query.set("projectId", input.projectId);
1719
+ if (input.q) query.set("q", input.q);
1720
+ if (input.name) query.set("name", input.name);
1721
+ if (input.version) query.set("version", input.version);
1722
+ if (input.visibility) query.set("visibility", input.visibility);
1723
+ if (input.tag) query.set("tag", input.tag);
1724
+ if (input.useCase) query.set("useCase", input.useCase);
1725
+ if (input.limit) query.set("limit", String(input.limit));
1726
+ return this.request(
1727
+ `/published-snapshots${query.size > 0 ? `?${query.toString()}` : ""}`
1728
+ ).then((payload) => {
1729
+ const publishedSnapshots = payload.publishedSnapshots ?? payload.templates;
1730
+ return {
1731
+ ...payload,
1732
+ templates: publishedSnapshots,
1733
+ publishedSnapshots
1734
+ };
1735
+ });
1736
+ }
1737
+ launchTemplate(input) {
1738
+ const query = new URLSearchParams();
1739
+ if (input.teamId) query.set("teamId", input.teamId);
1740
+ if (input.projectId) query.set("projectId", input.projectId);
1741
+ const { teamId: _teamId, projectId: _projectId, ...body } = input;
1742
+ return this.request(
1743
+ `/templates/launch${query.size > 0 ? `?${query.toString()}` : ""}`,
1744
+ {
1745
+ method: "POST",
1746
+ body: JSON.stringify(body)
1747
+ }
1748
+ );
1749
+ }
1750
+ runPublishedSnapshot(input) {
1751
+ const query = new URLSearchParams();
1752
+ if (input.teamId) query.set("teamId", input.teamId);
1753
+ if (input.projectId) query.set("projectId", input.projectId);
1754
+ const { teamId: _teamId, projectId: _projectId, ...body } = input;
1755
+ return this.request(
1756
+ `/published-snapshots/launch${query.size > 0 ? `?${query.toString()}` : ""}`,
1757
+ {
1758
+ method: "POST",
1759
+ body: JSON.stringify(body)
1760
+ }
1761
+ ).then((payload) => {
1762
+ const publishedSnapshot = payload.publishedSnapshot ?? payload.template;
1763
+ return {
1764
+ ...payload,
1765
+ template: publishedSnapshot,
1766
+ publishedSnapshot
1767
+ };
1768
+ });
1769
+ }
1770
+ listSchedules(input = {}) {
1771
+ const query = new URLSearchParams();
1772
+ if (input.teamId) query.set("teamId", input.teamId);
1773
+ if (input.projectId) query.set("projectId", input.projectId);
1774
+ if (input.sourceSandboxId)
1775
+ query.set("sourceSandboxId", input.sourceSandboxId);
1776
+ return this.request(
1777
+ `/schedules${query.size > 0 ? `?${query.toString()}` : ""}`
1778
+ );
1779
+ }
1780
+ createSchedule(input) {
1781
+ const query = new URLSearchParams();
1782
+ if (input.projectId) query.set("projectId", input.projectId);
1783
+ const { projectId: _projectId, ...body } = input;
1784
+ return this.request(
1785
+ `/schedules${query.size > 0 ? `?${query.toString()}` : ""}`,
1786
+ {
1787
+ method: "POST",
1788
+ body: JSON.stringify(body)
1789
+ }
1790
+ );
1791
+ }
1792
+ getSchedule(scheduleId) {
1793
+ return this.request(
1794
+ `/schedules/${encodeURIComponent(scheduleId)}`
1795
+ );
1796
+ }
1797
+ updateSchedule(scheduleId, input) {
1798
+ return this.request(
1799
+ `/schedules/${encodeURIComponent(scheduleId)}`,
1800
+ {
1801
+ method: "PATCH",
1802
+ body: JSON.stringify(input)
1803
+ }
1804
+ );
1805
+ }
1806
+ deleteSchedule(scheduleId) {
1807
+ return this.request(
1808
+ `/schedules/${encodeURIComponent(scheduleId)}`,
1809
+ {
1810
+ method: "DELETE"
1811
+ }
1812
+ );
1813
+ }
1814
+ listScheduleRuns(scheduleId, input = {}) {
1815
+ const query = new URLSearchParams();
1816
+ if (input.limit !== void 0) query.set("limit", String(input.limit));
1817
+ return this.request(
1818
+ `/schedules/${encodeURIComponent(scheduleId)}/runs${query.size > 0 ? `?${query.toString()}` : ""}`
1819
+ );
1820
+ }
1821
+ runScheduleNow(scheduleId, input = {}) {
1822
+ return this.request(
1823
+ `/schedules/${encodeURIComponent(scheduleId)}/run`,
1824
+ {
1825
+ method: "POST",
1826
+ body: JSON.stringify(input)
1827
+ }
1828
+ );
1829
+ }
1830
+ listTemplateBuilds(input) {
1831
+ const query = new URLSearchParams({ teamId: input.teamId });
1832
+ return this.requestApiRoot(
1833
+ `/sandbox-template-builds?${query.toString()}`
1834
+ ).then((payload) => payload.builds);
1835
+ }
1836
+ createTemplateBuild(input) {
1837
+ return this.requestApiRoot(
1838
+ "/sandbox-template-builds",
1839
+ {
1840
+ method: "POST",
1841
+ body: JSON.stringify(input)
1842
+ }
1843
+ ).then((payload) => payload.build);
1844
+ }
1845
+ getTemplateBuild(buildId) {
1846
+ return this.requestApiRoot(
1847
+ `/sandbox-template-builds/${encodeURIComponent(buildId)}`
1848
+ ).then((payload) => payload.build);
1849
+ }
1850
+ getTemplateBuildLogs(buildId) {
1851
+ return this.requestApiRoot(
1852
+ `/sandbox-template-builds/${encodeURIComponent(buildId)}/logs`
1853
+ );
1854
+ }
1855
+ cancelTemplateBuild(buildId) {
1856
+ return this.requestApiRoot(
1857
+ `/sandbox-template-builds/${encodeURIComponent(buildId)}/cancel`,
1858
+ {
1859
+ method: "POST"
1860
+ }
1861
+ ).then((payload) => payload.build);
1862
+ }
1863
+ listPublishedSnapshotBuilds(input) {
1864
+ const query = new URLSearchParams({ teamId: input.teamId });
1865
+ return this.requestApiRoot(
1866
+ `/published-snapshot-builds?${query.toString()}`
1867
+ ).then((payload) => payload.builds);
1868
+ }
1869
+ createPublishedSnapshotBuild(input) {
1870
+ return this.requestApiRoot(
1871
+ "/published-snapshot-builds",
1872
+ {
1873
+ method: "POST",
1874
+ body: JSON.stringify(input)
1875
+ }
1876
+ ).then((payload) => payload.build);
1877
+ }
1878
+ getPublishedSnapshotBuild(buildId) {
1879
+ return this.requestApiRoot(
1880
+ `/published-snapshot-builds/${encodeURIComponent(buildId)}`
1881
+ ).then((payload) => payload.build);
1882
+ }
1883
+ getPublishedSnapshotBuildLogs(buildId) {
1884
+ return this.requestApiRoot(
1885
+ `/published-snapshot-builds/${encodeURIComponent(buildId)}/logs`
1886
+ );
1887
+ }
1888
+ cancelPublishedSnapshotBuild(buildId) {
1889
+ return this.requestApiRoot(
1890
+ `/published-snapshot-builds/${encodeURIComponent(buildId)}/cancel`,
1891
+ {
1892
+ method: "POST"
1893
+ }
1894
+ ).then((payload) => payload.build);
1895
+ }
1896
+ listOrganizations() {
1897
+ return this.requestApiRoot(
1898
+ "/organizations"
1899
+ ).then((payload) => payload.organizations ?? payload.teams ?? []);
1900
+ }
1901
+ createOrganization(input) {
1902
+ return this.requestApiRoot("/organizations", {
1903
+ method: "POST",
1904
+ body: JSON.stringify(input)
1905
+ }).then((payload) => payload.organization);
1906
+ }
1907
+ getOrganization(slug) {
1908
+ return this.requestApiRoot(
1909
+ `/organizations/${encodeURIComponent(slug)}`
1910
+ ).then((payload) => payload.organization);
1911
+ }
1912
+ updateOrganization(slug, input) {
1913
+ return this.requestApiRoot(
1914
+ `/organizations/${encodeURIComponent(slug)}`,
1915
+ {
1916
+ method: "PATCH",
1917
+ body: JSON.stringify(input)
1918
+ }
1919
+ ).then((payload) => payload.organization);
1920
+ }
1921
+ listOrganizationMembers(slug) {
1922
+ return this.requestApiRoot(
1923
+ `/organizations/${encodeURIComponent(slug)}/members`
1924
+ ).then((payload) => payload.members);
1925
+ }
1926
+ upsertOrganizationMember(slug, input) {
1927
+ return this.requestApiRoot(
1928
+ `/organizations/${encodeURIComponent(slug)}/members`,
1929
+ {
1930
+ method: "POST",
1931
+ body: JSON.stringify(input)
1932
+ }
1933
+ ).then((payload) => payload.member);
1934
+ }
1935
+ getOrganizationMcpServer(slug) {
1936
+ return this.requestApiRoot(
1937
+ `/organizations/${encodeURIComponent(slug)}/mcp-server`
1938
+ ).then((payload) => payload.mcpServer);
1939
+ }
1940
+ generateOrganizationMcpServer(slug, input = {}) {
1941
+ return this.requestApiRoot(
1942
+ `/organizations/${encodeURIComponent(slug)}/mcp-server`,
1943
+ {
1944
+ method: "POST",
1945
+ body: JSON.stringify(input)
1946
+ }
1947
+ ).then((payload) => payload.mcpServer);
1948
+ }
1949
+ rotateOrganizationMcpServer(slug) {
1950
+ return this.requestApiRoot(
1951
+ `/organizations/${encodeURIComponent(slug)}/mcp-server/rotate`,
1952
+ {
1953
+ method: "POST"
1954
+ }
1955
+ ).then((payload) => payload.mcpServer);
1956
+ }
1957
+ disableOrganizationMcpServer(slug) {
1958
+ return this.requestApiRoot(
1959
+ `/organizations/${encodeURIComponent(slug)}/mcp-server/disable`,
1960
+ {
1961
+ method: "POST"
1962
+ }
1963
+ ).then((payload) => payload.mcpServer);
1964
+ }
1965
+ enableOrganizationMcpServer(slug) {
1966
+ return this.requestApiRoot(
1967
+ `/organizations/${encodeURIComponent(slug)}/mcp-server/enable`,
1968
+ {
1969
+ method: "POST"
1970
+ }
1971
+ ).then((payload) => payload.mcpServer);
1972
+ }
1973
+ startReplay(input) {
1974
+ const query = new URLSearchParams();
1975
+ if (input.teamId) query.set("teamId", input.teamId);
1976
+ if (input.projectId) query.set("projectId", input.projectId);
1977
+ const { teamId: _teamId, projectId: _projectId, ...body } = input;
1978
+ return this.requestApiRoot(
1979
+ `/sandbox-replays${query.size > 0 ? `?${query.toString()}` : ""}`,
1980
+ {
1981
+ method: "POST",
1982
+ body: JSON.stringify(body)
1983
+ }
1984
+ );
1985
+ }
1986
+ listReplays(input = {}) {
1987
+ const query = new URLSearchParams();
1988
+ if (input.teamId) query.set("teamId", input.teamId);
1989
+ if (input.projectId) query.set("projectId", input.projectId);
1990
+ return this.requestApiRoot(
1991
+ `/sandbox-replays${query.size > 0 ? `?${query.toString()}` : ""}`
1992
+ );
1993
+ }
1994
+ getReplay(replayId, input = {}) {
1995
+ const query = new URLSearchParams();
1996
+ if (input.teamId) query.set("teamId", input.teamId);
1997
+ if (input.projectId) query.set("projectId", input.projectId);
1998
+ return this.requestApiRoot(
1999
+ `/sandbox-replays/${encodeURIComponent(replayId)}${query.size > 0 ? `?${query.toString()}` : ""}`
2000
+ );
2001
+ }
2002
+ getReplayLogs(replayId, input = {}) {
2003
+ const query = new URLSearchParams();
2004
+ if (input.teamId) query.set("teamId", input.teamId);
2005
+ if (input.projectId) query.set("projectId", input.projectId);
2006
+ return this.requestApiRoot(
2007
+ `/sandbox-replays/${encodeURIComponent(replayId)}/logs${query.size > 0 ? `?${query.toString()}` : ""}`
2008
+ );
2009
+ }
2010
+ getReplayArtifacts(replayId, input = {}) {
2011
+ const query = new URLSearchParams();
2012
+ if (input.teamId) query.set("teamId", input.teamId);
2013
+ if (input.projectId) query.set("projectId", input.projectId);
2014
+ return this.requestApiRoot(
2015
+ `/sandbox-replays/${encodeURIComponent(replayId)}/artifacts${query.size > 0 ? `?${query.toString()}` : ""}`
2016
+ );
2017
+ }
2018
+ cancelReplay(replayId, input = {}) {
2019
+ const query = new URLSearchParams();
2020
+ if (input.teamId) query.set("teamId", input.teamId);
2021
+ if (input.projectId) query.set("projectId", input.projectId);
2022
+ return this.requestApiRoot(
2023
+ `/sandbox-replays/${encodeURIComponent(replayId)}/cancel${query.size > 0 ? `?${query.toString()}` : ""}`,
2024
+ {
2025
+ method: "POST"
2026
+ }
2027
+ );
2028
+ }
2029
+ integrationConnections(input = {}) {
2030
+ const query = new URLSearchParams();
2031
+ if (input.teamId) query.set("teamId", input.teamId);
2032
+ if (input.projectId) query.set("projectId", input.projectId);
2033
+ if (input.agentId) query.set("agentId", input.agentId);
2034
+ if (input.status) query.set("status", input.status);
2035
+ return this.requestApiRoot(
2036
+ `/integrations/connections${query.size > 0 ? `?${query.toString()}` : ""}`
2037
+ );
2038
+ }
2039
+ mcpServerConfig() {
2040
+ return {
2041
+ name: "openpond-sandboxes",
2042
+ transport: "streamable-http",
2043
+ url: `${this.sandboxApiUrl}/mcp`,
2044
+ headers: {
2045
+ "openpond-api-key": this.apiKey
2046
+ }
2047
+ };
2048
+ }
2049
+ smoke(options = {}) {
2050
+ return runSandboxSmoke(this, options);
2051
+ }
2052
+ };
2053
+ function createOpenPondSandboxClient(options) {
2054
+ return new OpenPondSandboxClient(options);
2055
+ }
2056
+
2057
+ // ../cloud/src/hosted-chat.ts
2058
+ import { randomUUID } from "node:crypto";
2059
+ function normalizeApiBaseUrl(value) {
2060
+ const trimmed = normalizeOptionalOpChatApiBaseUrl(value);
2061
+ if (!trimmed) throw new Error("apiBaseUrl is required");
2062
+ return trimmed;
2063
+ }
2064
+ function trimTrailingSlashes(value) {
2065
+ return value.replace(/\/+$/, "");
2066
+ }
2067
+ function normalizeOptionalOpChatApiBaseUrl(value) {
2068
+ let trimmed = trimTrailingSlashes(value?.trim() ?? "");
2069
+ if (!trimmed) return null;
2070
+ trimmed = trimmed.replace(/\/chat\/completions$/i, "").replace(/\/models(?:\/[^/]+)?$/i, "");
2071
+ if (trimmed.endsWith("/opchat/v1")) return trimmed;
2072
+ if (trimmed.endsWith("/opchat")) return `${trimmed}/v1`;
2073
+ if (trimmed.endsWith("/v1")) {
2074
+ trimmed = trimmed.slice(0, -"/v1".length);
2075
+ }
2076
+ return `${trimTrailingSlashes(trimmed)}/opchat/v1`;
2077
+ }
2078
+ function resolveOpChatApiBaseUrl(options = {}) {
2079
+ const runtimeEnv = options.env ?? (typeof process !== "undefined" ? process.env : {});
2080
+ const explicit = normalizeOptionalOpChatApiBaseUrl(options.opChatApiBaseUrl) ?? normalizeOptionalOpChatApiBaseUrl(runtimeEnv.OPENPOND_OPCHAT_API_URL);
2081
+ if (explicit) return explicit;
2082
+ const migrationInput = normalizeOptionalOpChatApiBaseUrl(options.chatApiBaseUrl) ?? normalizeOptionalOpChatApiBaseUrl(runtimeEnv.OPENPOND_CHAT_API_URL) ?? normalizeOptionalOpChatApiBaseUrl(runtimeEnv.OPENPOND_GATEWAY_URL);
2083
+ if (migrationInput) return migrationInput;
2084
+ const apiBase = normalizeOptionalOpChatApiBaseUrl(options.apiBaseUrl) ?? normalizeOptionalOpChatApiBaseUrl(runtimeEnv.OPENPOND_API_URL);
2085
+ return apiBase ?? DEFAULT_OPENPOND_OPCHAT_API_BASE_URL;
2086
+ }
2087
+ function requireToken(value) {
2088
+ const trimmed = value.trim();
2089
+ if (!trimmed) throw new Error("OpenPond API key is required");
2090
+ return trimmed;
2091
+ }
2092
+ function hostedHeaders(requestUrl, token, accept, requestId) {
2093
+ const headers = new Headers();
2094
+ headers.set("Authorization", `Bearer ${requireToken(token)}`);
2095
+ headers.set("Content-Type", "application/json");
2096
+ headers.set("Accept", accept);
2097
+ headers.set("x-openpond-client", "openpond-code");
2098
+ headers.set("x-openpond-request-id", requestId || randomUUID());
2099
+ return withVercelProtectionBypass(requestUrl, headers);
2100
+ }
2101
+ async function readError(response) {
2102
+ const text = await response.text().catch(() => "");
2103
+ if (!text) return response.statusText || `HTTP ${response.status}`;
2104
+ try {
2105
+ const payload = JSON.parse(text);
2106
+ const error = typeof payload.error === "string" ? payload.error : payload.error && typeof payload.error === "object" && !Array.isArray(payload.error) ? payload.error : null;
2107
+ const code = typeof payload.code === "string" ? payload.code : error && typeof error !== "string" && typeof error.code === "string" ? error.code : null;
2108
+ const message = typeof payload.message === "string" ? payload.message : error && typeof error !== "string" && typeof error.message === "string" ? error.message : null;
2109
+ const label = typeof error === "string" ? error : error && typeof error.type === "string" ? error.type : null;
2110
+ return [code, label, message].filter(Boolean).join(": ") || text;
2111
+ } catch {
2112
+ return text;
2113
+ }
2114
+ }
2115
+ function buildHostedChatBody(options, stream) {
2116
+ const body = {
2117
+ model: options.model,
2118
+ messages: options.messages,
2119
+ stream
2120
+ };
2121
+ if (typeof options.temperature === "number") {
2122
+ body.temperature = options.temperature;
2123
+ }
2124
+ if (typeof options.maxTokens === "number") {
2125
+ body.max_tokens = options.maxTokens;
2126
+ }
2127
+ if (options.tools) {
2128
+ body.tools = options.tools;
2129
+ }
2130
+ const toolChoice = options.toolChoice ?? options.tool_choice;
2131
+ if (toolChoice !== void 0) {
2132
+ body.tool_choice = toolChoice;
2133
+ }
2134
+ if (options.metadata) {
2135
+ body.metadata = options.metadata;
2136
+ }
2137
+ return body;
2138
+ }
2139
+ async function listOpChatModels(options) {
2140
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2141
+ const requestUrl = `${apiBaseUrl}/models`;
2142
+ const response = await fetch(requestUrl, {
2143
+ method: "GET",
2144
+ headers: hostedHeaders(requestUrl, options.token, "application/json"),
2145
+ signal: options.signal
2146
+ });
2147
+ if (!response.ok) {
2148
+ throw new Error(
2149
+ `Hosted model list failed: ${response.status} ${await readError(
2150
+ response
2151
+ )}`
2152
+ );
2153
+ }
2154
+ return await response.json();
2155
+ }
2156
+ async function getOpChatModel(options) {
2157
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2158
+ const requestUrl = `${apiBaseUrl}/models/${encodeURIComponent(options.model)}`;
2159
+ const response = await fetch(
2160
+ requestUrl,
2161
+ {
2162
+ method: "GET",
2163
+ headers: hostedHeaders(requestUrl, options.token, "application/json"),
2164
+ signal: options.signal
2165
+ }
2166
+ );
2167
+ if (!response.ok) {
2168
+ throw new Error(
2169
+ `Hosted model lookup failed: ${response.status} ${await readError(
2170
+ response
2171
+ )}`
2172
+ );
2173
+ }
2174
+ return await response.json();
2175
+ }
2176
+ async function listOpChatProviders(options) {
2177
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2178
+ const requestUrl = `${apiBaseUrl}/providers`;
2179
+ const response = await fetch(requestUrl, {
2180
+ method: "GET",
2181
+ headers: hostedHeaders(requestUrl, options.token, "application/json"),
2182
+ signal: options.signal
2183
+ });
2184
+ if (!response.ok) {
2185
+ throw new Error(
2186
+ `Hosted provider list failed: ${response.status} ${await readError(
2187
+ response
2188
+ )}`
2189
+ );
2190
+ }
2191
+ return await response.json();
2192
+ }
2193
+ async function getOpChatProvider(options) {
2194
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2195
+ const requestUrl = `${apiBaseUrl}/providers/${encodeURIComponent(options.provider)}`;
2196
+ const response = await fetch(
2197
+ requestUrl,
2198
+ {
2199
+ method: "GET",
2200
+ headers: hostedHeaders(requestUrl, options.token, "application/json"),
2201
+ signal: options.signal
2202
+ }
2203
+ );
2204
+ if (!response.ok) {
2205
+ throw new Error(
2206
+ `Hosted provider lookup failed: ${response.status} ${await readError(
2207
+ response
2208
+ )}`
2209
+ );
2210
+ }
2211
+ return await response.json();
2212
+ }
2213
+ async function sendHostedChatTurn(options) {
2214
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2215
+ const requestUrl = `${apiBaseUrl}/chat/completions`;
2216
+ const response = await fetch(requestUrl, {
2217
+ method: "POST",
2218
+ headers: hostedHeaders(
2219
+ requestUrl,
2220
+ options.token,
2221
+ "application/json",
2222
+ options.requestId
2223
+ ),
2224
+ body: JSON.stringify(buildHostedChatBody(options, false)),
2225
+ signal: options.signal
2226
+ });
2227
+ if (!response.ok) {
2228
+ throw new Error(
2229
+ `Hosted chat failed: ${response.status} ${await readError(response)}`
2230
+ );
2231
+ }
2232
+ return await response.json();
2233
+ }
2234
+ async function* parseOpenAISSE(stream, signal) {
2235
+ const reader = stream.getReader();
2236
+ const decoder = new TextDecoder();
2237
+ let buffer = "";
2238
+ const readAbortError = () => signal?.reason instanceof Error ? signal.reason : new Error("hosted_chat_aborted");
2239
+ try {
2240
+ while (true) {
2241
+ if (signal?.aborted) throw readAbortError();
2242
+ const result = await reader.read();
2243
+ if (result.done) break;
2244
+ buffer += decoder.decode(result.value, { stream: true });
2245
+ const lines = buffer.split("\n");
2246
+ buffer = lines.pop() || "";
2247
+ for (const line of lines) {
2248
+ const trimmed = line.trim();
2249
+ if (!trimmed.startsWith("data:")) continue;
2250
+ const data = trimmed.slice(5).trim();
2251
+ if (!data) continue;
2252
+ if (data === "[DONE]") return;
2253
+ yield JSON.parse(data);
2254
+ }
2255
+ }
2256
+ } finally {
2257
+ try {
2258
+ reader.releaseLock();
2259
+ } catch {
2260
+ }
2261
+ }
2262
+ }
2263
+ async function* streamHostedChatTurn(options) {
2264
+ const apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
2265
+ const requestUrl = `${apiBaseUrl}/chat/completions`;
2266
+ const response = await fetch(requestUrl, {
2267
+ method: "POST",
2268
+ headers: hostedHeaders(
2269
+ requestUrl,
2270
+ options.token,
2271
+ "text/event-stream",
2272
+ options.requestId
2273
+ ),
2274
+ body: JSON.stringify(buildHostedChatBody(options, true)),
2275
+ signal: options.signal
2276
+ });
2277
+ if (!response.ok || !response.body) {
2278
+ throw new Error(
2279
+ `Hosted chat stream failed: ${response.status} ${await readError(
2280
+ response
2281
+ )}`
2282
+ );
2283
+ }
2284
+ for await (const raw of parseOpenAISSE(response.body, options.signal)) {
2285
+ const chunk = raw;
2286
+ if (chunk.error) {
2287
+ throw new Error(chunk.error.message || "Hosted chat stream error");
2288
+ }
2289
+ if (chunk.usage) {
2290
+ yield { type: "usage", usage: chunk.usage, raw };
2291
+ }
2292
+ const choice = chunk.choices?.[0];
2293
+ if (!choice) continue;
2294
+ const content = choice.delta?.content;
2295
+ if (content) {
2296
+ yield { type: "text_delta", text: content, raw };
2297
+ }
2298
+ const reasoning = choice.delta?.reasoning_content;
2299
+ if (reasoning) {
2300
+ yield { type: "reasoning_delta", text: reasoning, raw };
2301
+ }
2302
+ const toolCalls = choice.delta?.tool_calls;
2303
+ if (Array.isArray(toolCalls) && toolCalls.length > 0) {
2304
+ yield { type: "tool_call_delta", toolCalls, raw };
2305
+ }
2306
+ if (choice.finish_reason !== void 0 && choice.finish_reason !== null) {
2307
+ yield { type: "finish", finishReason: choice.finish_reason, raw };
2308
+ }
2309
+ }
2310
+ }
2311
+
2312
+ // src/work.ts
2313
+ var DEFAULT_MODEL = "openpond-chat";
2314
+ var DEFAULT_MAX_STEPS = 24;
2315
+ var MAX_TOOL_OUTPUT_CHARS = 4e4;
2316
+ var OpenPondNonExecutingSandboxError = class extends Error {
2317
+ constructor(sandboxId) {
2318
+ super(
2319
+ `Sandbox ${sandboxId} accepted a command without executing it. A real remote runner is required for OpenPond Work.`
2320
+ );
2321
+ this.sandboxId = sandboxId;
2322
+ this.name = "OpenPondNonExecutingSandboxError";
2323
+ }
2324
+ sandboxId;
2325
+ code = "OPENPOND_NON_EXECUTING_SANDBOX";
2326
+ };
2327
+ var OpenPondWorkClient = class {
2328
+ #apiKey;
2329
+ #apiBaseUrl;
2330
+ #chatApiBaseUrl;
2331
+ #sandboxes;
2332
+ constructor(input) {
2333
+ this.#apiKey = input.apiKey;
2334
+ this.#apiBaseUrl = input.apiBaseUrl;
2335
+ this.#chatApiBaseUrl = input.chatApiBaseUrl;
2336
+ this.#sandboxes = input.sandboxes;
2337
+ }
2338
+ async run(input) {
2339
+ const prompt = input.prompt.trim();
2340
+ if (!prompt) throw new Error("Work prompt is required");
2341
+ input.signal?.throwIfAborted();
2342
+ const emit = async (event) => input.onEvent?.(event);
2343
+ await emit({ type: "status", message: "Preparing sandbox" });
2344
+ const sandbox = await this.#resolveSandbox(input);
2345
+ if (sandbox.runtimeDriver === "simulated-firecracker" && !input.allowSimulated) {
2346
+ if (!input.sandboxId) {
2347
+ await this.#sandboxes.delete(sandbox.id, { async: true }).catch(() => void 0);
2348
+ }
2349
+ throw new Error(
2350
+ "OpenPond Work requires a remote-firecracker sandbox, but this environment returned the non-executing simulated-firecracker driver."
2351
+ );
2352
+ }
2353
+ await emit({
2354
+ type: "sandbox",
2355
+ sandboxId: sandbox.id,
2356
+ state: sandbox.state,
2357
+ runtimeDriver: sandbox.runtimeDriver
2358
+ });
2359
+ const messages = [
2360
+ { role: "system", content: systemPrompt(sandbox.id) },
2361
+ ...(input.history ?? []).map((message) => ({ ...message })),
2362
+ { role: "user", content: prompt }
2363
+ ];
2364
+ const maxSteps = boundedInteger(input.maxSteps, 1, 100, DEFAULT_MAX_STEPS);
2365
+ let finalText = "";
2366
+ for (let step = 1; step <= maxSteps; step += 1) {
2367
+ input.signal?.throwIfAborted();
2368
+ await emit({ type: "status", message: `Thinking \xB7 step ${step}` });
2369
+ const completion = await sendHostedChatTurn({
2370
+ apiBaseUrl: this.#chatApiBaseUrl,
2371
+ token: this.#apiKey,
2372
+ model: input.model?.trim() || DEFAULT_MODEL,
2373
+ messages,
2374
+ tools: WORK_TOOLS,
2375
+ toolChoice: "auto",
2376
+ signal: input.signal,
2377
+ metadata: {
2378
+ source: "openpond-sdk-work",
2379
+ sandboxId: sandbox.id,
2380
+ apiBaseUrl: this.#apiBaseUrl,
2381
+ ...input.metadata
2382
+ }
2383
+ });
2384
+ const choice = completion.choices?.[0];
2385
+ const assistantText = choice?.message?.content?.trim() ?? "";
2386
+ const toolCalls = choice?.message?.tool_calls ?? [];
2387
+ messages.push({
2388
+ role: "assistant",
2389
+ content: assistantText || null,
2390
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
2391
+ });
2392
+ if (assistantText) {
2393
+ finalText = assistantText;
2394
+ await emit({ type: "assistant", text: assistantText });
2395
+ }
2396
+ if (toolCalls.length === 0) {
2397
+ const result = { sandboxId: sandbox.id, text: finalText, steps: step };
2398
+ await emit({ type: "done", ...result });
2399
+ return result;
2400
+ }
2401
+ for (const [index, toolCall] of toolCalls.entries()) {
2402
+ const result = await this.#executeTool(
2403
+ sandbox.id,
2404
+ toolCall,
2405
+ index,
2406
+ input.timeoutSeconds,
2407
+ emit
2408
+ );
2409
+ messages.push(result);
2410
+ }
2411
+ }
2412
+ throw new Error(`Work did not finish within ${maxSteps} steps`);
2413
+ }
2414
+ async deleteSandbox(sandboxId) {
2415
+ const sandbox = await this.#sandboxes.get(sandboxId);
2416
+ if (sandbox.state === "deleted") return;
2417
+ await this.#sandboxes.delete(sandboxId, { async: true });
2418
+ }
2419
+ async #resolveSandbox(input) {
2420
+ if (input.sandboxId) {
2421
+ const existing = await this.#sandboxes.get(input.sandboxId);
2422
+ if (existing.state === "stopped") {
2423
+ await this.#sandboxes.start(existing.id, { async: true });
2424
+ } else if (existing.state === "deleted" || existing.state === "error") {
2425
+ throw new Error(`Cannot resume sandbox ${existing.id} in state ${existing.state}`);
2426
+ }
2427
+ const ready = await this.#waitUntilRunning(existing.id, input.signal);
2428
+ return ready;
2429
+ }
2430
+ const budgetUsd = input.budgetUsd?.trim() || "1.00";
2431
+ const created = await this.#sandboxes.create(
2432
+ {
2433
+ ...input.repo?.trim() ? { repo: input.repo.trim() } : {},
2434
+ runtimeProfileId: "openpond-work-v1",
2435
+ resources: { cpu: 2, memoryGb: 4, diskGb: 16 },
2436
+ budget: { maxUsd: budgetUsd },
2437
+ quotas: {
2438
+ maxSpendUsd: budgetUsd,
2439
+ maxDurationSeconds: 3600,
2440
+ idleTimeoutSeconds: 900,
2441
+ maxCommands: 200,
2442
+ maxOpenPorts: 4
2443
+ },
2444
+ metadata: { source: "openpond-sdk-work", ...input.metadata }
2445
+ },
2446
+ { async: true }
2447
+ );
2448
+ return this.#waitUntilRunning(created.id, input.signal);
2449
+ }
2450
+ async #waitUntilRunning(sandboxId, signal) {
2451
+ const deadline = Date.now() + 12 * 6e4;
2452
+ let sandbox = await this.#sandboxes.get(sandboxId);
2453
+ while (Date.now() < deadline) {
2454
+ signal?.throwIfAborted();
2455
+ if (sandbox.state === "running") return sandbox;
2456
+ if (sandbox.state === "error" || sandbox.state === "deleted") {
2457
+ throw new Error(
2458
+ `Sandbox ${sandbox.id} entered ${sandbox.state}${sandbox.logs.length ? `: ${sandbox.logs.join("\n")}` : ""}`
2459
+ );
2460
+ }
2461
+ await sleep2(2e3, signal);
2462
+ sandbox = await this.#sandboxes.get(sandboxId);
2463
+ }
2464
+ throw new Error(`Sandbox ${sandboxId} did not become ready before timeout`);
2465
+ }
2466
+ async #executeTool(sandboxId, toolCall, index, timeoutSeconds, emit) {
2467
+ const toolCallId = toolCall.id || `work_tool_${index}`;
2468
+ const name = toolCall.function?.name;
2469
+ if (name !== "run_command") {
2470
+ return toolMessage(toolCallId, { error: `Unknown tool: ${name ?? "missing"}` });
2471
+ }
2472
+ let args;
2473
+ try {
2474
+ args = JSON.parse(toolCall.function?.arguments || "{}");
2475
+ } catch (error) {
2476
+ return toolMessage(toolCallId, { error: `Invalid tool arguments: ${errorMessage(error)}` });
2477
+ }
2478
+ const command = typeof args.command === "string" ? args.command.trim() : "";
2479
+ if (!command) return toolMessage(toolCallId, { error: "command is required" });
2480
+ await emit({ type: "tool", toolCallId, command, status: "started" });
2481
+ try {
2482
+ const response = await this.#sandboxes.exec(sandboxId, {
2483
+ command,
2484
+ timeoutSeconds: boundedInteger(timeoutSeconds, 1, 900, 180)
2485
+ });
2486
+ const output = truncate(response.command.output, MAX_TOOL_OUTPUT_CHARS);
2487
+ if (isNonExecutingSandboxOutput(output)) {
2488
+ await emit({
2489
+ type: "tool",
2490
+ toolCallId,
2491
+ command,
2492
+ status: "failed",
2493
+ output: "Staging accepted the command but did not execute it.",
2494
+ exitCode: response.command.exitCode
2495
+ });
2496
+ await this.#sandboxes.delete(sandboxId, { async: true }).catch(() => void 0);
2497
+ throw new OpenPondNonExecutingSandboxError(sandboxId);
2498
+ }
2499
+ const status = response.command.status === "succeeded" ? "succeeded" : "failed";
2500
+ await emit({
2501
+ type: "tool",
2502
+ toolCallId,
2503
+ command,
2504
+ status,
2505
+ output,
2506
+ exitCode: response.command.exitCode
2507
+ });
2508
+ return toolMessage(toolCallId, {
2509
+ status: response.command.status,
2510
+ exitCode: response.command.exitCode,
2511
+ output
2512
+ });
2513
+ } catch (error) {
2514
+ if (error instanceof OpenPondNonExecutingSandboxError) throw error;
2515
+ const output = errorMessage(error);
2516
+ await emit({ type: "tool", toolCallId, command, status: "failed", output });
2517
+ return toolMessage(toolCallId, { status: "failed", error: output });
2518
+ }
2519
+ }
2520
+ };
2521
+ var WORK_TOOLS = [
2522
+ {
2523
+ type: "function",
2524
+ function: {
2525
+ name: "run_command",
2526
+ description: "Run a shell command inside the persistent OpenPond sandbox. Use standard shell tools to inspect, edit, build, and test files. Commands start in the repository workspace.",
2527
+ parameters: {
2528
+ type: "object",
2529
+ additionalProperties: false,
2530
+ properties: {
2531
+ command: { type: "string", description: "Shell command to execute." }
2532
+ },
2533
+ required: ["command"]
2534
+ }
2535
+ }
2536
+ }
2537
+ ];
2538
+ function systemPrompt(sandboxId) {
2539
+ return [
2540
+ "You are OpenPond Work, a careful coding agent operating in a persistent Linux sandbox.",
2541
+ `The active sandbox is ${sandboxId}.`,
2542
+ "Use run_command to inspect the workspace, edit files, and validate your work.",
2543
+ "Do the requested work completely. Preserve existing user changes and avoid destructive commands.",
2544
+ "Keep the user informed with concise prose, but call tools whenever verification or file changes are needed.",
2545
+ "Before finishing, run relevant tests and summarize the concrete result."
2546
+ ].join("\n");
2547
+ }
2548
+ function toolMessage(toolCallId, payload) {
2549
+ return { role: "tool", tool_call_id: toolCallId, content: JSON.stringify(payload) };
2550
+ }
2551
+ function boundedInteger(value, minimum, maximum, fallback) {
2552
+ if (!Number.isFinite(value)) return fallback;
2553
+ return Math.min(maximum, Math.max(minimum, Math.floor(value)));
2554
+ }
2555
+ function truncate(value, maximum) {
2556
+ if (value.length <= maximum) return value;
2557
+ return `${value.slice(0, maximum)}
2558
+ \u2026 output truncated by openpond-sdk`;
2559
+ }
2560
+ function errorMessage(error) {
2561
+ return error instanceof Error ? error.message : String(error);
2562
+ }
2563
+ function isNonExecutingSandboxOutput(output) {
2564
+ const normalized = output.toLowerCase();
2565
+ return normalized.includes("command accepted by simulated-firecracker driver") || normalized.includes("no host command was executed");
2566
+ }
2567
+ function sleep2(milliseconds, signal) {
2568
+ return new Promise((resolve, reject) => {
2569
+ if (signal?.aborted) {
2570
+ reject(signal.reason);
2571
+ return;
2572
+ }
2573
+ const timer = setTimeout(resolve, milliseconds);
2574
+ timer.unref?.();
2575
+ signal?.addEventListener(
2576
+ "abort",
2577
+ () => {
2578
+ clearTimeout(timer);
2579
+ reject(signal.reason);
2580
+ },
2581
+ { once: true }
2582
+ );
2583
+ });
2584
+ }
2585
+
2586
+ // ../cloud/src/sandbox/types/runtime-profiles.ts
2587
+ var SANDBOX_RUNTIME_PROFILE_IDS = [
2588
+ "openpond-generic-firecracker-v1",
2589
+ "openpond-work-v1",
2590
+ "openpond-coding-core-v1",
2591
+ "openpond-agent-harness-v1"
2592
+ ];
2593
+
2594
+ // src/index.ts
2595
+ var OpenPondClient = class {
2596
+ sandboxes;
2597
+ work;
2598
+ constructor(options) {
2599
+ const apiKey = options.apiKey.trim();
2600
+ if (!apiKey) throw new Error("OpenPond API key is required");
2601
+ const apiBaseUrl = options.baseUrl?.trim() || "https://api.openpond.ai";
2602
+ this.sandboxes = createOpenPondSandboxClient({
2603
+ apiKey,
2604
+ baseUrl: apiBaseUrl,
2605
+ sandboxApiUrl: options.sandboxApiUrl
2606
+ });
2607
+ this.work = new OpenPondWorkClient({
2608
+ apiKey,
2609
+ apiBaseUrl,
2610
+ chatApiBaseUrl: options.chatApiUrl?.trim() || resolveOpChatApiBaseUrl({ apiBaseUrl, env: {} }),
2611
+ sandboxes: this.sandboxes
2612
+ });
2613
+ }
2614
+ };
2615
+ function createOpenPondClient(options) {
2616
+ return new OpenPondClient(options);
2617
+ }
2618
+ export {
2619
+ OpenPondClient,
2620
+ OpenPondNonExecutingSandboxError,
2621
+ OpenPondSandboxClient,
2622
+ OpenPondWorkClient,
2623
+ SANDBOX_RUNTIME_PROFILE_IDS,
2624
+ createOpenPondClient,
2625
+ createOpenPondSandboxClient,
2626
+ getOpChatModel,
2627
+ getOpChatProvider,
2628
+ listOpChatModels,
2629
+ listOpChatProviders,
2630
+ normalizeSandboxApiUrl,
2631
+ resolveOpChatApiBaseUrl,
2632
+ sendHostedChatTurn,
2633
+ streamHostedChatTurn
2634
+ };
2635
+ //# sourceMappingURL=index.js.map