@astralbeam/sdk 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -7
- package/dist/api-DzeMhfHU.js +653 -0
- package/dist/api.d.ts +2 -2
- package/dist/api.js +2 -2
- package/dist/client.d.ts +21 -7
- package/dist/client.js +1 -1
- package/dist/{core-BGDo_tQ4.js → core-D84VNYWJ.js} +947 -148
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/index-CH3RVjha.d.ts +827 -0
- package/dist/{index-DUznpmNz.d.ts → index-CM3pzsKR.d.ts} +108 -29
- package/dist/listings-dAoOEUGK.js +1 -0
- package/dist/react.d.ts +14 -6
- package/dist/react.js +22 -7
- package/dist/rolldown-runtime-Bh1tDfsg.js +1 -0
- package/dist/styles.generated-Ucyw8D9G.js +98 -0
- package/dist/widget-h5LX5aq8.js +11 -0
- package/package.json +3 -3
- package/dist/api-DUe8JSVU.d.ts +0 -372
- package/dist/api-r11gRy91.js +0 -323
- package/dist/index-BVVgDSdq.d.ts +0 -1
- package/dist/listings-6eaCXB6G.js +0 -21
- package/dist/styles.generated-Bub4csY_.js +0 -60
- package/dist/widget-Bjm0sUjE.js +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as listChatMessages, C as getCurrentUser, U as getResolveChatToolResultUrl, W as getRunChatUrl, _ as getChatConfig, dt as updateChatThread, f as createChatThread, g as getChatAttachment, gt as resolveApiUrl, h as deleteChatThread, ht as isAstralBeamApiError, mt as astralBeamChatFetch, tt as listChatThreads } from "./api-DzeMhfHU.js";
|
|
2
2
|
import { d as JWTInvalid, h as strictDecoder, r as isObject, s as decode } from "./type_checks-C-WTHaWs.js";
|
|
3
3
|
//#region \0rolldown/runtime.js
|
|
4
4
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
@@ -26,7 +26,7 @@ function decodeJwt(jwt) {
|
|
|
26
26
|
return result;
|
|
27
27
|
}
|
|
28
28
|
//#endregion
|
|
29
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
29
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
|
|
30
30
|
var UnsupportedResponseStreamError = class extends Error {
|
|
31
31
|
missingFeature;
|
|
32
32
|
constructor(missingFeature) {
|
|
@@ -48,14 +48,14 @@ function createResponseStreamTextDecoder() {
|
|
|
48
48
|
return new globalThis.TextDecoder();
|
|
49
49
|
}
|
|
50
50
|
//#endregion
|
|
51
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
51
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/sse-utils.js
|
|
52
52
|
function parseSseDataLine(line) {
|
|
53
53
|
if (!line.startsWith("data:")) return line;
|
|
54
54
|
const data = line.slice(5);
|
|
55
55
|
return data.startsWith(" ") ? data.slice(1) : data;
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
58
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/message-date-normalizer.js
|
|
59
59
|
function validDate(value) {
|
|
60
60
|
if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value;
|
|
61
61
|
if (typeof value !== "string") return void 0;
|
|
@@ -87,7 +87,7 @@ function normalizeMessagesDates(messages) {
|
|
|
87
87
|
return messages.map(normalizeMessageDates);
|
|
88
88
|
}
|
|
89
89
|
//#endregion
|
|
90
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
90
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-usage.js
|
|
91
91
|
function definedDetails(value) {
|
|
92
92
|
return Object.keys(value).length > 0 ? value : void 0;
|
|
93
93
|
}
|
|
@@ -132,7 +132,7 @@ function fromSpecTokenUsage(usage, leftover) {
|
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
//#endregion
|
|
135
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
135
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/merge-metadata.js
|
|
136
136
|
function isPlainRecord$1(value) {
|
|
137
137
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
138
138
|
}
|
|
@@ -211,7 +211,19 @@ let EventType = /* @__PURE__ */ function(EventType) {
|
|
|
211
211
|
return EventType;
|
|
212
212
|
}({});
|
|
213
213
|
//#endregion
|
|
214
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
214
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/reasoning-encrypted-value.js
|
|
215
|
+
/**
|
|
216
|
+
* Id prefix for the reasoning message of a redacted thinking block (Anthropic
|
|
217
|
+
* `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of
|
|
218
|
+
* bytes it holds (ag-ui-protocol/ag-ui#2884), so the id that `entityId` points
|
|
219
|
+
* to says it. AG-UI clients keep message ids, but they drop event metadata.
|
|
220
|
+
*/
|
|
221
|
+
var REDACTED_THINKING_ID_PREFIX = "redacted_thinking-";
|
|
222
|
+
function isRedactedThinkingId(id) {
|
|
223
|
+
return typeof id === "string" && id.startsWith("redacted_thinking-");
|
|
224
|
+
}
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-serialization.js
|
|
215
227
|
var SHA256_K = new Uint32Array([
|
|
216
228
|
1116352408,
|
|
217
229
|
1899447441,
|
|
@@ -386,7 +398,7 @@ function cloneAndDeepFreezeJson(value) {
|
|
|
386
398
|
return clone;
|
|
387
399
|
}
|
|
388
400
|
//#endregion
|
|
389
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
401
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupts.js
|
|
390
402
|
function canonicalizeInterruptResolutions(resolutions) {
|
|
391
403
|
const frozen = cloneAndDeepFreezeJson([...resolutions].sort((left, right) => left.interruptId.localeCompare(right.interruptId)));
|
|
392
404
|
const canonicalResolutions = canonicalInterruptJson(frozen);
|
|
@@ -397,7 +409,7 @@ function canonicalizeInterruptResolutions(resolutions) {
|
|
|
397
409
|
});
|
|
398
410
|
}
|
|
399
411
|
//#endregion
|
|
400
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
412
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/schema-converter.js
|
|
401
413
|
/**
|
|
402
414
|
* Build a JSONSchema object from any plain key/value source. The `JSONSchema`
|
|
403
415
|
* interface's `[key: string]: any` index signature makes every property
|
|
@@ -550,16 +562,17 @@ function makeStructuredOutputCompatible(schema, originalRequired = []) {
|
|
|
550
562
|
*
|
|
551
563
|
* - Standard JSON Schemas are rebuilt structurally (dropping `$schema`, which
|
|
552
564
|
* LLM providers ignore) and given the explicit `type`/`properties`/`required`
|
|
553
|
-
* defaults object shapes need downstream.
|
|
565
|
+
* defaults object shapes need downstream. `io` picks the `input` (default)
|
|
566
|
+
* or `output` view.
|
|
554
567
|
* - Plain `JSONSchema` inputs are rebuilt into the typed view; non-object inputs
|
|
555
568
|
* are surfaced untouched (they can't be widened).
|
|
556
569
|
* - Standard Schema validators lacking a `~standard.jsonSchema` converter throw
|
|
557
570
|
* with actionable guidance, rather than shipping `{ '~standard': … }` to the
|
|
558
571
|
* provider and producing an opaque downstream error.
|
|
559
572
|
*/
|
|
560
|
-
function toTypedJsonSchema(schema) {
|
|
573
|
+
function toTypedJsonSchema(schema, io = "input") {
|
|
561
574
|
if (isStandardJSONSchema(schema)) {
|
|
562
|
-
const result = toJsonSchema$2(schema["~standard"].jsonSchema
|
|
575
|
+
const result = toJsonSchema$2(schema["~standard"].jsonSchema[io]({ target: "draft-07" }));
|
|
563
576
|
if ("properties" in result && !result.type) result.type = "object";
|
|
564
577
|
if (result.type === "object" && !("properties" in result)) result.properties = {};
|
|
565
578
|
if (result.type === "object" && !("required" in result)) result.required = [];
|
|
@@ -631,9 +644,9 @@ function toTypedJsonSchema(schema) {
|
|
|
631
644
|
*/
|
|
632
645
|
function convertSchemaToJsonSchema(schema, options = {}) {
|
|
633
646
|
if (!schema) return void 0;
|
|
634
|
-
const { forStructuredOutput = false } = options;
|
|
647
|
+
const { forStructuredOutput = false, io } = options;
|
|
635
648
|
if (!forStructuredOutput && !isStandardJSONSchema(schema) && !isStandardSchema(schema)) return schema;
|
|
636
|
-
const base = toTypedJsonSchema(schema);
|
|
649
|
+
const base = toTypedJsonSchema(schema, io);
|
|
637
650
|
if (!base || typeof base !== "object") return base;
|
|
638
651
|
if (!forStructuredOutput) return base;
|
|
639
652
|
return makeStructuredOutputCompatible(base, base.required || []).schema;
|
|
@@ -664,7 +677,7 @@ async function validateWithStandardSchema(schema, data) {
|
|
|
664
677
|
};
|
|
665
678
|
}
|
|
666
679
|
//#endregion
|
|
667
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
680
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/approval-schema.js
|
|
668
681
|
var jsonSchemaKeywords = /* @__PURE__ */ new Set([
|
|
669
682
|
"$schema",
|
|
670
683
|
"$id",
|
|
@@ -776,7 +789,7 @@ function hashSchemaInput(schema) {
|
|
|
776
789
|
return digestInterruptJson(canonicalInterruptJson(schemaToWire(schema).jsonSchema ?? { standardValidator: "unserialized" }));
|
|
777
790
|
}
|
|
778
791
|
//#endregion
|
|
779
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
792
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-resume.js
|
|
780
793
|
/**
|
|
781
794
|
* The `Interrupt.metadata` key under which this package's resume binding
|
|
782
795
|
* travels.
|
|
@@ -897,7 +910,7 @@ function readInterruptBinding(descriptor) {
|
|
|
897
910
|
};
|
|
898
911
|
}
|
|
899
912
|
//#endregion
|
|
900
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
913
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-definition.js
|
|
901
914
|
var INTERRUPT_PAYLOAD_METADATA_KEY = "tanstack:interruptPayload";
|
|
902
915
|
function schemaJson(schema, name) {
|
|
903
916
|
if (!isStandardJSONSchema(schema)) throw new TypeError(`${name} must be a Standard Schema with a JSON Schema converter.`);
|
|
@@ -922,7 +935,7 @@ function hashInterruptDefinitionSchema(schema) {
|
|
|
922
935
|
return digestInterruptJson(schemaJson(schema, "Interrupt schema").canonicalJson);
|
|
923
936
|
}
|
|
924
937
|
//#endregion
|
|
925
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
938
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/generic-interrupt-continuation.js
|
|
926
939
|
/**
|
|
927
940
|
* `ResumeEntry.metadata` key for a first-party generic request.
|
|
928
941
|
*
|
|
@@ -961,7 +974,7 @@ function genericInterruptContinuationFromDescriptor(interrupt) {
|
|
|
961
974
|
};
|
|
962
975
|
}
|
|
963
976
|
//#endregion
|
|
964
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
977
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/provider-executed.js
|
|
965
978
|
/**
|
|
966
979
|
* Narrow a tool call's opaque `metadata` to the provider-executed convention.
|
|
967
980
|
* Returns the typed metadata when the call is provider-executed, else `null`.
|
|
@@ -991,7 +1004,7 @@ function isAssistantSegmentOf(id, parentId) {
|
|
|
991
1004
|
return id?.startsWith(`${parentId}-segment-`) === true;
|
|
992
1005
|
}
|
|
993
1006
|
//#endregion
|
|
994
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
1007
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/tool-result.js
|
|
995
1008
|
var CONTENT_PART_TYPES = /* @__PURE__ */ new Set([
|
|
996
1009
|
"text",
|
|
997
1010
|
"image",
|
|
@@ -1052,7 +1065,7 @@ function normalizeToolResult(result) {
|
|
|
1052
1065
|
return JSON.stringify(result);
|
|
1053
1066
|
}
|
|
1054
1067
|
//#endregion
|
|
1055
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
1068
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/subagent-wire.js
|
|
1056
1069
|
function isRecord$2(value) {
|
|
1057
1070
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1058
1071
|
}
|
|
@@ -1156,7 +1169,7 @@ function splitSubagentWire(messages) {
|
|
|
1156
1169
|
};
|
|
1157
1170
|
}
|
|
1158
1171
|
//#endregion
|
|
1159
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
1172
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
|
|
1160
1173
|
function isRecord$1(value) {
|
|
1161
1174
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1162
1175
|
}
|
|
@@ -1184,6 +1197,10 @@ function encryptedValueFrom(value) {
|
|
|
1184
1197
|
}
|
|
1185
1198
|
return nonEmptyString(tanstackMetadata(value)?.signature);
|
|
1186
1199
|
}
|
|
1200
|
+
/** `{ redacted: true }` when a reasoning message's id marks a redacted block. */
|
|
1201
|
+
function redactedFrom(value) {
|
|
1202
|
+
return "id" in value && isRedactedThinkingId(value.id) ? { redacted: true } : {};
|
|
1203
|
+
}
|
|
1187
1204
|
/**
|
|
1188
1205
|
* Collapse an array of ContentParts into the most compact ModelMessage content:
|
|
1189
1206
|
* - Empty array → null
|
|
@@ -1456,7 +1473,8 @@ function buildAssistantMessages(uiMessage) {
|
|
|
1456
1473
|
if (current.toolCalls.some(isProviderExecutedToolCall)) flushSegment();
|
|
1457
1474
|
pendingThinking.push({
|
|
1458
1475
|
content: part.content,
|
|
1459
|
-
...part.signature && { signature: part.signature }
|
|
1476
|
+
...part.signature && { signature: part.signature },
|
|
1477
|
+
...part.redacted && { redacted: true }
|
|
1460
1478
|
});
|
|
1461
1479
|
}
|
|
1462
1480
|
break;
|
|
@@ -1538,7 +1556,8 @@ function modelMessageToUIMessage(modelMessage, id) {
|
|
|
1538
1556
|
parts.push({
|
|
1539
1557
|
type: "thinking",
|
|
1540
1558
|
content: thinking.content,
|
|
1541
|
-
...thinking.signature && { signature: thinking.signature }
|
|
1559
|
+
...thinking.signature && { signature: thinking.signature },
|
|
1560
|
+
...thinking.redacted && { redacted: true }
|
|
1542
1561
|
});
|
|
1543
1562
|
}
|
|
1544
1563
|
const structuredOutput = modelMessage.structuredOutput ?? snapshotStructuredOutput(tanstackMetadata(modelMessage)?.structuredOutput);
|
|
@@ -1683,7 +1702,8 @@ function aguiSnapshotMessageToUIMessage(message) {
|
|
|
1683
1702
|
parts: content || signature !== void 0 ? [{
|
|
1684
1703
|
type: "thinking",
|
|
1685
1704
|
content,
|
|
1686
|
-
...signature !== void 0 ? { signature } : {}
|
|
1705
|
+
...signature !== void 0 ? { signature } : {},
|
|
1706
|
+
...redactedFrom(message)
|
|
1687
1707
|
}] : []
|
|
1688
1708
|
});
|
|
1689
1709
|
}
|
|
@@ -1798,7 +1818,7 @@ function generateMessageId() {
|
|
|
1798
1818
|
return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
1799
1819
|
}
|
|
1800
1820
|
//#endregion
|
|
1801
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
1821
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-wire.js
|
|
1802
1822
|
function isRecord(value) {
|
|
1803
1823
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1804
1824
|
}
|
|
@@ -2081,7 +2101,8 @@ function collectToolCalls(parts) {
|
|
|
2081
2101
|
return calls.length > 0 ? calls : void 0;
|
|
2082
2102
|
}
|
|
2083
2103
|
function deriveReasoningId(messageId, part) {
|
|
2084
|
-
|
|
2104
|
+
const id = `${messageId}-reasoning-${part.id ?? hashContent(part.content)}`;
|
|
2105
|
+
return part.type === "thinking" && part.redacted ? `${REDACTED_THINKING_ID_PREFIX}${id}` : id;
|
|
2085
2106
|
}
|
|
2086
2107
|
function deriveToolMessageId(toolCallId) {
|
|
2087
2108
|
return `tool-${toolCallId}`;
|
|
@@ -2111,7 +2132,7 @@ function hashContent(s) {
|
|
|
2111
2132
|
return Math.abs(h).toString(36);
|
|
2112
2133
|
}
|
|
2113
2134
|
//#endregion
|
|
2114
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2135
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/restore-inbound-chunk.js
|
|
2115
2136
|
/**
|
|
2116
2137
|
* Rebuild TanStack `TokenUsage` (`promptTokens`) from spec `usage[]` plus
|
|
2117
2138
|
* leftover fields in `metadata.tanstack.usage`. Restore in-process aliases
|
|
@@ -2148,7 +2169,7 @@ function restoreInboundChunk(chunk) {
|
|
|
2148
2169
|
return next;
|
|
2149
2170
|
}
|
|
2150
2171
|
//#endregion
|
|
2151
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2172
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
|
|
2152
2173
|
/**
|
|
2153
2174
|
* Create an isomorphic tool definition that can be used directly or instantiated for server/client
|
|
2154
2175
|
*
|
|
@@ -2246,7 +2267,7 @@ function toolDefinition(config) {
|
|
|
2246
2267
|
};
|
|
2247
2268
|
}
|
|
2248
2269
|
//#endregion
|
|
2249
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2270
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/chunk-ids.js
|
|
2250
2271
|
function stringField(value) {
|
|
2251
2272
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
2252
2273
|
}
|
|
@@ -2349,7 +2370,7 @@ var require_options = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
2349
2370
|
exports.default = exports.Allow;
|
|
2350
2371
|
}));
|
|
2351
2372
|
//#endregion
|
|
2352
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2373
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
|
|
2353
2374
|
var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2354
2375
|
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
2355
2376
|
if (k2 === void 0) k2 = k;
|
|
@@ -2571,7 +2592,7 @@ function parsePartialJSON(jsonString) {
|
|
|
2571
2592
|
return defaultJSONParser.parse(jsonString);
|
|
2572
2593
|
}
|
|
2573
2594
|
//#endregion
|
|
2574
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2595
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
|
|
2575
2596
|
/**
|
|
2576
2597
|
* Immediate Strategy - emit on every chunk (default behavior)
|
|
2577
2598
|
*/
|
|
@@ -2581,7 +2602,7 @@ var ImmediateStrategy = class {
|
|
|
2581
2602
|
}
|
|
2582
2603
|
};
|
|
2583
2604
|
//#endregion
|
|
2584
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2605
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/errors.js
|
|
2585
2606
|
/**
|
|
2586
2607
|
* Convert an AG-UI RUN_ERROR event to the Error shape exposed to consumers.
|
|
2587
2608
|
* Preserves the provider code and sanitized raw event when available, while
|
|
@@ -2595,7 +2616,7 @@ function runErrorEventToError(chunk) {
|
|
|
2595
2616
|
return error;
|
|
2596
2617
|
}
|
|
2597
2618
|
//#endregion
|
|
2598
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2619
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
|
|
2599
2620
|
/**
|
|
2600
2621
|
* Message Updaters (Internal)
|
|
2601
2622
|
*
|
|
@@ -2880,11 +2901,13 @@ function updateThinkingPart(messages, messageId, stepId, content, signature) {
|
|
|
2880
2901
|
if (candidate?.type === "thinking") adopted = candidate;
|
|
2881
2902
|
}
|
|
2882
2903
|
const nextSignature = signature ?? adopted?.signature;
|
|
2904
|
+
const redacted = isRedactedThinkingId(stepId) || adopted?.redacted === true;
|
|
2883
2905
|
const thinkingPart = {
|
|
2884
2906
|
type: "thinking",
|
|
2885
2907
|
content,
|
|
2886
2908
|
stepId,
|
|
2887
|
-
...nextSignature && { signature: nextSignature }
|
|
2909
|
+
...nextSignature && { signature: nextSignature },
|
|
2910
|
+
...redacted && { redacted: true }
|
|
2888
2911
|
};
|
|
2889
2912
|
if (thinkingPartIndex >= 0) parts[thinkingPartIndex] = thinkingPart;
|
|
2890
2913
|
else parts.push(thinkingPart);
|
|
@@ -2895,7 +2918,7 @@ function updateThinkingPart(messages, messageId, stepId, content, signature) {
|
|
|
2895
2918
|
});
|
|
2896
2919
|
}
|
|
2897
2920
|
//#endregion
|
|
2898
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
2921
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
|
|
2899
2922
|
/**
|
|
2900
2923
|
* Unified Stream Processor
|
|
2901
2924
|
*
|
|
@@ -4679,14 +4702,14 @@ function createReplayStream(recording) {
|
|
|
4679
4702
|
} };
|
|
4680
4703
|
}
|
|
4681
4704
|
//#endregion
|
|
4682
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
4705
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/providers.js
|
|
4683
4706
|
/** `[a-z][a-z0-9-]{0,63}` — lowercase, no underscores, max 64 chars. */
|
|
4684
4707
|
var BYOK_PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
4685
4708
|
function isProviderId(value) {
|
|
4686
4709
|
return typeof value === "string" && BYOK_PROVIDER_ID_PATTERN.test(value);
|
|
4687
4710
|
}
|
|
4688
4711
|
//#endregion
|
|
4689
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
4712
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/missing.js
|
|
4690
4713
|
function isByokMissingBody(value) {
|
|
4691
4714
|
if (typeof value !== "object" || value === null) return false;
|
|
4692
4715
|
if (!("error" in value)) return false;
|
|
@@ -4699,7 +4722,7 @@ function isByokMissingBody(value) {
|
|
|
4699
4722
|
return true;
|
|
4700
4723
|
}
|
|
4701
4724
|
//#endregion
|
|
4702
|
-
//#region node_modules/.deno/@tanstack+ai@0.
|
|
4725
|
+
//#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/errors.js
|
|
4703
4726
|
var ByokMissingError = class extends Error {
|
|
4704
4727
|
provider;
|
|
4705
4728
|
constructor(provider) {
|
|
@@ -4725,7 +4748,7 @@ var ByokUnresolvedProviderError = class extends Error {
|
|
|
4725
4748
|
}
|
|
4726
4749
|
};
|
|
4727
4750
|
//#endregion
|
|
4728
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
4751
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
|
|
4729
4752
|
/**
|
|
4730
4753
|
* Associates connect-wrapped chunks with the run they were produced under.
|
|
4731
4754
|
* Content events (TEXT_MESSAGE_CONTENT, TOOL_CALL_*, …) carry no `runId` of
|
|
@@ -5420,7 +5443,7 @@ async function* abortableIterable(iterable, signal) {
|
|
|
5420
5443
|
}
|
|
5421
5444
|
}
|
|
5422
5445
|
//#endregion
|
|
5423
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
5446
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/interrupt-manager.js
|
|
5424
5447
|
function isClientOwnedInterrupt(item) {
|
|
5425
5448
|
return item.resumable;
|
|
5426
5449
|
}
|
|
@@ -6362,7 +6385,7 @@ var InterruptManager = class {
|
|
|
6362
6385
|
}
|
|
6363
6386
|
};
|
|
6364
6387
|
//#endregion
|
|
6365
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6388
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/byok/client.js
|
|
6366
6389
|
var registeredProviderIds = /* @__PURE__ */ new WeakMap();
|
|
6367
6390
|
/**
|
|
6368
6391
|
* Provider to stamp when the caller did not pass a slug.
|
|
@@ -6375,7 +6398,7 @@ function byokFallbackProviderId(byok) {
|
|
|
6375
6398
|
if (registered.length === 1) return registered[0];
|
|
6376
6399
|
}
|
|
6377
6400
|
//#endregion
|
|
6378
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6401
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/byok/resolve.js
|
|
6379
6402
|
function resolveByokProviderId(byokProvider, ...candidates) {
|
|
6380
6403
|
const fromFn = byokProvider?.();
|
|
6381
6404
|
if (isProviderId(fromFn)) return fromFn;
|
|
@@ -6391,7 +6414,7 @@ async function prepareResolvedByokHeaders(byok, provider) {
|
|
|
6391
6414
|
return byok.headers(provider);
|
|
6392
6415
|
}
|
|
6393
6416
|
//#endregion
|
|
6394
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6417
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/events.js
|
|
6395
6418
|
/**
|
|
6396
6419
|
* Abstract base class for ChatClient event emission
|
|
6397
6420
|
*/
|
|
@@ -6565,7 +6588,7 @@ var ChatClientEventEmitter = class {
|
|
|
6565
6588
|
}
|
|
6566
6589
|
};
|
|
6567
6590
|
//#endregion
|
|
6568
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6591
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/devtools-noop.js
|
|
6569
6592
|
var NoOpChatClientEventEmitter = class extends ChatClientEventEmitter {
|
|
6570
6593
|
emitEvent() {}
|
|
6571
6594
|
};
|
|
@@ -6610,7 +6633,7 @@ var NoOpChatDevtoolsBridge = class {
|
|
|
6610
6633
|
};
|
|
6611
6634
|
var createNoOpChatDevtoolsBridge = (options) => new NoOpChatDevtoolsBridge(options);
|
|
6612
6635
|
//#endregion
|
|
6613
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6636
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/client-persistor.js
|
|
6614
6637
|
/** Normalize a raw `getItem` result (legacy bare array or combined record). */
|
|
6615
6638
|
function normalizePersistedState(raw) {
|
|
6616
6639
|
if (Array.isArray(raw)) return { messages: raw };
|
|
@@ -6874,7 +6897,7 @@ var ChatPersistor = class {
|
|
|
6874
6897
|
}
|
|
6875
6898
|
};
|
|
6876
6899
|
//#endregion
|
|
6877
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6900
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/cleared-stream-tracker.js
|
|
6878
6901
|
function getChunkToolCallId(chunk) {
|
|
6879
6902
|
return "toolCallId" in chunk && typeof chunk.toolCallId === "string" ? chunk.toolCallId : void 0;
|
|
6880
6903
|
}
|
|
@@ -6967,7 +6990,7 @@ var ClearedStreamTracker = class {
|
|
|
6967
6990
|
}
|
|
6968
6991
|
};
|
|
6969
6992
|
//#endregion
|
|
6970
|
-
//#region node_modules/.deno/@tanstack+ai-client@0.36.
|
|
6993
|
+
//#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
|
|
6971
6994
|
var STREAM_PROCESSING_BUDGET_MS = 8;
|
|
6972
6995
|
function yieldToHost() {
|
|
6973
6996
|
const { scheduler } = globalThis;
|
|
@@ -9043,16 +9066,11 @@ function toJsonSchema(parameters) {
|
|
|
9043
9066
|
properties: {}
|
|
9044
9067
|
};
|
|
9045
9068
|
if (!("~standard" in parameters)) return parameters;
|
|
9046
|
-
|
|
9047
|
-
return convertSchemaToJsonSchema(parameters);
|
|
9048
|
-
} catch {
|
|
9049
|
-
return { type: "object" };
|
|
9050
|
-
}
|
|
9069
|
+
return "jsonSchema" in parameters["~standard"] ? convertSchemaToJsonSchema(parameters) : { type: "object" };
|
|
9051
9070
|
}
|
|
9052
9071
|
async function validateParameters(parameters, input) {
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
return result.issues ? null : result.value ?? {};
|
|
9072
|
+
const result = await validateWithStandardSchema(parameters, input);
|
|
9073
|
+
return result.success ? result.data ?? {} : null;
|
|
9056
9074
|
}
|
|
9057
9075
|
//#endregion
|
|
9058
9076
|
//#region src/core/agent-tools.ts
|
|
@@ -9558,9 +9576,116 @@ function describeSandboxCommandRun(run) {
|
|
|
9558
9576
|
return parts.join(" · ");
|
|
9559
9577
|
}
|
|
9560
9578
|
//#endregion
|
|
9579
|
+
//#region src/core/threads.ts
|
|
9580
|
+
function newUuid() {
|
|
9581
|
+
const bytes = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
|
|
9582
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
9583
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
9584
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
9585
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
9586
|
+
}
|
|
9587
|
+
function threadFromRecord(record, hasMessages = true) {
|
|
9588
|
+
return {
|
|
9589
|
+
id: record.id,
|
|
9590
|
+
title: record.title,
|
|
9591
|
+
agentId: record.agent_id,
|
|
9592
|
+
version: record.version,
|
|
9593
|
+
role: record.role,
|
|
9594
|
+
writerActive: record.writer_active,
|
|
9595
|
+
hasMessages,
|
|
9596
|
+
updatedAt: record.updated_at
|
|
9597
|
+
};
|
|
9598
|
+
}
|
|
9599
|
+
function savedToolCallId(messageId, partId, targetId) {
|
|
9600
|
+
return `saved:${messageId}:${partId}${targetId ? `:${targetId}` : ""}`;
|
|
9601
|
+
}
|
|
9602
|
+
async function loadThreadMessages(id, options, pageAfter, liveToolMessageIds = /* @__PURE__ */ new Map()) {
|
|
9603
|
+
const page = await listChatMessages(id, {
|
|
9604
|
+
page_size: 100,
|
|
9605
|
+
...pageAfter ? { page_after: pageAfter } : {}
|
|
9606
|
+
}, options);
|
|
9607
|
+
const pendingInteractions = page.pending_interactions.map((pending) => ({
|
|
9608
|
+
sourceMessageId: pending.source_message_id,
|
|
9609
|
+
sourcePartId: pending.source_part_id,
|
|
9610
|
+
responseTargetId: pending.response_target_id,
|
|
9611
|
+
toolCallId: liveToolMessageIds.get(pending.tool_call_id) === pending.source_message_id ? pending.tool_call_id : savedToolCallId(pending.source_message_id, pending.source_part_id, pending.response_target_id),
|
|
9612
|
+
targetTenantUserId: pending.target_tenant_user_id,
|
|
9613
|
+
targetClientId: pending.target_client_id,
|
|
9614
|
+
executionLocation: pending.execution_location
|
|
9615
|
+
}));
|
|
9616
|
+
return {
|
|
9617
|
+
...page,
|
|
9618
|
+
pendingInteractions
|
|
9619
|
+
};
|
|
9620
|
+
}
|
|
9621
|
+
function projectThreadMessages(records, pendingInteractions = [], liveToolMessageIds = /* @__PURE__ */ new Map()) {
|
|
9622
|
+
const messages = [];
|
|
9623
|
+
const calls = /* @__PURE__ */ new Map();
|
|
9624
|
+
for (const message of records) {
|
|
9625
|
+
if (message.role === "tool") {
|
|
9626
|
+
for (const part of message.parts) {
|
|
9627
|
+
const call = calls.get(savedToolCallId(message.source_assistant_message_id, message.source_tool_part_id, message.response_target_id));
|
|
9628
|
+
if (!call) continue;
|
|
9629
|
+
call.output = part.output ?? null;
|
|
9630
|
+
Object.assign(call, { resultOutcome: part.outcome });
|
|
9631
|
+
call.state = part.outcome === "succeeded" ? "complete" : "error";
|
|
9632
|
+
}
|
|
9633
|
+
continue;
|
|
9634
|
+
}
|
|
9635
|
+
const parts = message.parts.flatMap((part) => {
|
|
9636
|
+
const source = part.source;
|
|
9637
|
+
if ((part.type === "image" || part.type === "document") && source && typeof source === "object" && !Array.isArray(source) && "type" in source && source.type === "attachment") return [{
|
|
9638
|
+
...part,
|
|
9639
|
+
source: {
|
|
9640
|
+
...source,
|
|
9641
|
+
type: "url",
|
|
9642
|
+
value: ""
|
|
9643
|
+
},
|
|
9644
|
+
savedAttachmentId: part.id
|
|
9645
|
+
}];
|
|
9646
|
+
if (part.type !== "tool-call") return [part];
|
|
9647
|
+
const toolCallId = String(part.toolCallId);
|
|
9648
|
+
const targets = Array.isArray(part.targets) ? part.targets.flatMap((target) => target && typeof target === "object" && !Array.isArray(target) && "id" in target && typeof target.id === "string" ? [target.id] : []) : pendingInteractions.filter((pending) => pending.sourceMessageId === message.id && pending.sourcePartId === part.id).map((pending) => pending.responseTargetId);
|
|
9649
|
+
return (targets.length ? targets : [void 0]).map((responseTargetId) => {
|
|
9650
|
+
const savedId = savedToolCallId(message.id, String(part.id), responseTargetId);
|
|
9651
|
+
const call = {
|
|
9652
|
+
...part,
|
|
9653
|
+
id: liveToolMessageIds.get(toolCallId) === message.id ? toolCallId : savedId,
|
|
9654
|
+
upstreamToolCallId: toolCallId,
|
|
9655
|
+
applicationPartId: part.id,
|
|
9656
|
+
sourceMessageId: message.id,
|
|
9657
|
+
responseTargetId
|
|
9658
|
+
};
|
|
9659
|
+
calls.set(savedId, call);
|
|
9660
|
+
return call;
|
|
9661
|
+
});
|
|
9662
|
+
});
|
|
9663
|
+
messages.push({
|
|
9664
|
+
id: message.id,
|
|
9665
|
+
role: message.role,
|
|
9666
|
+
parts,
|
|
9667
|
+
createdAt: new Date(message.created_at),
|
|
9668
|
+
metadata: { astralbeam: {
|
|
9669
|
+
state: message.state,
|
|
9670
|
+
authorTenantUserId: message.author_tenant_user_id
|
|
9671
|
+
} }
|
|
9672
|
+
});
|
|
9673
|
+
}
|
|
9674
|
+
return messages;
|
|
9675
|
+
}
|
|
9676
|
+
/** Cache selection within this tab. Stored IDs are reauthorized before loading history. */
|
|
9677
|
+
function selectedThread(key, id) {
|
|
9678
|
+
try {
|
|
9679
|
+
if (id === void 0) return globalThis.sessionStorage?.getItem(key) ?? void 0;
|
|
9680
|
+
if (id === null) globalThis.sessionStorage?.removeItem(key);
|
|
9681
|
+
else globalThis.sessionStorage?.setItem(key, id);
|
|
9682
|
+
} catch {}
|
|
9683
|
+
}
|
|
9684
|
+
//#endregion
|
|
9561
9685
|
//#region src/core/session.ts
|
|
9562
9686
|
const CORE_OPTION_KEYS = Object.keys({
|
|
9563
9687
|
agentId: true,
|
|
9688
|
+
threadId: true,
|
|
9564
9689
|
apiUrl: true,
|
|
9565
9690
|
fetchAstralBeamToken: true,
|
|
9566
9691
|
tools: true,
|
|
@@ -9592,7 +9717,15 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9592
9717
|
sandbox: {
|
|
9593
9718
|
files: [],
|
|
9594
9719
|
commands: []
|
|
9595
|
-
}
|
|
9720
|
+
},
|
|
9721
|
+
thread: void 0,
|
|
9722
|
+
threadLoading: false,
|
|
9723
|
+
threadLoadFailed: false,
|
|
9724
|
+
messagesCursor: void 0,
|
|
9725
|
+
olderMessagesLoading: false,
|
|
9726
|
+
unsentMessage: void 0,
|
|
9727
|
+
activeToolCallIds: [],
|
|
9728
|
+
pendingInteractions: []
|
|
9596
9729
|
};
|
|
9597
9730
|
const update = (next) => {
|
|
9598
9731
|
state = {
|
|
@@ -9610,24 +9743,89 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9610
9743
|
let unsubscribeAuthentication;
|
|
9611
9744
|
let identity;
|
|
9612
9745
|
let started = false;
|
|
9746
|
+
let selectionGeneration = 0;
|
|
9747
|
+
let navigationGeneration = 0;
|
|
9748
|
+
let historyGeneration = 0;
|
|
9749
|
+
let hydration = Promise.resolve();
|
|
9750
|
+
let requestController = new AbortController();
|
|
9751
|
+
let threadKey;
|
|
9752
|
+
let startWithNewThread = false;
|
|
9753
|
+
let threadRecords = [];
|
|
9754
|
+
const clientId = newUuid();
|
|
9755
|
+
let pendingSend;
|
|
9756
|
+
let sending = false;
|
|
9757
|
+
const pendingSends = /* @__PURE__ */ new Map();
|
|
9758
|
+
const acceptPendingSend = () => {
|
|
9759
|
+
if (!pendingSend || pendingSend.accepted) return;
|
|
9760
|
+
pendingSend.accepted = true;
|
|
9761
|
+
if (state.thread) update({ thread: {
|
|
9762
|
+
...state.thread,
|
|
9763
|
+
hasMessages: true
|
|
9764
|
+
} });
|
|
9765
|
+
pendingSend.callbacks?.onAccepted?.();
|
|
9766
|
+
};
|
|
9767
|
+
const liveToolCalls = /* @__PURE__ */ new Set();
|
|
9768
|
+
const liveToolMessageIds = /* @__PURE__ */ new Map();
|
|
9769
|
+
const historicalToolIds = /* @__PURE__ */ new Map();
|
|
9770
|
+
let toolResults = /* @__PURE__ */ new Map();
|
|
9771
|
+
const threadToolResults = /* @__PURE__ */ new Map();
|
|
9772
|
+
const toolResultKey = (id) => {
|
|
9773
|
+
const messageId = liveToolMessageIds.get(id);
|
|
9774
|
+
return messageId ? `live:${messageId}:${id}` : id;
|
|
9775
|
+
};
|
|
9776
|
+
const retainToolResults = (history) => {
|
|
9777
|
+
const retained = /* @__PURE__ */ new Map();
|
|
9778
|
+
for (const pending of history.pending_interactions) {
|
|
9779
|
+
const nativeKey = `live:${pending.source_message_id}:${pending.tool_call_id}`;
|
|
9780
|
+
const savedKey = savedToolCallId(pending.source_message_id, pending.source_part_id, pending.response_target_id);
|
|
9781
|
+
const result = toolResults.get(nativeKey) ?? toolResults.get(savedKey);
|
|
9782
|
+
if (!result) continue;
|
|
9783
|
+
retained.set(savedKey, result);
|
|
9784
|
+
if (liveToolMessageIds.get(pending.tool_call_id) === pending.source_message_id) retained.set(nativeKey, result);
|
|
9785
|
+
}
|
|
9786
|
+
toolResults.clear();
|
|
9787
|
+
for (const [id, result] of retained) toolResults.set(id, result);
|
|
9788
|
+
};
|
|
9789
|
+
const reportError = (error) => {
|
|
9790
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
9791
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
9792
|
+
update({
|
|
9793
|
+
error: failure,
|
|
9794
|
+
status: "error"
|
|
9795
|
+
});
|
|
9796
|
+
live.streamCallbacks?.onError?.(failure);
|
|
9797
|
+
};
|
|
9798
|
+
const requestOptions = async () => {
|
|
9799
|
+
const generation = selectionGeneration;
|
|
9800
|
+
const token = await getValidChatAuthToken(authentication);
|
|
9801
|
+
if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
9802
|
+
return {
|
|
9803
|
+
apiUrl: authentication.apiUrl,
|
|
9804
|
+
astralBeamToken: token,
|
|
9805
|
+
cache: "no-store",
|
|
9806
|
+
signal: AbortSignal.any([requestController.signal, authentication.session.abortController.signal]),
|
|
9807
|
+
fetchClient: (input, init) => fetchAuthenticatedChat({
|
|
9808
|
+
...authentication,
|
|
9809
|
+
input,
|
|
9810
|
+
init
|
|
9811
|
+
})
|
|
9812
|
+
};
|
|
9813
|
+
};
|
|
9613
9814
|
let capabilitiesGeneration = 0;
|
|
9614
9815
|
let capabilityIdentity;
|
|
9615
9816
|
const resolveCapabilities = async () => {
|
|
9616
9817
|
const generation = ++capabilitiesGeneration;
|
|
9818
|
+
const selection = selectionGeneration;
|
|
9819
|
+
if (state.thread?.agentId === null) {
|
|
9820
|
+
update({ capabilities: { attachments: false } });
|
|
9821
|
+
return;
|
|
9822
|
+
}
|
|
9823
|
+
const agentId = state.thread ? state.thread.agentId : live.agentId;
|
|
9617
9824
|
try {
|
|
9618
|
-
const
|
|
9619
|
-
if (generation !== capabilitiesGeneration) return;
|
|
9620
|
-
const body = await getChatConfig(
|
|
9621
|
-
|
|
9622
|
-
astralBeamToken: token,
|
|
9623
|
-
signal: authentication.session.abortController.signal,
|
|
9624
|
-
fetchClient: (input, init) => fetchAuthenticatedChat({
|
|
9625
|
-
...authentication,
|
|
9626
|
-
input,
|
|
9627
|
-
init
|
|
9628
|
-
})
|
|
9629
|
-
});
|
|
9630
|
-
if (generation !== capabilitiesGeneration) return;
|
|
9825
|
+
const auth = await requestOptions();
|
|
9826
|
+
if (generation !== capabilitiesGeneration || selection !== selectionGeneration) return;
|
|
9827
|
+
const body = await getChatConfig(agentId ? { agentId } : {}, auth);
|
|
9828
|
+
if (generation !== capabilitiesGeneration || selection !== selectionGeneration) return;
|
|
9631
9829
|
const attachments = body.capabilities?.attachments !== false;
|
|
9632
9830
|
update({ capabilities: { attachments } });
|
|
9633
9831
|
debug?.("mount", "agent capabilities resolved", { attachments });
|
|
@@ -9636,23 +9834,38 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9636
9834
|
}
|
|
9637
9835
|
};
|
|
9638
9836
|
const renderCleanups = /* @__PURE__ */ new Map();
|
|
9837
|
+
const restoredWidgets = /* @__PURE__ */ new Set();
|
|
9838
|
+
const restoringWidgets = /* @__PURE__ */ new Set();
|
|
9639
9839
|
const disposeRenders = () => {
|
|
9640
9840
|
for (const cleanup of renderCleanups.values()) cleanup();
|
|
9641
9841
|
renderCleanups.clear();
|
|
9842
|
+
restoredWidgets.clear();
|
|
9843
|
+
restoringWidgets.clear();
|
|
9642
9844
|
};
|
|
9643
9845
|
const renderWidget = async (input, toolCallId) => {
|
|
9846
|
+
const generation = selectionGeneration;
|
|
9644
9847
|
const widgets = live.widgets ?? {};
|
|
9645
9848
|
if (!Object.hasOwn(widgets, input.widget)) throw new Error(`Unknown widget "${input.widget}"`);
|
|
9646
9849
|
const declaration = widgets[input.widget];
|
|
9647
9850
|
const validated = await validateParameters(declaration?.parameters, input.props ?? {});
|
|
9851
|
+
if (generation !== selectionGeneration || state.thread?.role === "viewer") return {
|
|
9852
|
+
widget: input.widget,
|
|
9853
|
+
rendered: false
|
|
9854
|
+
};
|
|
9855
|
+
if (declaration !== live.widgets?.[input.widget]) return renderWidget(input, toolCallId);
|
|
9648
9856
|
if (validated == null) throw new Error(`Props for widget "${input.widget}" failed validation`);
|
|
9857
|
+
const onRenderWidget = live.onRenderWidget;
|
|
9858
|
+
if (!onRenderWidget) return {
|
|
9859
|
+
widget: input.widget,
|
|
9860
|
+
rendered: false
|
|
9861
|
+
};
|
|
9649
9862
|
renderCleanups.get(toolCallId)?.();
|
|
9650
9863
|
renderCleanups.delete(toolCallId);
|
|
9651
9864
|
let registered;
|
|
9652
9865
|
const release = () => {
|
|
9653
9866
|
if (renderCleanups.get(toolCallId) === registered) renderCleanups.delete(toolCallId);
|
|
9654
9867
|
};
|
|
9655
|
-
const cleanup =
|
|
9868
|
+
const cleanup = onRenderWidget({
|
|
9656
9869
|
widget: input.widget,
|
|
9657
9870
|
props: validated,
|
|
9658
9871
|
toolCallId,
|
|
@@ -9662,12 +9875,68 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9662
9875
|
registered = cleanup;
|
|
9663
9876
|
renderCleanups.set(toolCallId, cleanup);
|
|
9664
9877
|
}
|
|
9878
|
+
restoredWidgets.add(toolCallId);
|
|
9665
9879
|
return {
|
|
9666
9880
|
widget: input.widget,
|
|
9667
|
-
rendered:
|
|
9881
|
+
rendered: true
|
|
9668
9882
|
};
|
|
9669
9883
|
};
|
|
9670
|
-
const
|
|
9884
|
+
const restoreCompletedWidgets = (messages) => {
|
|
9885
|
+
if (state.thread?.role === "viewer") return;
|
|
9886
|
+
const renderIds = /* @__PURE__ */ new Map();
|
|
9887
|
+
for (const message of state.messages) for (const part of message.parts) {
|
|
9888
|
+
if (part.type !== "tool-call" || part.name !== "render_widget") continue;
|
|
9889
|
+
const stored = part;
|
|
9890
|
+
if (!stored.widgetRenderId) continue;
|
|
9891
|
+
renderIds.set(savedToolCallId(message.id, part.id), stored.widgetRenderId);
|
|
9892
|
+
if (stored.applicationPartId) renderIds.set(savedToolCallId(message.id, stored.applicationPartId, stored.responseTargetId), stored.widgetRenderId);
|
|
9893
|
+
}
|
|
9894
|
+
for (const message of messages) for (const part of message.parts) {
|
|
9895
|
+
if (part.type !== "tool-call" || part.name !== "render_widget" || part.state !== "complete" || !part.input) continue;
|
|
9896
|
+
const stored = part;
|
|
9897
|
+
const upstream = stored.upstreamToolCallId;
|
|
9898
|
+
const renderId = stored.widgetRenderId ?? renderIds.get(savedToolCallId(message.id, part.id)) ?? (stored.applicationPartId ? renderIds.get(savedToolCallId(message.id, stored.applicationPartId, stored.responseTargetId)) : void 0) ?? (upstream && liveToolMessageIds.get(upstream) === message.id && restoredWidgets.has(upstream) ? upstream : part.id);
|
|
9899
|
+
stored.widgetRenderId = renderId;
|
|
9900
|
+
if (restoredWidgets.has(renderId) || restoringWidgets.has(renderId)) continue;
|
|
9901
|
+
restoringWidgets.add(renderId);
|
|
9902
|
+
const generation = selectionGeneration;
|
|
9903
|
+
const { widgets, onRenderWidget } = live;
|
|
9904
|
+
renderWidget(part.input, renderId).catch((error) => debug?.("error", "Saved widget could not be rendered", error)).finally(() => {
|
|
9905
|
+
if (generation !== selectionGeneration) return;
|
|
9906
|
+
restoringWidgets.delete(renderId);
|
|
9907
|
+
if (widgets !== live.widgets || onRenderWidget !== live.onRenderWidget) restoreCompletedWidgets(state.messages);
|
|
9908
|
+
});
|
|
9909
|
+
}
|
|
9910
|
+
};
|
|
9911
|
+
const buildTools = () => buildAgentTools(live.widgets ?? {}, live.tools ?? {}, renderWidget, debug).map((tool) => {
|
|
9912
|
+
if (!tool.execute) return tool;
|
|
9913
|
+
const execute = tool.execute;
|
|
9914
|
+
return {
|
|
9915
|
+
...tool,
|
|
9916
|
+
execute: async (input, context) => {
|
|
9917
|
+
const toolCallId = context?.toolCallId;
|
|
9918
|
+
if (!toolCallId || !liveToolCalls.has(toolCallId)) throw new Error("A saved tool call cannot execute again. Send a new message to request it.");
|
|
9919
|
+
const results = toolResults;
|
|
9920
|
+
const key = toolResultKey(toolCallId);
|
|
9921
|
+
const resultIdentity = identity;
|
|
9922
|
+
const apiUrl = authentication.apiUrl;
|
|
9923
|
+
try {
|
|
9924
|
+
const output = await execute(input, context);
|
|
9925
|
+
if (identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
|
|
9926
|
+
outcome: "succeeded",
|
|
9927
|
+
output: output ?? null
|
|
9928
|
+
});
|
|
9929
|
+
return output;
|
|
9930
|
+
} catch (error) {
|
|
9931
|
+
if (identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
|
|
9932
|
+
outcome: "unknown",
|
|
9933
|
+
output: { error: error instanceof Error ? error.message : String(error) }
|
|
9934
|
+
});
|
|
9935
|
+
throw error;
|
|
9936
|
+
}
|
|
9937
|
+
}
|
|
9938
|
+
};
|
|
9939
|
+
});
|
|
9671
9940
|
const declareTools = () => {
|
|
9672
9941
|
const tools = buildTools();
|
|
9673
9942
|
const agentTools = tools.map((tool) => {
|
|
@@ -9680,40 +9949,200 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9680
9949
|
if (!sameAgentTools(state.agentTools, agentTools)) update({ agentTools });
|
|
9681
9950
|
return tools;
|
|
9682
9951
|
};
|
|
9683
|
-
const forwardedProps = () =>
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9952
|
+
const forwardedProps = () => live.debug ? { debug: true } : {};
|
|
9953
|
+
const threadRequest = async (init, auth) => {
|
|
9954
|
+
const thread = state.thread;
|
|
9955
|
+
if (!thread || typeof init.body !== "string") throw new Error("Open a conversation before sending.");
|
|
9956
|
+
const generation = selectionGeneration;
|
|
9957
|
+
const body = JSON.parse(init.body);
|
|
9958
|
+
let path = getRunChatUrl();
|
|
9959
|
+
let payload;
|
|
9960
|
+
const submission = body.messages.at(-1)?.role === "user" ? pendingSend : void 0;
|
|
9961
|
+
const previouslyAttempted = submission?.tools !== void 0;
|
|
9962
|
+
if (submission) payload = {
|
|
9963
|
+
...body,
|
|
9964
|
+
threadId: thread.id,
|
|
9965
|
+
resume: void 0,
|
|
9966
|
+
parentRunId: void 0,
|
|
9967
|
+
messages: [body.messages.at(-1)],
|
|
9968
|
+
tools: submission.tools ??= body.tools,
|
|
9969
|
+
forwardedProps: {
|
|
9970
|
+
...body.forwardedProps,
|
|
9971
|
+
clientId
|
|
9972
|
+
}
|
|
9973
|
+
};
|
|
9974
|
+
else {
|
|
9975
|
+
scopeCompletedToolCalls();
|
|
9976
|
+
const history = await loadThreadMessages(thread.id, auth, void 0, liveToolMessageIds);
|
|
9977
|
+
if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
9978
|
+
update({ thread: threadFromRecord(history.thread, history.messages.length > 0) });
|
|
9979
|
+
retainToolResults(history);
|
|
9980
|
+
const available = history.pendingInteractions.filter((pending) => toolResults.has(toolResultKey(pending.toolCallId)));
|
|
9981
|
+
const source = available.find((pending) => pending.toolCallId === body.messages.at(-1)?.toolCallId) ?? available[0];
|
|
9982
|
+
const results = history.pendingInteractions.flatMap((pending) => {
|
|
9983
|
+
const submitted = toolResults.get(toolResultKey(pending.toolCallId));
|
|
9984
|
+
return submitted && pending.sourceMessageId === source?.sourceMessageId ? [{
|
|
9985
|
+
source_message_id: pending.sourceMessageId,
|
|
9986
|
+
source_part_id: pending.sourcePartId,
|
|
9987
|
+
response_target_id: pending.responseTargetId,
|
|
9988
|
+
...submitted
|
|
9989
|
+
}] : [];
|
|
9990
|
+
});
|
|
9991
|
+
if (results.length === 0) return new Response("", { headers: { "Content-Type": "text/event-stream" } });
|
|
9992
|
+
path = getResolveChatToolResultUrl(thread.id);
|
|
9993
|
+
payload = {
|
|
9994
|
+
client_id: clientId,
|
|
9995
|
+
run_id: body.runId,
|
|
9996
|
+
...body.parentRunId ? { parent_run_id: body.parentRunId } : {},
|
|
9997
|
+
results
|
|
9998
|
+
};
|
|
9999
|
+
}
|
|
10000
|
+
liveToolCalls.clear();
|
|
10001
|
+
update({ activeToolCallIds: [] });
|
|
10002
|
+
const headers = new Headers(init.headers);
|
|
10003
|
+
if (submission) headers.set("Idempotency-Key", submission.key);
|
|
10004
|
+
const response = await astralBeamChatFetch(path, {
|
|
10005
|
+
...auth,
|
|
10006
|
+
...init,
|
|
10007
|
+
headers,
|
|
10008
|
+
body: JSON.stringify(payload)
|
|
10009
|
+
}).catch((error) => {
|
|
10010
|
+
if (submission && !previouslyAttempted && isAstralBeamApiError(error) && (error.status === 400 || error.status === 413 || error.status === 429)) delete submission.tools;
|
|
10011
|
+
throw error;
|
|
10012
|
+
});
|
|
10013
|
+
if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
10014
|
+
if (response.headers.get("Content-Type")?.includes("application/json")) {
|
|
10015
|
+
const receipt = await response.json();
|
|
10016
|
+
if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
10017
|
+
update({ thread: {
|
|
10018
|
+
...state.thread,
|
|
10019
|
+
version: receipt.thread_version
|
|
10020
|
+
} });
|
|
10021
|
+
if (submission) acceptPendingSend();
|
|
10022
|
+
return new Response("", { headers: { "Content-Type": "text/event-stream" } });
|
|
10023
|
+
}
|
|
10024
|
+
return response;
|
|
10025
|
+
};
|
|
9687
10026
|
const connection = fetchServerSentEvents(() => resolveApiUrl(getRunChatUrl(), authentication.apiUrl), async () => {
|
|
9688
10027
|
const previousIdentity = identity;
|
|
9689
10028
|
const token = await getValidChatAuthToken(authentication);
|
|
9690
10029
|
if (previousIdentity !== void 0 && previousIdentity !== identity) throw new DOMException("Identity changed", "AbortError");
|
|
9691
|
-
return { fetchClient: (_input, init) =>
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
input,
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
10030
|
+
return { fetchClient: (_input, init) => {
|
|
10031
|
+
const auth = {
|
|
10032
|
+
apiUrl: authentication.apiUrl,
|
|
10033
|
+
astralBeamToken: token,
|
|
10034
|
+
...init?.signal ? { signal: init.signal } : {},
|
|
10035
|
+
cache: "no-store",
|
|
10036
|
+
fetchClient: (input, request) => fetchAuthenticatedChat({
|
|
10037
|
+
...authentication,
|
|
10038
|
+
input,
|
|
10039
|
+
init: request
|
|
10040
|
+
})
|
|
10041
|
+
};
|
|
10042
|
+
return threadRequest(init ?? {}, auth);
|
|
10043
|
+
} };
|
|
9701
10044
|
});
|
|
9702
10045
|
const connect = connection.connect;
|
|
9703
10046
|
connection.connect = async function* (...args) {
|
|
9704
10047
|
try {
|
|
9705
|
-
|
|
10048
|
+
for await (const chunk of connect(...args)) {
|
|
10049
|
+
if (chunk.type === EventType.TOOL_CALL_START && chunk.parentMessageId) liveToolMessageIds.set(chunk.toolCallId, chunk.parentMessageId);
|
|
10050
|
+
if (chunk.type !== EventType.MESSAGES_SNAPSHOT) {
|
|
10051
|
+
yield chunk;
|
|
10052
|
+
continue;
|
|
10053
|
+
}
|
|
10054
|
+
let aliases;
|
|
10055
|
+
yield {
|
|
10056
|
+
...chunk,
|
|
10057
|
+
messages: chunk.messages.map((message) => {
|
|
10058
|
+
if (message.role === "assistant") {
|
|
10059
|
+
aliases = historicalToolIds.get(message.id);
|
|
10060
|
+
return aliases && message.toolCalls ? {
|
|
10061
|
+
...message,
|
|
10062
|
+
toolCalls: message.toolCalls.map((call) => ({
|
|
10063
|
+
...call,
|
|
10064
|
+
id: aliases?.get(call.id) ?? call.id
|
|
10065
|
+
}))
|
|
10066
|
+
} : message;
|
|
10067
|
+
}
|
|
10068
|
+
if (message.role === "tool") return {
|
|
10069
|
+
...message,
|
|
10070
|
+
toolCallId: aliases?.get(message.toolCallId) ?? message.toolCallId
|
|
10071
|
+
};
|
|
10072
|
+
aliases = void 0;
|
|
10073
|
+
return message;
|
|
10074
|
+
})
|
|
10075
|
+
};
|
|
10076
|
+
}
|
|
9706
10077
|
} catch (error) {
|
|
9707
10078
|
throw error instanceof Error && isAstralBeamApiError(error.cause) ? error.cause : error;
|
|
9708
10079
|
}
|
|
9709
10080
|
};
|
|
9710
|
-
const createClient = () => {
|
|
10081
|
+
const createClient = (threadId = state.thread?.id) => {
|
|
10082
|
+
const generation = selectionGeneration;
|
|
10083
|
+
const adapter = { ...connection };
|
|
10084
|
+
delete adapter.hydrate;
|
|
10085
|
+
if (threadId) adapter.hydrate = (_id, options) => {
|
|
10086
|
+
const readGeneration = ++historyGeneration;
|
|
10087
|
+
if (!options?.before) update({ threadLoading: true });
|
|
10088
|
+
const read = (async () => {
|
|
10089
|
+
let history = await loadThreadMessages(threadId, await requestOptions(), options?.before, liveToolMessageIds);
|
|
10090
|
+
while (options?.before && history.messages.every((message) => message.role === "tool") && history.page_after) {
|
|
10091
|
+
const earlier = await loadThreadMessages(threadId, await requestOptions(), history.page_after, liveToolMessageIds);
|
|
10092
|
+
history = {
|
|
10093
|
+
...earlier,
|
|
10094
|
+
messages: [...earlier.messages, ...history.messages]
|
|
10095
|
+
};
|
|
10096
|
+
}
|
|
10097
|
+
if (generation !== selectionGeneration || readGeneration !== historyGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
10098
|
+
retainToolResults(history);
|
|
10099
|
+
threadRecords = options?.before ? [...history.messages, ...threadRecords] : history.messages;
|
|
10100
|
+
const pageIds = new Set(history.messages.map((message) => message.id));
|
|
10101
|
+
const messages = projectThreadMessages(threadRecords, history.pendingInteractions, liveToolMessageIds).filter((message) => pageIds.has(message.id));
|
|
10102
|
+
if (history.thread.role === "viewer") disposeRenders();
|
|
10103
|
+
const agentChanged = state.thread?.agentId !== history.thread.agent_id;
|
|
10104
|
+
update({
|
|
10105
|
+
thread: threadFromRecord(history.thread, history.messages.length > 0),
|
|
10106
|
+
messagesCursor: history.page_after ?? void 0,
|
|
10107
|
+
pendingInteractions: history.pendingInteractions,
|
|
10108
|
+
threadLoadFailed: false
|
|
10109
|
+
});
|
|
10110
|
+
restoreCompletedWidgets(messages);
|
|
10111
|
+
if (!options?.before && agentChanged) resolveCapabilities();
|
|
10112
|
+
if (!options?.before && messages.length === 0) next.setMessagesManually([]);
|
|
10113
|
+
return {
|
|
10114
|
+
messages,
|
|
10115
|
+
activeRun: null,
|
|
10116
|
+
interrupts: null,
|
|
10117
|
+
page: history.page_after ? {
|
|
10118
|
+
truncated: true,
|
|
10119
|
+
cursor: history.page_after
|
|
10120
|
+
} : { truncated: false }
|
|
10121
|
+
};
|
|
10122
|
+
})();
|
|
10123
|
+
if (!options?.before) {
|
|
10124
|
+
hydration = read;
|
|
10125
|
+
const settled = (failed) => queueMicrotask(() => {
|
|
10126
|
+
if (generation === selectionGeneration && readGeneration === historyGeneration) update({
|
|
10127
|
+
threadLoading: false,
|
|
10128
|
+
threadLoadFailed: failed
|
|
10129
|
+
});
|
|
10130
|
+
});
|
|
10131
|
+
read.then(() => settled(false), () => settled(true));
|
|
10132
|
+
}
|
|
10133
|
+
return read;
|
|
10134
|
+
};
|
|
9711
10135
|
const next = new ChatClient({
|
|
9712
|
-
connection,
|
|
10136
|
+
connection: adapter,
|
|
10137
|
+
threadId: threadId ?? clientId,
|
|
10138
|
+
persistence: true,
|
|
10139
|
+
history: { pageSize: 100 },
|
|
10140
|
+
queue: "drop",
|
|
9713
10141
|
tools: declareTools(),
|
|
9714
10142
|
forwardedProps: forwardedProps(),
|
|
9715
10143
|
onMessagesChange: (messages) => {
|
|
9716
|
-
if (client !== next) return;
|
|
10144
|
+
if (client !== next || generation !== selectionGeneration) return;
|
|
10145
|
+
restoreCompletedWidgets(messages);
|
|
9717
10146
|
update({
|
|
9718
10147
|
messages,
|
|
9719
10148
|
sandbox: collectSandboxActivity(messages),
|
|
@@ -9721,13 +10150,35 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9721
10150
|
});
|
|
9722
10151
|
},
|
|
9723
10152
|
onStatusChange: (status) => {
|
|
9724
|
-
if (client === next) update({
|
|
10153
|
+
if (client === next && generation === selectionGeneration) update({
|
|
9725
10154
|
status,
|
|
9726
10155
|
error: next.getError()
|
|
9727
10156
|
});
|
|
9728
10157
|
},
|
|
10158
|
+
onInterruptStateChange: (interrupts) => {
|
|
10159
|
+
if (client === next) debug?.("tool", "interrupt state changed", interrupts);
|
|
10160
|
+
},
|
|
9729
10161
|
onCustomEvent: (eventType, data) => {
|
|
9730
10162
|
if (client !== next) return;
|
|
10163
|
+
if (eventType === "astralbeam_thread") {
|
|
10164
|
+
const event = data;
|
|
10165
|
+
if (state.thread?.id === event.threadId) {
|
|
10166
|
+
if (event.acceptedMessageId) acceptPendingSend();
|
|
10167
|
+
if (event.saved) for (const id of event.executableToolCallIds ?? []) {
|
|
10168
|
+
if (!liveToolCalls.has(id)) toolResults.delete(toolResultKey(id));
|
|
10169
|
+
liveToolCalls.add(id);
|
|
10170
|
+
}
|
|
10171
|
+
update({
|
|
10172
|
+
thread: {
|
|
10173
|
+
...state.thread,
|
|
10174
|
+
version: event.version
|
|
10175
|
+
},
|
|
10176
|
+
activeToolCallIds: [...liveToolCalls],
|
|
10177
|
+
...event.acceptedMessageId ? { unsentMessage: void 0 } : {}
|
|
10178
|
+
});
|
|
10179
|
+
}
|
|
10180
|
+
return;
|
|
10181
|
+
}
|
|
9731
10182
|
const value = data?.state;
|
|
9732
10183
|
if (eventType === "astralbeam.sandbox.status" && (value === "starting" || value === "ready" || value === "error")) {
|
|
9733
10184
|
debug?.("sandbox", `sandbox ${value}`);
|
|
@@ -9736,43 +10187,343 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9736
10187
|
}
|
|
9737
10188
|
debug?.("stream", `custom event "${eventType}"`, data);
|
|
9738
10189
|
},
|
|
9739
|
-
onChunk: (chunk) =>
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
10190
|
+
onChunk: (chunk) => {
|
|
10191
|
+
if (client !== next) return;
|
|
10192
|
+
live.streamCallbacks?.onChunk?.(chunk);
|
|
10193
|
+
},
|
|
10194
|
+
onResponse: (response) => {
|
|
10195
|
+
if (client === next) live.streamCallbacks?.onResponse?.(response);
|
|
10196
|
+
},
|
|
10197
|
+
onFinish: (message) => {
|
|
10198
|
+
if (client === next) live.streamCallbacks?.onFinish?.(message);
|
|
10199
|
+
},
|
|
10200
|
+
onError: (error) => {
|
|
10201
|
+
if (client === next) live.streamCallbacks?.onError?.(error);
|
|
10202
|
+
}
|
|
9743
10203
|
});
|
|
9744
10204
|
return next;
|
|
9745
10205
|
};
|
|
9746
10206
|
let client = createClient();
|
|
9747
|
-
const replaceClient = () => {
|
|
10207
|
+
const replaceClient = (threadId = state.thread?.id) => {
|
|
9748
10208
|
client.stop();
|
|
9749
10209
|
const previous = client;
|
|
9750
|
-
|
|
10210
|
+
previous.detach();
|
|
10211
|
+
liveToolCalls.clear();
|
|
10212
|
+
liveToolMessageIds.clear();
|
|
10213
|
+
update({ activeToolCallIds: [] });
|
|
10214
|
+
client = createClient(threadId);
|
|
10215
|
+
if (started) client.attach();
|
|
9751
10216
|
previous.dispose();
|
|
9752
10217
|
};
|
|
9753
|
-
const
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
10218
|
+
const scopeCompletedToolCalls = () => {
|
|
10219
|
+
historicalToolIds.clear();
|
|
10220
|
+
client.setMessagesManually(state.messages.map((message) => {
|
|
10221
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
10222
|
+
const parts = message.parts.map((part) => {
|
|
10223
|
+
if (part.type !== "tool-call") return part;
|
|
10224
|
+
const stored = part;
|
|
10225
|
+
const upstreamToolCallId = stored.upstreamToolCallId ?? part.id;
|
|
10226
|
+
if (liveToolMessageIds.get(upstreamToolCallId) === message.id && !isSettledToolCall(part)) return part;
|
|
10227
|
+
const id = savedToolCallId(message.id, stored.applicationPartId ?? upstreamToolCallId, stored.responseTargetId);
|
|
10228
|
+
aliases.set(upstreamToolCallId, id);
|
|
10229
|
+
return {
|
|
10230
|
+
...part,
|
|
10231
|
+
upstreamToolCallId,
|
|
10232
|
+
id,
|
|
10233
|
+
...part.name === "render_widget" && liveToolMessageIds.get(upstreamToolCallId) === message.id ? { widgetRenderId: stored.widgetRenderId ?? part.id } : {}
|
|
10234
|
+
};
|
|
10235
|
+
});
|
|
10236
|
+
if (aliases.size) historicalToolIds.set(message.id, aliases);
|
|
10237
|
+
return {
|
|
10238
|
+
...message,
|
|
10239
|
+
parts
|
|
10240
|
+
};
|
|
10241
|
+
}));
|
|
10242
|
+
};
|
|
10243
|
+
const changeSelection = (threadId) => {
|
|
10244
|
+
const previousId = state.thread?.id;
|
|
10245
|
+
if (previousId) {
|
|
10246
|
+
if (pendingSend && !pendingSend.accepted) pendingSends.set(previousId, pendingSend);
|
|
10247
|
+
else pendingSends.delete(previousId);
|
|
10248
|
+
threadToolResults.set(previousId, toolResults);
|
|
10249
|
+
}
|
|
10250
|
+
selectionGeneration++;
|
|
10251
|
+
historyGeneration++;
|
|
10252
|
+
sending = false;
|
|
10253
|
+
requestController.abort();
|
|
10254
|
+
requestController = new AbortController();
|
|
10255
|
+
pendingSend = void 0;
|
|
10256
|
+
toolResults = threadToolResults.get(threadId ?? "") ?? /* @__PURE__ */ new Map();
|
|
10257
|
+
historicalToolIds.clear();
|
|
10258
|
+
threadRecords = [];
|
|
10259
|
+
disposeRenders();
|
|
10260
|
+
update({
|
|
10261
|
+
thread: void 0,
|
|
10262
|
+
messages: [],
|
|
10263
|
+
unsentMessage: void 0,
|
|
10264
|
+
error: void 0,
|
|
10265
|
+
status: "ready",
|
|
10266
|
+
sandbox: {
|
|
10267
|
+
files: [],
|
|
10268
|
+
commands: []
|
|
10269
|
+
},
|
|
10270
|
+
sandboxStatus: void 0,
|
|
10271
|
+
pendingInteractions: [],
|
|
10272
|
+
threadLoadFailed: false,
|
|
10273
|
+
messagesCursor: void 0,
|
|
10274
|
+
olderMessagesLoading: false
|
|
10275
|
+
});
|
|
10276
|
+
replaceClient(threadId);
|
|
10277
|
+
};
|
|
10278
|
+
const openThread = async (id, restoring = false) => {
|
|
10279
|
+
if (!restoring) navigationGeneration++;
|
|
10280
|
+
changeSelection(id);
|
|
10281
|
+
const generation = selectionGeneration;
|
|
10282
|
+
update({ threadLoading: true });
|
|
10283
|
+
try {
|
|
10284
|
+
pendingSend = pendingSends.get(id);
|
|
10285
|
+
update({ unsentMessage: pendingSend?.content });
|
|
10286
|
+
if (!started) client.attach();
|
|
10287
|
+
await hydration;
|
|
10288
|
+
if (generation !== selectionGeneration) return;
|
|
10289
|
+
if (threadKey) selectedThread(threadKey, id);
|
|
10290
|
+
} catch (error) {
|
|
10291
|
+
if (generation === selectionGeneration) {
|
|
10292
|
+
if (restoring && (live.threadId === void 0 || live.threadId === "auto") && isAstralBeamApiError(error) && error.status === 404) {
|
|
10293
|
+
newThread();
|
|
10294
|
+
return;
|
|
10295
|
+
}
|
|
10296
|
+
update({ threadLoadFailed: true });
|
|
10297
|
+
reportError(error);
|
|
10298
|
+
}
|
|
10299
|
+
} finally {
|
|
10300
|
+
if (generation === selectionGeneration) update({ threadLoading: false });
|
|
10301
|
+
}
|
|
10302
|
+
};
|
|
10303
|
+
const newThread = () => {
|
|
10304
|
+
navigationGeneration++;
|
|
10305
|
+
changeSelection();
|
|
10306
|
+
update({ threadLoading: false });
|
|
10307
|
+
if (started) resolveCapabilities();
|
|
10308
|
+
if (threadKey) selectedThread(threadKey, null);
|
|
10309
|
+
else startWithNewThread = true;
|
|
10310
|
+
};
|
|
10311
|
+
const selectConfiguredThread = (restoring = false) => {
|
|
10312
|
+
let selected = live.threadId;
|
|
10313
|
+
if (selected === void 0 || selected === "auto") {
|
|
10314
|
+
if (!threadKey) return;
|
|
10315
|
+
selected = selectedThread(threadKey);
|
|
10316
|
+
}
|
|
10317
|
+
if (selected && selected !== "new") openThread(selected, restoring);
|
|
10318
|
+
else if (!restoring) newThread();
|
|
10319
|
+
};
|
|
10320
|
+
const ensureThread = async () => {
|
|
10321
|
+
if (state.thread) return;
|
|
10322
|
+
const generation = selectionGeneration;
|
|
10323
|
+
const options = await requestOptions();
|
|
10324
|
+
const record = await createChatThread(live.agentId ? { agent_id: live.agentId } : {}, options);
|
|
10325
|
+
if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
|
|
10326
|
+
const thread = threadFromRecord(record, false);
|
|
10327
|
+
update({ thread });
|
|
10328
|
+
replaceClient();
|
|
10329
|
+
await hydration;
|
|
10330
|
+
resolveCapabilities();
|
|
10331
|
+
if (threadKey) selectedThread(threadKey, thread.id);
|
|
10332
|
+
};
|
|
10333
|
+
const refreshThread = async (preserveError = false, resetClient = true) => {
|
|
10334
|
+
if (!state.thread?.id) return;
|
|
10335
|
+
const generation = selectionGeneration;
|
|
10336
|
+
const previousError = state.error;
|
|
10337
|
+
update({
|
|
10338
|
+
threadLoading: true,
|
|
10339
|
+
olderMessagesLoading: false
|
|
10340
|
+
});
|
|
10341
|
+
try {
|
|
10342
|
+
if (resetClient) replaceClient();
|
|
10343
|
+
else {
|
|
10344
|
+
client.detach();
|
|
10345
|
+
client.attach();
|
|
10346
|
+
}
|
|
10347
|
+
await hydration;
|
|
10348
|
+
if (generation !== selectionGeneration) return;
|
|
10349
|
+
if (preserveError && previousError) update({
|
|
10350
|
+
error: previousError,
|
|
10351
|
+
status: "error"
|
|
10352
|
+
});
|
|
10353
|
+
} catch (error) {
|
|
10354
|
+
if (generation === selectionGeneration) {
|
|
10355
|
+
if (isAstralBeamApiError(error) && error.status === 404) {
|
|
10356
|
+
newThread();
|
|
10357
|
+
return;
|
|
10358
|
+
}
|
|
10359
|
+
reportError(error);
|
|
10360
|
+
}
|
|
10361
|
+
} finally {
|
|
10362
|
+
if (generation === selectionGeneration) update({ threadLoading: false });
|
|
10363
|
+
}
|
|
10364
|
+
};
|
|
10365
|
+
const loadOlderMessages = async () => {
|
|
10366
|
+
if (!client.getHasOlderMessages() || state.olderMessagesLoading || state.threadLoading || sending) return;
|
|
10367
|
+
const generation = selectionGeneration;
|
|
10368
|
+
update({ olderMessagesLoading: true });
|
|
10369
|
+
try {
|
|
10370
|
+
await client.loadOlderMessages();
|
|
10371
|
+
} catch (error) {
|
|
10372
|
+
if (generation === selectionGeneration) reportError(error);
|
|
10373
|
+
} finally {
|
|
10374
|
+
if (generation === selectionGeneration) update({ olderMessagesLoading: false });
|
|
10375
|
+
}
|
|
10376
|
+
};
|
|
10377
|
+
const renameThread = async (title) => {
|
|
10378
|
+
const thread = state.thread;
|
|
10379
|
+
if (!thread || thread.role !== "manager") return false;
|
|
10380
|
+
const generation = selectionGeneration;
|
|
10381
|
+
try {
|
|
10382
|
+
const record = await updateChatThread(thread.id, {
|
|
10383
|
+
title,
|
|
10384
|
+
expected_version: thread.version
|
|
10385
|
+
}, await requestOptions());
|
|
10386
|
+
if (generation !== selectionGeneration) return false;
|
|
10387
|
+
const renamed = threadFromRecord(record, thread.hasMessages);
|
|
10388
|
+
update({
|
|
10389
|
+
thread: renamed,
|
|
10390
|
+
error: client.getError(),
|
|
10391
|
+
status: client.getStatus()
|
|
10392
|
+
});
|
|
10393
|
+
return true;
|
|
10394
|
+
} catch (error) {
|
|
10395
|
+
if (generation === selectionGeneration) reportError(error);
|
|
10396
|
+
return false;
|
|
10397
|
+
}
|
|
10398
|
+
};
|
|
10399
|
+
const deleteThread = async (thread = state.thread) => {
|
|
10400
|
+
if (!thread || thread.role !== "manager") return false;
|
|
10401
|
+
const generation = selectionGeneration;
|
|
10402
|
+
try {
|
|
10403
|
+
await deleteChatThread(thread.id, { expected_version: String(thread.version) }, await requestOptions());
|
|
10404
|
+
if (generation === selectionGeneration && state.thread?.id === thread.id) newThread();
|
|
10405
|
+
return true;
|
|
10406
|
+
} catch (error) {
|
|
10407
|
+
if (generation === selectionGeneration) reportError(error);
|
|
10408
|
+
return false;
|
|
10409
|
+
}
|
|
10410
|
+
};
|
|
10411
|
+
const addToolResult = async (result) => {
|
|
10412
|
+
const generation = selectionGeneration;
|
|
10413
|
+
if (sending || client.getIsLoading()) {
|
|
10414
|
+
reportError(/* @__PURE__ */ new Error("Wait for this client's current request to finish before responding."));
|
|
10415
|
+
return;
|
|
10416
|
+
}
|
|
10417
|
+
const current = authenticationState(authentication);
|
|
10418
|
+
const pending = state.pendingInteractions.find((item) => item.toolCallId === result.toolCallId);
|
|
10419
|
+
const closure = !("tool" in result) && pending && (state.thread?.role === "manager" || current.status === "ready" && pending.targetTenantUserId === current.currentUser.user.id);
|
|
10420
|
+
const questionnaire = "tool" in result && result.tool === "ask_questionnaire" && current.status === "ready" && pending?.targetTenantUserId === current.currentUser.user.id;
|
|
10421
|
+
if (state.thread?.role === "viewer" || !liveToolCalls.has(result.toolCallId) && !questionnaire && !closure && !toolResults.has(toolResultKey(result.toolCallId))) {
|
|
10422
|
+
reportError(/* @__PURE__ */ new Error("This tool call belongs to another session and cannot be executed here."));
|
|
10423
|
+
return;
|
|
10424
|
+
}
|
|
10425
|
+
if (closure && !toolResults.has(toolResultKey(result.toolCallId))) toolResults.set(toolResultKey(result.toolCallId), {
|
|
10426
|
+
outcome: "unknown",
|
|
10427
|
+
output: null
|
|
10428
|
+
});
|
|
10429
|
+
else if (!toolResults.has(toolResultKey(result.toolCallId)) && "tool" in result) {
|
|
10430
|
+
const output = result.output;
|
|
10431
|
+
toolResults.set(toolResultKey(result.toolCallId), {
|
|
10432
|
+
outcome: result.state === "output-error" ? "failed" : "succeeded",
|
|
10433
|
+
output: output ?? null
|
|
10434
|
+
});
|
|
10435
|
+
}
|
|
10436
|
+
scopeCompletedToolCalls();
|
|
10437
|
+
if (pending && (!("tool" in result) || result.toolCallId === savedToolCallId(pending.sourceMessageId, pending.sourcePartId, pending.responseTargetId))) {
|
|
10438
|
+
replaceClient();
|
|
10439
|
+
await hydration;
|
|
10440
|
+
if (generation !== selectionGeneration) return;
|
|
10441
|
+
update({ threadLoading: false });
|
|
10442
|
+
await client.append({
|
|
10443
|
+
role: "tool",
|
|
10444
|
+
toolCallId: result.toolCallId,
|
|
10445
|
+
content: JSON.stringify(toolResults.get(toolResultKey(result.toolCallId)))
|
|
10446
|
+
});
|
|
10447
|
+
} else if ("tool" in result) await client.addToolResult(result);
|
|
10448
|
+
if (generation === selectionGeneration) await refreshThread(client.getError() !== void 0, false);
|
|
10449
|
+
};
|
|
10450
|
+
const abandonToolCall = (toolCallId) => addToolResult({ toolCallId });
|
|
10451
|
+
const sendMessage = async (content, callbacks) => {
|
|
10452
|
+
const navigation = navigationGeneration;
|
|
10453
|
+
try {
|
|
10454
|
+
await getValidChatAuthToken(authentication);
|
|
10455
|
+
} catch (error) {
|
|
10456
|
+
if (navigation !== navigationGeneration) return;
|
|
10457
|
+
update({ unsentMessage: content });
|
|
10458
|
+
reportError(error);
|
|
10459
|
+
return;
|
|
10460
|
+
}
|
|
10461
|
+
if (navigation !== navigationGeneration) return;
|
|
10462
|
+
if (sending || state.threadLoading || state.status === "streaming") {
|
|
10463
|
+
reportError(/* @__PURE__ */ new Error("Wait for this client's current request to finish before sending."));
|
|
10464
|
+
return;
|
|
10465
|
+
}
|
|
10466
|
+
if (state.threadLoadFailed) {
|
|
10467
|
+
reportError(/* @__PURE__ */ new Error("Reopen this conversation or start a new one before sending."));
|
|
10468
|
+
return;
|
|
10469
|
+
}
|
|
10470
|
+
const samePendingContent = pendingSend !== void 0 && JSON.stringify(pendingSend.content) === JSON.stringify(content);
|
|
10471
|
+
const uncertainSend = pendingSend?.tools !== void 0 && !pendingSend.accepted ? pendingSend : void 0;
|
|
10472
|
+
const retrying = uncertainSend !== void 0 && samePendingContent;
|
|
10473
|
+
if (state.thread?.agentId === null && !retrying) {
|
|
10474
|
+
reportError(/* @__PURE__ */ new Error("This conversation’s agent is unavailable. Start a new conversation to continue."));
|
|
10475
|
+
return;
|
|
10476
|
+
}
|
|
10477
|
+
if (state.thread?.role === "viewer" && !retrying) {
|
|
10478
|
+
reportError(/* @__PURE__ */ new Error("You have read-only access to this conversation."));
|
|
10479
|
+
return;
|
|
10480
|
+
}
|
|
10481
|
+
if (uncertainSend && !samePendingContent) {
|
|
10482
|
+
update({ unsentMessage: uncertainSend.content });
|
|
10483
|
+
reportError(/* @__PURE__ */ new Error("The previous message’s acceptance is unconfirmed. Retry that message before sending different text, or start a new conversation."));
|
|
10484
|
+
return;
|
|
10485
|
+
}
|
|
10486
|
+
const generation = selectionGeneration;
|
|
10487
|
+
historyGeneration++;
|
|
10488
|
+
update({ olderMessagesLoading: false });
|
|
10489
|
+
sending = true;
|
|
10490
|
+
if (!pendingSend || pendingSend.accepted || !samePendingContent) {
|
|
10491
|
+
pendingSend = {
|
|
10492
|
+
content,
|
|
10493
|
+
accepted: false,
|
|
10494
|
+
key: newUuid(),
|
|
10495
|
+
callbacks
|
|
10496
|
+
};
|
|
10497
|
+
client.stop();
|
|
10498
|
+
liveToolCalls.clear();
|
|
10499
|
+
scopeCompletedToolCalls();
|
|
10500
|
+
liveToolMessageIds.clear();
|
|
10501
|
+
update({ activeToolCallIds: [] });
|
|
10502
|
+
}
|
|
10503
|
+
pendingSend.callbacks ??= callbacks;
|
|
10504
|
+
update({
|
|
10505
|
+
unsentMessage: content,
|
|
10506
|
+
error: void 0,
|
|
10507
|
+
status: "submitted"
|
|
10508
|
+
});
|
|
10509
|
+
try {
|
|
10510
|
+
await ensureThread();
|
|
10511
|
+
if (generation !== selectionGeneration) return;
|
|
10512
|
+
pendingSend.callbacks?.onThreadReady?.(state.thread.id);
|
|
10513
|
+
if (generation !== selectionGeneration) return;
|
|
10514
|
+
scopeCompletedToolCalls();
|
|
10515
|
+
await client.sendMessage(content);
|
|
10516
|
+
if (generation !== selectionGeneration) return;
|
|
10517
|
+
const failed = client.getError() !== void 0;
|
|
10518
|
+
if (pendingSend?.accepted) {
|
|
10519
|
+
pendingSend = void 0;
|
|
10520
|
+
update({ unsentMessage: void 0 });
|
|
9775
10521
|
}
|
|
10522
|
+
await refreshThread(failed, false);
|
|
10523
|
+
} catch (error) {
|
|
10524
|
+
if (generation === selectionGeneration) reportError(error);
|
|
10525
|
+
} finally {
|
|
10526
|
+
if (generation === selectionGeneration) sending = false;
|
|
9776
10527
|
}
|
|
9777
10528
|
};
|
|
9778
10529
|
const observeAuthentication = () => {
|
|
@@ -9780,18 +10531,22 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9780
10531
|
if (auth.status === "ready") {
|
|
9781
10532
|
const nextIdentity = authenticationIdentity(auth.currentUser);
|
|
9782
10533
|
if (identity !== void 0 && identity !== nextIdentity) {
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
files: [],
|
|
9789
|
-
commands: []
|
|
9790
|
-
},
|
|
9791
|
-
sandboxStatus: void 0
|
|
9792
|
-
});
|
|
10534
|
+
navigationGeneration++;
|
|
10535
|
+
pendingSends.clear();
|
|
10536
|
+
threadToolResults.clear();
|
|
10537
|
+
toolResults.clear();
|
|
10538
|
+
pendingSend = void 0;
|
|
9793
10539
|
}
|
|
9794
10540
|
identity = nextIdentity;
|
|
10541
|
+
const nextThreadKey = `astralbeam:thread:${live.apiUrl ?? "https://astralbeam.ai/api"}:${nextIdentity}`;
|
|
10542
|
+
if (threadKey !== nextThreadKey) {
|
|
10543
|
+
changeSelection();
|
|
10544
|
+
threadKey = nextThreadKey;
|
|
10545
|
+
if (startWithNewThread) {
|
|
10546
|
+
selectedThread(nextThreadKey, null);
|
|
10547
|
+
startWithNewThread = false;
|
|
10548
|
+
} else selectConfiguredThread(true);
|
|
10549
|
+
}
|
|
9795
10550
|
if (capabilityIdentity !== nextIdentity) {
|
|
9796
10551
|
capabilityIdentity = nextIdentity;
|
|
9797
10552
|
resolveCapabilities();
|
|
@@ -9802,6 +10557,8 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9802
10557
|
const start = () => {
|
|
9803
10558
|
if (started) return;
|
|
9804
10559
|
started = true;
|
|
10560
|
+
client.attach();
|
|
10561
|
+
if (requestController.signal.aborted) requestController = new AbortController();
|
|
9805
10562
|
unsubscribeAuthentication = subscribeAuthentication(authentication, observeAuthentication);
|
|
9806
10563
|
observeAuthentication();
|
|
9807
10564
|
stopAuthentication = startAuthentication(authentication);
|
|
@@ -9817,6 +10574,8 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9817
10574
|
updateOptions: (next) => {
|
|
9818
10575
|
const agent = live.agentId;
|
|
9819
10576
|
const apiUrl = live.apiUrl;
|
|
10577
|
+
const selectedId = live.threadId;
|
|
10578
|
+
const { widgets, onRenderWidget } = live;
|
|
9820
10579
|
live = {
|
|
9821
10580
|
...live,
|
|
9822
10581
|
...next
|
|
@@ -9831,13 +10590,22 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9831
10590
|
tools: declareTools(),
|
|
9832
10591
|
forwardedProps: forwardedProps()
|
|
9833
10592
|
});
|
|
10593
|
+
if (live.apiUrl !== apiUrl) {
|
|
10594
|
+
navigationGeneration++;
|
|
10595
|
+
pendingSends.clear();
|
|
10596
|
+
threadToolResults.clear();
|
|
10597
|
+
toolResults.clear();
|
|
10598
|
+
pendingSend = void 0;
|
|
10599
|
+
changeSelection();
|
|
10600
|
+
threadKey = void 0;
|
|
10601
|
+
update({ threadLoading: false });
|
|
10602
|
+
observeAuthentication();
|
|
10603
|
+
} else if (live.threadId !== selectedId) selectConfiguredThread();
|
|
10604
|
+
if (widgets !== live.widgets || onRenderWidget !== live.onRenderWidget) restoreCompletedWidgets(state.messages);
|
|
9834
10605
|
if (started && (live.agentId !== agent || live.apiUrl !== apiUrl)) resolveCapabilities();
|
|
9835
10606
|
},
|
|
9836
|
-
sendMessage
|
|
9837
|
-
|
|
9838
|
-
return client.sendMessage(content);
|
|
9839
|
-
},
|
|
9840
|
-
addToolResult: (result) => client.addToolResult(result),
|
|
10607
|
+
sendMessage,
|
|
10608
|
+
addToolResult,
|
|
9841
10609
|
stop: () => client.stop(),
|
|
9842
10610
|
retryAuthentication: () => {
|
|
9843
10611
|
getValidChatAuthToken({
|
|
@@ -9845,25 +10613,56 @@ function createAstralBeamChat(options, deferStart = false) {
|
|
|
9845
10613
|
force: true
|
|
9846
10614
|
}).catch(() => void 0);
|
|
9847
10615
|
},
|
|
9848
|
-
reload: () =>
|
|
10616
|
+
reload: async () => {
|
|
10617
|
+
const generation = selectionGeneration;
|
|
10618
|
+
await refreshThread();
|
|
10619
|
+
if (generation !== selectionGeneration || state.error) return;
|
|
10620
|
+
const attempted = /* @__PURE__ */ new Set();
|
|
10621
|
+
while (generation === selectionGeneration) {
|
|
10622
|
+
const pending = state.pendingInteractions.find((item) => !attempted.has(item.sourceMessageId) && toolResults.has(toolResultKey(item.toolCallId)));
|
|
10623
|
+
if (!pending) return;
|
|
10624
|
+
attempted.add(pending.sourceMessageId);
|
|
10625
|
+
await addToolResult({ toolCallId: pending.toolCallId });
|
|
10626
|
+
if (state.error) return;
|
|
10627
|
+
}
|
|
10628
|
+
},
|
|
10629
|
+
searchThreads: async (q = "", cursor, signal) => {
|
|
10630
|
+
const options = await requestOptions();
|
|
10631
|
+
const page = await listChatThreads({
|
|
10632
|
+
q,
|
|
10633
|
+
page_size: 50,
|
|
10634
|
+
...cursor ? { page_after: cursor } : {}
|
|
10635
|
+
}, {
|
|
10636
|
+
...options,
|
|
10637
|
+
signal: AbortSignal.any([options.signal, ...signal ? [signal] : []])
|
|
10638
|
+
});
|
|
10639
|
+
return {
|
|
10640
|
+
items: page.items.map((record) => threadFromRecord(record)),
|
|
10641
|
+
page_after: page.page_after
|
|
10642
|
+
};
|
|
10643
|
+
},
|
|
10644
|
+
openThread,
|
|
10645
|
+
renameThread,
|
|
10646
|
+
deleteThread,
|
|
10647
|
+
refreshThread,
|
|
10648
|
+
loadOlderMessages,
|
|
10649
|
+
getAttachment: async (messageId, partId) => {
|
|
10650
|
+
const thread = state.thread;
|
|
10651
|
+
if (!thread) throw new Error("Open a conversation before downloading attachments.");
|
|
10652
|
+
return (await getChatAttachment(thread.id, messageId, partId, await requestOptions())).blob();
|
|
10653
|
+
},
|
|
10654
|
+
abandonToolCall,
|
|
9849
10655
|
reset: () => {
|
|
9850
10656
|
debug?.("status", "conversation reset");
|
|
9851
|
-
|
|
9852
|
-
disposeRenders();
|
|
9853
|
-
update({
|
|
9854
|
-
messages: [],
|
|
9855
|
-
status: "ready",
|
|
9856
|
-
sandbox: {
|
|
9857
|
-
files: [],
|
|
9858
|
-
commands: []
|
|
9859
|
-
},
|
|
9860
|
-
sandboxStatus: void 0,
|
|
9861
|
-
error: void 0
|
|
9862
|
-
});
|
|
10657
|
+
newThread();
|
|
9863
10658
|
},
|
|
9864
10659
|
dispose: () => {
|
|
10660
|
+
client.detach();
|
|
9865
10661
|
disposeRenders();
|
|
9866
10662
|
client.stop();
|
|
10663
|
+
requestController.abort();
|
|
10664
|
+
selectionGeneration++;
|
|
10665
|
+
threadKey = void 0;
|
|
9867
10666
|
capabilitiesGeneration++;
|
|
9868
10667
|
capabilityIdentity = void 0;
|
|
9869
10668
|
stopAuthentication?.();
|