@tangle-network/agent-app 0.44.27 → 0.44.29
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.
- package/dist/{auth-anc7mv2W.d.ts → auth-DJs6lfAs.d.ts} +1 -1
- package/dist/chat-routes/index.d.ts +2 -2
- package/dist/chat-routes/index.js +1 -1
- package/dist/{chunk-7775L5NN.js → chunk-BAC2B2KI.js} +170 -7
- package/dist/chunk-BAC2B2KI.js.map +1 -0
- package/dist/design-canvas/index.d.ts +3 -3
- package/dist/eval/index.d.ts +109 -2
- package/dist/eval/index.js +44 -0
- package/dist/eval/index.js.map +1 -1
- package/dist/{mcp-D3qVzbE1.d.ts → mcp-Dt4V4ZLT.d.ts} +2 -2
- package/dist/preset-cloudflare/index.d.ts +1 -1
- package/dist/runtime/index.d.ts +3 -3
- package/dist/sandbox/index.d.ts +255 -3
- package/dist/sandbox/index.js +9 -1
- package/dist/sequences/index.d.ts +3 -3
- package/dist/tools/index.d.ts +5 -5
- package/dist/{types-BCxK0wyS.d.ts → types-DbU-oO5h.d.ts} +1 -1
- package/dist/work-product/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-7775L5NN.js.map +0 -1
|
@@ -14,8 +14,8 @@ import '../contract-CEewO6DI.js';
|
|
|
14
14
|
import '../types-DB82fktc.js';
|
|
15
15
|
import '../plans/index.js';
|
|
16
16
|
import '@tangle-network/sandbox';
|
|
17
|
-
import '../auth-
|
|
18
|
-
import '../types-
|
|
17
|
+
import '../auth-DJs6lfAs.js';
|
|
18
|
+
import '../types-DbU-oO5h.js';
|
|
19
19
|
import '../harness/index.js';
|
|
20
20
|
import '../model-CdCDfBA9.js';
|
|
21
21
|
import '../budget-BOucfcb_.js';
|
|
@@ -304,6 +304,11 @@ function createWorkspaceSandboxConnectionHandler(opts) {
|
|
|
304
304
|
});
|
|
305
305
|
};
|
|
306
306
|
}
|
|
307
|
+
function sandboxSidecarProxyUrl(baseUrl, sandboxId) {
|
|
308
|
+
if (!baseUrl) throw new Error("baseUrl is required");
|
|
309
|
+
if (!sandboxId) throw new Error("sandboxId is required");
|
|
310
|
+
return new URL(`/v1/sidecar-proxy/${encodeURIComponent(sandboxId)}`, baseUrl).toString().replace(/\/+$/, "");
|
|
311
|
+
}
|
|
307
312
|
function createWorkspaceSandboxRuntimeProxyHandler(opts) {
|
|
308
313
|
return async function handleWorkspaceSandboxRuntimeProxy({ request, params }) {
|
|
309
314
|
const user = await opts.requireUser(request);
|
|
@@ -325,10 +330,7 @@ function createWorkspaceSandboxRuntimeProxyHandler(opts) {
|
|
|
325
330
|
const runtimeConnection = await opts.getSandboxRuntimeConnection?.({ request, userId: user.id, workspaceId, sandboxId });
|
|
326
331
|
const directRuntimeConnection = runtimeConnection?.runtimeUrl && runtimeConnection.authToken ? runtimeConnection : null;
|
|
327
332
|
const credentials = directRuntimeConnection ? null : await opts.getSandboxApiCredentials({ request, userId: user.id, workspaceId, sandboxId });
|
|
328
|
-
const upstreamUrl = directRuntimeConnection ? new URL(encodedRuntimePath, `${directRuntimeConnection.runtimeUrl.replace(/\/+$/, "")}/`) : new URL(
|
|
329
|
-
`/v1/sandboxes/${encodeURIComponent(sandboxId)}/runtime/${encodedRuntimePath}`,
|
|
330
|
-
credentials.baseUrl
|
|
331
|
-
);
|
|
333
|
+
const upstreamUrl = directRuntimeConnection ? new URL(encodedRuntimePath, `${directRuntimeConnection.runtimeUrl.replace(/\/+$/, "")}/`) : new URL(encodedRuntimePath, `${sandboxSidecarProxyUrl(credentials.baseUrl, sandboxId)}/`);
|
|
332
334
|
upstreamUrl.search = requestUrl.search;
|
|
333
335
|
const headers = buildSandboxRuntimeProxyHeaders(
|
|
334
336
|
request.headers,
|
|
@@ -405,17 +407,41 @@ function createWorkspaceSandboxTerminalUpgradeHandler(opts) {
|
|
|
405
407
|
const runtimeConnection = await opts.getSandboxRuntimeConnection?.({ request, userId: user.id, workspaceId, sandboxId });
|
|
406
408
|
const directRuntimeConnection = runtimeConnection?.runtimeUrl && runtimeConnection.authToken ? runtimeConnection : null;
|
|
407
409
|
const credentials = directRuntimeConnection ? null : await opts.getSandboxApiCredentials({ request, userId: user.id, workspaceId, sandboxId });
|
|
408
|
-
const upstreamUrl = directRuntimeConnection ? new URL(subPath, `${directRuntimeConnection.runtimeUrl.replace(/\/+$/, "")}/`) : new URL(
|
|
410
|
+
const upstreamUrl = directRuntimeConnection ? new URL(subPath, `${directRuntimeConnection.runtimeUrl.replace(/\/+$/, "")}/`) : new URL(subPath, `${sandboxSidecarProxyUrl(credentials.baseUrl, sandboxId)}/`);
|
|
409
411
|
upstreamUrl.search = url.search;
|
|
410
412
|
const upstreamHeaders = new Headers(request.headers);
|
|
411
413
|
const upstreamBearer = directRuntimeConnection?.authToken ?? credentials.apiKey;
|
|
412
414
|
upstreamHeaders.set("Authorization", `Bearer ${upstreamBearer}`);
|
|
413
415
|
upstreamHeaders.delete("host");
|
|
416
|
+
const browserProtocol = selectedBearerSubprotocol(request.headers.get("Sec-WebSocket-Protocol"));
|
|
414
417
|
stripBearerSubprotocol(upstreamHeaders);
|
|
415
418
|
const fetchImpl = opts.fetch ?? fetch;
|
|
416
|
-
|
|
419
|
+
const upstream = await fetchImpl(upstreamUrl.toString(), { method: request.method, headers: upstreamHeaders });
|
|
420
|
+
const echo = terminalUpgradeSubprotocolEcho(upstream, browserProtocol);
|
|
421
|
+
if (!echo) return upstream;
|
|
422
|
+
return new Response(null, {
|
|
423
|
+
status: echo.status,
|
|
424
|
+
statusText: echo.statusText,
|
|
425
|
+
headers: echo.headers,
|
|
426
|
+
webSocket: upstream.webSocket ?? null
|
|
427
|
+
});
|
|
417
428
|
};
|
|
418
429
|
}
|
|
430
|
+
function terminalUpgradeSubprotocolEcho(upstream, browserProtocol) {
|
|
431
|
+
if (upstream.status !== 101 || !browserProtocol) return null;
|
|
432
|
+
if (upstream.headers.has("Sec-WebSocket-Protocol")) return null;
|
|
433
|
+
const headers = new Headers(upstream.headers);
|
|
434
|
+
headers.set("Sec-WebSocket-Protocol", browserProtocol);
|
|
435
|
+
return { status: upstream.status, statusText: upstream.statusText ?? "", headers };
|
|
436
|
+
}
|
|
437
|
+
function selectedBearerSubprotocol(value) {
|
|
438
|
+
if (!value) return null;
|
|
439
|
+
for (const part of value.split(",")) {
|
|
440
|
+
const protocol = part.trim();
|
|
441
|
+
if (protocol.toLowerCase().startsWith(BEARER_SUBPROTOCOL_PREFIX)) return protocol;
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
419
445
|
var DEFAULT_RUNTIME_PROXY_HEADERS = ["accept", "content-type", "last-event-id", "x-session-id"];
|
|
420
446
|
function buildSandboxRuntimeProxyHeaders(source, sandboxApiKey, forwardHeaders = DEFAULT_RUNTIME_PROXY_HEADERS) {
|
|
421
447
|
const headers = new Headers();
|
|
@@ -484,6 +510,139 @@ function validateTerminalSubject(subject) {
|
|
|
484
510
|
if (!subject.sandboxId) throw new Error("sandboxId is required");
|
|
485
511
|
}
|
|
486
512
|
|
|
513
|
+
// src/sandbox/prewarm.ts
|
|
514
|
+
function prewarmKey(scope) {
|
|
515
|
+
return `${scope.workspaceId}::${scope.harness}`;
|
|
516
|
+
}
|
|
517
|
+
function errText(err) {
|
|
518
|
+
return err instanceof Error ? err.message : String(err);
|
|
519
|
+
}
|
|
520
|
+
function createSandboxPrewarmer(shell, options) {
|
|
521
|
+
const mode = options.mode ?? "resume-only";
|
|
522
|
+
const claimTtlSeconds = options.claimTtlSeconds ?? 180;
|
|
523
|
+
const failureCooldownMs = options.failureCooldownMs ?? 6e4;
|
|
524
|
+
const now = options.now ?? (() => Date.now());
|
|
525
|
+
const claim = options.claim === "single-isolate-only" ? null : options.claim;
|
|
526
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
527
|
+
const failures = /* @__PURE__ */ new Map();
|
|
528
|
+
const emit = (event) => {
|
|
529
|
+
try {
|
|
530
|
+
options.onEvent?.(event);
|
|
531
|
+
} catch {
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
async function releaseClaim(key) {
|
|
535
|
+
if (!claim) return;
|
|
536
|
+
try {
|
|
537
|
+
await claim.release(key);
|
|
538
|
+
} catch {
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async function runWarm(key, scope, holdsClaim) {
|
|
542
|
+
const startedAt = now();
|
|
543
|
+
emit({ type: "started", key, workspaceId: scope.workspaceId });
|
|
544
|
+
try {
|
|
545
|
+
const box = await ensureWorkspaceSandbox(shell, {
|
|
546
|
+
workspaceId: scope.workspaceId,
|
|
547
|
+
userId: scope.userId,
|
|
548
|
+
harness: scope.harness,
|
|
549
|
+
billingOwnerId: scope.billingOwnerId
|
|
550
|
+
});
|
|
551
|
+
const ms = now() - startedAt;
|
|
552
|
+
failures.delete(key);
|
|
553
|
+
emit({ type: "succeeded", key, workspaceId: scope.workspaceId, boxId: box.id, ms });
|
|
554
|
+
return { ok: true, boxId: box.id, ms };
|
|
555
|
+
} catch (err) {
|
|
556
|
+
const ms = now() - startedAt;
|
|
557
|
+
const error = errText(err);
|
|
558
|
+
failures.set(key, { error, until: now() + failureCooldownMs });
|
|
559
|
+
emit({ type: "failed", key, workspaceId: scope.workspaceId, error, ms });
|
|
560
|
+
return { ok: false, error, ms };
|
|
561
|
+
} finally {
|
|
562
|
+
inFlight.delete(key);
|
|
563
|
+
if (holdsClaim) await releaseClaim(key);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
async prewarm(scope) {
|
|
568
|
+
const key = prewarmKey(scope);
|
|
569
|
+
if (inFlight.has(key)) {
|
|
570
|
+
emit({ type: "skipped", key, workspaceId: scope.workspaceId, outcome: "already-warming" });
|
|
571
|
+
return { outcome: "already-warming" };
|
|
572
|
+
}
|
|
573
|
+
const failure = failures.get(key);
|
|
574
|
+
if (failure && now() < failure.until) {
|
|
575
|
+
emit({ type: "skipped", key, workspaceId: scope.workspaceId, outcome: "cooling-down" });
|
|
576
|
+
return { outcome: "cooling-down" };
|
|
577
|
+
}
|
|
578
|
+
let settle = () => {
|
|
579
|
+
};
|
|
580
|
+
const reservation = new Promise((resolve) => {
|
|
581
|
+
settle = resolve;
|
|
582
|
+
});
|
|
583
|
+
inFlight.set(key, reservation);
|
|
584
|
+
const abandon = (outcome) => {
|
|
585
|
+
inFlight.delete(key);
|
|
586
|
+
settle({ ok: false, error: outcome, ms: 0 });
|
|
587
|
+
emit({ type: "skipped", key, workspaceId: scope.workspaceId, outcome });
|
|
588
|
+
return { outcome };
|
|
589
|
+
};
|
|
590
|
+
try {
|
|
591
|
+
const peek = await peekWorkspaceSandbox(shell, {
|
|
592
|
+
workspaceId: scope.workspaceId,
|
|
593
|
+
userId: scope.userId
|
|
594
|
+
});
|
|
595
|
+
if (peek.status === "running") return abandon("already-running");
|
|
596
|
+
if (peek.status === "absent" && mode === "resume-only") {
|
|
597
|
+
return abandon("absent-and-resume-only");
|
|
598
|
+
}
|
|
599
|
+
if (options.shouldPrewarm) {
|
|
600
|
+
const allowed = await options.shouldPrewarm(scope);
|
|
601
|
+
if (!allowed) return abandon("declined-by-policy");
|
|
602
|
+
}
|
|
603
|
+
let holdsClaim = false;
|
|
604
|
+
if (claim) {
|
|
605
|
+
holdsClaim = await claim.acquire(key, claimTtlSeconds);
|
|
606
|
+
if (!holdsClaim) return abandon("warming-elsewhere");
|
|
607
|
+
}
|
|
608
|
+
const warm = runWarm(key, scope, holdsClaim);
|
|
609
|
+
void warm.then(settle);
|
|
610
|
+
return { outcome: "started", completion: warm };
|
|
611
|
+
} catch (err) {
|
|
612
|
+
const error = errText(err);
|
|
613
|
+
inFlight.delete(key);
|
|
614
|
+
failures.set(key, { error, until: now() + failureCooldownMs });
|
|
615
|
+
settle({ ok: false, error, ms: 0 });
|
|
616
|
+
emit({ type: "failed", key, workspaceId: scope.workspaceId, error, ms: 0 });
|
|
617
|
+
return { outcome: "cooling-down" };
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
async readiness(scope) {
|
|
621
|
+
const key = prewarmKey(scope);
|
|
622
|
+
const peek = await peekWorkspaceSandbox(shell, {
|
|
623
|
+
workspaceId: scope.workspaceId,
|
|
624
|
+
userId: scope.userId
|
|
625
|
+
});
|
|
626
|
+
if (peek.status === "running") return { status: "ready", boxId: peek.box.id };
|
|
627
|
+
if (inFlight.has(key)) return { status: "warming" };
|
|
628
|
+
if (claim?.isHeld) {
|
|
629
|
+
try {
|
|
630
|
+
if (await claim.isHeld(key)) return { status: "warming" };
|
|
631
|
+
} catch {
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const failure = failures.get(key);
|
|
635
|
+
if (failure && now() < failure.until) {
|
|
636
|
+
return { status: "failed", error: failure.error, retryAfterMs: failure.until - now() };
|
|
637
|
+
}
|
|
638
|
+
return { status: "absent" };
|
|
639
|
+
},
|
|
640
|
+
clearFailure(scope) {
|
|
641
|
+
failures.delete(prewarmKey(scope));
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
487
646
|
// src/sandbox/index.ts
|
|
488
647
|
var DEFAULT_SANDBOX_DIRECT_KEY_NAMES = [
|
|
489
648
|
"TCLOUD_SANDBOX_API_KEY",
|
|
@@ -1726,15 +1885,19 @@ export {
|
|
|
1726
1885
|
createSandboxTerminalToken,
|
|
1727
1886
|
verifySandboxTerminalToken,
|
|
1728
1887
|
createWorkspaceSandboxConnectionHandler,
|
|
1888
|
+
sandboxSidecarProxyUrl,
|
|
1729
1889
|
createWorkspaceSandboxRuntimeProxyHandler,
|
|
1730
1890
|
matchSandboxTerminalWsPath,
|
|
1731
1891
|
isSandboxTerminalWsUpgrade,
|
|
1732
1892
|
createWorkspaceSandboxTerminalUpgradeHandler,
|
|
1893
|
+
terminalUpgradeSubprotocolEcho,
|
|
1894
|
+
selectedBearerSubprotocol,
|
|
1733
1895
|
buildSandboxRuntimeProxyHeaders,
|
|
1734
1896
|
encodeSandboxRuntimePath,
|
|
1735
1897
|
bearerToken,
|
|
1736
1898
|
bearerSubprotocolToken,
|
|
1737
1899
|
terminalTokenFromRequest,
|
|
1900
|
+
createSandboxPrewarmer,
|
|
1738
1901
|
resolveSandboxClientCredentials,
|
|
1739
1902
|
DEFAULT_SANDBOX_RESOURCES,
|
|
1740
1903
|
getClient,
|
|
@@ -1778,4 +1941,4 @@ export {
|
|
|
1778
1941
|
isTerminalPromptEvent,
|
|
1779
1942
|
detectInteractiveQuestion
|
|
1780
1943
|
};
|
|
1781
|
-
//# sourceMappingURL=chunk-
|
|
1944
|
+
//# sourceMappingURL=chunk-BAC2B2KI.js.map
|