@tangle-network/agent-runtime 0.79.0 → 0.79.2

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 (34) hide show
  1. package/dist/agent.js +3 -2
  2. package/dist/agent.js.map +1 -1
  3. package/dist/{chunk-GZX3PI7V.js → chunk-2DS6T46I.js} +3 -3
  4. package/dist/{chunk-N2JJDGLJ.js → chunk-75V2XXYJ.js} +8 -6
  5. package/dist/{chunk-N2JJDGLJ.js.map → chunk-75V2XXYJ.js.map} +1 -1
  6. package/dist/{chunk-F6G3SSHY.js → chunk-SONQUREI.js} +2 -2
  7. package/dist/{chunk-EZ2QESTP.js → chunk-TSDKBFZP.js} +34 -925
  8. package/dist/chunk-TSDKBFZP.js.map +1 -0
  9. package/dist/chunk-Z3RRRPRB.js +916 -0
  10. package/dist/chunk-Z3RRRPRB.js.map +1 -0
  11. package/dist/{coordination-09JTQnlF.d.ts → coordination-BoEPhGas.d.ts} +7 -62
  12. package/dist/environment-provider.d.ts +66 -0
  13. package/dist/environment-provider.js +16 -0
  14. package/dist/environment-provider.js.map +1 -0
  15. package/dist/index.d.ts +4 -3
  16. package/dist/index.js +5 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/{loop-runner-bin-Ddgf4DkS.d.ts → loop-runner-bin-DCr5OMe5.d.ts} +2 -2
  19. package/dist/loop-runner-bin.d.ts +4 -3
  20. package/dist/loop-runner-bin.js +4 -3
  21. package/dist/loops.d.ts +9 -6
  22. package/dist/loops.js +9 -7
  23. package/dist/mcp/bin.js +2 -1
  24. package/dist/mcp/bin.js.map +1 -1
  25. package/dist/mcp/index.d.ts +6 -4
  26. package/dist/mcp/index.js +9 -7
  27. package/dist/mcp/index.js.map +1 -1
  28. package/dist/{worktree-CUn0d-ZT.d.ts → types-C1sozrte.d.ts} +1 -123
  29. package/dist/worktree-CpptK3oF.d.ts +125 -0
  30. package/dist/{worktree-fanout-DwwatTdY.d.ts → worktree-fanout-CtQrRDME.d.ts} +2 -1
  31. package/package.json +6 -1
  32. package/dist/chunk-EZ2QESTP.js.map +0 -1
  33. /package/dist/{chunk-GZX3PI7V.js.map → chunk-2DS6T46I.js.map} +0 -0
  34. /package/dist/{chunk-F6G3SSHY.js.map → chunk-SONQUREI.js.map} +0 -0
