@aparte/core 0.12.1 → 0.13.1
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/client/stream-adapter.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 +80 -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 +7372 -5219
- 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 +5109 -2121
- package/dist/index.d.ts +37 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +184 -68
- 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-CWp1ffHh.js} +347 -171
- package/dist/is-awaiting-reply-CWp1ffHh.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/segment-renderers.d.ts +18 -0
- package/dist/renderers/segment-renderers.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 = {
|
|
@@ -2529,10 +2539,12 @@ const toolCallRenderer = {
|
|
|
2529
2539
|
const toolCallId = segment.toolCall?.id ?? "";
|
|
2530
2540
|
const customRenderer = contextConfig().getToolRenderer(segment.toolCall?.name);
|
|
2531
2541
|
if (customRenderer) {
|
|
2542
|
+
injectToolRendererStyles(segment.toolCall?.name ?? "", customRenderer);
|
|
2532
2543
|
const out = customRenderer.render(segment);
|
|
2533
2544
|
if (out) return out;
|
|
2534
2545
|
}
|
|
2535
2546
|
const pill = pillMarkup(segment, name, status);
|
|
2547
|
+
const toggle = contextConfig().getIcon("expand");
|
|
2536
2548
|
const input = describeInput(segment);
|
|
2537
2549
|
const result = segment.result;
|
|
2538
2550
|
if (!input && !result) {
|
|
@@ -2544,7 +2556,7 @@ const toolCallRenderer = {
|
|
|
2544
2556
|
const cfg = contextConfig();
|
|
2545
2557
|
return `
|
|
2546
2558
|
<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"
|
|
2559
|
+
<summary class="aparte-tool-summary"><span class="aparte-tool-toggle">${toggle}</span>${pill}</summary>
|
|
2548
2560
|
<div class="aparte-tool-detail">
|
|
2549
2561
|
${input ? `
|
|
2550
2562
|
<div class="aparte-tool-part" data-part="input">
|
|
@@ -2619,7 +2631,7 @@ const toolCallRenderer = {
|
|
|
2619
2631
|
const customRenderer = contextConfig().getToolRenderer(segment.toolCall?.name);
|
|
2620
2632
|
customRenderer?.setup?.(element, segment);
|
|
2621
2633
|
},
|
|
2622
|
-
// CSS lives in styles/
|
|
2634
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
2623
2635
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
2624
2636
|
// has no other way onto the page.
|
|
2625
2637
|
getStyles: () => ""
|
|
@@ -2630,9 +2642,9 @@ const pipelineWaitingRenderer = {
|
|
|
2630
2642
|
render: (segment) => {
|
|
2631
2643
|
return `
|
|
2632
2644
|
<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>
|
|
2645
|
+
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2646
|
+
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2647
|
+
<span class="aparte-dot aparte-pw-dot"></span>
|
|
2636
2648
|
</div>`;
|
|
2637
2649
|
},
|
|
2638
2650
|
update: () => {
|
|
@@ -2657,7 +2669,7 @@ const pipelineWaitingRenderer = {
|
|
|
2657
2669
|
});
|
|
2658
2670
|
observer.observe(parent, { childList: true });
|
|
2659
2671
|
},
|
|
2660
|
-
// CSS lives in styles/
|
|
2672
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
2661
2673
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
2662
2674
|
// has no other way onto the page.
|
|
2663
2675
|
getStyles: () => ""
|
|
@@ -2863,7 +2875,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2863
2875
|
if (cached && !isStreaming) {
|
|
2864
2876
|
const previewBody = cached.previewHtml ? contextConfig().sanitizeHtml(cached.previewHtml) : `<div class="aparte-art-file__preview-empty">Preview not available for ${escapeHtml(kind)} yet</div>`;
|
|
2865
2877
|
return `
|
|
2866
|
-
<div class="aparte-segment aparte-segment-artifact-file"
|
|
2878
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-file"
|
|
2867
2879
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
2868
2880
|
data-artifact-type="${escapeHtml(kind)}"
|
|
2869
2881
|
data-state="ready">
|
|
@@ -2874,7 +2886,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2874
2886
|
<div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(formatBytes(cached.bytes))} · ${escapeHtml(kind.toUpperCase())}</div>
|
|
2875
2887
|
</div>
|
|
2876
2888
|
<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>` : ""}
|
|
2889
|
+
${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
2890
|
</div>
|
|
2879
2891
|
</div>
|
|
2880
2892
|
<div class="aparte-art-file__body">
|
|
@@ -2889,7 +2901,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2889
2901
|
const cleanContent = stripCodeFences(segment.content || "");
|
|
2890
2902
|
const subText = isStreaming ? contextConfig().t("generating") : contextConfig().t("rebuildingPreview");
|
|
2891
2903
|
return `
|
|
2892
|
-
<div class="aparte-segment aparte-segment-artifact-file"
|
|
2904
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-file"
|
|
2893
2905
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
2894
2906
|
data-artifact-type="${escapeHtml(kind)}"
|
|
2895
2907
|
data-state="${isStreaming ? "streaming" : "compiling"}">
|
|
@@ -2900,7 +2912,7 @@ function renderBinaryFileArtifact(segment, kind) {
|
|
|
2900
2912
|
<div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(subText)}</div>
|
|
2901
2913
|
</div>
|
|
2902
2914
|
<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>` : ""}
|
|
2915
|
+
${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
2916
|
</div>
|
|
2905
2917
|
</div>
|
|
2906
2918
|
<div class="aparte-art-file__body">
|
|
@@ -3058,7 +3070,7 @@ function showSandboxError(element, phase, errorMsg) {
|
|
|
3058
3070
|
body.innerHTML = `
|
|
3059
3071
|
<div class="aparte-art-file__error">
|
|
3060
3072
|
<div class="aparte-art-file__error-title">${escapeHtml(contextConfig().t("sandboxError"))}</div>
|
|
3061
|
-
<div class="aparte-art-file__error-msg">${escapeHtml(short)}</div>
|
|
3073
|
+
<div class="aparte-output aparte-art-file__error-msg">${escapeHtml(short)}</div>
|
|
3062
3074
|
<div class="aparte-art-file__error-hint">${escapeHtml(contextConfig().t("sandboxErrorHint"))}</div>
|
|
3063
3075
|
</div>
|
|
3064
3076
|
`;
|
|
@@ -3083,8 +3095,9 @@ const artifactRenderer = {
|
|
|
3083
3095
|
const codeLabel = cfg.t("code");
|
|
3084
3096
|
const isBinary = BINARY_FILE_KINDS.has(kind);
|
|
3085
3097
|
const cleanContent = stripCodeFences(segment.content || "");
|
|
3098
|
+
const cardId = escapeAttr(segment.id);
|
|
3086
3099
|
return `
|
|
3087
|
-
<div class="aparte-segment aparte-segment-artifact-card"
|
|
3100
|
+
<div class="aparte-segment aparte-card aparte-segment-artifact-card"
|
|
3088
3101
|
data-segment-id="${escapeHtml(segment.id)}"
|
|
3089
3102
|
data-artifact-type="${escapeHtml(kind)}"
|
|
3090
3103
|
data-streaming="${isStreaming ? "true" : "false"}"
|
|
@@ -3093,31 +3106,31 @@ const artifactRenderer = {
|
|
|
3093
3106
|
data-binary="${isBinary ? "true" : "false"}">
|
|
3094
3107
|
<header class="aparte-art-card__header">
|
|
3095
3108
|
<div class="aparte-art-card__title-block">
|
|
3096
|
-
<span class="aparte-art-card__kind" data-kind="${escapeHtml(kind)}">${escapeHtml(displayLang)}</span>
|
|
3109
|
+
<span class="aparte-badge aparte-badge--outline aparte-art-card__kind" data-kind="${escapeHtml(kind)}">${escapeHtml(displayLang)}</span>
|
|
3097
3110
|
<span class="aparte-art-card__title">${escapeHtml(title)}</span>
|
|
3098
|
-
${isStreaming ?
|
|
3111
|
+
${isStreaming ? `<span class="aparte-dot aparte-art-card__pulse" role="img" aria-label="${escapeAttr(cfg.t("generating"))}"></span>` : ""}
|
|
3099
3112
|
</div>
|
|
3100
3113
|
<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"))}">
|
|
3114
|
+
<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
3115
|
${contextConfig().getIcon("copy")}
|
|
3103
3116
|
</button>
|
|
3104
|
-
<button type="button" class="aparte-art-card__btn" data-action="download" title="${escapeAttr(downloadLabel)}" aria-label="${escapeAttr(downloadLabel)}" ${isStreaming ? "disabled" : ""}>
|
|
3105
|
-
|
|
3117
|
+
<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" : ""}>
|
|
3118
|
+
${contextConfig().getIcon("download")}
|
|
3106
3119
|
</button>
|
|
3107
3120
|
</div>
|
|
3108
3121
|
</header>
|
|
3109
|
-
<nav class="aparte-art-card__tabs" role="tablist">
|
|
3110
|
-
<button type="button" role="tab"
|
|
3111
|
-
${previewable ? `<button type="button" role="tab"
|
|
3122
|
+
<nav class="aparte-tabs aparte-tabs--underline aparte-art-card__tabs" role="tablist">
|
|
3123
|
+
<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>
|
|
3124
|
+
${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
3125
|
</nav>
|
|
3113
3126
|
<div class="aparte-art-card__body">
|
|
3114
|
-
<div class="aparte-art-card__pane" data-pane="code">
|
|
3127
|
+
<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
3128
|
<div class="aparte-code-content-wrapper">
|
|
3116
3129
|
<pre><code class="language-${escapeHtml(displayLang)}">${escapeHtml(cleanContent)}</code></pre>
|
|
3117
3130
|
</div>
|
|
3118
3131
|
</div>
|
|
3119
3132
|
${previewable ? `
|
|
3120
|
-
<div class="aparte-art-card__pane" data-pane="preview">
|
|
3133
|
+
<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
3134
|
<div class="aparte-art-card__pending">${escapeHtml(cfg.t("previewPending"))}</div>
|
|
3122
3135
|
</div>
|
|
3123
3136
|
` : ""}
|
|
@@ -3172,17 +3185,38 @@ const artifactRenderer = {
|
|
|
3172
3185
|
}).catch(() => {
|
|
3173
3186
|
});
|
|
3174
3187
|
}
|
|
3175
|
-
element.querySelectorAll("[data-tab-target]")
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3188
|
+
const tabs = [...element.querySelectorAll("[data-tab-target]")];
|
|
3189
|
+
const select = (btn, focus) => {
|
|
3190
|
+
const target = btn.getAttribute("data-tab-target");
|
|
3191
|
+
if (!target || btn.disabled) return;
|
|
3192
|
+
if (target === "preview") mountPreviewFrame(element, segment);
|
|
3193
|
+
element.setAttribute("data-tab", target);
|
|
3194
|
+
for (const b of tabs) {
|
|
3195
|
+
const on = b === btn;
|
|
3196
|
+
b.setAttribute("aria-selected", on ? "true" : "false");
|
|
3197
|
+
b.tabIndex = on ? 0 : -1;
|
|
3198
|
+
}
|
|
3199
|
+
if (focus) btn.focus();
|
|
3200
|
+
};
|
|
3201
|
+
for (const [i, btn] of tabs.entries()) {
|
|
3202
|
+
btn.addEventListener("click", () => select(btn, false));
|
|
3203
|
+
btn.addEventListener("keydown", (e) => {
|
|
3204
|
+
const step = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
|
|
3205
|
+
let next = -1;
|
|
3206
|
+
if (step) next = (i + step + tabs.length) % tabs.length;
|
|
3207
|
+
else if (e.key === "Home") next = 0;
|
|
3208
|
+
else if (e.key === "End") next = tabs.length - 1;
|
|
3209
|
+
if (next < 0) return;
|
|
3210
|
+
e.preventDefault();
|
|
3211
|
+
for (let n = 0; n < tabs.length; n++) {
|
|
3212
|
+
const candidate = tabs[(next + n * (step || 1) + tabs.length) % tabs.length];
|
|
3213
|
+
if (candidate && !candidate.disabled) {
|
|
3214
|
+
select(candidate, true);
|
|
3215
|
+
return;
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3184
3218
|
});
|
|
3185
|
-
}
|
|
3219
|
+
}
|
|
3186
3220
|
const copyBtn = element.querySelector('[data-action="copy"]');
|
|
3187
3221
|
if (copyBtn) {
|
|
3188
3222
|
copyBtn.addEventListener("click", () => {
|
|
@@ -3267,7 +3301,7 @@ const artifactRenderer = {
|
|
|
3267
3301
|
});
|
|
3268
3302
|
}
|
|
3269
3303
|
},
|
|
3270
|
-
// CSS lives in styles/
|
|
3304
|
+
// CSS lives in styles/segment/ — see that folder for why a
|
|
3271
3305
|
// built-in's rules belong there. `getStyles` stays for a CONSUMER's renderer, which
|
|
3272
3306
|
// has no other way onto the page.
|
|
3273
3307
|
getStyles: () => ""
|
|
@@ -3407,6 +3441,17 @@ function injectRendererStyles(config = contextConfig()) {
|
|
|
3407
3441
|
}
|
|
3408
3442
|
if (added) styleElement.textContent = Array.from(injectedRendererStyles).join("\n");
|
|
3409
3443
|
}
|
|
3444
|
+
function injectToolRendererStyles(toolName, renderer) {
|
|
3445
|
+
if (typeof document === "undefined") return;
|
|
3446
|
+
const css = renderer.getStyles?.();
|
|
3447
|
+
if (!css) return;
|
|
3448
|
+
const id = `aparte-tool-renderer-${toolName}`;
|
|
3449
|
+
if (document.getElementById(id)) return;
|
|
3450
|
+
const el2 = document.createElement("style");
|
|
3451
|
+
el2.id = id;
|
|
3452
|
+
el2.textContent = css;
|
|
3453
|
+
document.head.appendChild(el2);
|
|
3454
|
+
}
|
|
3410
3455
|
function registerDefaultRenderers(config = contextConfig()) {
|
|
3411
3456
|
const reg = registryFor(config);
|
|
3412
3457
|
reg.defaultsInstalled = true;
|
|
@@ -5170,18 +5215,7 @@ function createStreamAdapter(opts) {
|
|
|
5170
5215
|
};
|
|
5171
5216
|
const renderer = config.getToolRenderer(e.name);
|
|
5172
5217
|
if (renderer) {
|
|
5173
|
-
|
|
5174
|
-
const styles = renderer.getStyles();
|
|
5175
|
-
if (styles) {
|
|
5176
|
-
const styleId = `aparte-tool-renderer-${e.name}`;
|
|
5177
|
-
if (!document.getElementById(styleId)) {
|
|
5178
|
-
const styleEl = document.createElement("style");
|
|
5179
|
-
styleEl.id = styleId;
|
|
5180
|
-
styleEl.textContent = styles;
|
|
5181
|
-
document.head.appendChild(styleEl);
|
|
5182
|
-
}
|
|
5183
|
-
}
|
|
5184
|
-
}
|
|
5218
|
+
injectToolRendererStyles(e.name, renderer);
|
|
5185
5219
|
const html = renderer.render(toolSeg);
|
|
5186
5220
|
if (html) target.addSegment?.(toolSeg);
|
|
5187
5221
|
} else {
|
|
@@ -5269,6 +5303,7 @@ function readableToAsyncIterable(stream, signal) {
|
|
|
5269
5303
|
}
|
|
5270
5304
|
};
|
|
5271
5305
|
}
|
|
5306
|
+
let steppedPanelSeq = 0;
|
|
5272
5307
|
let _relabels = null;
|
|
5273
5308
|
function onRelabel(fn) {
|
|
5274
5309
|
_relabels?.push(fn);
|
|
@@ -5279,6 +5314,18 @@ function el$1(tag, className, text) {
|
|
|
5279
5314
|
if (text != null) node.textContent = text;
|
|
5280
5315
|
return node;
|
|
5281
5316
|
}
|
|
5317
|
+
function optionBody(label, description) {
|
|
5318
|
+
const body = el$1("span", "aparte-elic-option-body");
|
|
5319
|
+
body.appendChild(el$1("span", "aparte-elic-option-title", label));
|
|
5320
|
+
if (description) body.appendChild(el$1("span", "aparte-elic-option-desc", description));
|
|
5321
|
+
return body;
|
|
5322
|
+
}
|
|
5323
|
+
function commandOption(label, description, recommended) {
|
|
5324
|
+
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" : ""));
|
|
5325
|
+
button.type = "button";
|
|
5326
|
+
button.appendChild(optionBody(label, description));
|
|
5327
|
+
return button;
|
|
5328
|
+
}
|
|
5282
5329
|
function fieldHeader(parent, field, skipTitle) {
|
|
5283
5330
|
let titleId;
|
|
5284
5331
|
if (field.title && field.title.trim() !== skipTitle?.trim()) {
|
|
@@ -5291,61 +5338,87 @@ function fieldHeader(parent, field, skipTitle) {
|
|
|
5291
5338
|
return titleId;
|
|
5292
5339
|
}
|
|
5293
5340
|
function labelGroup(list, opts) {
|
|
5294
|
-
list.setAttribute("role", opts.multiple ? "group" : "radiogroup");
|
|
5341
|
+
list.setAttribute("role", opts.multiple || opts.commands ? "group" : "radiogroup");
|
|
5295
5342
|
if (opts.titleId) list.setAttribute("aria-labelledby", opts.titleId);
|
|
5296
5343
|
else if (opts.fallbackLabel) list.setAttribute("aria-label", opts.fallbackLabel);
|
|
5297
5344
|
}
|
|
5298
|
-
function buildEnumField(field, onChange, fallbackLabel) {
|
|
5345
|
+
function buildEnumField(field, onChange, fallbackLabel, settle) {
|
|
5299
5346
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-enum");
|
|
5300
5347
|
const titleId = fieldHeader(wrap, field, fallbackLabel);
|
|
5301
5348
|
const list = el$1("div", "aparte-elic-options");
|
|
5302
|
-
labelGroup(list, { multiple: field.multiple, titleId, fallbackLabel });
|
|
5303
5349
|
const name = `elic-${uuid()}`;
|
|
5304
5350
|
const type = field.multiple ? "checkbox" : "radio";
|
|
5351
|
+
const controlRecipe = type === "checkbox" ? "aparte-checkbox" : "aparte-radio";
|
|
5305
5352
|
const allowOther = field.allowOther ?? contextConfig().getElicitationOptions().allowOther;
|
|
5306
5353
|
const defaults = new Set(Array.isArray(field.default) ? field.default : field.default != null ? [field.default] : []);
|
|
5354
|
+
const settling = settle != null && !field.multiple && defaults.size === 0;
|
|
5355
|
+
labelGroup(list, { multiple: field.multiple, commands: settling, titleId, fallbackLabel });
|
|
5307
5356
|
const buildOption = (value, label, description, recommended) => {
|
|
5308
|
-
|
|
5309
|
-
|
|
5357
|
+
if (settling) {
|
|
5358
|
+
const button = commandOption(label, description, recommended);
|
|
5359
|
+
button.addEventListener("click", () => settle?.(value));
|
|
5360
|
+
return button;
|
|
5361
|
+
}
|
|
5362
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option" + (recommended ? " aparte-elic-option--recommended" : ""));
|
|
5363
|
+
const control = el$1("input", controlRecipe + " aparte-elic-control");
|
|
5310
5364
|
control.type = type;
|
|
5311
5365
|
control.name = name;
|
|
5312
5366
|
control.value = value;
|
|
5313
5367
|
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);
|
|
5368
|
+
row.append(control, optionBody(label, description));
|
|
5318
5369
|
return row;
|
|
5319
5370
|
};
|
|
5320
5371
|
for (const opt of field.options) {
|
|
5321
5372
|
list.appendChild(buildOption(opt.value, opt.label ?? opt.value, opt.description, opt.recommended));
|
|
5322
5373
|
}
|
|
5323
5374
|
let otherText = null;
|
|
5375
|
+
let otherOpen = false;
|
|
5324
5376
|
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
5377
|
const t = contextConfig();
|
|
5332
|
-
|
|
5333
|
-
body.appendChild(otherTitle);
|
|
5334
|
-
otherText = el$1("input", "aparte-elic-other-input");
|
|
5378
|
+
otherText = el$1("input", "aparte-field aparte-elic-other-input");
|
|
5335
5379
|
otherText.type = "text";
|
|
5336
5380
|
otherText.placeholder = t.t("elicitationOtherPlaceholder");
|
|
5337
5381
|
otherText.style.display = "none";
|
|
5338
5382
|
otherText.setAttribute("aria-label", t.t("elicitationOtherLabel"));
|
|
5339
5383
|
const otherInput = otherText;
|
|
5340
|
-
|
|
5341
|
-
const
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5384
|
+
if (settling) {
|
|
5385
|
+
const button = commandOption(t.t("elicitationOther"));
|
|
5386
|
+
button.classList.add("aparte-elic-option--other");
|
|
5387
|
+
button.setAttribute("aria-expanded", "false");
|
|
5388
|
+
button.addEventListener("click", () => {
|
|
5389
|
+
otherOpen = true;
|
|
5390
|
+
button.setAttribute("aria-expanded", "true");
|
|
5391
|
+
otherInput.style.display = "";
|
|
5392
|
+
otherInput.focus();
|
|
5393
|
+
onChange();
|
|
5394
|
+
});
|
|
5395
|
+
const otherTitle = button.querySelector(".aparte-elic-option-title");
|
|
5396
|
+
onRelabel(() => {
|
|
5397
|
+
const now = contextConfig();
|
|
5398
|
+
otherTitle.textContent = now.t("elicitationOther");
|
|
5399
|
+
otherInput.placeholder = now.t("elicitationOtherPlaceholder");
|
|
5400
|
+
otherInput.setAttribute("aria-label", now.t("elicitationOtherLabel"));
|
|
5401
|
+
});
|
|
5402
|
+
list.append(button, otherInput);
|
|
5403
|
+
} else {
|
|
5404
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option aparte-elic-option--other");
|
|
5405
|
+
const control = el$1("input", controlRecipe + " aparte-elic-control");
|
|
5406
|
+
control.type = type;
|
|
5407
|
+
control.name = name;
|
|
5408
|
+
control.value = "__other__";
|
|
5409
|
+
const body = el$1("span", "aparte-elic-option-body");
|
|
5410
|
+
const otherTitle = el$1("span", "aparte-elic-option-title", t.t("elicitationOther"));
|
|
5411
|
+
body.appendChild(otherTitle);
|
|
5412
|
+
onRelabel(() => {
|
|
5413
|
+
const now = contextConfig();
|
|
5414
|
+
otherTitle.textContent = now.t("elicitationOther");
|
|
5415
|
+
otherInput.placeholder = now.t("elicitationOtherPlaceholder");
|
|
5416
|
+
otherInput.setAttribute("aria-label", now.t("elicitationOtherLabel"));
|
|
5417
|
+
});
|
|
5418
|
+
body.appendChild(otherText);
|
|
5419
|
+
row.append(control, body);
|
|
5420
|
+
list.appendChild(row);
|
|
5421
|
+
}
|
|
5349
5422
|
}
|
|
5350
5423
|
wrap.appendChild(list);
|
|
5351
5424
|
const controls = () => Array.from(list.querySelectorAll(".aparte-elic-control"));
|
|
@@ -5359,8 +5432,18 @@ function buildEnumField(field, onChange, fallbackLabel) {
|
|
|
5359
5432
|
onChange();
|
|
5360
5433
|
});
|
|
5361
5434
|
otherText?.addEventListener("input", onChange);
|
|
5435
|
+
const typedOther = () => otherText?.value.trim() ?? "";
|
|
5436
|
+
if (settling) {
|
|
5437
|
+
return {
|
|
5438
|
+
el: wrap,
|
|
5439
|
+
getValue: () => typedOther(),
|
|
5440
|
+
isComplete: () => otherOpen && typedOther() !== "",
|
|
5441
|
+
focus: () => list.querySelector(".aparte-elic-option--command")?.focus(),
|
|
5442
|
+
offersSubmit: () => otherOpen
|
|
5443
|
+
};
|
|
5444
|
+
}
|
|
5362
5445
|
const getValue = () => {
|
|
5363
|
-
const otherVal = other()?.checked &&
|
|
5446
|
+
const otherVal = other()?.checked && typedOther() ? typedOther() : "";
|
|
5364
5447
|
if (field.multiple) {
|
|
5365
5448
|
const vals = controls().filter((c) => c.checked && c.value !== "__other__").map((c) => c.value);
|
|
5366
5449
|
if (otherVal) vals.push(otherVal);
|
|
@@ -5380,15 +5463,42 @@ function buildEnumField(field, onChange, fallbackLabel) {
|
|
|
5380
5463
|
focus: () => controls()[0]?.focus()
|
|
5381
5464
|
};
|
|
5382
5465
|
}
|
|
5383
|
-
function buildBooleanField(field, onChange, fallbackLabel) {
|
|
5466
|
+
function buildBooleanField(field, onChange, fallbackLabel, settle) {
|
|
5384
5467
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-boolean");
|
|
5385
5468
|
const titleId = fieldHeader(wrap, field, fallbackLabel);
|
|
5386
5469
|
const list = el$1("div", "aparte-elic-options");
|
|
5387
|
-
labelGroup(list, { titleId, fallbackLabel });
|
|
5388
5470
|
const name = `elic-${uuid()}`;
|
|
5471
|
+
const settling = settle != null && field.default == null;
|
|
5472
|
+
labelGroup(list, { commands: settling, titleId, fallbackLabel });
|
|
5473
|
+
if (settling) {
|
|
5474
|
+
const t2 = contextConfig();
|
|
5475
|
+
const mkCommand = (val, label, defaulted) => {
|
|
5476
|
+
const button = commandOption(label);
|
|
5477
|
+
button.addEventListener("click", () => settle?.(val));
|
|
5478
|
+
if (defaulted) {
|
|
5479
|
+
const title = button.querySelector(".aparte-elic-option-title");
|
|
5480
|
+
onRelabel(() => {
|
|
5481
|
+
title.textContent = contextConfig().t(defaulted);
|
|
5482
|
+
});
|
|
5483
|
+
}
|
|
5484
|
+
list.appendChild(button);
|
|
5485
|
+
};
|
|
5486
|
+
mkCommand(true, field.trueLabel ?? t2.t("elicitationYes"), field.trueLabel ? void 0 : "elicitationYes");
|
|
5487
|
+
mkCommand(false, field.falseLabel ?? t2.t("elicitationNo"), field.falseLabel ? void 0 : "elicitationNo");
|
|
5488
|
+
wrap.appendChild(list);
|
|
5489
|
+
return {
|
|
5490
|
+
el: wrap,
|
|
5491
|
+
// Never read: the click settles, so nothing downstream asks this shape for
|
|
5492
|
+
// a value. `false` rather than a throw keeps the field total.
|
|
5493
|
+
getValue: () => false,
|
|
5494
|
+
isComplete: () => false,
|
|
5495
|
+
focus: () => list.querySelector(".aparte-elic-option--command")?.focus(),
|
|
5496
|
+
offersSubmit: () => false
|
|
5497
|
+
};
|
|
5498
|
+
}
|
|
5389
5499
|
const mk = (val, label, defaulted) => {
|
|
5390
|
-
const row = el$1("label", "aparte-elic-option");
|
|
5391
|
-
const control = el$1("input", "aparte-elic-control");
|
|
5500
|
+
const row = el$1("label", "aparte-field-choice aparte-elic-option");
|
|
5501
|
+
const control = el$1("input", "aparte-radio aparte-elic-control");
|
|
5392
5502
|
control.type = "radio";
|
|
5393
5503
|
control.name = name;
|
|
5394
5504
|
control.value = val;
|
|
@@ -5418,7 +5528,7 @@ function buildBooleanField(field, onChange, fallbackLabel) {
|
|
|
5418
5528
|
function buildStringField(field, onChange, fallbackLabel) {
|
|
5419
5529
|
const wrap = el$1("div", "aparte-elic-field aparte-elic-string");
|
|
5420
5530
|
fieldHeader(wrap, field, fallbackLabel);
|
|
5421
|
-
const input = field.multiline ? el$1("textarea", "aparte-elic-text") : el$1("input", "aparte-elic-text");
|
|
5531
|
+
const input = field.multiline ? el$1("textarea", "aparte-field aparte-field--textarea aparte-elic-text") : el$1("input", "aparte-field aparte-elic-text");
|
|
5422
5532
|
if (!field.multiline) input.type = "text";
|
|
5423
5533
|
if (field.placeholder) input.setAttribute("placeholder", field.placeholder);
|
|
5424
5534
|
if (field.default) input.value = field.default;
|
|
@@ -5446,7 +5556,7 @@ function buildStringField(field, onChange, fallbackLabel) {
|
|
|
5446
5556
|
focus: () => input.focus()
|
|
5447
5557
|
};
|
|
5448
5558
|
}
|
|
5449
|
-
function buildField(field, onChange, fallbackLabel, key) {
|
|
5559
|
+
function buildField(field, onChange, fallbackLabel, key, settle) {
|
|
5450
5560
|
const custom = contextConfig().getElicitationFieldRenderer()?.(field, { key, notifyChange: onChange });
|
|
5451
5561
|
if (custom) {
|
|
5452
5562
|
return {
|
|
@@ -5458,9 +5568,10 @@ function buildField(field, onChange, fallbackLabel, key) {
|
|
|
5458
5568
|
}
|
|
5459
5569
|
switch (field.type) {
|
|
5460
5570
|
case "enum":
|
|
5461
|
-
return buildEnumField(field, onChange, fallbackLabel);
|
|
5571
|
+
return buildEnumField(field, onChange, fallbackLabel, settle);
|
|
5462
5572
|
case "boolean":
|
|
5463
|
-
return buildBooleanField(field, onChange, fallbackLabel);
|
|
5573
|
+
return buildBooleanField(field, onChange, fallbackLabel, settle);
|
|
5574
|
+
// No `settle`: text is written, not chosen, so it always needs a commit.
|
|
5464
5575
|
case "string":
|
|
5465
5576
|
return buildStringField(field, onChange, fallbackLabel);
|
|
5466
5577
|
}
|
|
@@ -5482,6 +5593,16 @@ function buildPanel(message, schema, onChange) {
|
|
|
5482
5593
|
const panel = el$1("div", "aparte-elic-panel");
|
|
5483
5594
|
const asked = typeof message === "function" ? message() : message;
|
|
5484
5595
|
if (asked) panel.appendChild(el$1("p", "aparte-elic-message", asked));
|
|
5596
|
+
let settleCb = null;
|
|
5597
|
+
let settled = false;
|
|
5598
|
+
const settle = (content) => {
|
|
5599
|
+
if (settled) return;
|
|
5600
|
+
settled = true;
|
|
5601
|
+
settleCb?.(content);
|
|
5602
|
+
};
|
|
5603
|
+
const onSettle = (cb) => {
|
|
5604
|
+
settleCb = cb;
|
|
5605
|
+
};
|
|
5485
5606
|
const body = el$1("div", "aparte-elic-body");
|
|
5486
5607
|
panel.appendChild(body);
|
|
5487
5608
|
const dismiss = el$1("div", "aparte-elic-dismiss");
|
|
@@ -5522,15 +5643,20 @@ function buildPanel(message, schema, onChange) {
|
|
|
5522
5643
|
mode: () => "submit",
|
|
5523
5644
|
canProceed: isComplete,
|
|
5524
5645
|
proceed: () => {
|
|
5525
|
-
}
|
|
5646
|
+
},
|
|
5647
|
+
// A form never settles from inside: its questions are collected and
|
|
5648
|
+
// submitted together, and answering the last one on the click would be
|
|
5649
|
+
// WCAG's F36 word for word. Registered so the shape is total; never fired.
|
|
5650
|
+
onSettle
|
|
5526
5651
|
};
|
|
5527
5652
|
if (fields.length < 2 || cfg.getElicitationOptions().layout !== "stepped") return api;
|
|
5528
5653
|
panel.classList.add("aparte-elic-panel--stepped");
|
|
5529
5654
|
let current = 0;
|
|
5530
|
-
const
|
|
5655
|
+
const scope = `aparte-elic-${++steppedPanelSeq}`;
|
|
5656
|
+
const steps = el$1("div", "aparte-tabs aparte-tabs--underline aparte-elic-steps");
|
|
5531
5657
|
steps.setAttribute("role", "tablist");
|
|
5532
5658
|
const chips = fields.map((f, i) => {
|
|
5533
|
-
const chip = el$1("button", "aparte-elic-step");
|
|
5659
|
+
const chip = el$1("button", "aparte-tabs__tab aparte-elic-step");
|
|
5534
5660
|
chip.type = "button";
|
|
5535
5661
|
chip.setAttribute("role", "tab");
|
|
5536
5662
|
chip.textContent = f.header?.trim() || String(i + 1);
|
|
@@ -5538,6 +5664,22 @@ function buildPanel(message, schema, onChange) {
|
|
|
5538
5664
|
show(i);
|
|
5539
5665
|
f.field.focus();
|
|
5540
5666
|
});
|
|
5667
|
+
chip.id = `${scope}-tab-${i}`;
|
|
5668
|
+
f.field.el.id = `${scope}-panel-${i}`;
|
|
5669
|
+
f.field.el.setAttribute("role", "tabpanel");
|
|
5670
|
+
f.field.el.setAttribute("aria-labelledby", chip.id);
|
|
5671
|
+
chip.setAttribute("aria-controls", f.field.el.id);
|
|
5672
|
+
chip.addEventListener("keydown", (e) => {
|
|
5673
|
+
const step = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
|
|
5674
|
+
let next = -1;
|
|
5675
|
+
if (step) next = (i + step + fields.length) % fields.length;
|
|
5676
|
+
else if (e.key === "Home") next = 0;
|
|
5677
|
+
else if (e.key === "End") next = fields.length - 1;
|
|
5678
|
+
if (next < 0) return;
|
|
5679
|
+
e.preventDefault();
|
|
5680
|
+
show(next);
|
|
5681
|
+
chips[next]?.focus();
|
|
5682
|
+
});
|
|
5541
5683
|
steps.appendChild(chip);
|
|
5542
5684
|
return chip;
|
|
5543
5685
|
});
|
|
@@ -5545,6 +5687,7 @@ function buildPanel(message, schema, onChange) {
|
|
|
5545
5687
|
syncNav = () => {
|
|
5546
5688
|
chips.forEach((chip, i) => {
|
|
5547
5689
|
chip.setAttribute("aria-selected", String(i === current));
|
|
5690
|
+
chip.tabIndex = i === current ? 0 : -1;
|
|
5548
5691
|
chip.toggleAttribute("data-answered", fields[i].field.isComplete());
|
|
5549
5692
|
});
|
|
5550
5693
|
};
|
|
@@ -5565,7 +5708,7 @@ function buildPanel(message, schema, onChange) {
|
|
|
5565
5708
|
}
|
|
5566
5709
|
};
|
|
5567
5710
|
}
|
|
5568
|
-
const field = buildField(schema, onChange, asked);
|
|
5711
|
+
const field = buildField(schema, onChange, asked, void 0, settle);
|
|
5569
5712
|
body.appendChild(field.el);
|
|
5570
5713
|
return {
|
|
5571
5714
|
el: panel,
|
|
@@ -5573,10 +5716,11 @@ function buildPanel(message, schema, onChange) {
|
|
|
5573
5716
|
getContent: () => field.getValue(),
|
|
5574
5717
|
isComplete: () => field.isComplete(),
|
|
5575
5718
|
focus: () => field.focus(),
|
|
5576
|
-
mode: () => "submit",
|
|
5719
|
+
mode: () => field.offersSubmit?.() ?? true ? "submit" : "none",
|
|
5577
5720
|
canProceed: () => field.isComplete(),
|
|
5578
5721
|
proceed: () => {
|
|
5579
|
-
}
|
|
5722
|
+
},
|
|
5723
|
+
onSettle
|
|
5580
5724
|
};
|
|
5581
5725
|
}
|
|
5582
5726
|
function el(tag, className, text) {
|
|
@@ -5606,7 +5750,8 @@ function buildApprovalPanel(message, options, onChange) {
|
|
|
5606
5750
|
const labelled = [];
|
|
5607
5751
|
const textOf = (option) => typeof option.label === "function" ? option.label() : option.label;
|
|
5608
5752
|
for (const option of options) {
|
|
5609
|
-
const
|
|
5753
|
+
const tone = option.tone ?? "affirm";
|
|
5754
|
+
const button = el("button", `aparte-btn aparte-btn--block aparte-btn--surface aparte-approval-option aparte-approval-option--${tone}`);
|
|
5610
5755
|
button.type = "button";
|
|
5611
5756
|
button.textContent = textOf(option);
|
|
5612
5757
|
button.addEventListener("click", () => fire({ option: option.value }));
|
|
@@ -5710,6 +5855,27 @@ class AparteClient {
|
|
|
5710
5855
|
}
|
|
5711
5856
|
this._setupListeners();
|
|
5712
5857
|
}
|
|
5858
|
+
/**
|
|
5859
|
+
* What every fresh user action does before it starts a turn.
|
|
5860
|
+
*
|
|
5861
|
+
* Clearing the abort flag has to happen at the START of the action rather than inside
|
|
5862
|
+
* `_streamTurn`, which runs after the auth and file-reading awaits — a reset there
|
|
5863
|
+
* erased an abort that arrived while the user was still waiting for a large attachment
|
|
5864
|
+
* to be read.
|
|
5865
|
+
*
|
|
5866
|
+
* Cancelling the previous turn's tool controllers used to happen only on `aparte-send`.
|
|
5867
|
+
* Retry and edit reset the flag and left them running, so a tool handler from the turn
|
|
5868
|
+
* being superseded stayed alive — with its timeout still counting — while its reply was
|
|
5869
|
+
* already off the active path. A cold audit found the asymmetry; three callers, one
|
|
5870
|
+
* rule, no third copy to fall out of step.
|
|
5871
|
+
*/
|
|
5872
|
+
_beginUserTurn() {
|
|
5873
|
+
this._isAborted = false;
|
|
5874
|
+
for (const controller of this._activeToolControllers) {
|
|
5875
|
+
controller.abort();
|
|
5876
|
+
}
|
|
5877
|
+
this._activeToolControllers.clear();
|
|
5878
|
+
}
|
|
5713
5879
|
/**
|
|
5714
5880
|
* Sets up the event listeners.
|
|
5715
5881
|
* This is called once in the constructor.
|
|
@@ -5720,11 +5886,7 @@ class AparteClient {
|
|
|
5720
5886
|
const event = e;
|
|
5721
5887
|
if (event.type !== "aparte-send") return;
|
|
5722
5888
|
if (!this._isForThisInstance(event)) return;
|
|
5723
|
-
this.
|
|
5724
|
-
for (const controller of this._activeToolControllers) {
|
|
5725
|
-
controller.abort();
|
|
5726
|
-
}
|
|
5727
|
-
this._activeToolControllers.clear();
|
|
5889
|
+
this._beginUserTurn();
|
|
5728
5890
|
void this._handleSend(event);
|
|
5729
5891
|
};
|
|
5730
5892
|
}
|
|
@@ -6074,7 +6236,7 @@ ${summary}`,
|
|
|
6074
6236
|
}
|
|
6075
6237
|
async _handleRetry(event) {
|
|
6076
6238
|
const { messageId, targetId } = event.detail ?? {};
|
|
6077
|
-
this.
|
|
6239
|
+
this._beginUserTurn();
|
|
6078
6240
|
if (!messageId) return;
|
|
6079
6241
|
const targetElement = this._resolveTarget(targetId);
|
|
6080
6242
|
if (!targetElement) {
|
|
@@ -6101,9 +6263,7 @@ ${summary}`,
|
|
|
6101
6263
|
if (!provider) return;
|
|
6102
6264
|
const authConfig = await this._resolveAuth(providerId);
|
|
6103
6265
|
const chatMessages = this._messagesToChatMessages(historyMessages);
|
|
6104
|
-
const systemMessages =
|
|
6105
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6106
|
-
if (userSystemPrompt) systemMessages.push({ role: "system", content: userSystemPrompt });
|
|
6266
|
+
const systemMessages = this._systemMessages();
|
|
6107
6267
|
await this._streamTurn(
|
|
6108
6268
|
targetElement,
|
|
6109
6269
|
newMessageId,
|
|
@@ -6114,13 +6274,30 @@ ${summary}`,
|
|
|
6114
6274
|
{ temperature: 0.4 }
|
|
6115
6275
|
);
|
|
6116
6276
|
}
|
|
6277
|
+
/**
|
|
6278
|
+
* The system messages a turn opens with: the app's own template, then the registered
|
|
6279
|
+
* tools' `systemPrompt`s.
|
|
6280
|
+
*
|
|
6281
|
+
* A helper rather than three copies. The two lines it replaces were written out at each
|
|
6282
|
+
* of the three turn entry points (send, retry, edit), which is exactly how the tool half
|
|
6283
|
+
* would have been added to two of them and forgotten in the third — the same shape as
|
|
6284
|
+
* the abort-flag asymmetry `_beginUserTurn` exists to prevent.
|
|
6285
|
+
*/
|
|
6286
|
+
_systemMessages() {
|
|
6287
|
+
const messages = [];
|
|
6288
|
+
const appPrompt = this._config.resolveSystemPrompt();
|
|
6289
|
+
if (appPrompt) messages.push({ role: "system", content: appPrompt });
|
|
6290
|
+
const toolPrompts = this._config.resolveToolSystemPrompts();
|
|
6291
|
+
if (toolPrompts) messages.push({ role: "system", content: toolPrompts });
|
|
6292
|
+
return messages;
|
|
6293
|
+
}
|
|
6117
6294
|
/**
|
|
6118
6295
|
* Handle aparte-edit — update the user message in place, truncate all subsequent
|
|
6119
6296
|
* messages, then re-stream a fresh assistant response.
|
|
6120
6297
|
*/
|
|
6121
6298
|
async _handleEdit(event) {
|
|
6122
6299
|
const { messageId, content: newContent, targetId } = event.detail ?? {};
|
|
6123
|
-
this.
|
|
6300
|
+
this._beginUserTurn();
|
|
6124
6301
|
if (!messageId || newContent === void 0) return;
|
|
6125
6302
|
const targetElement = this._resolveTarget(targetId);
|
|
6126
6303
|
if (!targetElement) {
|
|
@@ -6140,9 +6317,7 @@ ${summary}`,
|
|
|
6140
6317
|
}
|
|
6141
6318
|
const historyMessages = editIdx >= 0 ? allMessages.slice(0, editIdx + 1) : allMessages;
|
|
6142
6319
|
const chatMessages = this._messagesToChatMessages(historyMessages);
|
|
6143
|
-
const systemMessages =
|
|
6144
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6145
|
-
if (userSystemPrompt) systemMessages.push({ role: "system", content: userSystemPrompt });
|
|
6320
|
+
const systemMessages = this._systemMessages();
|
|
6146
6321
|
const config = this._config.getModelConfig();
|
|
6147
6322
|
const providerId = config.defaultProvider;
|
|
6148
6323
|
if (!providerId) return;
|
|
@@ -6311,11 +6486,7 @@ ${summary}`,
|
|
|
6311
6486
|
* Build the initial messages array, prepending system prompts and conversation history.
|
|
6312
6487
|
*/
|
|
6313
6488
|
_buildMessages(userContent, target, parts) {
|
|
6314
|
-
const messages =
|
|
6315
|
-
const userSystemPrompt = this._config.resolveSystemPrompt();
|
|
6316
|
-
if (userSystemPrompt) {
|
|
6317
|
-
messages.push({ role: "system", content: userSystemPrompt });
|
|
6318
|
-
}
|
|
6489
|
+
const messages = this._systemMessages();
|
|
6319
6490
|
const historyOption = this.options.history ?? "viewport";
|
|
6320
6491
|
const viewportMessages = target?.getMessages?.() ?? [];
|
|
6321
6492
|
if (historyOption === "viewport") {
|
|
@@ -6581,18 +6752,7 @@ ${content}
|
|
|
6581
6752
|
};
|
|
6582
6753
|
const toolRenderer = this._config.getToolRenderer(event.name);
|
|
6583
6754
|
if (toolRenderer) {
|
|
6584
|
-
|
|
6585
|
-
const styles = toolRenderer.getStyles();
|
|
6586
|
-
if (styles) {
|
|
6587
|
-
const styleId = `aparte-tool-renderer-${event.name}`;
|
|
6588
|
-
if (!document.getElementById(styleId)) {
|
|
6589
|
-
const el2 = document.createElement("style");
|
|
6590
|
-
el2.id = styleId;
|
|
6591
|
-
el2.textContent = styles;
|
|
6592
|
-
document.head.appendChild(el2);
|
|
6593
|
-
}
|
|
6594
|
-
}
|
|
6595
|
-
}
|
|
6755
|
+
injectToolRendererStyles(event.name, toolRenderer);
|
|
6596
6756
|
const html = toolRenderer.render(toolSeg);
|
|
6597
6757
|
if (html) {
|
|
6598
6758
|
targetElement.addSegment?.(toolSeg);
|
|
@@ -6771,6 +6931,21 @@ ${content}
|
|
|
6771
6931
|
...wholeParser.parse(response).segments,
|
|
6772
6932
|
...wholeParser.finalize()
|
|
6773
6933
|
];
|
|
6934
|
+
const stringHint = baseRequest._meta?.artifactHint;
|
|
6935
|
+
if (stringHint) {
|
|
6936
|
+
const codeIdx = parsed.findIndex((s) => s.type === "code");
|
|
6937
|
+
if (codeIdx !== -1) {
|
|
6938
|
+
const codeSeg = parsed[codeIdx];
|
|
6939
|
+
parsed[codeIdx] = {
|
|
6940
|
+
id: codeSeg.id,
|
|
6941
|
+
type: "artifact",
|
|
6942
|
+
mimeType: stringHint.mimeType,
|
|
6943
|
+
artifactType: stringHint.kind,
|
|
6944
|
+
title: codeSeg.filename ?? stringHint.kind,
|
|
6945
|
+
content: codeSeg.content
|
|
6946
|
+
};
|
|
6947
|
+
}
|
|
6948
|
+
}
|
|
6774
6949
|
if (parsed.length > 0) {
|
|
6775
6950
|
for (const segment of parsed) targetElement.addSegment?.(segment);
|
|
6776
6951
|
this._updateMessage(targetElement, messageId, { status: "completed" });
|
|
@@ -7107,7 +7282,7 @@ ${content}
|
|
|
7107
7282
|
details: error.code
|
|
7108
7283
|
};
|
|
7109
7284
|
if (target.updateMessage) {
|
|
7110
|
-
const rendered = target.getMessages?.()?.find((m) => m.id === messageId)?.segments ?? [];
|
|
7285
|
+
const rendered = target.getMessage?.(messageId)?.segments ?? target.getMessages?.()?.find((m) => m.id === messageId)?.segments ?? [];
|
|
7111
7286
|
target.updateMessage(messageId, {
|
|
7112
7287
|
status: "error",
|
|
7113
7288
|
segments: [...rendered, errorSegment]
|
|
@@ -7464,13 +7639,14 @@ export {
|
|
|
7464
7639
|
unregisterSegmentRenderer as a5,
|
|
7465
7640
|
uuid as a6,
|
|
7466
7641
|
mergeSegmentUpdate as a7,
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7642
|
+
writeStreamedMarkdown as a8,
|
|
7643
|
+
stampSegmentActivity as a9,
|
|
7644
|
+
stampSegmentOnInsert as aa,
|
|
7645
|
+
stampSegmentOnUpdate as ab,
|
|
7646
|
+
renumberSegments as ac,
|
|
7647
|
+
openSegmentIds as ad,
|
|
7648
|
+
isTerminalStatus as ae,
|
|
7649
|
+
adoptMessageSegments as af,
|
|
7474
7650
|
APARTE_DEFAULT_BUBBLE_ACTIONS as b,
|
|
7475
7651
|
APARTE_DEFAULT_HOST_HANDLERS as c,
|
|
7476
7652
|
APARTE_DEFAULT_ICON_FALLBACKS as d,
|
|
@@ -7497,4 +7673,4 @@ export {
|
|
|
7497
7673
|
buildElicitationPanel as y,
|
|
7498
7674
|
collectRendererStyles as z
|
|
7499
7675
|
};
|
|
7500
|
-
//# sourceMappingURL=is-awaiting-reply-
|
|
7676
|
+
//# sourceMappingURL=is-awaiting-reply-CWp1ffHh.js.map
|