@aparte/core 0.13.0 → 0.14.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 +2 -2
- package/dist/client/aparte-client.d.ts +36 -35
- package/dist/client/aparte-client.d.ts.map +1 -1
- package/dist/client/stream-adapter.d.ts +37 -145
- package/dist/client/stream-adapter.d.ts.map +1 -1
- package/dist/components/bubble/aparte-chat-bubble.d.ts +10 -2
- package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-add-attachment.d.ts +6 -6
- package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-input.d.ts +9 -1
- package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer.d.ts +12 -3
- package/dist/components/composer/aparte-composer.d.ts.map +1 -1
- package/dist/components/context/aparte-context.d.ts +81 -0
- package/dist/components/context/aparte-context.d.ts.map +1 -0
- package/dist/components/context/index.d.ts +3 -0
- package/dist/components/context/index.d.ts.map +1 -0
- package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/suggestions/aparte-suggestions.d.ts +95 -0
- package/dist/components/suggestions/aparte-suggestions.d.ts.map +1 -0
- package/dist/components/suggestions/index.d.ts +3 -0
- package/dist/components/suggestions/index.d.ts.map +1 -0
- package/dist/components/viewport/aparte-chat-viewport.d.ts +37 -7
- package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
- package/dist/config/aparte-config.d.ts +1 -21
- package/dist/config/aparte-config.d.ts.map +1 -1
- package/dist/config/index.d.ts +0 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/locale.d.ts +30 -1
- package/dist/config/locale.d.ts.map +1 -1
- package/dist/conversations/index.d.ts +1 -1
- package/dist/conversations/index.d.ts.map +1 -1
- package/dist/conversations/types.d.ts +9 -57
- package/dist/conversations/types.d.ts.map +1 -1
- package/dist/custom-elements.json +6484 -6103
- package/dist/generated/element-attributes.d.ts +34 -6
- package/dist/generated/element-attributes.d.ts.map +1 -1
- package/dist/{glyphs-QXfbL3n_.js → glyphs-B3BZ2TIb.js} +21 -21
- package/dist/glyphs-B3BZ2TIb.js.map +1 -0
- package/dist/host/aparte-chat-host.d.ts +1 -1
- package/dist/host/aparte-chat-host.d.ts.map +1 -1
- package/dist/icons/extended.d.ts +87 -85
- package/dist/icons/extended.d.ts.map +1 -1
- package/dist/icons/glyphs.d.ts +53 -50
- package/dist/icons/glyphs.d.ts.map +1 -1
- package/dist/icons.js +41 -41
- package/dist/icons.js.map +1 -1
- package/dist/index.css +539 -172
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +609 -183
- package/dist/index.js.map +1 -1
- package/dist/index.node.d.ts +6 -4
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +56 -56
- package/dist/index.node.js.map +1 -1
- package/dist/{is-awaiting-reply-DrO_oR32.js → is-awaiting-reply-BZ_iJ3s3.js} +188 -1017
- package/dist/is-awaiting-reply-BZ_iJ3s3.js.map +1 -0
- package/dist/parsers/aparte-stream-parser.d.ts +6 -17
- package/dist/parsers/aparte-stream-parser.d.ts.map +1 -1
- package/dist/primitives/select/aparte-select.d.ts +2 -2
- package/dist/primitives/select/aparte-select.d.ts.map +1 -1
- package/dist/renderers/segment-renderers.d.ts +18 -0
- package/dist/renderers/segment-renderers.d.ts.map +1 -1
- package/dist/renderers/segments/tool-call.d.ts.map +1 -1
- package/dist/runtime/message-repository.d.ts +7 -0
- package/dist/runtime/message-repository.d.ts.map +1 -1
- package/dist/transport/types.d.ts +8 -0
- package/dist/transport/types.d.ts.map +1 -1
- package/dist/types/chat.d.ts +32 -38
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/errors.d.ts +16 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/event-map.d.ts +4 -0
- package/dist/types/event-map.d.ts.map +1 -1
- package/dist/types/events.d.ts +15 -0
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/models.d.ts +1 -8
- package/dist/types/models.d.ts.map +1 -1
- package/dist/types/segments.d.ts +1 -13
- package/dist/types/segments.d.ts.map +1 -1
- package/dist/types/tools.d.ts +1 -1
- package/dist/utils/chat-boundary.d.ts +8 -4
- package/dist/utils/chat-boundary.d.ts.map +1 -1
- package/package.json +5 -2
- package/dist/client/xml-artifact-feed.d.ts +0 -76
- package/dist/client/xml-artifact-feed.d.ts.map +0 -1
- package/dist/config/skeleton-provider.d.ts +0 -26
- package/dist/config/skeleton-provider.d.ts.map +0 -1
- package/dist/glyphs-QXfbL3n_.js.map +0 -1
- package/dist/is-awaiting-reply-DrO_oR32.js.map +0 -1
- package/dist/renderers/segments/pipeline-waiting.d.ts +0 -3
- package/dist/renderers/segments/pipeline-waiting.d.ts.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { A as APARTE_ICON_GLYPHS } from "./glyphs-
|
|
1
|
+
import { A as APARTE_ICON_GLYPHS } from "./glyphs-B3BZ2TIb.js";
|
|
2
|
+
import { deriveArtifactKind, runStreamAgent } from "@aparte/engine";
|
|
2
3
|
function contentToText(content) {
|
|
3
4
|
if (typeof content === "string") return content;
|
|
4
5
|
return content.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
@@ -6,6 +7,7 @@ function contentToText(content) {
|
|
|
6
7
|
var AparteErrorCode = /* @__PURE__ */ ((AparteErrorCode2) => {
|
|
7
8
|
AparteErrorCode2["CONFIG_NO_PROVIDER"] = "CONFIG_NO_PROVIDER";
|
|
8
9
|
AparteErrorCode2["CONFIG_MISSING_KEY"] = "CONFIG_MISSING_KEY";
|
|
10
|
+
AparteErrorCode2["CONFIG_INVALID_KEY"] = "CONFIG_INVALID_KEY";
|
|
9
11
|
AparteErrorCode2["CONFIG_INVALID_MODEL"] = "CONFIG_INVALID_MODEL";
|
|
10
12
|
AparteErrorCode2["USAGE_RATE_LIMIT"] = "USAGE_RATE_LIMIT";
|
|
11
13
|
AparteErrorCode2["USAGE_CONTEXT_EXCEEDED"] = "USAGE_CONTEXT_EXCEEDED";
|
|
@@ -29,11 +31,50 @@ class AparteError extends Error {
|
|
|
29
31
|
this.httpStatus = httpStatus;
|
|
30
32
|
this.name = "AparteError";
|
|
31
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The code an HTTP status stands for — the table the enum's own comments promise.
|
|
36
|
+
* `undefined` for a status the enum does not name (a 404 can be a wrong model or a
|
|
37
|
+
* wrong URL; the message says which, a code would guess).
|
|
38
|
+
*/
|
|
39
|
+
static codeForStatus(status) {
|
|
40
|
+
switch (status) {
|
|
41
|
+
case 400:
|
|
42
|
+
return "USAGE_BAD_REQUEST";
|
|
43
|
+
case 401:
|
|
44
|
+
case 403:
|
|
45
|
+
return "CONFIG_INVALID_KEY";
|
|
46
|
+
case 408:
|
|
47
|
+
return "NET_TIMEOUT";
|
|
48
|
+
case 429:
|
|
49
|
+
return "USAGE_RATE_LIMIT";
|
|
50
|
+
case 503:
|
|
51
|
+
return "PROVIDER_UNAVAILABLE";
|
|
52
|
+
default:
|
|
53
|
+
return status !== void 0 && status >= 500 ? "PROVIDER_ERROR" : void 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
32
56
|
static from(error, defaultCode = "UNKNOWN_ERROR", defaultStatus) {
|
|
33
57
|
if (error instanceof AparteError) return error;
|
|
34
58
|
const message = error instanceof Error ? error.message : String(error);
|
|
35
59
|
const status = error?.status || error?.statusCode || defaultStatus;
|
|
36
|
-
|
|
60
|
+
const code = defaultCode !== "UNKNOWN_ERROR" ? defaultCode : AparteError.codeForStatus(status) ?? AparteError.codeForFailure(error) ?? defaultCode;
|
|
61
|
+
return new AparteError(message, code, void 0, error, status);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* What a thrown, statusless error says about itself. `fetch` rejects a network
|
|
65
|
+
* failure with a TypeError whose message names the fetch ("Failed to fetch",
|
|
66
|
+
* "NetworkError when attempting to fetch resource.", "Load failed") — any other
|
|
67
|
+
* TypeError is a bug, not the network, and stays unclassified. `AbortSignal.timeout()`
|
|
68
|
+
* rejects with a TimeoutError.
|
|
69
|
+
*/
|
|
70
|
+
static codeForFailure(error) {
|
|
71
|
+
if (!(error instanceof Error)) return void 0;
|
|
72
|
+
if (error.name === "TimeoutError") return "NET_TIMEOUT";
|
|
73
|
+
if (error instanceof TypeError && /fetch|network|load failed/i.test(error.message)) {
|
|
74
|
+
const offline = typeof navigator !== "undefined" && navigator.onLine === false;
|
|
75
|
+
return offline ? "NET_OFFLINE" : "NET_ERROR";
|
|
76
|
+
}
|
|
77
|
+
return void 0;
|
|
37
78
|
}
|
|
38
79
|
}
|
|
39
80
|
const APARTE_DEFAULT_ICON_FALLBACKS = APARTE_ICON_GLYPHS;
|
|
@@ -57,6 +98,10 @@ const APARTE_DEFAULT_LOCALE = {
|
|
|
57
98
|
approvalInstructionPlaceholder: "Or tell it what to do instead…",
|
|
58
99
|
approvalAsk: "Run {tool}?",
|
|
59
100
|
approvalWaiting: "waiting for you",
|
|
101
|
+
scrollToBottom: "Scroll to bottom",
|
|
102
|
+
suggestionsLabel: "Suggested prompts",
|
|
103
|
+
contextLabel: "Context window",
|
|
104
|
+
compactionSummaryTitle: "Conversation summary",
|
|
60
105
|
toolRunning: "Running",
|
|
61
106
|
toolCompleted: "Done",
|
|
62
107
|
toolRejected: "Rejected",
|
|
@@ -101,14 +146,6 @@ const APARTE_DEFAULT_LOCALE = {
|
|
|
101
146
|
unarchiveConversation: "Unarchive conversation",
|
|
102
147
|
direction: "ltr"
|
|
103
148
|
};
|
|
104
|
-
const APARTE_DEFAULT_SKELETON_FALLBACKS = {
|
|
105
|
-
message: '<div class="aparte-skeleton-fallback">Loading...</div>',
|
|
106
|
-
code: '<div class="aparte-skeleton-fallback aparte-skeleton-fallback--code">Loading code...</div>',
|
|
107
|
-
thinking: '<div class="aparte-skeleton-fallback aparte-skeleton-fallback--tight">Thinking...</div>',
|
|
108
|
-
input: '<div class="aparte-skeleton-fallback aparte-skeleton-fallback--snug">...</div>',
|
|
109
|
-
list: '<div class="aparte-skeleton-fallback">Loading items...</div>',
|
|
110
|
-
text: '<div class="aparte-skeleton-fallback aparte-skeleton-fallback--tight">...</div>'
|
|
111
|
-
};
|
|
112
149
|
function isFormatAdapter(p) {
|
|
113
150
|
return typeof p.buildRequest === "function" && typeof p.parseStream === "function" && typeof p.defaultEndpoint === "string" && (typeof p.authHeaders === "function" || typeof p.authQuery === "function");
|
|
114
151
|
}
|
|
@@ -123,6 +160,11 @@ async function vendorErrorMessage(response, label = "HTTP") {
|
|
|
123
160
|
const msg = typeof raw === "object" ? raw?.message : raw;
|
|
124
161
|
return typeof msg === "string" && msg ? msg : `${label} ${response.status}`;
|
|
125
162
|
}
|
|
163
|
+
async function vendorError(response, label = "HTTP") {
|
|
164
|
+
const message = await vendorErrorMessage(response, label);
|
|
165
|
+
const code = AparteError.codeForStatus(response.status) ?? AparteErrorCode.UNKNOWN_ERROR;
|
|
166
|
+
return new AparteError(message, code, void 0, void 0, response.status);
|
|
167
|
+
}
|
|
126
168
|
async function parseNonStreamText(provider, response, providerId) {
|
|
127
169
|
const json = await response.json();
|
|
128
170
|
if (typeof provider.parseText !== "function") {
|
|
@@ -163,7 +205,7 @@ class AparteDirectTransport {
|
|
|
163
205
|
signal: ctx.signal
|
|
164
206
|
});
|
|
165
207
|
if (!response.ok) {
|
|
166
|
-
throw
|
|
208
|
+
throw await vendorError(response);
|
|
167
209
|
}
|
|
168
210
|
if (request.stream === false) {
|
|
169
211
|
return parseNonStreamText(provider, response, ctx.providerId);
|
|
@@ -241,7 +283,7 @@ class AparteStreamParser {
|
|
|
241
283
|
if ("content" in this._state.activeSegment) {
|
|
242
284
|
const seg = this._state.activeSegment;
|
|
243
285
|
let content = seg.content + this._state.buffer;
|
|
244
|
-
if (seg.type === "text") content = stripTrailingFence(content);
|
|
286
|
+
if (seg.type === "text" || seg.type === "code") content = stripTrailingFence(content);
|
|
245
287
|
seg.content = content;
|
|
246
288
|
}
|
|
247
289
|
finalSegments.push(this._closed(this._state.activeSegment));
|
|
@@ -362,16 +404,6 @@ class AparteStreamParser {
|
|
|
362
404
|
_parseCodeMode(buffer) {
|
|
363
405
|
const closeIndex = buffer.indexOf("\n```");
|
|
364
406
|
if (closeIndex === -1) {
|
|
365
|
-
if (buffer.endsWith("```")) {
|
|
366
|
-
const codeContent2 = buffer.slice(0, -3);
|
|
367
|
-
if (this._state.activeSegment && "content" in this._state.activeSegment) {
|
|
368
|
-
this._state.activeSegment.content += codeContent2;
|
|
369
|
-
}
|
|
370
|
-
const segment2 = this._closed(this._state.activeSegment);
|
|
371
|
-
this._state.mode = "text";
|
|
372
|
-
this._state.activeSegment = null;
|
|
373
|
-
return { segment: segment2, remaining: "" };
|
|
374
|
-
}
|
|
375
407
|
if (buffer.length > 4) {
|
|
376
408
|
const safeContent = buffer.slice(0, -4);
|
|
377
409
|
if (this._state.activeSegment && "content" in this._state.activeSegment) {
|
|
@@ -594,28 +626,6 @@ function parseMarkdownToSegments(content, options) {
|
|
|
594
626
|
const finalSegments = parser.finalize();
|
|
595
627
|
return [...result.segments, ...finalSegments];
|
|
596
628
|
}
|
|
597
|
-
function deriveArtifactKind(mimeType, fallback = "unknown") {
|
|
598
|
-
const m = (mimeType || "").toLowerCase().trim();
|
|
599
|
-
const ant = m.match(/^application\/vnd\.ant\.([a-z0-9-]+)/);
|
|
600
|
-
if (ant) return ant[1];
|
|
601
|
-
if (m === "text/html" || m === "application/xhtml+xml") return "html";
|
|
602
|
-
if (m === "application/javascript" || m === "text/javascript") return "js";
|
|
603
|
-
if (m === "text/css") return "css";
|
|
604
|
-
if (m === "image/svg+xml") return "svg";
|
|
605
|
-
if (m === "application/json") return "json";
|
|
606
|
-
if (m === "text/markdown") return "markdown";
|
|
607
|
-
if (m === "text/csv") return "csv";
|
|
608
|
-
if (m === "text/plain") return "text";
|
|
609
|
-
if (m.includes("react")) return "react";
|
|
610
|
-
if (m.includes("html")) return "html";
|
|
611
|
-
if (m.includes("javascript")) return "js";
|
|
612
|
-
if (m.includes("css")) return "css";
|
|
613
|
-
if (m.includes("svg")) return "svg";
|
|
614
|
-
if (m.includes("json")) return "json";
|
|
615
|
-
if (m.includes("csv")) return "csv";
|
|
616
|
-
if (m.includes("markdown")) return "markdown";
|
|
617
|
-
return fallback;
|
|
618
|
-
}
|
|
619
629
|
function parseAparteEventStream(stream) {
|
|
620
630
|
const decoder = new TextDecoder();
|
|
621
631
|
let buffer = "";
|
|
@@ -668,7 +678,7 @@ class AparteBackendTransport {
|
|
|
668
678
|
signal: ctx.signal
|
|
669
679
|
});
|
|
670
680
|
if (!response.ok) {
|
|
671
|
-
throw
|
|
681
|
+
throw await vendorError(response, "Backend HTTP");
|
|
672
682
|
}
|
|
673
683
|
if (request.stream === false) {
|
|
674
684
|
const json = await response.json();
|
|
@@ -1056,7 +1066,7 @@ const escapeAttr = escapeHtml;
|
|
|
1056
1066
|
function isChatBoundary(el2) {
|
|
1057
1067
|
if (!el2) return false;
|
|
1058
1068
|
const tag = el2.tagName?.toLowerCase();
|
|
1059
|
-
return tag === "aparte-chat" ||
|
|
1069
|
+
return tag === "aparte-chat" || el2.hasAttribute?.("data-aparte-chat") === true;
|
|
1060
1070
|
}
|
|
1061
1071
|
function chatBoundaryOf(el2) {
|
|
1062
1072
|
let node = el2 ?? null;
|
|
@@ -1090,7 +1100,6 @@ class AparteConfig {
|
|
|
1090
1100
|
_sanitizer = defaultSanitizer;
|
|
1091
1101
|
_systemPromptTemplate;
|
|
1092
1102
|
_systemPromptVarsProvider;
|
|
1093
|
-
_skeletonProvider;
|
|
1094
1103
|
_statusRenderer;
|
|
1095
1104
|
_errorRenderer;
|
|
1096
1105
|
_attachmentRenderer;
|
|
@@ -1367,13 +1376,6 @@ class AparteConfig {
|
|
|
1367
1376
|
const resolved = this._systemPromptTemplate.replace(/\{\{([^}]+)\}\}/g, (_, key) => vars[key.trim()] ?? "");
|
|
1368
1377
|
return resolved.trim() || null;
|
|
1369
1378
|
}
|
|
1370
|
-
/**
|
|
1371
|
-
* Set a custom Skeleton generator for loading states
|
|
1372
|
-
* @param provider Object implementing AparteSkeletonProvider interface
|
|
1373
|
-
*/
|
|
1374
|
-
setSkeletonProvider(provider) {
|
|
1375
|
-
this._skeletonProvider = provider;
|
|
1376
|
-
}
|
|
1377
1379
|
/**
|
|
1378
1380
|
* Set a custom Icon provider (e.g., Lucide, FontAwesome, Material)
|
|
1379
1381
|
* @param provider Object implementing AparteIconProvider interface
|
|
@@ -1831,16 +1833,6 @@ class AparteConfig {
|
|
|
1831
1833
|
}
|
|
1832
1834
|
return this._defaultHighlightRenderer(code);
|
|
1833
1835
|
}
|
|
1834
|
-
/**
|
|
1835
|
-
* Get HTML for a skeleton loader
|
|
1836
|
-
* Fallback: Simple CSS-animated box
|
|
1837
|
-
*/
|
|
1838
|
-
getSkeleton(type) {
|
|
1839
|
-
if (this._skeletonProvider) {
|
|
1840
|
-
return this._skeletonProvider.getSkeleton(type);
|
|
1841
|
-
}
|
|
1842
|
-
return this._defaultSkeletonRenderer(type);
|
|
1843
|
-
}
|
|
1844
1836
|
// ─────────────────────────────────────────────────────────────────────────
|
|
1845
1837
|
// Tool Registry
|
|
1846
1838
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -2087,7 +2079,6 @@ class AparteConfig {
|
|
|
2087
2079
|
this._highlightProvider = void 0;
|
|
2088
2080
|
this._systemPromptTemplate = void 0;
|
|
2089
2081
|
this._systemPromptVarsProvider = void 0;
|
|
2090
|
-
this._skeletonProvider = void 0;
|
|
2091
2082
|
this._statusRenderer = void 0;
|
|
2092
2083
|
this._errorRenderer = void 0;
|
|
2093
2084
|
this._attachmentRenderer = void 0;
|
|
@@ -2128,16 +2119,6 @@ class AparteConfig {
|
|
|
2128
2119
|
_defaultHighlightRenderer(code) {
|
|
2129
2120
|
return `<pre><code>${escapeHtml(code)}</code></pre>`;
|
|
2130
2121
|
}
|
|
2131
|
-
/**
|
|
2132
|
-
* ONE owner. This used to hold a second, hand-written copy of
|
|
2133
|
-
* `APARTE_DEFAULT_SKELETON_FALLBACKS`, and the two had already drifted — `message`
|
|
2134
|
-
* said "Loading message…" here and "Loading…" there, `text` the reverse. A duplicate
|
|
2135
|
-
* that disagrees with its original is worse than either: whichever one you read, you
|
|
2136
|
-
* cannot tell which one ships.
|
|
2137
|
-
*/
|
|
2138
|
-
_defaultSkeletonRenderer(type) {
|
|
2139
|
-
return APARTE_DEFAULT_SKELETON_FALLBACKS[type] ?? APARTE_DEFAULT_SKELETON_FALLBACKS.text;
|
|
2140
|
-
}
|
|
2141
2122
|
}
|
|
2142
2123
|
const GLOBAL_CONFIG_KEY = Symbol.for("aparte.globalConfig.1");
|
|
2143
2124
|
function getGlobalConfig() {
|
|
@@ -2475,7 +2456,7 @@ function stateBadge(segment) {
|
|
|
2475
2456
|
if (status === "pending") return word("toolRunning");
|
|
2476
2457
|
if (status === "resolved") return `${cfg.getIcon("check")}${word("toolCompleted")}`;
|
|
2477
2458
|
if (status === "rejected") return `${cfg.getIcon("close")}${word("toolRejected")}`;
|
|
2478
|
-
if (status === "aborted") return `${cfg.getIcon("
|
|
2459
|
+
if (status === "aborted") return `${cfg.getIcon("stop")}${word("toolStopped")}`;
|
|
2479
2460
|
return "";
|
|
2480
2461
|
}
|
|
2481
2462
|
function setPart(element, part, text) {
|
|
@@ -2539,6 +2520,7 @@ const toolCallRenderer = {
|
|
|
2539
2520
|
const toolCallId = segment.toolCall?.id ?? "";
|
|
2540
2521
|
const customRenderer = contextConfig().getToolRenderer(segment.toolCall?.name);
|
|
2541
2522
|
if (customRenderer) {
|
|
2523
|
+
injectToolRendererStyles(segment.toolCall?.name ?? "", customRenderer);
|
|
2542
2524
|
const out = customRenderer.render(segment);
|
|
2543
2525
|
if (out) return out;
|
|
2544
2526
|
}
|
|
@@ -2635,44 +2617,6 @@ const toolCallRenderer = {
|
|
|
2635
2617
|
// has no other way onto the page.
|
|
2636
2618
|
getStyles: () => ""
|
|
2637
2619
|
};
|
|
2638
|
-
const waitingLabel = () => contextConfig().t("generating");
|
|
2639
|
-
const pipelineWaitingRenderer = {
|
|
2640
|
-
type: "pipeline-waiting",
|
|
2641
|
-
render: (segment) => {
|
|
2642
|
-
return `
|
|
2643
|
-
<div class="aparte-segment aparte-segment-pipeline-waiting" data-segment-id="${escapeHtml(segment.id)}" aria-label="${escapeAttr(waitingLabel())}" role="status">
|
|
2644
|
-
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2645
|
-
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2646
|
-
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2647
|
-
</div>`;
|
|
2648
|
-
},
|
|
2649
|
-
update: () => {
|
|
2650
|
-
},
|
|
2651
|
-
/**
|
|
2652
|
-
* Three dots and an accessible name. The dots are CSS; the name is the whole
|
|
2653
|
-
* content as far as a screen reader is concerned, and it was hardcoded English in
|
|
2654
|
-
* every locale — the one string in this library where being untranslated is
|
|
2655
|
-
* invisible to everyone who can see the screen.
|
|
2656
|
-
*/
|
|
2657
|
-
relabel: (element) => {
|
|
2658
|
-
element.setAttribute("aria-label", waitingLabel());
|
|
2659
|
-
},
|
|
2660
|
-
setup: (el2) => {
|
|
2661
|
-
const parent = el2.parentElement;
|
|
2662
|
-
if (!parent) return;
|
|
2663
|
-
const observer = new MutationObserver(() => {
|
|
2664
|
-
if (el2.nextElementSibling) {
|
|
2665
|
-
observer.disconnect();
|
|
2666
|
-
el2.remove();
|
|
2667
|
-
}
|
|
2668
|
-
});
|
|
2669
|
-
observer.observe(parent, { childList: true });
|
|
2670
|
-
},
|
|
2671
|
-
// CSS lives in styles/segment/ — see that folder for why a
|
|
2672
|
-
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
2673
|
-
// has no other way onto the page.
|
|
2674
|
-
getStyles: () => ""
|
|
2675
|
-
};
|
|
2676
2620
|
function stripCodeFences(content) {
|
|
2677
2621
|
let s = content;
|
|
2678
2622
|
if (s.startsWith("```") || s.startsWith("~~~")) {
|
|
@@ -3440,6 +3384,17 @@ function injectRendererStyles(config = contextConfig()) {
|
|
|
3440
3384
|
}
|
|
3441
3385
|
if (added) styleElement.textContent = Array.from(injectedRendererStyles).join("\n");
|
|
3442
3386
|
}
|
|
3387
|
+
function injectToolRendererStyles(toolName, renderer) {
|
|
3388
|
+
if (typeof document === "undefined") return;
|
|
3389
|
+
const css = renderer.getStyles?.();
|
|
3390
|
+
if (!css) return;
|
|
3391
|
+
const id = `aparte-tool-renderer-${toolName}`;
|
|
3392
|
+
if (document.getElementById(id)) return;
|
|
3393
|
+
const el2 = document.createElement("style");
|
|
3394
|
+
el2.id = id;
|
|
3395
|
+
el2.textContent = css;
|
|
3396
|
+
document.head.appendChild(el2);
|
|
3397
|
+
}
|
|
3443
3398
|
function registerDefaultRenderers(config = contextConfig()) {
|
|
3444
3399
|
const reg = registryFor(config);
|
|
3445
3400
|
reg.defaultsInstalled = true;
|
|
@@ -3455,8 +3410,7 @@ const DEFAULT_RENDERERS = [
|
|
|
3455
3410
|
codeRenderer,
|
|
3456
3411
|
errorRenderer,
|
|
3457
3412
|
toolCallRenderer,
|
|
3458
|
-
artifactRenderer
|
|
3459
|
-
pipelineWaitingRenderer
|
|
3413
|
+
artifactRenderer
|
|
3460
3414
|
];
|
|
3461
3415
|
const OPEN_TOOL_STATUSES = /* @__PURE__ */ new Set(["pending", "awaiting-approval"]);
|
|
3462
3416
|
const ACTIVITY_KEYS = ["content", "output", "result"];
|
|
@@ -4416,7 +4370,7 @@ class AparteChatHost {
|
|
|
4416
4370
|
this.binding.setMessages(next);
|
|
4417
4371
|
this.binding.onMessagesChange?.(next);
|
|
4418
4372
|
}
|
|
4419
|
-
/** Remove a transient segment (
|
|
4373
|
+
/** Remove a transient segment (a status row the host added itself). */
|
|
4420
4374
|
removeSegment(segmentId) {
|
|
4421
4375
|
this._flushStreamState();
|
|
4422
4376
|
this._lastBubble()?.removeSegment?.(segmentId);
|
|
@@ -4595,7 +4549,7 @@ class AparteChatHost {
|
|
|
4595
4549
|
this._bufferToken(messageId, res.value);
|
|
4596
4550
|
}
|
|
4597
4551
|
this._flushStreamState();
|
|
4598
|
-
|
|
4552
|
+
this._vp()?.completeMessage?.(messageId);
|
|
4599
4553
|
this._setStreamingId(null);
|
|
4600
4554
|
} catch (err) {
|
|
4601
4555
|
this._flushStreamState();
|
|
@@ -4852,176 +4806,6 @@ function dispatchArtifactLifecycle(target, messageId, segment, progress, isFinal
|
|
|
4852
4806
|
}));
|
|
4853
4807
|
}
|
|
4854
4808
|
}
|
|
4855
|
-
const INLINE_MAX_LINES = 15;
|
|
4856
|
-
const XML_OPEN_TAG = "<artifact";
|
|
4857
|
-
function partialXmlOpenTagLength(text) {
|
|
4858
|
-
const max = Math.min(text.length, XML_OPEN_TAG.length - 1);
|
|
4859
|
-
for (let k = max; k > 0; k--) {
|
|
4860
|
-
if (text.endsWith(XML_OPEN_TAG.slice(0, k))) return k;
|
|
4861
|
-
}
|
|
4862
|
-
return 0;
|
|
4863
|
-
}
|
|
4864
|
-
function feedXmlArtifactDelta(delta, xml, ctx) {
|
|
4865
|
-
const { targetElement, messageId, textParser, streamingSegmentIds, artifactProgress, artifactXmlHint } = ctx;
|
|
4866
|
-
let remaining = delta;
|
|
4867
|
-
const emitChatText = (text, syncActive = true) => {
|
|
4868
|
-
if (!text) return;
|
|
4869
|
-
const r = textParser.parse(text);
|
|
4870
|
-
for (const seg of r.segments) {
|
|
4871
|
-
if (!streamingSegmentIds.has(seg.id)) {
|
|
4872
|
-
targetElement.addSegment?.(seg);
|
|
4873
|
-
streamingSegmentIds.add(seg.id);
|
|
4874
|
-
} else if ("content" in seg) {
|
|
4875
|
-
targetElement.updateSegment?.(seg.id, segmentContentUpdate(seg));
|
|
4876
|
-
}
|
|
4877
|
-
}
|
|
4878
|
-
const active = textParser.getState().activeSegment;
|
|
4879
|
-
if (syncActive && active) {
|
|
4880
|
-
if (!streamingSegmentIds.has(active.id)) {
|
|
4881
|
-
targetElement.addSegment?.(active);
|
|
4882
|
-
streamingSegmentIds.add(active.id);
|
|
4883
|
-
} else {
|
|
4884
|
-
targetElement.updateSegment?.(active.id, segmentContentUpdate(active));
|
|
4885
|
-
}
|
|
4886
|
-
} else if (!r.segments.length && !active) ;
|
|
4887
|
-
};
|
|
4888
|
-
while (remaining.length > 0) {
|
|
4889
|
-
if (xml.state === "normal") {
|
|
4890
|
-
const tagStart = remaining.indexOf(XML_OPEN_TAG);
|
|
4891
|
-
if (tagStart === -1) {
|
|
4892
|
-
const held = partialXmlOpenTagLength(remaining);
|
|
4893
|
-
if (held > 0) {
|
|
4894
|
-
emitChatText(remaining.slice(0, remaining.length - held), false);
|
|
4895
|
-
xml.scanBuf = remaining.slice(remaining.length - held);
|
|
4896
|
-
xml.state = "scanning";
|
|
4897
|
-
} else {
|
|
4898
|
-
emitChatText(remaining);
|
|
4899
|
-
}
|
|
4900
|
-
remaining = "";
|
|
4901
|
-
} else {
|
|
4902
|
-
emitChatText(remaining.slice(0, tagStart), false);
|
|
4903
|
-
xml.scanBuf = "";
|
|
4904
|
-
remaining = remaining.slice(tagStart);
|
|
4905
|
-
xml.state = "scanning";
|
|
4906
|
-
}
|
|
4907
|
-
} else if (xml.state === "scanning") {
|
|
4908
|
-
xml.scanBuf += remaining;
|
|
4909
|
-
remaining = "";
|
|
4910
|
-
const cmp = Math.min(xml.scanBuf.length, XML_OPEN_TAG.length);
|
|
4911
|
-
if (xml.scanBuf.slice(0, cmp) !== XML_OPEN_TAG.slice(0, cmp)) {
|
|
4912
|
-
emitChatText(xml.scanBuf);
|
|
4913
|
-
xml.scanBuf = "";
|
|
4914
|
-
xml.state = "normal";
|
|
4915
|
-
continue;
|
|
4916
|
-
}
|
|
4917
|
-
const gtIdx = xml.scanBuf.indexOf(">");
|
|
4918
|
-
if (gtIdx !== -1) {
|
|
4919
|
-
const tag = xml.scanBuf.slice(0, gtIdx + 1);
|
|
4920
|
-
const mimeMatch = /mimeType=['"]([^'"]+)['"]/.exec(tag);
|
|
4921
|
-
const titleMatch = /title=['"]([^'"]+)['"]/.exec(tag);
|
|
4922
|
-
xml.mime = mimeMatch?.[1] ?? artifactXmlHint.mimeType;
|
|
4923
|
-
xml.title = titleMatch?.[1] ?? artifactXmlHint.kind;
|
|
4924
|
-
xml.kind = deriveArtifactKind(xml.mime, artifactXmlHint.kind);
|
|
4925
|
-
xml.segId = `artifact-xml-${uuid()}`;
|
|
4926
|
-
xml.content = "";
|
|
4927
|
-
const openSeg = {
|
|
4928
|
-
id: xml.segId,
|
|
4929
|
-
type: "artifact",
|
|
4930
|
-
mimeType: xml.mime,
|
|
4931
|
-
artifactType: xml.kind,
|
|
4932
|
-
title: xml.title,
|
|
4933
|
-
content: ""
|
|
4934
|
-
};
|
|
4935
|
-
targetElement.addSegment?.(openSeg);
|
|
4936
|
-
streamingSegmentIds.add(xml.segId);
|
|
4937
|
-
dispatchArtifactLifecycle(targetElement, messageId, openSeg, artifactProgress, false);
|
|
4938
|
-
xml.state = "in-artifact";
|
|
4939
|
-
remaining = xml.scanBuf.slice(gtIdx + 1);
|
|
4940
|
-
xml.scanBuf = "";
|
|
4941
|
-
}
|
|
4942
|
-
} else {
|
|
4943
|
-
const CLOSE = "</artifact>";
|
|
4944
|
-
const combined = xml.closeBuf + remaining;
|
|
4945
|
-
const closeIdx = combined.indexOf(CLOSE);
|
|
4946
|
-
if (closeIdx !== -1) {
|
|
4947
|
-
xml.content += combined.slice(0, closeIdx);
|
|
4948
|
-
const lineCount = xml.content.split("\n").length;
|
|
4949
|
-
const isInline = lineCount < INLINE_MAX_LINES;
|
|
4950
|
-
const finalSeg = {
|
|
4951
|
-
id: xml.segId,
|
|
4952
|
-
mimeType: xml.mime,
|
|
4953
|
-
artifactType: xml.kind,
|
|
4954
|
-
title: xml.title,
|
|
4955
|
-
content: xml.content
|
|
4956
|
-
};
|
|
4957
|
-
targetElement.updateSegment?.(xml.segId, { content: xml.content, inline: isInline });
|
|
4958
|
-
dispatchArtifactLifecycle(targetElement, messageId, finalSeg, artifactProgress, true);
|
|
4959
|
-
xml.state = "normal";
|
|
4960
|
-
xml.closeBuf = "";
|
|
4961
|
-
remaining = combined.slice(closeIdx + CLOSE.length);
|
|
4962
|
-
} else {
|
|
4963
|
-
const safeLen = Math.max(0, combined.length - CLOSE.length + 1);
|
|
4964
|
-
const safe = combined.slice(0, safeLen);
|
|
4965
|
-
xml.content += safe;
|
|
4966
|
-
xml.closeBuf = combined.slice(safeLen);
|
|
4967
|
-
remaining = "";
|
|
4968
|
-
if (xml.segId) {
|
|
4969
|
-
targetElement.updateSegment?.(xml.segId, { content: xml.content });
|
|
4970
|
-
dispatchArtifactLifecycle(targetElement, messageId, {
|
|
4971
|
-
id: xml.segId,
|
|
4972
|
-
mimeType: xml.mime,
|
|
4973
|
-
artifactType: xml.kind,
|
|
4974
|
-
title: xml.title,
|
|
4975
|
-
content: xml.content
|
|
4976
|
-
}, artifactProgress, false);
|
|
4977
|
-
}
|
|
4978
|
-
}
|
|
4979
|
-
}
|
|
4980
|
-
}
|
|
4981
|
-
}
|
|
4982
|
-
function finalizeXmlArtifact(xml, ctx) {
|
|
4983
|
-
const { targetElement, messageId, artifactProgress, artifactXmlHint } = ctx;
|
|
4984
|
-
if (xml.state === "scanning") {
|
|
4985
|
-
const held = xml.scanBuf;
|
|
4986
|
-
xml.scanBuf = "";
|
|
4987
|
-
xml.state = "normal";
|
|
4988
|
-
if (held) {
|
|
4989
|
-
const r = ctx.textParser.parse(held);
|
|
4990
|
-
for (const seg of r.segments) {
|
|
4991
|
-
if (!ctx.streamingSegmentIds.has(seg.id)) {
|
|
4992
|
-
targetElement.addSegment?.(seg);
|
|
4993
|
-
ctx.streamingSegmentIds.add(seg.id);
|
|
4994
|
-
} else if ("content" in seg) {
|
|
4995
|
-
targetElement.updateSegment?.(seg.id, segmentContentUpdate(seg));
|
|
4996
|
-
}
|
|
4997
|
-
}
|
|
4998
|
-
const active = ctx.textParser.getState().activeSegment;
|
|
4999
|
-
if (active) {
|
|
5000
|
-
if (!ctx.streamingSegmentIds.has(active.id)) {
|
|
5001
|
-
targetElement.addSegment?.(active);
|
|
5002
|
-
ctx.streamingSegmentIds.add(active.id);
|
|
5003
|
-
} else {
|
|
5004
|
-
targetElement.updateSegment?.(active.id, segmentContentUpdate(active));
|
|
5005
|
-
}
|
|
5006
|
-
}
|
|
5007
|
-
}
|
|
5008
|
-
return;
|
|
5009
|
-
}
|
|
5010
|
-
if (artifactXmlHint && xml.state === "in-artifact" && xml.segId) {
|
|
5011
|
-
xml.content += xml.closeBuf;
|
|
5012
|
-
const lineCount = xml.content.split("\n").length;
|
|
5013
|
-
const isInline = lineCount < INLINE_MAX_LINES;
|
|
5014
|
-
targetElement.updateSegment?.(xml.segId, { content: xml.content, inline: isInline });
|
|
5015
|
-
dispatchArtifactLifecycle(targetElement, messageId, {
|
|
5016
|
-
id: xml.segId,
|
|
5017
|
-
mimeType: xml.mime,
|
|
5018
|
-
artifactType: xml.kind,
|
|
5019
|
-
title: xml.title,
|
|
5020
|
-
content: xml.content
|
|
5021
|
-
}, artifactProgress, true);
|
|
5022
|
-
console.warn("[AparteClient] XML artifact finalized without closing tag — content may be partial.");
|
|
5023
|
-
}
|
|
5024
|
-
}
|
|
5025
4809
|
function createStreamAdapter(opts) {
|
|
5026
4810
|
const { target, config, messageId, artifactHint } = opts;
|
|
5027
4811
|
let parser = new AparteStreamParser();
|
|
@@ -5031,7 +4815,6 @@ function createStreamAdapter(opts) {
|
|
|
5031
4815
|
let thinkingCollapsed = false;
|
|
5032
4816
|
let artifactProgress = /* @__PURE__ */ new Map();
|
|
5033
4817
|
let artifactPromoted = false;
|
|
5034
|
-
let artifactMeta = /* @__PURE__ */ new Map();
|
|
5035
4818
|
return (e) => {
|
|
5036
4819
|
switch (e.type) {
|
|
5037
4820
|
case "run-start":
|
|
@@ -5045,7 +4828,6 @@ function createStreamAdapter(opts) {
|
|
|
5045
4828
|
thinkingCollapsed = false;
|
|
5046
4829
|
artifactProgress = /* @__PURE__ */ new Map();
|
|
5047
4830
|
artifactPromoted = false;
|
|
5048
|
-
artifactMeta = /* @__PURE__ */ new Map();
|
|
5049
4831
|
break;
|
|
5050
4832
|
case "thinking-delta": {
|
|
5051
4833
|
thinkingContent += e.delta;
|
|
@@ -5070,18 +4852,6 @@ function createStreamAdapter(opts) {
|
|
|
5070
4852
|
target.updateSegment?.(thinkingId, { collapsed: true, isStreaming: false });
|
|
5071
4853
|
thinkingCollapsed = true;
|
|
5072
4854
|
}
|
|
5073
|
-
if (e.reduced) {
|
|
5074
|
-
const r = parser.parse(e.delta);
|
|
5075
|
-
for (const segment of r.segments) {
|
|
5076
|
-
if (!streaming.has(segment.id)) {
|
|
5077
|
-
target.addSegment?.(segment);
|
|
5078
|
-
streaming.add(segment.id);
|
|
5079
|
-
} else if ("content" in segment) {
|
|
5080
|
-
target.updateSegment?.(segment.id, segmentContentUpdate(segment));
|
|
5081
|
-
}
|
|
5082
|
-
}
|
|
5083
|
-
break;
|
|
5084
|
-
}
|
|
5085
4855
|
const result = parser.parse(e.delta);
|
|
5086
4856
|
for (let segment of result.segments) {
|
|
5087
4857
|
if (artifactHint && !artifactPromoted && segment.type === "code") {
|
|
@@ -5154,33 +4924,6 @@ function createStreamAdapter(opts) {
|
|
|
5154
4924
|
}
|
|
5155
4925
|
break;
|
|
5156
4926
|
}
|
|
5157
|
-
case "artifact-open": {
|
|
5158
|
-
const seg = {
|
|
5159
|
-
id: e.id,
|
|
5160
|
-
type: "artifact",
|
|
5161
|
-
mimeType: e.mimeType,
|
|
5162
|
-
artifactType: e.kind,
|
|
5163
|
-
title: e.title,
|
|
5164
|
-
content: ""
|
|
5165
|
-
};
|
|
5166
|
-
target.addSegment?.(seg);
|
|
5167
|
-
streaming.add(e.id);
|
|
5168
|
-
artifactMeta.set(e.id, { mimeType: e.mimeType, artifactType: e.kind, title: e.title });
|
|
5169
|
-
dispatchArtifactLifecycle(target, messageId, seg, artifactProgress, false);
|
|
5170
|
-
break;
|
|
5171
|
-
}
|
|
5172
|
-
case "artifact-chunk": {
|
|
5173
|
-
const meta = artifactMeta.get(e.id);
|
|
5174
|
-
target.updateSegment?.(e.id, { content: e.content });
|
|
5175
|
-
dispatchArtifactLifecycle(target, messageId, { id: e.id, content: e.content, ...meta }, artifactProgress, false);
|
|
5176
|
-
break;
|
|
5177
|
-
}
|
|
5178
|
-
case "artifact-close": {
|
|
5179
|
-
const meta = artifactMeta.get(e.id);
|
|
5180
|
-
target.updateSegment?.(e.id, { content: e.content, inline: e.inline });
|
|
5181
|
-
dispatchArtifactLifecycle(target, messageId, { id: e.id, content: e.content, ...meta }, artifactProgress, true);
|
|
5182
|
-
break;
|
|
5183
|
-
}
|
|
5184
4927
|
case "artifact-ready": {
|
|
5185
4928
|
const seg = {
|
|
5186
4929
|
id: e.id,
|
|
@@ -5203,18 +4946,7 @@ function createStreamAdapter(opts) {
|
|
|
5203
4946
|
};
|
|
5204
4947
|
const renderer = config.getToolRenderer(e.name);
|
|
5205
4948
|
if (renderer) {
|
|
5206
|
-
|
|
5207
|
-
const styles = renderer.getStyles();
|
|
5208
|
-
if (styles) {
|
|
5209
|
-
const styleId = `aparte-tool-renderer-${e.name}`;
|
|
5210
|
-
if (!document.getElementById(styleId)) {
|
|
5211
|
-
const styleEl = document.createElement("style");
|
|
5212
|
-
styleEl.id = styleId;
|
|
5213
|
-
styleEl.textContent = styles;
|
|
5214
|
-
document.head.appendChild(styleEl);
|
|
5215
|
-
}
|
|
5216
|
-
}
|
|
5217
|
-
}
|
|
4949
|
+
injectToolRendererStyles(e.name, renderer);
|
|
5218
4950
|
const html = renderer.render(toolSeg);
|
|
5219
4951
|
if (html) target.addSegment?.(toolSeg);
|
|
5220
4952
|
} else {
|
|
@@ -5250,9 +4982,6 @@ function createStreamAdapter(opts) {
|
|
|
5250
4982
|
target.updateSegment?.(`tool-${e.toolCallId}`, { status: "aborted" });
|
|
5251
4983
|
}
|
|
5252
4984
|
break;
|
|
5253
|
-
case "phase-advance":
|
|
5254
|
-
target.addSegment?.({ id: `pw-${uuid()}`, type: "pipeline-waiting" });
|
|
5255
|
-
break;
|
|
5256
4985
|
case "run-aborted":
|
|
5257
4986
|
dispatchLifecycleEvent(target, "aparte-message-aborted", { messageId });
|
|
5258
4987
|
break;
|
|
@@ -5790,20 +5519,6 @@ function buildApprovalPanel(message, options, onChange) {
|
|
|
5790
5519
|
function requestUserInput(request) {
|
|
5791
5520
|
return resolveConfig(request.target ?? null).requestUserInput(request);
|
|
5792
5521
|
}
|
|
5793
|
-
const DEFAULT_TOOL_HANDLER_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
5794
|
-
function withToolTimeout(work, controller, timeoutMs) {
|
|
5795
|
-
let timer;
|
|
5796
|
-
const timedOut = new Promise((_resolve, reject) => {
|
|
5797
|
-
timer = setTimeout(() => {
|
|
5798
|
-
controller.abort();
|
|
5799
|
-
reject(Object.assign(new Error(`tool handler exceeded ${timeoutMs}ms`), { name: "AbortError" }));
|
|
5800
|
-
}, timeoutMs);
|
|
5801
|
-
});
|
|
5802
|
-
return {
|
|
5803
|
-
raced: Promise.race([work(controller.signal), timedOut]),
|
|
5804
|
-
done: () => clearTimeout(timer)
|
|
5805
|
-
};
|
|
5806
|
-
}
|
|
5807
5522
|
class AparteClient {
|
|
5808
5523
|
_boundHandler = null;
|
|
5809
5524
|
_boundAbortHandler = null;
|
|
@@ -5838,6 +5553,8 @@ class AparteClient {
|
|
|
5838
5553
|
}
|
|
5839
5554
|
/** Aborts the in-flight vendor/transport fetch when the user stops a stream. */
|
|
5840
5555
|
_streamController = null;
|
|
5556
|
+
/** Aborts an in-flight `compact()` summarisation — its own slot, see `compact`. */
|
|
5557
|
+
_compactController = null;
|
|
5841
5558
|
options;
|
|
5842
5559
|
/** Config read by this client — an instance config, or the global default. */
|
|
5843
5560
|
_config;
|
|
@@ -5963,6 +5680,7 @@ class AparteClient {
|
|
|
5963
5680
|
abort() {
|
|
5964
5681
|
this._isAborted = true;
|
|
5965
5682
|
this._streamController?.abort();
|
|
5683
|
+
this._compactController?.abort();
|
|
5966
5684
|
for (const controller of this._activeToolControllers) {
|
|
5967
5685
|
controller.abort();
|
|
5968
5686
|
}
|
|
@@ -6070,6 +5788,7 @@ class AparteClient {
|
|
|
6070
5788
|
}
|
|
6071
5789
|
if (this._isAborted) {
|
|
6072
5790
|
dispatchLifecycleEvent(targetElement, "aparte-message-aborted", { messageId });
|
|
5791
|
+
this._updateMessage(targetElement, messageId, { status: "completed" });
|
|
6073
5792
|
return;
|
|
6074
5793
|
}
|
|
6075
5794
|
dispatchLifecycleEvent(targetElement, "aparte-message-start", { messageId, role: "assistant" });
|
|
@@ -6149,7 +5868,7 @@ class AparteClient {
|
|
|
6149
5868
|
stream: false
|
|
6150
5869
|
};
|
|
6151
5870
|
const compactController = new AbortController();
|
|
6152
|
-
this.
|
|
5871
|
+
this._compactController = compactController;
|
|
6153
5872
|
const response = await this._config.getTransport().chat(
|
|
6154
5873
|
provider,
|
|
6155
5874
|
summarizeRequest,
|
|
@@ -6180,7 +5899,11 @@ class AparteClient {
|
|
|
6180
5899
|
target.appendMessage?.({
|
|
6181
5900
|
id: uuid(),
|
|
6182
5901
|
role: "assistant",
|
|
6183
|
-
|
|
5902
|
+
// Through the locale, like every string the user reads — this was a
|
|
5903
|
+
// hardcoded English title (with an emoji) in an otherwise localised
|
|
5904
|
+
// transcript. The engine compactor's `summaryLabel` is a separate,
|
|
5905
|
+
// per-call knob; this is the UI's own title.
|
|
5906
|
+
content: `**${this._config.t("compactionSummaryTitle")}**
|
|
6184
5907
|
|
|
6185
5908
|
${summary}`,
|
|
6186
5909
|
timestamp: Date.now(),
|
|
@@ -6634,67 +6357,6 @@ ${content}
|
|
|
6634
6357
|
);
|
|
6635
6358
|
return parts.filter((p) => p !== null);
|
|
6636
6359
|
}
|
|
6637
|
-
/**
|
|
6638
|
-
* Turn-1 forced tool call. When `toolChoice = { name, input }`
|
|
6639
|
-
* (orchestrator-driven), execute the handler directly instead of consulting
|
|
6640
|
-
* the LLM, render the tool segment, inject the result as `tool_result`, and
|
|
6641
|
-
* strip `toolChoice` for the follow-up turn. Returns the (possibly-updated)
|
|
6642
|
-
* request and whether the loop should skip to the next turn (handler missing
|
|
6643
|
-
* or aborted). Extracted from `_streamLoop`. `messages` is mutated in place.
|
|
6644
|
-
*/
|
|
6645
|
-
async _maybeRunSyntheticTool(baseRequest, turns, messages, targetElement) {
|
|
6646
|
-
const toolChoice = baseRequest.toolChoice;
|
|
6647
|
-
if (!(turns === 1 && toolChoice && typeof toolChoice === "object" && toolChoice.input !== void 0)) {
|
|
6648
|
-
return { baseRequest, skip: false };
|
|
6649
|
-
}
|
|
6650
|
-
const syntheticId = uuid();
|
|
6651
|
-
const syntheticCall = { id: syntheticId, name: toolChoice.name, input: toolChoice.input };
|
|
6652
|
-
const toolSeg = {
|
|
6653
|
-
id: `tool-${syntheticId}`,
|
|
6654
|
-
type: "tool_call",
|
|
6655
|
-
toolCall: syntheticCall,
|
|
6656
|
-
status: "pending"
|
|
6657
|
-
};
|
|
6658
|
-
const toolRenderer = this._config.getToolRenderer(toolChoice.name);
|
|
6659
|
-
if (toolRenderer) {
|
|
6660
|
-
const html = toolRenderer.render(toolSeg);
|
|
6661
|
-
if (html) targetElement.addSegment?.(toolSeg);
|
|
6662
|
-
} else {
|
|
6663
|
-
targetElement.addSegment?.(toolSeg);
|
|
6664
|
-
}
|
|
6665
|
-
const handler = this._config.getToolHandler(toolChoice.name);
|
|
6666
|
-
if (!handler) {
|
|
6667
|
-
console.warn(`[AparteClient] No handler for synthetic tool "${toolChoice.name}"`);
|
|
6668
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6669
|
-
return { baseRequest, skip: true };
|
|
6670
|
-
}
|
|
6671
|
-
const controller = new AbortController();
|
|
6672
|
-
this._activeToolControllers.add(controller);
|
|
6673
|
-
const { raced, done: clearToolTimeout } = withToolTimeout(
|
|
6674
|
-
(sig) => handler(syntheticCall, sig, {
|
|
6675
|
-
target: targetElement,
|
|
6676
|
-
config: this._config
|
|
6677
|
-
}),
|
|
6678
|
-
controller,
|
|
6679
|
-
this.options.toolTimeoutMs ?? DEFAULT_TOOL_HANDLER_TIMEOUT_MS
|
|
6680
|
-
);
|
|
6681
|
-
try {
|
|
6682
|
-
const result = await raced;
|
|
6683
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "resolved", result: result.content });
|
|
6684
|
-
messages.push({ role: "tool_call", content: "", toolCalls: [syntheticCall] });
|
|
6685
|
-
messages.push({ role: "tool_result", content: result.content, toolCallId: syntheticId });
|
|
6686
|
-
return { baseRequest: { ...baseRequest, toolChoice: "none", tools: void 0 }, skip: false };
|
|
6687
|
-
} catch (err) {
|
|
6688
|
-
if (err?.name === "AbortError") {
|
|
6689
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6690
|
-
return { baseRequest, skip: true };
|
|
6691
|
-
}
|
|
6692
|
-
throw err;
|
|
6693
|
-
} finally {
|
|
6694
|
-
clearToolTimeout();
|
|
6695
|
-
this._activeToolControllers.delete(controller);
|
|
6696
|
-
}
|
|
6697
|
-
}
|
|
6698
6360
|
/**
|
|
6699
6361
|
* What the loop does after one tool call. THREE outcomes, because a boolean
|
|
6700
6362
|
* conflated two questions that a refusal answers differently.
|
|
@@ -6707,536 +6369,41 @@ ${content}
|
|
|
6707
6369
|
* - `'halt'` — the run is over: an abort, a turn limit, a missing handler.
|
|
6708
6370
|
*/
|
|
6709
6371
|
/**
|
|
6710
|
-
*
|
|
6711
|
-
*
|
|
6712
|
-
* approval gate, and running the registered handler (timeout / abort).
|
|
6713
|
-
* Mutates the shared `messages` / `toolCallsThisTurn` history in place and
|
|
6714
|
-
* returns what the loop should do next.
|
|
6715
|
-
*/
|
|
6716
|
-
async _handleToolUseEvent(event, ctx) {
|
|
6717
|
-
const { targetElement, messageId, messages, toolCallsThisTurn, precedingText, artifactProgress, turns, globalMaxTurns } = ctx;
|
|
6718
|
-
let flow = "continue";
|
|
6719
|
-
toolCallsThisTurn.push({ id: event.id, name: event.name, input: event.input });
|
|
6720
|
-
if (event.name === "create_artifact") {
|
|
6721
|
-
const input = event.input;
|
|
6722
|
-
const mimeType = input.mimeType ?? "text/plain";
|
|
6723
|
-
const kind = deriveArtifactKind(mimeType, "text");
|
|
6724
|
-
const artifactSeg = {
|
|
6725
|
-
id: `artifact-${event.id}`,
|
|
6726
|
-
type: "artifact",
|
|
6727
|
-
mimeType,
|
|
6728
|
-
artifactType: kind,
|
|
6729
|
-
title: input.title ?? kind,
|
|
6730
|
-
content: input.content ?? ""
|
|
6731
|
-
};
|
|
6732
|
-
targetElement.addSegment?.(artifactSeg);
|
|
6733
|
-
dispatchArtifactLifecycle(targetElement, messageId, artifactSeg, artifactProgress, true);
|
|
6734
|
-
messages.push({
|
|
6735
|
-
role: "tool_call",
|
|
6736
|
-
content: "",
|
|
6737
|
-
toolCalls: [{ id: event.id, name: event.name, input: event.input }]
|
|
6738
|
-
});
|
|
6739
|
-
messages.push({
|
|
6740
|
-
role: "tool_result",
|
|
6741
|
-
content: "Artifact created successfully.",
|
|
6742
|
-
toolCallId: event.id
|
|
6743
|
-
});
|
|
6744
|
-
return { flow: "continue" };
|
|
6745
|
-
}
|
|
6746
|
-
const toolSeg = {
|
|
6747
|
-
id: `tool-${event.id}`,
|
|
6748
|
-
type: "tool_call",
|
|
6749
|
-
toolCall: { id: event.id, name: event.name, input: event.input },
|
|
6750
|
-
status: "pending"
|
|
6751
|
-
};
|
|
6752
|
-
const toolRenderer = this._config.getToolRenderer(event.name);
|
|
6753
|
-
if (toolRenderer) {
|
|
6754
|
-
if (toolRenderer.getStyles) {
|
|
6755
|
-
const styles = toolRenderer.getStyles();
|
|
6756
|
-
if (styles) {
|
|
6757
|
-
const styleId = `aparte-tool-renderer-${event.name}`;
|
|
6758
|
-
if (!document.getElementById(styleId)) {
|
|
6759
|
-
const el2 = document.createElement("style");
|
|
6760
|
-
el2.id = styleId;
|
|
6761
|
-
el2.textContent = styles;
|
|
6762
|
-
document.head.appendChild(el2);
|
|
6763
|
-
}
|
|
6764
|
-
}
|
|
6765
|
-
}
|
|
6766
|
-
const html = toolRenderer.render(toolSeg);
|
|
6767
|
-
if (html) {
|
|
6768
|
-
targetElement.addSegment?.(toolSeg);
|
|
6769
|
-
}
|
|
6770
|
-
} else {
|
|
6771
|
-
targetElement.addSegment?.(toolSeg);
|
|
6772
|
-
}
|
|
6773
|
-
const toolDef = this._config.getTools().find((t) => t.name === event.name);
|
|
6774
|
-
const effectiveMaxTurns = toolDef?.maxTurns ?? globalMaxTurns;
|
|
6775
|
-
if (turns >= effectiveMaxTurns) {
|
|
6776
|
-
console.warn(`[AparteClient] Tool "${event.name}" maxTurns (${effectiveMaxTurns}) reached.`);
|
|
6777
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6778
|
-
return { flow: "halt" };
|
|
6779
|
-
}
|
|
6780
|
-
const handler = this._config.getToolHandler(event.name);
|
|
6781
|
-
if (handler) {
|
|
6782
|
-
let effectiveInput = event.input;
|
|
6783
|
-
if (toolDef?.needsApproval) {
|
|
6784
|
-
const approvalController = new AbortController();
|
|
6785
|
-
this._activeToolControllers.add(approvalController);
|
|
6786
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "awaiting-approval" });
|
|
6787
|
-
dispatchLifecycleEvent(targetElement, "aparte-tool-approval-request", {
|
|
6788
|
-
toolCallId: event.id,
|
|
6789
|
-
toolName: event.name,
|
|
6790
|
-
input: event.input
|
|
6791
|
-
});
|
|
6792
|
-
let decision;
|
|
6793
|
-
const resolveApproval = this.options.approvalResolver ?? ((call, sig) => this._askForApproval(call, sig, targetElement));
|
|
6794
|
-
try {
|
|
6795
|
-
decision = await resolveApproval(event, approvalController.signal);
|
|
6796
|
-
} catch (err) {
|
|
6797
|
-
if (err?.name === "AbortError") {
|
|
6798
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6799
|
-
return { flow: "halt" };
|
|
6800
|
-
}
|
|
6801
|
-
throw err;
|
|
6802
|
-
} finally {
|
|
6803
|
-
this._activeToolControllers.delete(approvalController);
|
|
6804
|
-
}
|
|
6805
|
-
if (approvalController.signal.aborted) {
|
|
6806
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6807
|
-
return { flow: "halt" };
|
|
6808
|
-
}
|
|
6809
|
-
if (!decision.approved) {
|
|
6810
|
-
const rejection = decision.instruction ? `The user rejected this tool call and said: ${decision.instruction}` : "Tool execution was rejected by the user.";
|
|
6811
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "rejected", result: rejection });
|
|
6812
|
-
const existingToolCallMsg = messages.find(
|
|
6813
|
-
(m) => m.role === "tool_call" && m.toolCalls?.some((tc) => tc.id === event.id)
|
|
6814
|
-
);
|
|
6815
|
-
if (!existingToolCallMsg) {
|
|
6816
|
-
messages.push({
|
|
6817
|
-
role: "tool_call",
|
|
6818
|
-
content: "",
|
|
6819
|
-
toolCalls: toolCallsThisTurn,
|
|
6820
|
-
precedingText: precedingText.trim() || void 0
|
|
6821
|
-
});
|
|
6822
|
-
}
|
|
6823
|
-
messages.push({ role: "tool_result", content: rejection, toolCallId: event.id });
|
|
6824
|
-
return { flow: "respond" };
|
|
6825
|
-
}
|
|
6826
|
-
if (decision.payload && typeof decision.payload === "object" && !Array.isArray(decision.payload)) {
|
|
6827
|
-
effectiveInput = { ...event.input, ...decision.payload };
|
|
6828
|
-
}
|
|
6829
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "pending" });
|
|
6830
|
-
}
|
|
6831
|
-
const controller = new AbortController();
|
|
6832
|
-
this._activeToolControllers.add(controller);
|
|
6833
|
-
const { raced, done: clearToolTimeout } = withToolTimeout(
|
|
6834
|
-
(sig) => handler(
|
|
6835
|
-
{ id: event.id, name: event.name, input: effectiveInput },
|
|
6836
|
-
sig,
|
|
6837
|
-
{ target: targetElement, config: this._config }
|
|
6838
|
-
),
|
|
6839
|
-
controller,
|
|
6840
|
-
this.options.toolTimeoutMs ?? DEFAULT_TOOL_HANDLER_TIMEOUT_MS
|
|
6841
|
-
);
|
|
6842
|
-
try {
|
|
6843
|
-
const result = await raced;
|
|
6844
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "resolved", result: result.content });
|
|
6845
|
-
const existingToolCallMsg = messages.find(
|
|
6846
|
-
(m) => m.role === "tool_call" && m.toolCalls?.some((tc) => tc.id === event.id)
|
|
6847
|
-
);
|
|
6848
|
-
if (!existingToolCallMsg) {
|
|
6849
|
-
messages.push({
|
|
6850
|
-
role: "tool_call",
|
|
6851
|
-
content: "",
|
|
6852
|
-
toolCalls: toolCallsThisTurn,
|
|
6853
|
-
precedingText: precedingText.trim() || void 0
|
|
6854
|
-
});
|
|
6855
|
-
}
|
|
6856
|
-
messages.push({
|
|
6857
|
-
role: "tool_result",
|
|
6858
|
-
content: result.content,
|
|
6859
|
-
toolCallId: event.id
|
|
6860
|
-
});
|
|
6861
|
-
} catch (err) {
|
|
6862
|
-
if (err?.name === "AbortError") {
|
|
6863
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6864
|
-
flow = "halt";
|
|
6865
|
-
} else {
|
|
6866
|
-
throw err;
|
|
6867
|
-
}
|
|
6868
|
-
} finally {
|
|
6869
|
-
clearToolTimeout();
|
|
6870
|
-
this._activeToolControllers.delete(controller);
|
|
6871
|
-
}
|
|
6872
|
-
} else {
|
|
6873
|
-
console.warn(`[AparteClient] No handler registered for tool "${event.name}"`);
|
|
6874
|
-
targetElement.updateSegment?.(toolSeg.id, { status: "aborted" });
|
|
6875
|
-
flow = "halt";
|
|
6876
|
-
}
|
|
6877
|
-
return { flow };
|
|
6878
|
-
}
|
|
6879
|
-
/**
|
|
6880
|
-
* Stream loop: runs one provider.chat() call and repeats if a tool was called.
|
|
6881
|
-
* Maintains a running messages array to inject tool_call / tool_result turns.
|
|
6372
|
+
* The turn's agent loop — the engine's `runStreamAgent` rendered through the core
|
|
6373
|
+
* adapter, or the runner a host injected — after the fetch-level abort bookkeeping.
|
|
6882
6374
|
*/
|
|
6883
6375
|
async _streamLoop(targetElement, messageId, provider, baseRequest, authConfig) {
|
|
6884
6376
|
this._streamController?.abort();
|
|
6885
6377
|
const streamController = new AbortController();
|
|
6886
6378
|
this._streamController = streamController;
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
}
|
|
6890
|
-
const messages = [...baseRequest.messages];
|
|
6891
|
-
let continueLoop = true;
|
|
6892
|
-
let turns = 0;
|
|
6893
|
-
const globalMaxTurns = this.options.maxTurns ?? 10;
|
|
6894
|
-
let lastUsage;
|
|
6895
|
-
const pipeline = baseRequest._meta?.pipeline;
|
|
6896
|
-
let pipelineIndex = 0;
|
|
6897
|
-
this._updateMessage(targetElement, messageId, { status: "streaming" });
|
|
6898
|
-
for (const seg of baseRequest._meta?.prefixSegments ?? []) {
|
|
6899
|
-
targetElement.addSegment?.(seg);
|
|
6900
|
-
}
|
|
6901
|
-
while (continueLoop) {
|
|
6902
|
-
let endTurnEarly = false;
|
|
6903
|
-
if (this._isAborted) {
|
|
6904
|
-
dispatchLifecycleEvent(targetElement, "aparte-message-aborted", { messageId });
|
|
6905
|
-
break;
|
|
6906
|
-
}
|
|
6907
|
-
turns++;
|
|
6908
|
-
if (turns > globalMaxTurns) {
|
|
6909
|
-
console.warn(`[AparteClient] maxTurns (${globalMaxTurns}) exceeded — stopping loop.`);
|
|
6910
|
-
targetElement.addSegment?.({
|
|
6911
|
-
id: `max-turns-${uuid()}`,
|
|
6912
|
-
type: "error",
|
|
6913
|
-
content: `Stopped after ${globalMaxTurns} tool calls to prevent an infinite loop.`,
|
|
6914
|
-
details: "MAX_TURNS_EXCEEDED"
|
|
6915
|
-
});
|
|
6916
|
-
break;
|
|
6917
|
-
}
|
|
6918
|
-
const synthetic = await this._maybeRunSyntheticTool(baseRequest, turns, messages, targetElement);
|
|
6919
|
-
baseRequest = synthetic.baseRequest;
|
|
6920
|
-
if (synthetic.skip) {
|
|
6921
|
-
continueLoop = false;
|
|
6922
|
-
continue;
|
|
6923
|
-
}
|
|
6924
|
-
let phaseMessages = messages;
|
|
6925
|
-
let phaseMeta = baseRequest._meta;
|
|
6926
|
-
if (pipeline && pipelineIndex < pipeline.length) {
|
|
6927
|
-
const phase = pipeline[pipelineIndex];
|
|
6928
|
-
phaseMessages = [{ role: "system", content: phase.system }, ...messages];
|
|
6929
|
-
if (phase.mode === "artifact") {
|
|
6930
|
-
phaseMeta = { ...phaseMeta, artifactRaw: { mimeType: phase.mimeType, kind: phase.kind } };
|
|
6931
|
-
} else {
|
|
6932
|
-
const { artifactRaw: _dropped, pipeline: _p, ...restMeta } = phaseMeta ?? {};
|
|
6933
|
-
phaseMeta = restMeta;
|
|
6934
|
-
}
|
|
6935
|
-
}
|
|
6936
|
-
const request = { ...baseRequest, messages: phaseMessages, _meta: phaseMeta };
|
|
6937
|
-
const response = await this._config.getTransport().chat(provider, request, authConfig, { providerId: provider.id, signal: streamController.signal });
|
|
6938
|
-
if (typeof response === "string") {
|
|
6939
|
-
const wholeParser = new AparteStreamParser();
|
|
6940
|
-
const parsed = [
|
|
6941
|
-
...wholeParser.parse(response).segments,
|
|
6942
|
-
...wholeParser.finalize()
|
|
6943
|
-
];
|
|
6944
|
-
const stringHint = baseRequest._meta?.artifactHint;
|
|
6945
|
-
if (stringHint) {
|
|
6946
|
-
const codeIdx = parsed.findIndex((s) => s.type === "code");
|
|
6947
|
-
if (codeIdx !== -1) {
|
|
6948
|
-
const codeSeg = parsed[codeIdx];
|
|
6949
|
-
parsed[codeIdx] = {
|
|
6950
|
-
id: codeSeg.id,
|
|
6951
|
-
type: "artifact",
|
|
6952
|
-
mimeType: stringHint.mimeType,
|
|
6953
|
-
artifactType: stringHint.kind,
|
|
6954
|
-
title: codeSeg.filename ?? stringHint.kind,
|
|
6955
|
-
content: codeSeg.content
|
|
6956
|
-
};
|
|
6957
|
-
}
|
|
6958
|
-
}
|
|
6959
|
-
if (parsed.length > 0) {
|
|
6960
|
-
for (const segment of parsed) targetElement.addSegment?.(segment);
|
|
6961
|
-
this._updateMessage(targetElement, messageId, { status: "completed" });
|
|
6962
|
-
} else {
|
|
6963
|
-
this._updateMessage(targetElement, messageId, { content: response, status: "completed" });
|
|
6964
|
-
}
|
|
6965
|
-
return void 0;
|
|
6966
|
-
}
|
|
6967
|
-
const reader = response.getReader();
|
|
6968
|
-
const textParser = new AparteStreamParser();
|
|
6969
|
-
const streamingSegmentIds = /* @__PURE__ */ new Set();
|
|
6970
|
-
const artifactProgress = /* @__PURE__ */ new Map();
|
|
6971
|
-
let thinkingSegmentId = null;
|
|
6972
|
-
let thinkingContent = "";
|
|
6973
|
-
let thinkingCollapsed = false;
|
|
6974
|
-
const artifactHint = baseRequest._meta?.artifactHint;
|
|
6975
|
-
let artifactPromoted = false;
|
|
6976
|
-
const artifactRawHint = request._meta?.artifactRaw;
|
|
6977
|
-
let rawSegId = null;
|
|
6978
|
-
let rawContent = "";
|
|
6979
|
-
if (artifactRawHint) {
|
|
6980
|
-
rawSegId = `artifact-raw-${uuid()}`;
|
|
6981
|
-
const rawSeg = {
|
|
6982
|
-
id: rawSegId,
|
|
6983
|
-
type: "artifact",
|
|
6984
|
-
mimeType: artifactRawHint.mimeType,
|
|
6985
|
-
artifactType: artifactRawHint.kind,
|
|
6986
|
-
title: artifactRawHint.kind,
|
|
6987
|
-
content: ""
|
|
6988
|
-
};
|
|
6989
|
-
targetElement.addSegment?.(rawSeg);
|
|
6990
|
-
streamingSegmentIds.add(rawSegId);
|
|
6991
|
-
dispatchArtifactLifecycle(targetElement, messageId, rawSeg, artifactProgress, false);
|
|
6992
|
-
}
|
|
6993
|
-
const artifactXmlHint = baseRequest._meta?.artifactXml;
|
|
6994
|
-
const xmlCtx = {
|
|
6995
|
-
state: "normal",
|
|
6996
|
-
scanBuf: "",
|
|
6997
|
-
closeBuf: "",
|
|
6998
|
-
segId: null,
|
|
6999
|
-
content: "",
|
|
7000
|
-
mime: "",
|
|
7001
|
-
kind: "",
|
|
7002
|
-
title: ""
|
|
7003
|
-
};
|
|
7004
|
-
let precedingText = "";
|
|
7005
|
-
const toolCallsThisTurn = [];
|
|
7006
|
-
const bailOnAbort = () => {
|
|
7007
|
-
if (!this._isAborted) return false;
|
|
7008
|
-
try {
|
|
7009
|
-
void reader.cancel();
|
|
7010
|
-
} catch {
|
|
7011
|
-
}
|
|
7012
|
-
dispatchLifecycleEvent(targetElement, "aparte-message-aborted", { messageId });
|
|
7013
|
-
continueLoop = false;
|
|
7014
|
-
return true;
|
|
7015
|
-
};
|
|
7016
|
-
let streamDrained = false;
|
|
7017
|
-
try {
|
|
7018
|
-
while (true) {
|
|
7019
|
-
if (bailOnAbort()) break;
|
|
7020
|
-
const { done, value: event } = await reader.read();
|
|
7021
|
-
if (bailOnAbort()) break;
|
|
7022
|
-
if (done) {
|
|
7023
|
-
streamDrained = true;
|
|
7024
|
-
break;
|
|
7025
|
-
}
|
|
7026
|
-
switch (event.type) {
|
|
7027
|
-
case "thinking": {
|
|
7028
|
-
thinkingContent += event.delta;
|
|
7029
|
-
if (!thinkingSegmentId) {
|
|
7030
|
-
const seg = {
|
|
7031
|
-
id: `think-${uuid()}`,
|
|
7032
|
-
type: "thinking",
|
|
7033
|
-
content: thinkingContent,
|
|
7034
|
-
collapsed: true,
|
|
7035
|
-
label: "Thinking"
|
|
7036
|
-
};
|
|
7037
|
-
thinkingSegmentId = seg.id;
|
|
7038
|
-
streamingSegmentIds.add(seg.id);
|
|
7039
|
-
targetElement.addSegment?.(seg);
|
|
7040
|
-
} else {
|
|
7041
|
-
targetElement.updateSegment?.(thinkingSegmentId, { content: thinkingContent });
|
|
7042
|
-
}
|
|
7043
|
-
break;
|
|
7044
|
-
}
|
|
7045
|
-
case "text": {
|
|
7046
|
-
if (thinkingSegmentId && !thinkingCollapsed) {
|
|
7047
|
-
targetElement.updateSegment?.(thinkingSegmentId, { collapsed: true, isStreaming: false });
|
|
7048
|
-
thinkingCollapsed = true;
|
|
7049
|
-
}
|
|
7050
|
-
precedingText += event.delta;
|
|
7051
|
-
if (artifactRawHint && rawSegId) {
|
|
7052
|
-
rawContent += event.delta;
|
|
7053
|
-
targetElement.updateSegment?.(rawSegId, { content: rawContent });
|
|
7054
|
-
dispatchArtifactLifecycle(targetElement, messageId, {
|
|
7055
|
-
id: rawSegId,
|
|
7056
|
-
type: "artifact",
|
|
7057
|
-
mimeType: artifactRawHint.mimeType,
|
|
7058
|
-
artifactType: artifactRawHint.kind,
|
|
7059
|
-
title: artifactRawHint.kind,
|
|
7060
|
-
content: rawContent
|
|
7061
|
-
}, artifactProgress, false);
|
|
7062
|
-
break;
|
|
7063
|
-
}
|
|
7064
|
-
if (artifactXmlHint) {
|
|
7065
|
-
feedXmlArtifactDelta(event.delta, xmlCtx, {
|
|
7066
|
-
targetElement,
|
|
7067
|
-
messageId,
|
|
7068
|
-
textParser,
|
|
7069
|
-
streamingSegmentIds,
|
|
7070
|
-
artifactProgress,
|
|
7071
|
-
artifactXmlHint
|
|
7072
|
-
});
|
|
7073
|
-
break;
|
|
7074
|
-
}
|
|
7075
|
-
const result = textParser.parse(event.delta);
|
|
7076
|
-
for (let segment of result.segments) {
|
|
7077
|
-
if (artifactHint && !artifactPromoted && segment.type === "code") {
|
|
7078
|
-
const codeSeg = segment;
|
|
7079
|
-
const promoted = {
|
|
7080
|
-
id: codeSeg.id,
|
|
7081
|
-
type: "artifact",
|
|
7082
|
-
mimeType: artifactHint.mimeType,
|
|
7083
|
-
artifactType: artifactHint.kind,
|
|
7084
|
-
title: codeSeg.filename ?? artifactHint.kind,
|
|
7085
|
-
content: codeSeg.content
|
|
7086
|
-
};
|
|
7087
|
-
segment = promoted;
|
|
7088
|
-
artifactPromoted = true;
|
|
7089
|
-
}
|
|
7090
|
-
if (!streamingSegmentIds.has(segment.id)) {
|
|
7091
|
-
targetElement.addSegment?.(segment);
|
|
7092
|
-
streamingSegmentIds.add(segment.id);
|
|
7093
|
-
} else if ("content" in segment) {
|
|
7094
|
-
targetElement.updateSegment?.(segment.id, segmentContentUpdate(segment));
|
|
7095
|
-
}
|
|
7096
|
-
if (segment.type === "artifact") {
|
|
7097
|
-
dispatchArtifactLifecycle(targetElement, messageId, segment, artifactProgress, true);
|
|
7098
|
-
}
|
|
7099
|
-
}
|
|
7100
|
-
const active = textParser.getState().activeSegment;
|
|
7101
|
-
if (active) {
|
|
7102
|
-
if (!streamingSegmentIds.has(active.id)) {
|
|
7103
|
-
targetElement.addSegment?.(active);
|
|
7104
|
-
streamingSegmentIds.add(active.id);
|
|
7105
|
-
if (active.type === "artifact") {
|
|
7106
|
-
dispatchArtifactLifecycle(targetElement, messageId, active, artifactProgress, false);
|
|
7107
|
-
}
|
|
7108
|
-
} else {
|
|
7109
|
-
targetElement.updateSegment?.(active.id, segmentContentUpdate(active));
|
|
7110
|
-
if (active.type === "artifact") {
|
|
7111
|
-
dispatchArtifactLifecycle(targetElement, messageId, active, artifactProgress, false);
|
|
7112
|
-
}
|
|
7113
|
-
}
|
|
7114
|
-
} else if (result.segments.length === 0) {
|
|
7115
|
-
}
|
|
7116
|
-
break;
|
|
7117
|
-
}
|
|
7118
|
-
case "tool_use": {
|
|
7119
|
-
const toolResult = await this._handleToolUseEvent(
|
|
7120
|
-
{ id: event.id, name: event.name, input: event.input },
|
|
7121
|
-
{ targetElement, messageId, messages, toolCallsThisTurn, precedingText, artifactProgress, turns, globalMaxTurns }
|
|
7122
|
-
);
|
|
7123
|
-
if (toolResult.flow !== "continue") endTurnEarly = true;
|
|
7124
|
-
if (toolResult.flow === "halt") continueLoop = false;
|
|
7125
|
-
break;
|
|
7126
|
-
}
|
|
7127
|
-
case "error":
|
|
7128
|
-
throw new Error(event.message);
|
|
7129
|
-
case "done":
|
|
7130
|
-
if (event.usage) lastUsage = event.usage;
|
|
7131
|
-
break;
|
|
7132
|
-
default: {
|
|
7133
|
-
const exhaustive = event;
|
|
7134
|
-
void exhaustive;
|
|
7135
|
-
this._warnUnknownStreamEvent(event);
|
|
7136
|
-
break;
|
|
7137
|
-
}
|
|
7138
|
-
}
|
|
7139
|
-
if (endTurnEarly) break;
|
|
7140
|
-
}
|
|
7141
|
-
finalizeXmlArtifact(xmlCtx, { targetElement, messageId, artifactProgress, artifactXmlHint, textParser, streamingSegmentIds });
|
|
7142
|
-
const finals = textParser.finalize();
|
|
7143
|
-
if (artifactRawHint && rawSegId) {
|
|
7144
|
-
const lineCount = rawContent.split("\n").length;
|
|
7145
|
-
const isInline = lineCount < 15;
|
|
7146
|
-
targetElement.updateSegment?.(rawSegId, { content: rawContent, inline: isInline });
|
|
7147
|
-
dispatchArtifactLifecycle(targetElement, messageId, {
|
|
7148
|
-
id: rawSegId,
|
|
7149
|
-
type: "artifact",
|
|
7150
|
-
mimeType: artifactRawHint.mimeType,
|
|
7151
|
-
artifactType: artifactRawHint.kind,
|
|
7152
|
-
title: artifactRawHint.kind,
|
|
7153
|
-
content: rawContent,
|
|
7154
|
-
inline: isInline
|
|
7155
|
-
}, artifactProgress, true);
|
|
7156
|
-
}
|
|
7157
|
-
if (artifactHint && !artifactPromoted) {
|
|
7158
|
-
const codeIdx = finals.findIndex((s) => s.type === "code");
|
|
7159
|
-
if (codeIdx !== -1) {
|
|
7160
|
-
const codeSeg = finals[codeIdx];
|
|
7161
|
-
const promoted = {
|
|
7162
|
-
id: codeSeg.id,
|
|
7163
|
-
type: "artifact",
|
|
7164
|
-
mimeType: artifactHint.mimeType,
|
|
7165
|
-
artifactType: artifactHint.kind,
|
|
7166
|
-
title: codeSeg.filename ?? artifactHint.kind,
|
|
7167
|
-
content: codeSeg.content
|
|
7168
|
-
};
|
|
7169
|
-
finals[codeIdx] = promoted;
|
|
7170
|
-
artifactPromoted = true;
|
|
7171
|
-
if (streamingSegmentIds.has(promoted.id)) {
|
|
7172
|
-
targetElement.updateSegment?.(promoted.id, promoted);
|
|
7173
|
-
}
|
|
7174
|
-
}
|
|
7175
|
-
}
|
|
7176
|
-
for (const s of finals) {
|
|
7177
|
-
if (!streamingSegmentIds.has(s.id)) {
|
|
7178
|
-
targetElement.addSegment?.(s);
|
|
7179
|
-
} else if ("content" in s) {
|
|
7180
|
-
targetElement.updateSegment?.(s.id, segmentContentUpdate(s));
|
|
7181
|
-
}
|
|
7182
|
-
if (s.type === "artifact") {
|
|
7183
|
-
dispatchArtifactLifecycle(targetElement, messageId, s, artifactProgress, true);
|
|
7184
|
-
}
|
|
7185
|
-
}
|
|
7186
|
-
if (toolCallsThisTurn.length === 0) {
|
|
7187
|
-
if (pipeline && pipelineIndex < pipeline.length - 1) {
|
|
7188
|
-
if (precedingText.trim()) {
|
|
7189
|
-
messages.push({ role: "assistant", content: precedingText.trim() });
|
|
7190
|
-
}
|
|
7191
|
-
pipelineIndex++;
|
|
7192
|
-
const pwId = `pw-${uuid()}`;
|
|
7193
|
-
targetElement.addSegment?.({ id: pwId, type: "pipeline-waiting" });
|
|
7194
|
-
} else {
|
|
7195
|
-
continueLoop = false;
|
|
7196
|
-
}
|
|
7197
|
-
}
|
|
7198
|
-
} finally {
|
|
7199
|
-
if (!streamDrained) {
|
|
7200
|
-
try {
|
|
7201
|
-
await reader.cancel();
|
|
7202
|
-
} catch {
|
|
7203
|
-
}
|
|
7204
|
-
}
|
|
7205
|
-
reader.releaseLock();
|
|
7206
|
-
}
|
|
7207
|
-
}
|
|
7208
|
-
this._updateMessage(targetElement, messageId, { status: "completed" });
|
|
7209
|
-
if (lastUsage) {
|
|
7210
|
-
try {
|
|
7211
|
-
targetElement.setUsage?.(messageId, lastUsage);
|
|
7212
|
-
} catch {
|
|
7213
|
-
}
|
|
7214
|
-
}
|
|
7215
|
-
return lastUsage;
|
|
6379
|
+
const runner = this.options.streamRunner ?? runStreamAgent;
|
|
6380
|
+
return this._runViaStreamRunner(runner, targetElement, messageId, provider, baseRequest, authConfig, streamController);
|
|
7216
6381
|
}
|
|
7217
6382
|
/**
|
|
7218
|
-
*
|
|
7219
|
-
* rendering its DOM-free events through {@link createStreamAdapter}.
|
|
7220
|
-
*
|
|
7221
|
-
*
|
|
7222
|
-
*
|
|
7223
|
-
*
|
|
7224
|
-
*
|
|
6383
|
+
* Run the loop through a {@link AparteStreamRunner} — the engine's by default —
|
|
6384
|
+
* rendering its DOM-free events through {@link createStreamAdapter}. Builds the
|
|
6385
|
+
* runner's dependencies from this client's config / provider / transport. The
|
|
6386
|
+
* leading writes (status streaming, prefix segments) happen here; the runner's
|
|
6387
|
+
* `run-start` re-asserts `streaming` idempotently. The call sequence this
|
|
6388
|
+
* produces is pinned by the `stream-parity` suite's snapshots, recorded while
|
|
6389
|
+
* the inline loop it replaced still ran beside it.
|
|
7225
6390
|
*/
|
|
7226
6391
|
async _runViaStreamRunner(streamRunner, targetElement, messageId, provider, baseRequest, authConfig, streamController) {
|
|
7227
6392
|
const signal = streamController.signal;
|
|
7228
|
-
this._updateMessage(targetElement, messageId, { status: "streaming" });
|
|
7229
|
-
const prefixSegments = baseRequest._meta?.["prefixSegments"];
|
|
7230
|
-
if (prefixSegments?.length) {
|
|
7231
|
-
for (const seg of prefixSegments) targetElement.addSegment?.(seg);
|
|
7232
|
-
}
|
|
7233
6393
|
const artifactHint = baseRequest._meta?.artifactHint;
|
|
7234
|
-
const
|
|
6394
|
+
const adapter = createStreamAdapter({
|
|
7235
6395
|
target: targetElement,
|
|
7236
6396
|
config: this._config,
|
|
7237
6397
|
messageId,
|
|
7238
6398
|
artifactHint
|
|
7239
6399
|
});
|
|
6400
|
+
const prefixSegments = baseRequest._meta?.["prefixSegments"];
|
|
6401
|
+
const emitter = (event) => {
|
|
6402
|
+
adapter(event);
|
|
6403
|
+
if (event.type === "run-start" && prefixSegments?.length) {
|
|
6404
|
+
for (const seg of prefixSegments) targetElement.addSegment?.(seg);
|
|
6405
|
+
}
|
|
6406
|
+
};
|
|
7240
6407
|
const transportCall = async (request) => {
|
|
7241
6408
|
const response = await this._config.getTransport().chat(provider, request, authConfig, { providerId: provider.id, signal });
|
|
7242
6409
|
return typeof response === "string" ? response : readableToAsyncIterable(response, signal);
|
|
@@ -7267,7 +6434,7 @@ ${content}
|
|
|
7267
6434
|
// inline path, so setting it was silently ignored here. Exactly the
|
|
7268
6435
|
// asymmetry the option was added to remove.
|
|
7269
6436
|
toolTimeoutMs: this.options.toolTimeoutMs,
|
|
7270
|
-
//
|
|
6437
|
+
// The id conventions the loop always had: prefixed artifact ids, but a
|
|
7271
6438
|
// BARE uuid for the synthetic tool (the adapter renders `tool-<id>`).
|
|
7272
6439
|
idGen: (prefix) => prefix === "synthetic-tool" ? uuid() : `${prefix}-${uuid()}`
|
|
7273
6440
|
});
|
|
@@ -7308,16 +6475,6 @@ ${content}
|
|
|
7308
6475
|
}
|
|
7309
6476
|
dispatchLifecycleEvent(target, "aparte-message-error", { messageId, error });
|
|
7310
6477
|
}
|
|
7311
|
-
/** Warn once per client for an unrecognised stream event, then carry on. */
|
|
7312
|
-
_warnedUnknownEvents = /* @__PURE__ */ new Set();
|
|
7313
|
-
_warnUnknownStreamEvent(event) {
|
|
7314
|
-
const type = String(event?.type ?? "undefined");
|
|
7315
|
-
if (this._warnedUnknownEvents.has(type)) return;
|
|
7316
|
-
this._warnedUnknownEvents.add(type);
|
|
7317
|
-
console.warn(
|
|
7318
|
-
`[AparteClient] Ignoring unrecognised stream event "${type}". The reply is unaffected; this usually means the provider or its SDK emits a part this version of aparté does not map yet.`
|
|
7319
|
-
);
|
|
7320
|
-
}
|
|
7321
6478
|
}
|
|
7322
6479
|
function findHead(node) {
|
|
7323
6480
|
if (node.next) return findHead(node.next);
|
|
@@ -7489,6 +6646,12 @@ class AparteMessageRepository {
|
|
|
7489
6646
|
import(exported) {
|
|
7490
6647
|
this.clear();
|
|
7491
6648
|
for (const { message, parentId } of exported.messages) {
|
|
6649
|
+
if (parentId !== null && !this._nodes.has(parentId)) {
|
|
6650
|
+
console.warn(
|
|
6651
|
+
`[AparteMessageRepository] import: message "${message.id}" names a parent "${parentId}" the snapshot does not hold before it — skipped.`
|
|
6652
|
+
);
|
|
6653
|
+
continue;
|
|
6654
|
+
}
|
|
7492
6655
|
this.addOrUpdateMessage(parentId, message);
|
|
7493
6656
|
}
|
|
7494
6657
|
if (exported.headId) {
|
|
@@ -7498,15 +6661,25 @@ class AparteMessageRepository {
|
|
|
7498
6661
|
/**
|
|
7499
6662
|
* Export the full tree for serialisation or debugging.
|
|
7500
6663
|
* Compatible with the assistant-ui ExportedMessageRepository format.
|
|
6664
|
+
*
|
|
6665
|
+
* Walked from the root through each node's `children`, so a parent is always
|
|
6666
|
+
* written before its children. It used to iterate `_nodes` in insertion order and
|
|
6667
|
+
* call that topological — which holds until `_relink` re-parents an EXISTING node
|
|
6668
|
+
* under one inserted after it (`addOrUpdateMessage` with a known id and a newer
|
|
6669
|
+
* parent). The snapshot then listed the child first, and `import()` threw "parent
|
|
6670
|
+
* not found" on the very tree this method had just produced.
|
|
7501
6671
|
*/
|
|
7502
6672
|
export() {
|
|
7503
6673
|
const messages = [];
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
6674
|
+
const walk = (children, parentId) => {
|
|
6675
|
+
for (const id of children) {
|
|
6676
|
+
const node = this._nodes.get(id);
|
|
6677
|
+
if (!node) continue;
|
|
6678
|
+
messages.push({ message: node.current, parentId });
|
|
6679
|
+
walk(node.children, id);
|
|
6680
|
+
}
|
|
6681
|
+
};
|
|
6682
|
+
walk(this._root.children, null);
|
|
7510
6683
|
return { headId: this.headId, messages };
|
|
7511
6684
|
}
|
|
7512
6685
|
// ─── Private helpers ────────────────────────────────────────────────────
|
|
@@ -7612,75 +6785,73 @@ function isAwaitingReply(message) {
|
|
|
7612
6785
|
return message.status === void 0 && message.role === "assistant" && !message.content?.trim() && !message.segments?.length;
|
|
7613
6786
|
}
|
|
7614
6787
|
export {
|
|
7615
|
-
|
|
6788
|
+
runWithConfig as $,
|
|
7616
6789
|
APARTE_CONFIG_CHANGE as A,
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
6790
|
+
contextConfig as B,
|
|
6791
|
+
createAparteChatHandler as C,
|
|
6792
|
+
createStreamAdapter as D,
|
|
6793
|
+
cssEscape as E,
|
|
6794
|
+
declineDefaultRenderers as F,
|
|
6795
|
+
defaultSanitizer as G,
|
|
6796
|
+
detachConfig as H,
|
|
6797
|
+
escapeAttr as I,
|
|
6798
|
+
escapeHtml as J,
|
|
6799
|
+
filesToAttachments as K,
|
|
6800
|
+
getAllRenderers as L,
|
|
6801
|
+
getSegmentRenderer as M,
|
|
6802
|
+
installDefaultRenderersOnce as N,
|
|
6803
|
+
isAwaitingReply as O,
|
|
6804
|
+
isFormatAdapter as P,
|
|
6805
|
+
isSafeUrl as Q,
|
|
6806
|
+
isSegmentSettled as R,
|
|
6807
|
+
parseAparteEventStream as S,
|
|
6808
|
+
parseMarkdownToSegments as T,
|
|
6809
|
+
populateBubbleFromMessage as U,
|
|
6810
|
+
readableToAsyncIterable as V,
|
|
6811
|
+
registerDefaultRenderers as W,
|
|
6812
|
+
registerSegmentRenderer as X,
|
|
6813
|
+
requestUserInput as Y,
|
|
6814
|
+
resolveConfig as Z,
|
|
6815
|
+
revokeAttachmentUrls as _,
|
|
7643
6816
|
APARTE_CONVERSATION_SCHEMA_VERSION as a,
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
isTerminalStatus as ae,
|
|
7659
|
-
adoptMessageSegments as af,
|
|
6817
|
+
segmentDuration as a0,
|
|
6818
|
+
segmentTiming as a1,
|
|
6819
|
+
subscribeConfigChange as a2,
|
|
6820
|
+
unregisterSegmentRenderer as a3,
|
|
6821
|
+
uuid as a4,
|
|
6822
|
+
mergeSegmentUpdate as a5,
|
|
6823
|
+
writeStreamedMarkdown as a6,
|
|
6824
|
+
stampSegmentActivity as a7,
|
|
6825
|
+
stampSegmentOnInsert as a8,
|
|
6826
|
+
stampSegmentOnUpdate as a9,
|
|
6827
|
+
renumberSegments as aa,
|
|
6828
|
+
openSegmentIds as ab,
|
|
6829
|
+
isTerminalStatus as ac,
|
|
6830
|
+
adoptMessageSegments as ad,
|
|
7660
6831
|
APARTE_DEFAULT_BUBBLE_ACTIONS as b,
|
|
7661
6832
|
APARTE_DEFAULT_HOST_HANDLERS as c,
|
|
7662
6833
|
APARTE_DEFAULT_ICON_FALLBACKS as d,
|
|
7663
6834
|
APARTE_DEFAULT_LOCALE as e,
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
6835
|
+
APARTE_DEFAULT_UI_EVENTS as f,
|
|
6836
|
+
APARTE_HOST_ATTR as g,
|
|
6837
|
+
AparteBackendTransport as h,
|
|
6838
|
+
AparteChatHost as i,
|
|
6839
|
+
AparteClient as j,
|
|
6840
|
+
AparteConfig as k,
|
|
6841
|
+
AparteConversationController as l,
|
|
6842
|
+
AparteConversationManager as m,
|
|
6843
|
+
AparteDirectTransport as n,
|
|
6844
|
+
AparteElicitationAbortError as o,
|
|
6845
|
+
AparteError as p,
|
|
6846
|
+
AparteErrorCode as q,
|
|
6847
|
+
AparteMessageRepository as r,
|
|
6848
|
+
AparteStreamParser as s,
|
|
6849
|
+
aparteGlobalConfig as t,
|
|
6850
|
+
applyElementProps as u,
|
|
6851
|
+
attachConfig as v,
|
|
6852
|
+
buildApprovalPanel as w,
|
|
6853
|
+
buildElicitationPanel as x,
|
|
6854
|
+
collectRendererStyles as y,
|
|
6855
|
+
contentToText as z
|
|
7685
6856
|
};
|
|
7686
|
-
//# sourceMappingURL=is-awaiting-reply-
|
|
6857
|
+
//# sourceMappingURL=is-awaiting-reply-BZ_iJ3s3.js.map
|