@@ -0,0 +1,916 @@
1
+ // src/runtime/util.ts
2
+ async function deleteBoxSafe(box) {
3
+ if (!box || typeof box.delete !== "function") return true;
4
+ try {
5
+ await box.delete();
6
+ return true;
7
+ } catch {
8
+ return false;
9
+ }
10
+ }
11
+ function randomSuffix(len = 8) {
12
+ return Math.random().toString(36).slice(2, 2 + len);
13
+ }
14
+ function randomUuid() {
15
+ return crypto.randomUUID();
16
+ }
17
+ function abortError() {
18
+ const err = new Error("aborted");
19
+ err.name = "AbortError";
20
+ return err;
21
+ }
22
+ function throwAbort() {
23
+ throw abortError();
24
+ }
25
+ function throwIfAborted(signal) {
26
+ if (signal?.aborted) throw abortError();
27
+ }
28
+ function isAbortError(err) {
29
+ return err instanceof Error && err.name === "AbortError";
30
+ }
31
+ function sleep(ms, signal) {
32
+ return new Promise((resolve) => {
33
+ if (signal?.aborted) {
34
+ resolve();
35
+ return;
36
+ }
37
+ let onAbort;
38
+ const timer = setTimeout(() => {
39
+ if (onAbort && signal) signal.removeEventListener("abort", onAbort);
40
+ resolve();
41
+ }, ms);
42
+ if (signal) {
43
+ onAbort = () => {
44
+ clearTimeout(timer);
45
+ resolve();
46
+ };
47
+ signal.addEventListener("abort", onAbort, { once: true });
48
+ }
49
+ });
50
+ }
51
+ function withTimeout(promise, ms) {
52
+ return new Promise((resolve) => {
53
+ const timer = setTimeout(() => resolve(void 0), ms);
54
+ promise.then(
55
+ (value) => {
56
+ clearTimeout(timer);
57
+ resolve(value);
58
+ },
59
+ () => {
60
+ clearTimeout(timer);
61
+ resolve(void 0);
62
+ }
63
+ );
64
+ });
65
+ }
66
+ function stringifySafe(value, opts = {}) {
67
+ let s;
68
+ try {
69
+ if (typeof value === "string") {
70
+ s = value;
71
+ } else {
72
+ const json = opts.pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);
73
+ s = json ?? String(value);
74
+ }
75
+ } catch {
76
+ s = String(value);
77
+ }
78
+ if (opts.max !== void 0 && s.length > opts.max) return `${s.slice(0, opts.max)}\u2026`;
79
+ return s;
80
+ }
81
+ function zeroTokenUsage() {
82
+ return { input: 0, output: 0 };
83
+ }
84
+ function addTokenUsage(acc, delta) {
85
+ acc.input += delta.input ?? 0;
86
+ acc.output += delta.output ?? 0;
87
+ }
88
+ async function mapWithConcurrency(items, limit, fn) {
89
+ const bound = Math.max(1, Math.floor(limit));
90
+ const results = new Array(items.length);
91
+ let next = 0;
92
+ let failed = false;
93
+ const worker = async () => {
94
+ while (!failed) {
95
+ const i = next;
96
+ next += 1;
97
+ if (i >= items.length) return;
98
+ try {
99
+ results[i] = await fn(items[i], i);
100
+ } catch (err) {
101
+ failed = true;
102
+ throw err;
103
+ }
104
+ }
105
+ };
106
+ const workerCount = Math.min(bound, items.length);
107
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
108
+ return results;
109
+ }
110
+
111
+ // src/runtime/environment-provider.ts
112
+ var ValidationError = class extends Error {
113
+ constructor(message, options) {
114
+ super(message, options);
115
+ this.name = "ValidationError";
116
+ }
117
+ };
118
+ function createAgentEnvironmentProviderRegistry(providers = []) {
119
+ const entries = /* @__PURE__ */ new Map();
120
+ const registry = {
121
+ register(provider, options = {}) {
122
+ if (!provider.name) {
123
+ throw new ValidationError("agent environment provider registry: provider.name required");
124
+ }
125
+ if (!options.replace && entries.has(provider.name)) {
126
+ throw new ValidationError(
127
+ `agent environment provider registry: provider "${provider.name}" already registered`
128
+ );
129
+ }
130
+ entries.set(provider.name, provider);
131
+ },
132
+ has(name) {
133
+ return entries.has(name);
134
+ },
135
+ get(name) {
136
+ return entries.get(name);
137
+ },
138
+ require(name) {
139
+ const provider = entries.get(name);
140
+ if (!provider) {
141
+ const available = Array.from(entries.keys()).sort();
142
+ const suffix = available.length > 0 ? `; available: ${available.join(", ")}` : "";
143
+ throw new ValidationError(
144
+ `agent environment provider registry: provider "${name}" is not registered${suffix}`
145
+ );
146
+ }
147
+ return provider;
148
+ },
149
+ names() {
150
+ return Array.from(entries.keys()).sort();
151
+ },
152
+ providers() {
153
+ return registry.names().map((name) => registry.require(name));
154
+ },
155
+ async capabilities(name) {
156
+ return registry.require(name).capabilities();
157
+ }
158
+ };
159
+ for (const provider of providers) registry.register(provider);
160
+ return registry;
161
+ }
162
+ function resolveAgentEnvironmentProvider(provider, registry) {
163
+ if (typeof provider !== "string") return provider;
164
+ if (!registry) {
165
+ throw new ValidationError(
166
+ `agent environment provider "${provider}" requires an AgentEnvironmentProviderRegistry`
167
+ );
168
+ }
169
+ return registry.require(provider);
170
+ }
171
+ function providerAsSandboxClient(provider, options = {}) {
172
+ return {
173
+ async create(createOptions) {
174
+ const mapped = {
175
+ ...options.defaults ?? {},
176
+ ...createInputFromSandboxOptions(createOptions),
177
+ ...options.mapCreateOptions?.(createOptions) ?? {}
178
+ };
179
+ if (mapped.profile === void 0) {
180
+ throw new ValidationError(
181
+ `providerAsSandboxClient(${provider.name}): profile required in defaults or CreateSandboxOptions.backend.profile`
182
+ );
183
+ }
184
+ const environment = await provider.create(mapped);
185
+ return environmentAsSandboxInstance(environment, {
186
+ requireTerminalEvent: options.requireTerminalEvent ?? true
187
+ });
188
+ }
189
+ };
190
+ }
191
+ function sandboxClientAsProvider(client, options = {}) {
192
+ const providerName = options.name ?? "tangle-sandbox";
193
+ return {
194
+ name: providerName,
195
+ capabilities: async () => {
196
+ if (options.capabilities) {
197
+ return typeof options.capabilities === "function" ? options.capabilities() : options.capabilities;
198
+ }
199
+ return defaultTangleSandboxCapabilities();
200
+ },
201
+ ...options.validateProfile ? { validateProfile: options.validateProfile } : {},
202
+ async create(input) {
203
+ const createOptions = options.mapCreateInput?.(input) ?? sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode");
204
+ const box = await client.create(createOptions);
205
+ return sandboxInstanceAsEnvironment(box, providerName, client);
206
+ },
207
+ ...hasGet(client) ? {
208
+ async get(id) {
209
+ const box = await client.get(id);
210
+ return box ? sandboxInstanceAsEnvironment(box, providerName, client) : null;
211
+ }
212
+ } : {},
213
+ ...hasList(client) ? {
214
+ async list(query) {
215
+ const boxes = await client.list(query?.providerOptions);
216
+ return boxes.map((box) => ({
217
+ id: String(box.id),
218
+ provider: providerName,
219
+ name: typeof box.name === "string" ? box.name : void 0,
220
+ status: statusFromUnknown(readBoxStatus(box)),
221
+ metadata: readBoxMetadata(box)
222
+ }));
223
+ }
224
+ } : {}
225
+ };
226
+ }
227
+ function providerAsExecutor(provider, options = {}) {
228
+ return (spec, ctx) => createProviderExecutor(provider, spec.profile, ctx, options);
229
+ }
230
+ function createProviderExecutor(provider, profile, ctx, options) {
231
+ const controller = new AbortController();
232
+ const abortIfSignalled = () => {
233
+ if (ctx.signal.aborted) controller.abort();
234
+ };
235
+ abortIfSignalled();
236
+ if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
237
+ let environment;
238
+ let artifact;
239
+ return {
240
+ runtime: options.runtime ?? provider.name,
241
+ execute(task, signal) {
242
+ return streamProviderExecutor({
243
+ provider,
244
+ profile,
245
+ task,
246
+ signal,
247
+ controller,
248
+ options,
249
+ onEnvironment: (env) => {
250
+ environment = env;
251
+ },
252
+ onArtifact: (next) => {
253
+ artifact = next;
254
+ }
255
+ });
256
+ },
257
+ async teardown(_grace) {
258
+ controller.abort();
259
+ await environment?.destroy?.();
260
+ return { destroyed: true };
261
+ },
262
+ resultArtifact() {
263
+ if (!artifact) {
264
+ throw new ValidationError(
265
+ `providerAsExecutor(${provider.name}): resultArtifact() read before stream drained`
266
+ );
267
+ }
268
+ return artifact;
269
+ }
270
+ };
271
+ }
272
+ async function* streamProviderExecutor(args) {
273
+ const started = Date.now();
274
+ const linked = mergeAbortSignals(args.signal, args.controller.signal);
275
+ const environment = await args.provider.create({
276
+ ...args.options.defaults ?? {},
277
+ profile: args.profile,
278
+ signal: linked
279
+ });
280
+ args.onEnvironment(environment);
281
+ const turn = args.options.taskToTurn?.(args.task, args.profile) ?? taskToTurnInput(args.task, linked);
282
+ const events = [];
283
+ const tokens = zeroTokenUsage();
284
+ let usd = 0;
285
+ let text = "";
286
+ let terminal = false;
287
+ try {
288
+ for await (const event of environment.stream({ ...turn, signal: linked })) {
289
+ events.push(event);
290
+ text += textFromEnvironmentEvent(event);
291
+ const usage = usageFromEnvironmentEvent(event);
292
+ if (usage.input || usage.output) {
293
+ tokens.input += usage.input;
294
+ tokens.output += usage.output;
295
+ yield { kind: "tokens", input: usage.input, output: usage.output };
296
+ }
297
+ if (usage.usd) {
298
+ usd += usage.usd;
299
+ yield { kind: "cost", usd: usage.usd };
300
+ }
301
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
302
+ }
303
+ if ((args.options.requireTerminalEvent ?? true) && !terminal) {
304
+ throw new ValidationError(
305
+ `providerAsExecutor(${args.provider.name}): stream ended without a terminal result/done/status event`
306
+ );
307
+ }
308
+ yield { kind: "iteration" };
309
+ const result = resultFromEvents(events, text);
310
+ const spent = {
311
+ iterations: 1,
312
+ tokens,
313
+ usd,
314
+ ms: Date.now() - started
315
+ };
316
+ args.onArtifact({
317
+ outRef: contentRef(`provider:${args.provider.name}`, result),
318
+ out: result,
319
+ spent
320
+ });
321
+ } finally {
322
+ if (args.options.destroyOnSettle ?? true) await environment.destroy?.();
323
+ }
324
+ }
325
+ function createInputFromSandboxOptions(options) {
326
+ const profile = options?.backend?.profile;
327
+ const backend = options?.backend?.type;
328
+ return {
329
+ ...profile !== void 0 ? { profile } : {},
330
+ ...backend ? { backend } : {},
331
+ workspace: {
332
+ ...options?.environment ? { environment: options.environment } : {},
333
+ ...options?.image ? { image: options.image } : {},
334
+ ...options?.git?.url ? { repoUrl: options.git.url } : {},
335
+ ...options?.git?.ref ? { gitRef: options.git.ref } : {}
336
+ },
337
+ ...options?.resources ? { resources: options.resources } : {},
338
+ ...options?.env ? { env: options.env } : {},
339
+ ...options?.secrets ? { secrets: options.secrets } : {},
340
+ ...options?.metadata ? { metadata: options.metadata } : {},
341
+ ...options?.name ? { name: options.name } : {},
342
+ ...options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {},
343
+ providerOptions: { sandboxCreateOptions: options ?? {} }
344
+ };
345
+ }
346
+ function sandboxOptionsFromCreateInput(input, defaultBackend) {
347
+ const backendType = input.backend ?? defaultBackend;
348
+ const workspace = input.workspace ?? {};
349
+ const providerOptions = input.providerOptions?.sandboxCreateOptions;
350
+ const base = providerOptions && typeof providerOptions === "object" ? { ...providerOptions } : {};
351
+ return {
352
+ ...base,
353
+ ...workspace.environment ? { environment: workspace.environment } : {},
354
+ ...workspace.image ? { image: workspace.image } : {},
355
+ ...workspace.repoUrl ? { git: { url: workspace.repoUrl, ref: workspace.gitRef } } : {},
356
+ ...input.resources ? { resources: input.resources } : {},
357
+ ...input.env ? { env: input.env } : {},
358
+ ...Array.isArray(input.secrets) ? { secrets: input.secrets } : {},
359
+ ...input.metadata ? { metadata: input.metadata } : {},
360
+ ...input.name ? { name: input.name } : {},
361
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {},
362
+ backend: {
363
+ ...base.backend ?? {},
364
+ type: backendType,
365
+ profile: input.profile
366
+ }
367
+ };
368
+ }
369
+ function environmentAsSandboxInstance(environment, options) {
370
+ const box = {
371
+ id: environment.id,
372
+ name: environment.name,
373
+ status: "running",
374
+ async refresh() {
375
+ await environment.refresh?.();
376
+ },
377
+ async *streamPrompt(message, promptOptions) {
378
+ let terminal = false;
379
+ const input = turnInputFromPrompt(message, promptOptions);
380
+ for await (const event of environment.stream(input)) {
381
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
382
+ const usageEvent = usageSandboxEvent(event);
383
+ if (usageEvent) yield usageEvent;
384
+ yield sandboxEventFromEnvironmentEvent(event);
385
+ }
386
+ if (options.requireTerminalEvent && !terminal) {
387
+ throw new ValidationError(
388
+ `providerAsSandboxClient(${environment.provider}): stream ended without a terminal result/done/status event`
389
+ );
390
+ }
391
+ },
392
+ async prompt(message, promptOptions) {
393
+ const events = [];
394
+ let text = "";
395
+ let usage;
396
+ let terminal = false;
397
+ for await (const event of environment.stream(turnInputFromPrompt(message, promptOptions))) {
398
+ events.push(event);
399
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
400
+ text += textFromEnvironmentEvent(event);
401
+ usage = mergeTokenUsage(usage, event.usage);
402
+ }
403
+ if (options.requireTerminalEvent && !terminal) {
404
+ throw new ValidationError(
405
+ `providerAsSandboxClient(${environment.provider}): prompt ended without a terminal result/done/status event`
406
+ );
407
+ }
408
+ return {
409
+ response: resultFromEvents(events, text).content,
410
+ success: true,
411
+ durationMs: 0,
412
+ ...usage ? { usage } : {}
413
+ };
414
+ },
415
+ ...environment.dispatch ? {
416
+ async dispatchPrompt(message, promptOptions) {
417
+ const session = await environment.dispatch?.(
418
+ turnInputFromPrompt(message, promptOptions)
419
+ );
420
+ if (!session)
421
+ throw new ValidationError("providerAsSandboxClient: dispatch returned no session");
422
+ return sandboxDispatchResultFromSessionRef(session);
423
+ }
424
+ } : {},
425
+ ...environment.session ? {
426
+ session(id) {
427
+ return sessionAsSandboxSession(environment.session?.(id));
428
+ }
429
+ } : {},
430
+ ...environment.read ? { read: environment.read.bind(environment) } : {},
431
+ ...environment.write ? { write: environment.write.bind(environment) } : {},
432
+ ...environment.exec ? {
433
+ exec: environment.exec.bind(environment)
434
+ } : {},
435
+ ...environment.checkpoint ? {
436
+ async checkpoint(checkpointOptions) {
437
+ const checkpoint = await environment.checkpoint?.(checkpointOptions);
438
+ return { checkpointId: checkpoint?.id, id: checkpoint?.id };
439
+ }
440
+ } : {},
441
+ ...environment.fork ? {
442
+ async fork(checkpointId, forkOptions) {
443
+ const forked = await environment.fork?.({ id: checkpointId }, forkOptions);
444
+ if (!forked)
445
+ throw new ValidationError("providerAsSandboxClient: fork returned no environment");
446
+ return environmentAsSandboxInstance(forked, options);
447
+ }
448
+ } : {},
449
+ async delete() {
450
+ await environment.destroy?.();
451
+ }
452
+ };
453
+ return box;
454
+ }
455
+ function sandboxInstanceAsEnvironment(box, providerName, client) {
456
+ const environment = {
457
+ id: String(box.id),
458
+ provider: providerName,
459
+ ...typeof box.name === "string" ? { name: box.name } : {},
460
+ async status() {
461
+ await maybeRefresh(box);
462
+ return statusFromUnknown(readBoxStatus(box));
463
+ },
464
+ async *stream(input) {
465
+ for await (const event of box.streamPrompt(
466
+ promptFromTurnInput(input),
467
+ promptOptionsFromTurnInput(input)
468
+ )) {
469
+ yield environmentEventFromSandboxEvent(event);
470
+ }
471
+ },
472
+ ...hasDispatchPrompt(box) ? {
473
+ async dispatch(input) {
474
+ const dispatched = await box.dispatchPrompt(
475
+ promptFromTurnInput(input),
476
+ promptOptionsFromTurnInput(input)
477
+ );
478
+ return sessionRefFromSandboxDispatch(dispatched, providerName);
479
+ }
480
+ } : {},
481
+ ...hasSession(box) ? {
482
+ session(id) {
483
+ return sandboxSessionAsAgentSession(box.session(id));
484
+ }
485
+ } : {},
486
+ ...hasRead(box) ? { read: box.read.bind(box) } : {},
487
+ ...hasWrite(box) ? { write: box.write.bind(box) } : {},
488
+ ...hasExec(box) ? {
489
+ async exec(command, options) {
490
+ return execResultFromSandboxExecResult(await box.exec(command, options));
491
+ }
492
+ } : {},
493
+ ...hasCheckpoint(box) ? {
494
+ async checkpoint(options) {
495
+ const result = await box.checkpoint(options);
496
+ return { id: checkpointIdFromResult(result), provider: providerName };
497
+ }
498
+ } : {},
499
+ ...hasFork(box) ? {
500
+ async fork(checkpoint, options) {
501
+ const forked = await box.fork(checkpoint.id, options);
502
+ return sandboxInstanceAsEnvironment(forked, providerName, client);
503
+ }
504
+ } : {},
505
+ async placement() {
506
+ return placementInfoFromLoopPlacement(client.describePlacement?.(box), box);
507
+ },
508
+ async refresh() {
509
+ await maybeRefresh(box);
510
+ },
511
+ async destroy() {
512
+ await destroyBox(box);
513
+ }
514
+ };
515
+ return environment;
516
+ }
517
+ function sandboxSessionAsAgentSession(session) {
518
+ return {
519
+ id: session.id,
520
+ async status() {
521
+ const status = await session.status();
522
+ if (!status) return null;
523
+ return sessionStatusFromUnknown(status.status);
524
+ },
525
+ async *events(options) {
526
+ for await (const event of session.events(options))
527
+ yield environmentEventFromSandboxEvent(event);
528
+ },
529
+ async result() {
530
+ return agentTurnResultFromPromptResult(await session.result());
531
+ },
532
+ async prompt(input) {
533
+ return agentTurnResultFromPromptResult(
534
+ await session.prompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input))
535
+ );
536
+ },
537
+ cancel() {
538
+ return session.cancel();
539
+ }
540
+ };
541
+ }
542
+ function sessionAsSandboxSession(session) {
543
+ if (!session) throw new ValidationError("providerAsSandboxClient: session(id) returned undefined");
544
+ return {
545
+ id: session.id,
546
+ status: session.status.bind(session),
547
+ async *events(options) {
548
+ for await (const event of session.events(options))
549
+ yield sandboxEventFromEnvironmentEvent(event);
550
+ },
551
+ async result() {
552
+ return promptResultFromAgentTurnResult(await session.result());
553
+ },
554
+ async prompt(message, options) {
555
+ return promptResultFromAgentTurnResult(
556
+ await session.prompt(turnInputFromPrompt(message, options))
557
+ );
558
+ },
559
+ cancel: session.cancel.bind(session)
560
+ };
561
+ }
562
+ function environmentEventFromSandboxEvent(event) {
563
+ const data = event.data && typeof event.data === "object" ? event.data : {};
564
+ return {
565
+ type: String(event.type),
566
+ data,
567
+ ...event.id ? { id: event.id } : {},
568
+ usage: tokenUsageFromData(data),
569
+ providerEvent: event
570
+ };
571
+ }
572
+ function sandboxEventFromEnvironmentEvent(event) {
573
+ return {
574
+ type: event.type,
575
+ data: {
576
+ ...event.data,
577
+ ...event.usage ? { usage: tokenUsageData(event.usage) } : {}
578
+ },
579
+ ...event.id ? { id: event.id } : {}
580
+ };
581
+ }
582
+ function usageSandboxEvent(event) {
583
+ if (!event.usage || isUsageType(event.type)) return void 0;
584
+ const usage = tokenUsageData(event.usage);
585
+ if (usage.inputTokens === void 0 && usage.outputTokens === void 0 && usage.totalCostUsd === void 0) {
586
+ return void 0;
587
+ }
588
+ return { type: "llm_call", data: usage };
589
+ }
590
+ function tokenUsageData(usage) {
591
+ return {
592
+ inputTokens: usage.inputTokens,
593
+ outputTokens: usage.outputTokens,
594
+ totalCostUsd: usage.cost
595
+ };
596
+ }
597
+ function turnInputFromPrompt(message, options) {
598
+ return {
599
+ ...typeof message === "string" ? { prompt: message } : { parts: message },
600
+ ...options?.sessionId ? { sessionId: options.sessionId } : {},
601
+ ...options?.model ? { model: options.model } : {},
602
+ ...options?.timeoutMs ? { timeoutMs: options.timeoutMs } : {},
603
+ ...options?.executionId ? { executionId: options.executionId } : {},
604
+ ...options?.lastEventId ? { lastEventId: options.lastEventId } : {},
605
+ ...options?.turnId ? { turnId: options.turnId } : {},
606
+ ...options?.detach !== void 0 ? { detach: options.detach } : {},
607
+ ...options?.context ? { context: options.context } : {},
608
+ ...options?.signal ? { signal: options.signal } : {},
609
+ ...options?.backend ? { providerOptions: { backend: options.backend } } : {}
610
+ };
611
+ }
612
+ function promptFromTurnInput(input) {
613
+ if (input.parts) return input.parts;
614
+ return input.prompt ?? "";
615
+ }
616
+ function promptOptionsFromTurnInput(input) {
617
+ return {
618
+ ...input.sessionId ? { sessionId: input.sessionId } : {},
619
+ ...input.model ? { model: input.model } : {},
620
+ ...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {},
621
+ ...input.context ? { context: input.context } : {},
622
+ ...input.signal ? { signal: input.signal } : {},
623
+ ...input.executionId ? { executionId: input.executionId } : {},
624
+ ...input.lastEventId ? { lastEventId: input.lastEventId } : {},
625
+ ...input.turnId ? { turnId: input.turnId } : {},
626
+ ...input.detach !== void 0 ? { detach: input.detach } : {}
627
+ };
628
+ }
629
+ function taskToTurnInput(task, signal) {
630
+ return { prompt: taskToPrompt(task), signal };
631
+ }
632
+ function taskToPrompt(task) {
633
+ if (typeof task === "string") return task;
634
+ if (task && typeof task === "object") {
635
+ const record = task;
636
+ for (const key of ["prompt", "content", "task", "message"]) {
637
+ if (typeof record[key] === "string") return record[key];
638
+ }
639
+ }
640
+ return JSON.stringify(task);
641
+ }
642
+ function resultFromEvents(events, fallbackText) {
643
+ for (let i = events.length - 1; i >= 0; i -= 1) {
644
+ const event = events[i];
645
+ const text = event ? resultTextFromData(event.data) : void 0;
646
+ if (text !== void 0) return { content: text, events };
647
+ }
648
+ return { content: fallbackText, events };
649
+ }
650
+ function textFromEnvironmentEvent(event) {
651
+ if (typeof event.normalized === "object" && event.normalized && event.normalized.type === "message.part.updated") {
652
+ return typeof event.normalized.delta === "string" ? event.normalized.delta : "";
653
+ }
654
+ const data = event.data;
655
+ for (const key of ["delta", "chunk", "content", "text"]) {
656
+ if (typeof data[key] === "string" && !isTerminalEnvironmentEvent(event)) return data[key];
657
+ }
658
+ return "";
659
+ }
660
+ function resultTextFromData(data) {
661
+ for (const key of ["finalText", "text", "response", "resultSummary", "content"]) {
662
+ if (typeof data[key] === "string") return data[key];
663
+ }
664
+ return void 0;
665
+ }
666
+ function isTerminalEnvironmentEvent(event) {
667
+ if (event.type === "result" || event.type === "done" || event.type === "final") return true;
668
+ if (event.type.endsWith(".completed") || event.type.endsWith(".failed")) return true;
669
+ if (event.type === "status") {
670
+ const status = event.data.status;
671
+ return status === "completed" || status === "failed" || status === "cancelled";
672
+ }
673
+ return false;
674
+ }
675
+ function isUsageType(type) {
676
+ return type === "llm_call" || type === "usage" || type === "cost.usage";
677
+ }
678
+ function usageFromEnvironmentEvent(event) {
679
+ const usage = event.usage ?? tokenUsageFromData(event.data);
680
+ return {
681
+ input: finiteNumber(usage?.inputTokens) ?? 0,
682
+ output: finiteNumber(usage?.outputTokens) ?? 0,
683
+ usd: finiteNumber(usage?.cost) ?? finiteNumber(event.data.costUsd) ?? finiteNumber(event.data.totalCostUsd) ?? 0
684
+ };
685
+ }
686
+ function tokenUsageFromData(data) {
687
+ const usageRecord = data.usage && typeof data.usage === "object" ? data.usage : data.tokenUsage && typeof data.tokenUsage === "object" ? data.tokenUsage : data;
688
+ const inputTokens = finiteNumber(usageRecord.inputTokens) ?? finiteNumber(usageRecord.tokensIn) ?? finiteNumber(usageRecord.prompt_tokens);
689
+ const outputTokens = finiteNumber(usageRecord.outputTokens) ?? finiteNumber(usageRecord.tokensOut) ?? finiteNumber(usageRecord.completion_tokens);
690
+ const cost = finiteNumber(usageRecord.cost) ?? finiteNumber(usageRecord.costUsd) ?? finiteNumber(usageRecord.totalCostUsd) ?? finiteNumber(data.costUsd) ?? finiteNumber(data.totalCostUsd);
691
+ if (inputTokens === void 0 && outputTokens === void 0 && cost === void 0)
692
+ return void 0;
693
+ return {
694
+ inputTokens: inputTokens ?? 0,
695
+ outputTokens: outputTokens ?? 0,
696
+ ...cost !== void 0 ? { cost } : {}
697
+ };
698
+ }
699
+ function mergeTokenUsage(left, right) {
700
+ if (!left) return right;
701
+ if (!right) return left;
702
+ return {
703
+ inputTokens: left.inputTokens + right.inputTokens,
704
+ outputTokens: left.outputTokens + right.outputTokens,
705
+ ...left.cost !== void 0 || right.cost !== void 0 ? { cost: (left.cost ?? 0) + (right.cost ?? 0) } : {}
706
+ };
707
+ }
708
+ function finiteNumber(value) {
709
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
710
+ }
711
+ function promptResultFromAgentTurnResult(result) {
712
+ return {
713
+ response: result.text,
714
+ success: result.success,
715
+ durationMs: 0,
716
+ ...result.error ? { error: result.error } : {},
717
+ ...result.usage ? { usage: result.usage } : {}
718
+ };
719
+ }
720
+ function agentTurnResultFromPromptResult(result) {
721
+ const record = result;
722
+ const text = typeof record.response === "string" ? record.response : typeof record.text === "string" ? record.text : typeof record.finalText === "string" ? record.finalText : "";
723
+ const success = typeof record.success === "boolean" ? record.success : true;
724
+ return {
725
+ text,
726
+ success,
727
+ ...typeof record.error === "string" ? { error: record.error } : {},
728
+ usage: tokenUsageFromData(record)
729
+ };
730
+ }
731
+ function sandboxDispatchResultFromSessionRef(session) {
732
+ const hasStatus = session.metadata && Object.hasOwn(session.metadata, "status");
733
+ const status = hasStatus ? sessionStatusFromUnknown(session.metadata?.status) : "running";
734
+ return {
735
+ sessionId: session.id,
736
+ status,
737
+ alreadyExisted: session.metadata?.alreadyExisted === true
738
+ };
739
+ }
740
+ function sessionRefFromSandboxDispatch(dispatched, providerName) {
741
+ const record = dispatched && typeof dispatched === "object" ? dispatched : void 0;
742
+ const id = record?.sessionId ?? record?.id;
743
+ if (typeof id !== "string" || id.length === 0) {
744
+ throw new ValidationError("sandboxClientAsProvider: dispatch returned no session id");
745
+ }
746
+ if (!record) {
747
+ throw new ValidationError("sandboxClientAsProvider: dispatch returned no session record");
748
+ }
749
+ return {
750
+ id,
751
+ provider: providerName,
752
+ metadata: {
753
+ ...record.status ? { status: record.status } : {},
754
+ ...record.alreadyExisted !== void 0 ? { alreadyExisted: record.alreadyExisted } : {}
755
+ }
756
+ };
757
+ }
758
+ function execResultFromSandboxExecResult(result) {
759
+ const record = result;
760
+ const exitCode = finiteNumber(record.exitCode) ?? finiteNumber(record.code);
761
+ if (exitCode === void 0) {
762
+ throw new ValidationError("sandboxClientAsProvider: exec returned no exit code");
763
+ }
764
+ return {
765
+ exitCode,
766
+ stdout: typeof record.stdout === "string" ? record.stdout : "",
767
+ stderr: typeof record.stderr === "string" ? record.stderr : ""
768
+ };
769
+ }
770
+ function statusFromUnknown(status) {
771
+ if (status === "pending" || status === "provisioning" || status === "running") return status;
772
+ if (status === "stopped" || status === "failed" || status === "expired") return status;
773
+ if (status === "completed") return "stopped";
774
+ if (status === "cancelled") return "stopped";
775
+ return "unknown";
776
+ }
777
+ function sessionStatusFromUnknown(status) {
778
+ if (status === "completed" || status === "cancelled") return status;
779
+ return statusFromUnknown(status);
780
+ }
781
+ function readBoxStatus(box) {
782
+ return box.status;
783
+ }
784
+ function readBoxMetadata(box) {
785
+ const metadata = box.metadata;
786
+ return metadata && typeof metadata === "object" ? metadata : void 0;
787
+ }
788
+ async function maybeRefresh(box) {
789
+ const refresh = box.refresh;
790
+ if (typeof refresh === "function") await refresh.call(box);
791
+ }
792
+ async function destroyBox(box) {
793
+ const deleteBox = box.delete;
794
+ if (typeof deleteBox === "function") await deleteBox.call(box);
795
+ }
796
+ function placementInfoFromLoopPlacement(placement, box) {
797
+ if (!placement) return { kind: "sandbox", sandboxId: String(box.id) };
798
+ return {
799
+ kind: placement.kind === "fleet" ? "fleet" : "sandbox",
800
+ ...placement.sandboxId ? { sandboxId: placement.sandboxId } : { sandboxId: String(box.id) },
801
+ ...placement.fleetId ? { fleetId: placement.fleetId } : {},
802
+ ...placement.machineId ? { machineId: placement.machineId } : {}
803
+ };
804
+ }
805
+ function checkpointIdFromResult(result) {
806
+ const record = result && typeof result === "object" ? result : {};
807
+ const id = record.checkpointId ?? record.id;
808
+ if (typeof id !== "string" || id.length === 0) {
809
+ throw new ValidationError("sandboxClientAsProvider: checkpoint returned no checkpoint id");
810
+ }
811
+ return id;
812
+ }
813
+ function defaultTangleSandboxCapabilities() {
814
+ return {
815
+ profile: {
816
+ namedProfiles: true,
817
+ systemPrompt: true,
818
+ instructions: true,
819
+ tools: true,
820
+ permissions: true,
821
+ mcp: true,
822
+ subagents: true,
823
+ resources: {
824
+ files: true,
825
+ instructions: true,
826
+ tools: true,
827
+ skills: true,
828
+ agents: true,
829
+ commands: true
830
+ },
831
+ hooks: true,
832
+ modes: true,
833
+ runtimeUpdate: true,
834
+ validation: true
835
+ },
836
+ streaming: { live: true, replay: true, detach: true, turnIdempotency: true },
837
+ sessions: { continue: true, list: true, messages: true },
838
+ workspace: { read: true, write: true, exec: true, git: true, upload: true, download: true },
839
+ branching: { checkpoint: true, fork: true },
840
+ placement: true,
841
+ usage: true,
842
+ confidential: true
843
+ };
844
+ }
845
+ function mergeAbortSignals(a, b) {
846
+ const controller = new AbortController();
847
+ const abort = () => controller.abort();
848
+ if (a.aborted || b.aborted) controller.abort();
849
+ else {
850
+ a.addEventListener("abort", abort, { once: true });
851
+ b.addEventListener("abort", abort, { once: true });
852
+ }
853
+ return controller.signal;
854
+ }
855
+ function contentRef(prefix, value) {
856
+ let str;
857
+ try {
858
+ str = JSON.stringify(value) ?? String(value);
859
+ } catch {
860
+ str = String(value);
861
+ }
862
+ let hash = 2166136261;
863
+ for (let i = 0; i < str.length; i += 1) {
864
+ hash ^= str.charCodeAt(i);
865
+ hash = Math.imul(hash, 16777619);
866
+ }
867
+ return `${prefix}:${(hash >>> 0).toString(16).padStart(8, "0")}`;
868
+ }
869
+ function hasGet(client) {
870
+ return typeof client.get === "function";
871
+ }
872
+ function hasList(client) {
873
+ return typeof client.list === "function";
874
+ }
875
+ function hasDispatchPrompt(box) {
876
+ return typeof box.dispatchPrompt === "function";
877
+ }
878
+ function hasSession(box) {
879
+ return typeof box.session === "function";
880
+ }
881
+ function hasRead(box) {
882
+ return typeof box.read === "function";
883
+ }
884
+ function hasWrite(box) {
885
+ return typeof box.write === "function";
886
+ }
887
+ function hasExec(box) {
888
+ return typeof box.exec === "function";
889
+ }
890
+ function hasCheckpoint(box) {
891
+ return typeof box.checkpoint === "function";
892
+ }
893
+ function hasFork(box) {
894
+ return typeof box.fork === "function";
895
+ }
896
+
897
+ export {
898
+ deleteBoxSafe,
899
+ randomSuffix,
900
+ randomUuid,
901
+ throwAbort,
902
+ throwIfAborted,
903
+ isAbortError,
904
+ sleep,
905
+ withTimeout,
906
+ stringifySafe,
907
+ zeroTokenUsage,
908
+ addTokenUsage,
909
+ mapWithConcurrency,
910
+ createAgentEnvironmentProviderRegistry,
911
+ resolveAgentEnvironmentProvider,
912
+ providerAsSandboxClient,
913
+ sandboxClientAsProvider,
914
+ providerAsExecutor
915
+ };
916
+ //# sourceMappingURL=chunk-Z3RRRPRB.js.map