@aparte/core 0.12.1 → 0.13.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/dist/client/aparte-client.d.ts +25 -0
- package/dist/client/aparte-client.d.ts.map +1 -1
- package/dist/components/bubble/aparte-chat-bubble.d.ts +117 -0
- package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
- package/dist/components/chat/aparte-chat.d.ts +70 -15
- package/dist/components/chat/aparte-chat.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-action.d.ts +48 -7
- package/dist/components/composer/aparte-composer-action.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-add-attachment.d.ts +37 -4
- package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-attachments.d.ts +35 -3
- package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-cancel.d.ts +25 -2
- package/dist/components/composer/aparte-composer-cancel.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-input.d.ts +54 -5
- package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-send.d.ts +47 -4
- package/dist/components/composer/aparte-composer-send.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-toolbar.d.ts +15 -4
- package/dist/components/composer/aparte-composer-toolbar.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer.d.ts +139 -7
- package/dist/components/composer/aparte-composer.d.ts.map +1 -1
- package/dist/components/composer/index.d.ts +1 -1
- package/dist/components/composer/index.d.ts.map +1 -1
- package/dist/components/conversation-list/aparte-conversation-list.d.ts +50 -8
- package/dist/components/conversation-list/aparte-conversation-list.d.ts.map +1 -1
- package/dist/components/elicitation/aparte-elicitation.d.ts +45 -0
- package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/status/aparte-chat-status.d.ts +47 -5
- package/dist/components/status/aparte-chat-status.d.ts.map +1 -1
- package/dist/components/viewport/aparte-chat-viewport.d.ts +78 -8
- package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
- package/dist/config/aparte-config.d.ts +22 -0
- package/dist/config/aparte-config.d.ts.map +1 -1
- package/dist/config/icon-provider.d.ts +17 -15
- package/dist/config/icon-provider.d.ts.map +1 -1
- package/dist/custom-elements.json +6249 -4138
- package/dist/elicitation/approval-panel.d.ts.map +1 -1
- package/dist/elicitation/panel.d.ts +23 -2
- package/dist/elicitation/panel.d.ts.map +1 -1
- package/dist/generated/element-attributes.d.ts +21 -15
- package/dist/generated/element-attributes.d.ts.map +1 -1
- package/dist/glyphs-QXfbL3n_.js +81 -0
- package/dist/glyphs-QXfbL3n_.js.map +1 -0
- package/dist/icons/extended.d.ts +153 -0
- package/dist/icons/extended.d.ts.map +1 -0
- package/dist/icons/glyphs.d.ts +98 -0
- package/dist/icons/glyphs.d.ts.map +1 -0
- package/dist/icons/index.d.ts +24 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/icons.d.ts +14 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +157 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.css +5082 -2119
- package/dist/index.d.ts +37 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +167 -67
- package/dist/index.js.map +1 -1
- package/dist/index.node.d.ts +2 -2
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +1 -1
- package/dist/index.node.js.map +1 -1
- package/dist/{is-awaiting-reply-BWTDvQ__.js → is-awaiting-reply-DrO_oR32.js} +333 -147
- package/dist/is-awaiting-reply-DrO_oR32.js.map +1 -0
- package/dist/primitives/icon/aparte-icon.d.ts +49 -0
- package/dist/primitives/icon/aparte-icon.d.ts.map +1 -0
- package/dist/primitives/icon/index.d.ts +2 -0
- package/dist/primitives/icon/index.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts +20 -5
- package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts.map +1 -1
- package/dist/primitives/select/aparte-optgroup.d.ts +30 -7
- package/dist/primitives/select/aparte-optgroup.d.ts.map +1 -1
- package/dist/primitives/select/aparte-option.d.ts +29 -3
- package/dist/primitives/select/aparte-option.d.ts.map +1 -1
- package/dist/primitives/select/aparte-select.d.ts +36 -11
- package/dist/primitives/select/aparte-select.d.ts.map +1 -1
- package/dist/renderers/segments/artifact/card.d.ts.map +1 -1
- package/dist/renderers/segments/thinking.d.ts.map +1 -1
- package/dist/renderers/segments/tool-call.d.ts.map +1 -1
- package/dist/types/element-map.d.ts +2 -0
- package/dist/types/element-map.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/segments.d.ts +92 -7
- package/dist/types/segments.d.ts.map +1 -1
- package/dist/types/tools.d.ts +2 -0
- package/dist/types/tools.d.ts.map +1 -1
- package/package.json +7 -1
- package/dist/is-awaiting-reply-BWTDvQ__.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { A as APARTE_ICON_GLYPHS } from "./glyphs-QXfbL3n_.js";
|
|
1
2
|
function contentToText(content) {
|
|
2
3
|
if (typeof content === "string") return content;
|
|
3
4
|
return content.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
@@ -35,29 +36,7 @@ class AparteError extends Error {
|
|
|
35
36
|
return new AparteError(message, defaultCode, void 0, error, status);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
const APARTE_DEFAULT_ICON_FALLBACKS =
|
|
39
|
-
copy: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,
|
|
40
|
-
check: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>`,
|
|
41
|
-
send: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>`,
|
|
42
|
-
loading: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="aparte-icon-spin"><circle cx="12" cy="12" r="10" stroke-opacity="0.25"/><path d="M12 2a10 10 0 0 1 10 10"/></svg>`,
|
|
43
|
-
error: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`,
|
|
44
|
-
expand: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>`,
|
|
45
|
-
collapse: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>`,
|
|
46
|
-
terminal: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>`,
|
|
47
|
-
paperclip: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>`,
|
|
48
|
-
image: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`,
|
|
49
|
-
file: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>`,
|
|
50
|
-
scrollDown: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>`,
|
|
51
|
-
retry: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>`,
|
|
52
|
-
edit: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>`,
|
|
53
|
-
thumbUp: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"/></svg>`,
|
|
54
|
-
thumbDown: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"/><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z"/></svg>`,
|
|
55
|
-
prevBranch: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>`,
|
|
56
|
-
nextBranch: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>`,
|
|
57
|
-
tool: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>`,
|
|
58
|
-
close: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`,
|
|
59
|
-
stop: `<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><rect x="2" y="2" width="12" height="12" rx="2"/></svg>`
|
|
60
|
-
};
|
|
39
|
+
const APARTE_DEFAULT_ICON_FALLBACKS = APARTE_ICON_GLYPHS;
|
|
61
40
|
const APARTE_DEFAULT_LOCALE = {
|
|
62
41
|
inputPlaceholder: "Type a message...",
|
|
63
42
|
sendButton: "Send",
|
|
@@ -122,6 +101,14 @@ const APARTE_DEFAULT_LOCALE = {
|
|
|
122
101
|
unarchiveConversation: "Unarchive conversation",
|
|
123
102
|
direction: "ltr"
|
|
124
103
|
};
|
|
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
|
+
};
|
|
125
112
|
function isFormatAdapter(p) {
|
|
126
113
|
return typeof p.buildRequest === "function" && typeof p.parseStream === "function" && typeof p.defaultEndpoint === "string" && (typeof p.authHeaders === "function" || typeof p.authQuery === "function");
|
|
127
114
|
}
|
|
@@ -1874,6 +1861,24 @@ class AparteConfig {
|
|
|
1874
1861
|
getTools() {
|
|
1875
1862
|
return Array.from(this._tools.values()).map((e) => e.tool);
|
|
1876
1863
|
}
|
|
1864
|
+
/**
|
|
1865
|
+
* The registered tools' own `systemPrompt`s, joined, or `null` if none set one.
|
|
1866
|
+
*
|
|
1867
|
+
* `AparteTool.systemPrompt` has always been documented as "injected automatically when
|
|
1868
|
+
* this tool is registered", on the type and in the tools guide — and nothing read it.
|
|
1869
|
+
* A field that is documented and dead is worse than one that does not exist: a caller
|
|
1870
|
+
* writes it, sees the tool work (the model has the schema either way), and never learns
|
|
1871
|
+
* that the sentence explaining WHEN to reach for it was dropped. `@aparte/plugin-ask-user`
|
|
1872
|
+
* sets one, so a shipped plugin was losing its instructions.
|
|
1873
|
+
*
|
|
1874
|
+
* Registration order, blank line between, because two tools' instructions are two
|
|
1875
|
+
* paragraphs and not one run-on sentence. The app's own template stays a separate
|
|
1876
|
+
* message — see `resolveSystemPrompt`, which is about the app and not about the tools.
|
|
1877
|
+
*/
|
|
1878
|
+
resolveToolSystemPrompts() {
|
|
1879
|
+
const prompts = Array.from(this._tools.values()).map((entry) => entry.tool.systemPrompt?.trim()).filter((prompt) => Boolean(prompt));
|
|
1880
|
+
return prompts.length ? prompts.join("\n\n") : null;
|
|
1881
|
+
}
|
|
1877
1882
|
/** Get the handler for a tool by name */
|
|
1878
1883
|
getToolHandler(name) {
|
|
1879
1884
|
return this._tools.get(name)?.handler;
|
|
@@ -2123,16 +2128,15 @@ class AparteConfig {
|
|
|
2123
2128
|
_defaultHighlightRenderer(code) {
|
|
2124
2129
|
return `<pre><code>${escapeHtml(code)}</code></pre>`;
|
|
2125
2130
|
}
|
|
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
|
+
*/
|
|
2126
2138
|
_defaultSkeletonRenderer(type) {
|
|
2127
|
-
|
|
2128
|
-
message: '<div class="aparte-skeleton-fallback" style="padding:16px;color:#9ca3af;">Loading message...</div>',
|
|
2129
|
-
code: '<div class="aparte-skeleton-fallback" style="padding:16px;background:#1e293b;color:#64748b;border-radius:8px;">Loading code...</div>',
|
|
2130
|
-
text: '<div class="aparte-skeleton-fallback" style="padding:8px;color:#9ca3af;">Loading...</div>',
|
|
2131
|
-
thinking: '<div class="aparte-skeleton-fallback" style="padding:8px;color:#9ca3af;">Thinking...</div>',
|
|
2132
|
-
input: '<div class="aparte-skeleton-fallback" style="padding:12px;color:#9ca3af;">...</div>',
|
|
2133
|
-
list: '<div class="aparte-skeleton-fallback" style="padding:16px;color:#9ca3af;">Loading items...</div>'
|
|
2134
|
-
};
|
|
2135
|
-
return fallbacks[type] || fallbacks.text;
|
|
2139
|
+
return APARTE_DEFAULT_SKELETON_FALLBACKS[type] ?? APARTE_DEFAULT_SKELETON_FALLBACKS.text;
|
|
2136
2140
|
}
|
|
2137
2141
|
}
|
|
2138
2142
|
const GLOBAL_CONFIG_KEY = Symbol.for("aparte.globalConfig.1");
|
|
@@ -2196,14 +2200,6 @@ function subscribeConfigChange(el2, handler) {
|
|
|
2196
2200
|
window.addEventListener(APARTE_CONFIG_CHANGE, listener);
|
|
2197
2201
|
return () => window.removeEventListener(APARTE_CONFIG_CHANGE, listener);
|
|
2198
2202
|
}
|
|
2199
|
-
const APARTE_DEFAULT_SKELETON_FALLBACKS = {
|
|
2200
|
-
message: '<div class="aparte-skeleton-fallback" style="padding:16px;color:#9ca3af;">Loading...</div>',
|
|
2201
|
-
code: '<div class="aparte-skeleton-fallback" style="padding:16px;background:#1e293b;color:#64748b;border-radius:8px;">Loading code...</div>',
|
|
2202
|
-
thinking: '<div class="aparte-skeleton-fallback" style="padding:8px;color:#9ca3af;">Thinking...</div>',
|
|
2203
|
-
input: '<div class="aparte-skeleton-fallback" style="padding:12px;color:#9ca3af;">...</div>',
|
|
2204
|
-
list: '<div class="aparte-skeleton-fallback" style="padding:16px;color:#9ca3af;">Loading items...</div>',
|
|
2205
|
-
text: '<div class="aparte-skeleton-fallback" style="padding:8px;color:#9ca3af;">...</div>'
|
|
2206
|
-
};
|
|
2207
2203
|
function writeStreamedMarkdown(host, contentEl, content, streaming) {
|
|
2208
2204
|
if (streaming) {
|
|
2209
2205
|
if (host._aparteSmd === void 0) {
|
|
@@ -2276,7 +2272,21 @@ const thinkingRenderer = {
|
|
|
2276
2272
|
* new class of risk. With no Markdown provider registered it degrades to the
|
|
2277
2273
|
* zero-dependency default (escape + `<br>`), which is what it used to be.
|
|
2278
2274
|
*/
|
|
2279
|
-
|
|
2275
|
+
/*
|
|
2276
|
+
* WEARS THE ACCORDION RECIPE. A reasoning block is a disclosure — `<details>`, a
|
|
2277
|
+
* `<summary>` you press, a panel, a chevron that turns — which is exactly what
|
|
2278
|
+
* `surface/accordion.css` already draws, and this renderer used to draw a second
|
|
2279
|
+
* time under four classes of its own. Two costs, both visible: it looked unrelated
|
|
2280
|
+
* to every other disclosure in the library, and its chevron was the CHARACTER `▼`,
|
|
2281
|
+
* a fourth way to draw a chevron here and the only one that is not a glyph — so it
|
|
2282
|
+
* could not take `--aparte-icon-size`, could not be replaced through the icon
|
|
2283
|
+
* provider, and rendered in whatever the platform font felt like.
|
|
2284
|
+
*
|
|
2285
|
+
* What stays thinking's own is the left rail and the quieter tone, which is the
|
|
2286
|
+
* only part that is genuinely about reasoning rather than about disclosure.
|
|
2287
|
+
* `.aparte-thinking-label` stays too: `relabel` below queries it.
|
|
2288
|
+
*/
|
|
2289
|
+
render: (segment) => `<details class="aparte-segment aparte-segment-thinking aparte-accordion__item" data-segment-id="${escapeHtml(segment.id)}" ${segment.collapsed === false ? "open" : ""}><summary class="aparte-accordion__header aparte-thinking-header"><span class="aparte-thinking-label">${escapeHtml(segment.label || contextConfig().t("thinking"))}</span>${contextConfig().getIcon("expand")}</summary><div class="aparte-accordion__panel aparte-thinking-content">${contextConfig().renderMarkdown(segment.content)}</div></details>`,
|
|
2280
2290
|
/**
|
|
2281
2291
|
* The default label is the only config-derived text here — and `segment.label`
|
|
2282
2292
|
* still wins, exactly as in `render`, because that string is the app's.
|
|
@@ -2350,7 +2360,7 @@ const codeRenderer = {
|
|
|
2350
2360
|
<div class="aparte-code-header">
|
|
2351
2361
|
${segment.filename ? `<span class="aparte-code-filename">${escapeHtml(segment.filename)}</span>` : `<span class="aparte-code-header-filler"></span>`}
|
|
2352
2362
|
<span class="aparte-code-language">${escapeHtml(segment.language || "")}</span>
|
|
2353
|
-
<button class="aparte-code-copy" data-action="copy" title="${escapeAttr(contextConfig().t("copy"))}">
|
|
2363
|
+
<button class="aparte-btn aparte-btn--icon aparte-btn--sm aparte-code-copy" data-action="copy" title="${escapeAttr(contextConfig().t("copy"))}">
|
|
2354
2364
|
${contextConfig().getIcon("copy")}
|
|
2355
2365
|
</button>
|
|
2356
2366
|
</div>
|
|
@@ -2419,7 +2429,7 @@ const errorRenderer = {
|
|
|
2419
2429
|
return out;
|
|
2420
2430
|
}
|
|
2421
2431
|
return `
|
|
2422
|
-
<div class="aparte-segment aparte-segment-error" data-segment-id="${escapeHtml(segment.id)}">
|
|
2432
|
+
<div class="aparte-segment aparte-alert aparte-alert--danger aparte-segment-error" data-segment-id="${escapeHtml(segment.id)}">
|
|
2423
2433
|
<div class="aparte-error-icon-wrapper">
|
|
2424
2434
|
${contextConfig().getIcon("error") || "⚠"}
|
|
2425
2435
|
</div>
|
|
@@ -2518,7 +2528,7 @@ function pillMarkup(segment, name, status) {
|
|
|
2518
2528
|
<span class="aparte-tool-icon">${contextConfig().getIcon("tool")}</span>
|
|
2519
2529
|
<span class="aparte-tool-name">${escapeHtml(name)}</span>
|
|
2520
2530
|
</span>
|
|
2521
|
-
<span class="aparte-tool-spinner" aria-hidden="true"${status === "pending" ? "" : " hidden"}></span>
|
|
2531
|
+
<span class="aparte-spinner aparte-tool-spinner" aria-hidden="true"${status === "pending" ? "" : " hidden"}></span>
|
|
2522
2532
|
<span class="aparte-tool-state">${badge}</span>`;
|
|
2523
2533
|
}
|
|
2524
2534
|
const toolCallRenderer = {
|
|
@@ -2533,6 +2543,7 @@ const toolCallRenderer = {
|
|
|
2533
2543
|
if (out) return out;
|
|
2534
2544
|
}
|
|
2535
2545
|
const pill = pillMarkup(segment, name, status);
|
|
2546
|
+
const toggle = contextConfig().getIcon("expand");
|
|
2536
2547
|
const input = describeInput(segment);
|
|
2537
2548
|
const result = segment.result;
|
|
2538
2549
|
if (!input && !result) {
|
|
@@ -2544,7 +2555,7 @@ const toolCallRenderer = {
|
|
|
2544
2555
|
const cfg = contextConfig();
|
|
2545
2556
|
return `
|
|
2546
2557
|
<details class="aparte-segment aparte-segment-tool-call" data-segment-id="${escapeHtml(segment.id)}" data-status="${escapeAttr(status)}" data-tool-call-id="${escapeAttr(toolCallId)}">
|
|
2547
|
-
<summary class="aparte-tool-summary"><span class="aparte-tool-toggle"
|
|
2558
|
+
<summary class="aparte-tool-summary"><span class="aparte-tool-toggle">${toggle}</span>${pill}</summary>
|
|
2548
2559
|
<div class="aparte-tool-detail">
|
|
2549
2560
|
${input ? `
|
|
2550
2561
|
<div class="aparte-tool-part" data-part="input">
|
|
@@ -2619,7 +2630,7 @@ const toolCallRenderer = {
|
|
|
2619
2630
|
const customRenderer = contextConfig().getToolRenderer(segment.toolCall?.name);
|
|
2620
2631
|
customRenderer?.setup?.(element, segment);
|
|
2621
2632
|
},
|
|
2622
|
-
// CSS lives in styles/
|
|
2633
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
2623
2634
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
2624
2635
|
// has no other way onto the page.
|
|
2625
2636
|
getStyles: () => ""
|
|
@@ -2630,9 +2641,9 @@ const pipelineWaitingRenderer = {
|
|
|
2630
2641
|
render: (segment) => {
|
|
2631
2642
|
return `
|
|
2632
2643
|
<div class="aparte-segment aparte-segment-pipeline-waiting" data-segment-id="${escapeHtml(segment.id)}" aria-label="${escapeAttr(waitingLabel())}" role="status">
|
|
2633
|
-
<span class="aparte-pw-dot"></span>
|
|
2634
|
-
<span class="aparte-pw-dot"></span>
|
|
2635
|
-
<span class="aparte-pw-dot"></span>
|
|
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>
|
|
2636
2647
|
</div>`;
|
|
2637
2648
|
},
|
|
2638
2649
|
update: () => {
|
|
@@ -2657,7 +2668,7 @@ const pipelineWaitingRenderer = {
|
|
|
2657
2668
|
});
|
|
2658
2669
|
observer.observe(parent, { childList: true });
|
|
2659
2670
|
},
|
|
2660
|
-
// CSS lives in styles/
|
|
2671
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
2661
2672
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
2662
2673
|
// has no other way onto the page.
|
|
2663
2674
|
getStyles: () => ""
|
|
@@ -2863,7 +2874,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2863
2874
|
if (cached && !isStreaming) {
|
|
2864
2875
|
const previewBody = cached.previewHtml ? contextConfig().sanitizeHtml(cached.previewHtml) : `<div class="aparte-art-file__preview-empty">Preview not available for ${escapeHtml(kind)} yet</div>`;
|
|
2865
2876
|
return `
|
|
2866
|
-
<div class="aparte-segment aparte-segment-artifact-file"
|
|
2877
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-file"
|
|
2867
2878
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
2868
2879
|
data-artifact-type="${escapeHtml(kind)}"
|
|
2869
2880
|
data-state="ready">
|
|
@@ -2874,7 +2885,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2874
2885
|
<div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(formatBytes(cached.bytes))} · ${escapeHtml(kind.toUpperCase())}</div>
|
|
2875
2886
|
</div>
|
|
2876
2887
|
<div class="aparte-art-file__actions">
|
|
2877
|
-
${canRedownload ? `<button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download">${downloadLabel}</button>` : ""}
|
|
2888
|
+
${canRedownload ? `<button type="button" class="aparte-btn aparte-btn--primary aparte-btn--solid aparte-art-file__btn aparte-art-file__btn--primary" data-action="download">${downloadLabel}</button>` : ""}
|
|
2878
2889
|
</div>
|
|
2879
2890
|
</div>
|
|
2880
2891
|
<div class="aparte-art-file__body">
|
|
@@ -2889,7 +2900,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2889
2900
|
const cleanContent = stripCodeFences(segment.content || "");
|
|
2890
2901
|
const subText = isStreaming ? contextConfig().t("generating") : contextConfig().t("rebuildingPreview");
|
|
2891
2902
|
return `
|
|
2892
|
-
<div class="aparte-segment aparte-segment-artifact-file"
|
|
2903
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-file"
|
|
2893
2904
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
2894
2905
|
data-artifact-type="${escapeHtml(kind)}"
|
|
2895
2906
|
data-state="${isStreaming ? "streaming" : "compiling"}">
|
|
@@ -2900,7 +2911,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2900
2911
|
<div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(subText)}</div>
|
|
2901
2912
|
</div>
|
|
2902
2913
|
<div class="aparte-art-file__actions">
|
|
2903
|
-
${canRedownload ? `<button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download" disabled>${downloadLabel}</button>` : ""}
|
|
2914
|
+
${canRedownload ? `<button type="button" class="aparte-btn aparte-btn--primary aparte-btn--solid aparte-art-file__btn aparte-art-file__btn--primary" data-action="download" disabled>${downloadLabel}</button>` : ""}
|
|
2904
2915
|
</div>
|
|
2905
2916
|
</div>
|
|
2906
2917
|
<div class="aparte-art-file__body">
|
|
@@ -3058,7 +3069,7 @@ function showSandboxError(element, phase, errorMsg) {
|
|
|
3058
3069
|
body.innerHTML = `
|
|
3059
3070
|
<div class="aparte-art-file__error">
|
|
3060
3071
|
<div class="aparte-art-file__error-title">${escapeHtml(contextConfig().t("sandboxError"))}</div>
|
|
3061
|
-
<div class="aparte-art-file__error-msg">${escapeHtml(short)}</div>
|
|
3072
|
+
<div class="aparte-output aparte-art-file__error-msg">${escapeHtml(short)}</div>
|
|
3062
3073
|
<div class="aparte-art-file__error-hint">${escapeHtml(contextConfig().t("sandboxErrorHint"))}</div>
|
|
3063
3074
|
</div>
|
|
3064
3075
|
`;
|
|
@@ -3083,8 +3094,9 @@ const artifactRenderer = {
|
|
|
3083
3094
|
const codeLabel = cfg.t("code");
|
|
3084
3095
|
const isBinary = BINARY_FILE_KINDS.has(kind);
|
|
3085
3096
|
const cleanContent = stripCodeFences(segment.content || "");
|
|
3097
|
+
const cardId = escapeAttr(segment.id);
|
|
3086
3098
|
return `
|
|
3087
|
-
<div class="aparte-segment aparte-segment-artifact-card"
|
|
3099
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-card"
|
|
3088
3100
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
3089
3101
|
data-artifact-type="${escapeHtml(kind)}"
|
|
3090
3102
|
data-streaming="${isStreaming ? "true" : "false"}"
|
|
@@ -3093,31 +3105,31 @@ const artifactRenderer = {
|
|
|
3093
3105
|
data-binary="${isBinary ? "true" : "false"}">
|
|
3094
3106
|
<header class="aparte-art-card__header">
|
|
3095
3107
|
<div class="aparte-art-card__title-block">
|
|
3096
|
-
<span class="aparte-art-card__kind" data-kind="${escapeHtml(kind)}">${escapeHtml(displayLang)}</span>
|
|
3108
|
+
<span class="aparte-badge aparte-badge--outline aparte-art-card__kind" data-kind="${escapeHtml(kind)}">${escapeHtml(displayLang)}</span>
|
|
3097
3109
|
<span class="aparte-art-card__title">${escapeHtml(title)}</span>
|
|
3098
|
-
${isStreaming ?
|
|
3110
|
+
${isStreaming ? `<span class="aparte-dot aparte-art-card__pulse" role="img" aria-label="${escapeAttr(cfg.t("generating"))}"></span>` : ""}
|
|
3099
3111
|
</div>
|
|
3100
3112
|
<div class="aparte-art-card__actions">
|
|
3101
|
-
<button type="button" class="aparte-art-card__btn" data-action="copy" title="${escapeAttr(contextConfig().t("copy"))}" aria-label="${escapeAttr(contextConfig().t("copy"))}">
|
|
3113
|
+
<button type="button" class="aparte-btn aparte-btn--icon aparte-art-card__btn" data-action="copy" title="${escapeAttr(contextConfig().t("copy"))}" aria-label="${escapeAttr(contextConfig().t("copy"))}">
|
|
3102
3114
|
${contextConfig().getIcon("copy")}
|
|
3103
3115
|
</button>
|
|
3104
|
-
<button type="button" class="aparte-art-card__btn" data-action="download" title="${escapeAttr(downloadLabel)}" aria-label="${escapeAttr(downloadLabel)}" ${isStreaming ? "disabled" : ""}>
|
|
3105
|
-
|
|
3116
|
+
<button type="button" class="aparte-btn aparte-btn--icon aparte-art-card__btn" data-action="download" title="${escapeAttr(downloadLabel)}" aria-label="${escapeAttr(downloadLabel)}" ${isStreaming ? "disabled" : ""}>
|
|
3117
|
+
${contextConfig().getIcon("download")}
|
|
3106
3118
|
</button>
|
|
3107
3119
|
</div>
|
|
3108
3120
|
</header>
|
|
3109
|
-
<nav class="aparte-art-card__tabs" role="tablist">
|
|
3110
|
-
<button type="button" role="tab"
|
|
3111
|
-
${previewable ? `<button type="button" role="tab"
|
|
3121
|
+
<nav class="aparte-tabs aparte-tabs--underline aparte-art-card__tabs" role="tablist">
|
|
3122
|
+
<button type="button" class="aparte-tabs__tab" role="tab" id="aparte-art-${cardId}-tab-code" aria-controls="aparte-art-${cardId}-pane-code" aria-selected="true" tabindex="0" data-tab-target="code">${escapeHtml(codeLabel)}</button>
|
|
3123
|
+
${previewable ? `<button type="button" class="aparte-tabs__tab" role="tab" id="aparte-art-${cardId}-tab-preview" aria-controls="aparte-art-${cardId}-pane-preview" aria-selected="false" tabindex="-1" data-tab-target="preview" ${isStreaming ? "disabled" : ""}>${escapeHtml(previewLabel)}</button>` : ""}
|
|
3112
3124
|
</nav>
|
|
3113
3125
|
<div class="aparte-art-card__body">
|
|
3114
|
-
<div class="aparte-art-card__pane" data-pane="code">
|
|
3126
|
+
<div class="aparte-art-card__pane" role="tabpanel" id="aparte-art-${cardId}-pane-code" aria-labelledby="aparte-art-${cardId}-tab-code" tabindex="0" data-pane="code">
|
|
3115
3127
|
<div class="aparte-code-content-wrapper">
|
|
3116
3128
|
<pre><code class="language-${escapeHtml(displayLang)}">${escapeHtml(cleanContent)}</code></pre>
|
|
3117
3129
|
</div>
|
|
3118
3130
|
</div>
|
|
3119
3131
|
${previewable ? `
|
|
3120
|
-
<div class="aparte-art-card__pane" data-pane="preview">
|
|
3132
|
+
<div class="aparte-art-card__pane" role="tabpanel" id="aparte-art-${cardId}-pane-preview" aria-labelledby="aparte-art-${cardId}-tab-preview" tabindex="0" data-pane="preview">
|
|
3121
3133
|
<div class="aparte-art-card__pending">${escapeHtml(cfg.t("previewPending"))}</div>
|
|
3122
3134
|
</div>
|
|
3123
3135
|
` : ""}
|
|
@@ -3172,17 +3184,38 @@ const artifactRenderer = {
|
|
|
3172
3184
|
}).catch(() => {
|
|
3173
3185
|
});
|
|
3174
3186
|
}
|
|
3175
|
-
element.querySelectorAll("[data-tab-target]")
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3187
|
+
const tabs = [...element.querySelectorAll("[data-tab-target]")];
|
|
3188
|
+
const select = (btn, focus) => {
|
|
3189
|
+
const target = btn.getAttribute("data-tab-target");
|
|
3190
|
+
if (!target || btn.disabled) return;
|
|
3191
|
+
if (target === "preview") mountPreviewFrame(element, segment);
|
|
3192
|
+
element.setAttribute("data-tab", target);
|
|
3193
|
+
for (const b of tabs) {
|
|
3194
|
+
const on = b === btn;
|
|
3195
|
+
b.setAttribute("aria-selected", on ? "true" : "false");
|
|
3196
|
+
b.tabIndex = on ? 0 : -1;
|
|
3197
|
+
}
|
|
3198
|
+
if (focus) btn.focus();
|
|
3199
|
+
};
|
|
3200
|
+
for (const [i, btn] of tabs.entries()) {
|
|
3201
|
+
btn.addEventListener("click", () => select(btn, false));
|
|
3202
|
+
btn.addEventListener("keydown", (e) => {
|
|
3203
|
+
const step = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
|
|
3204
|
+
let next = -1;
|
|
3205
|
+
if (step) next = (i + step + tabs.length) % tabs.length;
|
|
3206
|
+
else if (e.key === "Home") next = 0;
|
|
3207
|
+
else if (e.key === "End") next = tabs.length - 1;
|
|
3208
|
+
if (next < 0) return;
|
|
3209
|
+
e.preventDefault();
|
|
3210
|
+
for (let n = 0; n < tabs.length; n++) {
|
|
3211
|
+
const candidate = tabs[(next + n * (step || 1) + tabs.length) % tabs.length];
|
|
3212
|
+
if (candidate && !candidate.disabled) {
|
|
3213
|
+
select(candidate, true);
|
|
3214
|
+
return;
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3184
3217
|
});
|
|
3185
|
-
}
|
|
3218
|
+
}
|
|
3186
3219
|
const copyBtn = element.querySelector('[data-action="copy"]');
|
|
3187
3220
|
if (copyBtn) {
|
|
3188
3221
|
copyBtn.addEventListener("click", () => {
|
|
@@ -3267,7 +3300,7 @@ const artifactRenderer = {
|
|
|
3267
3300
|
});
|
|
3268
3301
|
}
|
|
3269
3302
|
},
|
|
3270
|
-
// CSS lives in styles/
|
|
3303
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
3271
3304
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
3272
3305
|
// has no other way onto the page.
|
|
3273
3306
|
getStyles: () => ""
|
|
@@ -5269,6 +5302,7 @@ function readableToAsyncIterable(stream, signal) {
|
|
|
5269
5302
|
}
|
|
5270
5303
|
};
|
|
5271
5304
|
}
|
|
5305
|
+
let steppedPanelSeq = 0;
|
|
5272
5306
|
let _relabels = null;
|
|
5273
5307
|
function onRelabel(fn) {
|
|
5274
5308
|
_relabels?.push(fn);
|
|
@@ -5279,6 +5313,18 @@ function el$1(tag, className, text) {
|
|
|
5279
5313
|
if (text != null) node.textContent = text;
|
|
5280
5314
|
return node;
|
|
5281
5315
|
}
|
|
5316
|
+
function optionBody(label, description) {
|
|
5317
|
+
const body = el$1("span", "aparte-elic-option-body");
|
|
5318
|
+
body.appendChild(el$1("span", "aparte-elic-option-title", label));
|
|
5319
|
+
if (description) body.appendChild(el$1("span", "aparte-elic-option-desc", description));
|
|
5320
|
+
return body;
|
|
5321
|
+
}
|
|
5322
|
+
function commandOption(label, description, recommended) {
|
|
5323
|
+
const button = el$1("button", "aparte-btn aparte-btn--block aparte-btn--surface aparte-elic-option aparte-elic-option--command" + (recommended ? " aparte-elic-option--recommended" : ""));
|
|
5324
|
+
button.type = "button";
|
|
5325
|
+
button.appendChild(optionBody(label, description));
|
|
5326
|
+
return button;
|
|
5327
|
+
}
|
|
5282
5328
|
function fieldHeader(parent, field, skipTitle) {
|
|
5283
5329
|
let titleId;
|
|
5284
5330
|
if (field.title && field.title.trim() !== skipTitle?.trim()) {
|
|
@@ -5291,61 +5337,87 @@ function fieldHeader(parent, field, skipTitle) {
|
|
|
5291
5337
|
return titleId;
|
|
5292
5338
|
}
|
|
5293
5339
|
function labelGroup(list, opts) {
|
|
5294
|
-
list.setAttribute("role", opts.multiple ? "group" : "radiogroup");
|
|
5340
|
+
list.setAttribute("role", opts.multiple || opts.commands ? "group" : "radiogroup");
|
|
5295
5341
|
if (opts.titleId) list.setAttribute("aria-labelledby", opts.titleId);
|
|
5296
5342
|
else if (opts.fallbackLabel) list.setAttribute("aria-label", opts.fallbackLabel);
|
|
5297
5343
|
}
|
|
5298
|
-
function buildEnumField(field, onChange, fallbackLabel) {
|
|
5344
|
+
function buildEnumField(field, onChange, fallbackLabel, settle) {
|
|
5299
5345
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-enum");
|
|
5300
5346
|
const titleId = fieldHeader(wrap, field, fallbackLabel);
|
|
5301
5347
|
const list = el$1("div", "aparte-elic-options");
|
|
5302
|
-
labelGroup(list, { multiple: field.multiple, titleId, fallbackLabel });
|
|
5303
5348
|
const name = `elic-${uuid()}`;
|
|
5304
5349
|
const type = field.multiple ? "checkbox" : "radio";
|
|
5350
|
+
const controlRecipe = type === "checkbox" ? "aparte-checkbox" : "aparte-radio";
|
|
5305
5351
|
const allowOther = field.allowOther ?? contextConfig().getElicitationOptions().allowOther;
|
|
5306
5352
|
const defaults = new Set(Array.isArray(field.default) ? field.default : field.default != null ? [field.default] : []);
|
|
5353
|
+
const settling = settle != null && !field.multiple && defaults.size === 0;
|
|
5354
|
+
labelGroup(list, { multiple: field.multiple, commands: settling, titleId, fallbackLabel });
|
|
5307
5355
|
const buildOption = (value, label, description, recommended) => {
|
|
5308
|
-
|
|
5309
|
-
|
|
5356
|
+
if (settling) {
|
|
5357
|
+
const button = commandOption(label, description, recommended);
|
|
5358
|
+
button.addEventListener("click", () => settle?.(value));
|
|
5359
|
+
return button;
|
|
5360
|
+
}
|
|
5361
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option" + (recommended ? " aparte-elic-option--recommended" : ""));
|
|
5362
|
+
const control = el$1("input", controlRecipe + " aparte-elic-control");
|
|
5310
5363
|
control.type = type;
|
|
5311
5364
|
control.name = name;
|
|
5312
5365
|
control.value = value;
|
|
5313
5366
|
if (defaults.has(value)) control.checked = true;
|
|
5314
|
-
|
|
5315
|
-
body.appendChild(el$1("span", "aparte-elic-option-title", label));
|
|
5316
|
-
if (description) body.appendChild(el$1("span", "aparte-elic-option-desc", description));
|
|
5317
|
-
row.append(control, body);
|
|
5367
|
+
row.append(control, optionBody(label, description));
|
|
5318
5368
|
return row;
|
|
5319
5369
|
};
|
|
5320
5370
|
for (const opt of field.options) {
|
|
5321
5371
|
list.appendChild(buildOption(opt.value, opt.label ?? opt.value, opt.description, opt.recommended));
|
|
5322
5372
|
}
|
|
5323
5373
|
let otherText = null;
|
|
5374
|
+
let otherOpen = false;
|
|
5324
5375
|
if (allowOther) {
|
|
5325
|
-
const row = el$1("label", "aparte-elic-option aparte-elic-option--other");
|
|
5326
|
-
const control = el$1("input", "aparte-elic-control");
|
|
5327
|
-
control.type = type;
|
|
5328
|
-
control.name = name;
|
|
5329
|
-
control.value = "__other__";
|
|
5330
|
-
const body = el$1("span", "aparte-elic-option-body");
|
|
5331
5376
|
const t = contextConfig();
|
|
5332
|
-
|
|
5333
|
-
body.appendChild(otherTitle);
|
|
5334
|
-
otherText = el$1("input", "aparte-elic-other-input");
|
|
5377
|
+
otherText = el$1("input", "aparte-field aparte-elic-other-input");
|
|
5335
5378
|
otherText.type = "text";
|
|
5336
5379
|
otherText.placeholder = t.t("elicitationOtherPlaceholder");
|
|
5337
5380
|
otherText.style.display = "none";
|
|
5338
5381
|
otherText.setAttribute("aria-label", t.t("elicitationOtherLabel"));
|
|
5339
5382
|
const otherInput = otherText;
|
|
5340
|
-
|
|
5341
|
-
const
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5383
|
+
if (settling) {
|
|
5384
|
+
const button = commandOption(t.t("elicitationOther"));
|
|
5385
|
+
button.classList.add("aparte-elic-option--other");
|
|
5386
|
+
button.setAttribute("aria-expanded", "false");
|
|
5387
|
+
button.addEventListener("click", () => {
|
|
5388
|
+
otherOpen = true;
|
|
5389
|
+
button.setAttribute("aria-expanded", "true");
|
|
5390
|
+
otherInput.style.display = "";
|
|
5391
|
+
otherInput.focus();
|
|
5392
|
+
onChange();
|
|
5393
|
+
});
|
|
5394
|
+
const otherTitle = button.querySelector(".aparte-elic-option-title");
|
|
5395
|
+
onRelabel(() => {
|
|
5396
|
+
const now = contextConfig();
|
|
5397
|
+
otherTitle.textContent = now.t("elicitationOther");
|
|
5398
|
+
otherInput.placeholder = now.t("elicitationOtherPlaceholder");
|
|
5399
|
+
otherInput.setAttribute("aria-label", now.t("elicitationOtherLabel"));
|
|
5400
|
+
});
|
|
5401
|
+
list.append(button, otherInput);
|
|
5402
|
+
} else {
|
|
5403
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option aparte-elic-option--other");
|
|
5404
|
+
const control = el$1("input", controlRecipe + " aparte-elic-control");
|
|
5405
|
+
control.type = type;
|
|
5406
|
+
control.name = name;
|
|
5407
|
+
control.value = "__other__";
|
|
5408
|
+
const body = el$1("span", "aparte-elic-option-body");
|
|
5409
|
+
const otherTitle = el$1("span", "aparte-elic-option-title", t.t("elicitationOther"));
|
|
5410
|
+
body.appendChild(otherTitle);
|
|
5411
|
+
onRelabel(() => {
|
|
5412
|
+
const now = contextConfig();
|
|
5413
|
+
otherTitle.textContent = now.t("elicitationOther");
|
|
5414
|
+
otherInput.placeholder = now.t("elicitationOtherPlaceholder");
|
|
5415
|
+
otherInput.setAttribute("aria-label", now.t("elicitationOtherLabel"));
|
|
5416
|
+
});
|
|
5417
|
+
body.appendChild(otherText);
|
|
5418
|
+
row.append(control, body);
|
|
5419
|
+
list.appendChild(row);
|
|
5420
|
+
}
|
|
5349
5421
|
}
|
|
5350
5422
|
wrap.appendChild(list);
|
|
5351
5423
|
const controls = () => Array.from(list.querySelectorAll(".aparte-elic-control"));
|
|
@@ -5359,8 +5431,18 @@ function buildEnumField(field, onChange, fallbackLabel) {
|
|
|
5359
5431
|
onChange();
|
|
5360
5432
|
});
|
|
5361
5433
|
otherText?.addEventListener("input", onChange);
|
|
5434
|
+
const typedOther = () => otherText?.value.trim() ?? "";
|
|
5435
|
+
if (settling) {
|
|
5436
|
+
return {
|
|
5437
|
+
el: wrap,
|
|
5438
|
+
getValue: () => typedOther(),
|
|
5439
|
+
isComplete: () => otherOpen && typedOther() !== "",
|
|
5440
|
+
focus: () => list.querySelector(".aparte-elic-option--command")?.focus(),
|
|
5441
|
+
offersSubmit: () => otherOpen
|
|
5442
|
+
};
|
|
5443
|
+
}
|
|
5362
5444
|
const getValue = () => {
|
|
5363
|
-
const otherVal = other()?.checked &&
|
|
5445
|
+
const otherVal = other()?.checked && typedOther() ? typedOther() : "";
|
|
5364
5446
|
if (field.multiple) {
|
|
5365
5447
|
const vals = controls().filter((c) => c.checked && c.value !== "__other__").map((c) => c.value);
|
|
5366
5448
|
if (otherVal) vals.push(otherVal);
|
|
@@ -5380,15 +5462,42 @@ function buildEnumField(field, onChange, fallbackLabel) {
|
|
|
5380
5462
|
focus: () => controls()[0]?.focus()
|
|
5381
5463
|
};
|
|
5382
5464
|
}
|
|
5383
|
-
function buildBooleanField(field, onChange, fallbackLabel) {
|
|
5465
|
+
function buildBooleanField(field, onChange, fallbackLabel, settle) {
|
|
5384
5466
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-boolean");
|
|
5385
5467
|
const titleId = fieldHeader(wrap, field, fallbackLabel);
|
|
5386
5468
|
const list = el$1("div", "aparte-elic-options");
|
|
5387
|
-
labelGroup(list, { titleId, fallbackLabel });
|
|
5388
5469
|
const name = `elic-${uuid()}`;
|
|
5470
|
+
const settling = settle != null && field.default == null;
|
|
5471
|
+
labelGroup(list, { commands: settling, titleId, fallbackLabel });
|
|
5472
|
+
if (settling) {
|
|
5473
|
+
const t2 = contextConfig();
|
|
5474
|
+
const mkCommand = (val, label, defaulted) => {
|
|
5475
|
+
const button = commandOption(label);
|
|
5476
|
+
button.addEventListener("click", () => settle?.(val));
|
|
5477
|
+
if (defaulted) {
|
|
5478
|
+
const title = button.querySelector(".aparte-elic-option-title");
|
|
5479
|
+
onRelabel(() => {
|
|
5480
|
+
title.textContent = contextConfig().t(defaulted);
|
|
5481
|
+
});
|
|
5482
|
+
}
|
|
5483
|
+
list.appendChild(button);
|
|
5484
|
+
};
|
|
5485
|
+
mkCommand(true, field.trueLabel ?? t2.t("elicitationYes"), field.trueLabel ? void 0 : "elicitationYes");
|
|
5486
|
+
mkCommand(false, field.falseLabel ?? t2.t("elicitationNo"), field.falseLabel ? void 0 : "elicitationNo");
|
|
5487
|
+
wrap.appendChild(list);
|
|
5488
|
+
return {
|
|
5489
|
+
el: wrap,
|
|
5490
|
+
// Never read: the click settles, so nothing downstream asks this shape for
|
|
5491
|
+
// a value. `false` rather than a throw keeps the field total.
|
|
5492
|
+
getValue: () => false,
|
|
5493
|
+
isComplete: () => false,
|
|
5494
|
+
focus: () => list.querySelector(".aparte-elic-option--command")?.focus(),
|
|
5495
|
+
offersSubmit: () => false
|
|
5496
|
+
};
|
|
5497
|
+
}
|
|
5389
5498
|
const mk = (val, label, defaulted) => {
|
|
5390
|
-
const row = el$1("label", "aparte-elic-option");
|
|
5391
|
-
const control = el$1("input", "aparte-elic-control");
|
|
5499
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option");
|
|
5500
|
+
const control = el$1("input", "aparte-radio aparte-elic-control");
|
|
5392
5501
|
control.type = "radio";
|
|
5393
5502
|
control.name = name;
|
|
5394
5503
|
control.value = val;
|
|
@@ -5418,7 +5527,7 @@ function buildBooleanField(field, onChange, fallbackLabel) {
|
|
|
5418
5527
|
function buildStringField(field, onChange, fallbackLabel) {
|
|
5419
5528
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-string");
|
|
5420
5529
|
fieldHeader(wrap, field, fallbackLabel);
|
|
5421
|
-
const input = field.multiline ? el$1("textarea", "aparte-elic-text") : el$1("input", "aparte-elic-text");
|
|
5530
|
+
const input = field.multiline ? el$1("textarea", "aparte-field aparte-field--textarea aparte-elic-text") : el$1("input", "aparte-field aparte-elic-text");
|
|
5422
5531
|
if (!field.multiline) input.type = "text";
|
|
5423
5532
|
if (field.placeholder) input.setAttribute("placeholder", field.placeholder);
|
|
5424
5533
|
if (field.default) input.value = field.default;
|
|
@@ -5446,7 +5555,7 @@ function buildStringField(field, onChange, fallbackLabel) {
|
|
|
5446
5555
|
focus: () => input.focus()
|
|
5447
5556
|
};
|
|
5448
5557
|
}
|
|
5449
|
-
function buildField(field, onChange, fallbackLabel, key) {
|
|
5558
|
+
function buildField(field, onChange, fallbackLabel, key, settle) {
|
|
5450
5559
|
const custom = contextConfig().getElicitationFieldRenderer()?.(field, { key, notifyChange: onChange });
|
|
5451
5560
|
if (custom) {
|
|
5452
5561
|
return {
|
|
@@ -5458,9 +5567,10 @@ function buildField(field, onChange, fallbackLabel, key) {
|
|
|
5458
5567
|
}
|
|
5459
5568
|
switch (field.type) {
|
|
5460
5569
|
case "enum":
|
|
5461
|
-
return buildEnumField(field, onChange, fallbackLabel);
|
|
5570
|
+
return buildEnumField(field, onChange, fallbackLabel, settle);
|
|
5462
5571
|
case "boolean":
|
|
5463
|
-
return buildBooleanField(field, onChange, fallbackLabel);
|
|
5572
|
+
return buildBooleanField(field, onChange, fallbackLabel, settle);
|
|
5573
|
+
// No `settle`: text is written, not chosen, so it always needs a commit.
|
|
5464
5574
|
case "string":
|
|
5465
5575
|
return buildStringField(field, onChange, fallbackLabel);
|
|
5466
5576
|
}
|
|
@@ -5482,6 +5592,16 @@ function buildPanel(message, schema, onChange) {
|
|
|
5482
5592
|
const panel = el$1("div", "aparte-elic-panel");
|
|
5483
5593
|
const asked = typeof message === "function" ? message() : message;
|
|
5484
5594
|
if (asked) panel.appendChild(el$1("p", "aparte-elic-message", asked));
|
|
5595
|
+
let settleCb = null;
|
|
5596
|
+
let settled = false;
|
|
5597
|
+
const settle = (content) => {
|
|
5598
|
+
if (settled) return;
|
|
5599
|
+
settled = true;
|
|
5600
|
+
settleCb?.(content);
|
|
5601
|
+
};
|
|
5602
|
+
const onSettle = (cb) => {
|
|
5603
|
+
settleCb = cb;
|
|
5604
|
+
};
|
|
5485
5605
|
const body = el$1("div", "aparte-elic-body");
|
|
5486
5606
|
panel.appendChild(body);
|
|
5487
5607
|
const dismiss = el$1("div", "aparte-elic-dismiss");
|
|
@@ -5522,15 +5642,20 @@ function buildPanel(message, schema, onChange) {
|
|
|
5522
5642
|
mode: () => "submit",
|
|
5523
5643
|
canProceed: isComplete,
|
|
5524
5644
|
proceed: () => {
|
|
5525
|
-
}
|
|
5645
|
+
},
|
|
5646
|
+
// A form never settles from inside: its questions are collected and
|
|
5647
|
+
// submitted together, and answering the last one on the click would be
|
|
5648
|
+
// WCAG's F36 word for word. Registered so the shape is total; never fired.
|
|
5649
|
+
onSettle
|
|
5526
5650
|
};
|
|
5527
5651
|
if (fields.length < 2 || cfg.getElicitationOptions().layout !== "stepped") return api;
|
|
5528
5652
|
panel.classList.add("aparte-elic-panel--stepped");
|
|
5529
5653
|
let current = 0;
|
|
5530
|
-
const
|
|
5654
|
+
const scope = `aparte-elic-${++steppedPanelSeq}`;
|
|
5655
|
+
const steps = el$1("div", "aparte-tabs aparte-tabs--underline aparte-elic-steps");
|
|
5531
5656
|
steps.setAttribute("role", "tablist");
|
|
5532
5657
|
const chips = fields.map((f, i) => {
|
|
5533
|
-
const chip = el$1("button", "aparte-elic-step");
|
|
5658
|
+
const chip = el$1("button", "aparte-tabs__tab aparte-elic-step");
|
|
5534
5659
|
chip.type = "button";
|
|
5535
5660
|
chip.setAttribute("role", "tab");
|
|
5536
5661
|
chip.textContent = f.header?.trim() || String(i + 1);
|
|
@@ -5538,6 +5663,22 @@ function buildPanel(message, schema, onChange) {
|
|
|
5538
5663
|
show(i);
|
|
5539
5664
|
f.field.focus();
|
|
5540
5665
|
});
|
|
5666
|
+
chip.id = `${scope}-tab-${i}`;
|
|
5667
|
+
f.field.el.id = `${scope}-panel-${i}`;
|
|
5668
|
+
f.field.el.setAttribute("role", "tabpanel");
|
|
5669
|
+
f.field.el.setAttribute("aria-labelledby", chip.id);
|
|
5670
|
+
chip.setAttribute("aria-controls", f.field.el.id);
|
|
5671
|
+
chip.addEventListener("keydown", (e) => {
|
|
5672
|
+
const step = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
|
|
5673
|
+
let next = -1;
|
|
5674
|
+
if (step) next = (i + step + fields.length) % fields.length;
|
|
5675
|
+
else if (e.key === "Home") next = 0;
|
|
5676
|
+
else if (e.key === "End") next = fields.length - 1;
|
|
5677
|
+
if (next < 0) return;
|
|
5678
|
+
e.preventDefault();
|
|
5679
|
+
show(next);
|
|
5680
|
+
chips[next]?.focus();
|
|
5681
|
+
});
|
|
5541
5682
|
steps.appendChild(chip);
|
|
5542
5683
|
return chip;
|
|
5543
5684
|
});
|
|
@@ -5545,6 +5686,7 @@ function buildPanel(message, schema, onChange) {
|
|
|
5545
5686
|
syncNav = () => {
|
|
5546
5687
|
chips.forEach((chip, i) => {
|
|
5547
5688
|
chip.setAttribute("aria-selected", String(i === current));
|
|
5689
|
+
chip.tabIndex = i === current ? 0 : -1;
|
|
5548
5690
|
chip.toggleAttribute("data-answered", fields[i].field.isComplete());
|
|
5549
5691
|
});
|
|
5550
5692
|
};
|
|
@@ -5565,7 +5707,7 @@ function buildPanel(message, schema, onChange) {
|
|
|
5565
5707
|
}
|
|
5566
5708
|
};
|
|
5567
5709
|
}
|
|
5568
|
-
const field = buildField(schema, onChange, asked);
|
|
5710
|
+
const field = buildField(schema, onChange, asked, void 0, settle);
|
|
5569
5711
|
body.appendChild(field.el);
|
|
5570
5712
|
return {
|
|
5571
5713
|
el: panel,
|
|
@@ -5573,10 +5715,11 @@ function buildPanel(message, schema, onChange) {
|
|
|
5573
5715
|
getContent: () => field.getValue(),
|
|
5574
5716
|
isComplete: () => field.isComplete(),
|
|
5575
5717
|
focus: () => field.focus(),
|
|
5576
|
-
mode: () => "submit",
|
|
5718
|
+
mode: () => field.offersSubmit?.() ?? true ? "submit" : "none",
|
|
5577
5719
|
canProceed: () => field.isComplete(),
|
|
5578
5720
|
proceed: () => {
|
|
5579
|
-
}
|
|
5721
|
+
},
|
|
5722
|
+
onSettle
|
|
5580
5723
|
};
|
|
5581
5724
|
}
|
|
5582
5725
|
function el(tag, className, text) {
|
|
@@ -5606,7 +5749,8 @@ function buildApprovalPanel(message, options, onChange) {
|
|
|
5606
5749
|
const labelled = [];
|
|
5607
5750
|
const textOf = (option) => typeof option.label === "function" ? option.label() : option.label;
|
|
5608
5751
|
for (const option of options) {
|
|
5609
|
-
const
|
|
5752
|
+
const tone = option.tone ?? "affirm";
|
|
5753
|
+
const button = el("button", `aparte-btn aparte-btn--block aparte-btn--surface aparte-approval-option aparte-approval-option--${tone}`);
|
|
5610
5754
|
button.type = "button";
|
|
5611
5755
|
button.textContent = textOf(option);
|
|
5612
5756
|
button.addEventListener("click", () => fire({ option: option.value }));
|
|
@@ -5710,6 +5854,27 @@ class AparteClient {
|
|
|
5710
5854
|
}
|
|
5711
5855
|
this._setupListeners();
|
|
5712
5856
|
}
|
|
5857
|
+
/**
|
|
5858
|
+
* What every fresh user action does before it starts a turn.
|
|
5859
|
+
*
|
|
5860
|
+
* Clearing the abort flag has to happen at the START of the action rather than inside
|
|
5861
|
+
* `_streamTurn`, which runs after the auth and file-reading awaits — a reset there
|
|
5862
|
+
* erased an abort that arrived while the user was still waiting for a large attachment
|
|
5863
|
+
* to be read.
|
|
5864
|
+
*
|
|
5865
|
+
* Cancelling the previous turn's tool controllers used to happen only on `aparte-send`.
|
|
5866
|
+
* Retry and edit reset the flag and left them running, so a tool handler from the turn
|
|
5867
|
+
* being superseded stayed alive — with its timeout still counting — while its reply was
|
|
5868
|
+
* already off the active path. A cold audit found the asymmetry; three callers, one
|
|
5869
|
+
* rule, no third copy to fall out of step.
|
|
5870
|
+
*/
|
|
5871
|
+
_beginUserTurn() {
|
|
5872
|
+
this._isAborted = false;
|
|
5873
|
+
for (const controller of this._activeToolControllers) {
|
|
5874
|
+
controller.abort();
|
|
5875
|
+
}
|
|
5876
|
+
this._activeToolControllers.clear();
|
|
5877
|
+
}
|
|
5713
5878
|
/**
|
|
5714
5879
|
* Sets up the event listeners.
|
|
5715
5880
|
* This is called once in the constructor.
|
|
@@ -5720,11 +5885,7 @@ class AparteClient {
|
|
|
5720
5885
|
const event = e;
|
|
5721
5886
|
if (event.type !== "aparte-send") return;
|
|
5722
5887
|
if (!this._isForThisInstance(event)) return;
|
|
5723
|
-
this.
|
|
5724
|
-
for (const controller of this._activeToolControllers) {
|
|
5725
|
-
controller.abort();
|
|
5726
|
-
}
|
|
5727
|
-
this._activeToolControllers.clear();
|
|
5888
|
+
this._beginUserTurn();
|
|
5728
5889
|
void this._handleSend(event);
|
|
5729
5890
|
};
|
|
5730
5891
|
}
|
|
@@ -6074,7 +6235,7 @@ ${summary}`,
|
|
|
6074
6235
|
}
|
|
6075
6236
|
async _handleRetry(event) {
|
|
6076
6237
|
const { messageId, targetId } = event.detail ?? {};
|
|
6077
|
-
this.
|
|
6238
|
+
this._beginUserTurn();
|
|
6078
6239
|
if (!messageId) return;
|
|
6079
6240
|
const targetElement = this._resolveTarget(targetId);
|
|
6080
6241
|
if (!targetElement) {
|
|
@@ -6101,9 +6262,7 @@ ${summary}`,
|
|
|
6101
6262
|
if (!provider) return;
|
|
6102
6263
|
const authConfig = await this._resolveAuth(providerId);
|
|
6103
6264
|
const chatMessages = this._messagesToChatMessages(historyMessages);
|
|
6104
|
-
const systemMessages =
|
|
6105
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6106
|
-
if (userSystemPrompt) systemMessages.push({ role: "system", content: userSystemPrompt });
|
|
6265
|
+
const systemMessages = this._systemMessages();
|
|
6107
6266
|
await this._streamTurn(
|
|
6108
6267
|
targetElement,
|
|
6109
6268
|
newMessageId,
|
|
@@ -6114,13 +6273,30 @@ ${summary}`,
|
|
|
6114
6273
|
{ temperature: 0.4 }
|
|
6115
6274
|
);
|
|
6116
6275
|
}
|
|
6276
|
+
/**
|
|
6277
|
+
* The system messages a turn opens with: the app's own template, then the registered
|
|
6278
|
+
* tools' `systemPrompt`s.
|
|
6279
|
+
*
|
|
6280
|
+
* A helper rather than three copies. The two lines it replaces were written out at each
|
|
6281
|
+
* of the three turn entry points (send, retry, edit), which is exactly how the tool half
|
|
6282
|
+
* would have been added to two of them and forgotten in the third — the same shape as
|
|
6283
|
+
* the abort-flag asymmetry `_beginUserTurn` exists to prevent.
|
|
6284
|
+
*/
|
|
6285
|
+
_systemMessages() {
|
|
6286
|
+
const messages = [];
|
|
6287
|
+
const appPrompt = this._config.resolveSystemPrompt();
|
|
6288
|
+
if (appPrompt) messages.push({ role: "system", content: appPrompt });
|
|
6289
|
+
const toolPrompts = this._config.resolveToolSystemPrompts();
|
|
6290
|
+
if (toolPrompts) messages.push({ role: "system", content: toolPrompts });
|
|
6291
|
+
return messages;
|
|
6292
|
+
}
|
|
6117
6293
|
/**
|
|
6118
6294
|
* Handle aparte-edit — update the user message in place, truncate all subsequent
|
|
6119
6295
|
* messages, then re-stream a fresh assistant response.
|
|
6120
6296
|
*/
|
|
6121
6297
|
async _handleEdit(event) {
|
|
6122
6298
|
const { messageId, content: newContent, targetId } = event.detail ?? {};
|
|
6123
|
-
this.
|
|
6299
|
+
this._beginUserTurn();
|
|
6124
6300
|
if (!messageId || newContent === void 0) return;
|
|
6125
6301
|
const targetElement = this._resolveTarget(targetId);
|
|
6126
6302
|
if (!targetElement) {
|
|
@@ -6140,9 +6316,7 @@ ${summary}`,
|
|
|
6140
6316
|
}
|
|
6141
6317
|
const historyMessages = editIdx >= 0 ? allMessages.slice(0, editIdx + 1) : allMessages;
|
|
6142
6318
|
const chatMessages = this._messagesToChatMessages(historyMessages);
|
|
6143
|
-
const systemMessages =
|
|
6144
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6145
|
-
if (userSystemPrompt) systemMessages.push({ role: "system", content: userSystemPrompt });
|
|
6319
|
+
const systemMessages = this._systemMessages();
|
|
6146
6320
|
const config = this._config.getModelConfig();
|
|
6147
6321
|
const providerId = config.defaultProvider;
|
|
6148
6322
|
if (!providerId) return;
|
|
@@ -6311,11 +6485,7 @@ ${summary}`,
|
|
|
6311
6485
|
* Build the initial messages array, prepending system prompts and conversation history.
|
|
6312
6486
|
*/
|
|
6313
6487
|
_buildMessages(userContent, target, parts) {
|
|
6314
|
-
const messages =
|
|
6315
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6316
|
-
if (userSystemPrompt) {
|
|
6317
|
-
messages.push({ role: "system", content: userSystemPrompt });
|
|
6318
|
-
}
|
|
6488
|
+
const messages = this._systemMessages();
|
|
6319
6489
|
const historyOption = this.options.history ?? "viewport";
|
|
6320
6490
|
const viewportMessages = target?.getMessages?.() ?? [];
|
|
6321
6491
|
if (historyOption === "viewport") {
|
|
@@ -6771,6 +6941,21 @@ ${content}
|
|
|
6771
6941
|
...wholeParser.parse(response).segments,
|
|
6772
6942
|
...wholeParser.finalize()
|
|
6773
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
|
+
}
|
|
6774
6959
|
if (parsed.length > 0) {
|
|
6775
6960
|
for (const segment of parsed) targetElement.addSegment?.(segment);
|
|
6776
6961
|
this._updateMessage(targetElement, messageId, { status: "completed" });
|
|
@@ -7107,7 +7292,7 @@ ${content}
|
|
|
7107
7292
|
details: error.code
|
|
7108
7293
|
};
|
|
7109
7294
|
if (target.updateMessage) {
|
|
7110
|
-
const rendered = target.getMessages?.()?.find((m) => m.id === messageId)?.segments ?? [];
|
|
7295
|
+
const rendered = target.getMessage?.(messageId)?.segments ?? target.getMessages?.()?.find((m) => m.id === messageId)?.segments ?? [];
|
|
7111
7296
|
target.updateMessage(messageId, {
|
|
7112
7297
|
status: "error",
|
|
7113
7298
|
segments: [...rendered, errorSegment]
|
|
@@ -7464,13 +7649,14 @@ export {
|
|
|
7464
7649
|
unregisterSegmentRenderer as a5,
|
|
7465
7650
|
uuid as a6,
|
|
7466
7651
|
mergeSegmentUpdate as a7,
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7652
|
+
writeStreamedMarkdown as a8,
|
|
7653
|
+
stampSegmentActivity as a9,
|
|
7654
|
+
stampSegmentOnInsert as aa,
|
|
7655
|
+
stampSegmentOnUpdate as ab,
|
|
7656
|
+
renumberSegments as ac,
|
|
7657
|
+
openSegmentIds as ad,
|
|
7658
|
+
isTerminalStatus as ae,
|
|
7659
|
+
adoptMessageSegments as af,
|
|
7474
7660
|
APARTE_DEFAULT_BUBBLE_ACTIONS as b,
|
|
7475
7661
|
APARTE_DEFAULT_HOST_HANDLERS as c,
|
|
7476
7662
|
APARTE_DEFAULT_ICON_FALLBACKS as d,
|
|
@@ -7497,4 +7683,4 @@ export {
|
|
|
7497
7683
|
buildElicitationPanel as y,
|
|
7498
7684
|
collectRendererStyles as z
|
|
7499
7685
|
};
|
|
7500
|
-
//# sourceMappingURL=is-awaiting-reply-
|
|
7686
|
+
//# sourceMappingURL=is-awaiting-reply-DrO_oR32.js.map
|