@helpai/elements 0.61.4 → 0.62.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/configurator.mjs +3 -0
- package/elements-web-component.esm.js +17 -17
- package/elements-web-component.esm.js.map +3 -3
- package/elements.cjs.js +17 -17
- package/elements.cjs.js.map +3 -3
- package/elements.esm.js +17 -17
- package/elements.esm.js.map +3 -3
- package/elements.js +17 -17
- package/elements.js.map +3 -3
- package/index.d.ts +5 -1
- package/index.mjs +43 -31
- package/package.json +1 -1
- package/schema.d.ts +2 -1
- package/schema.json +14 -2
- package/schema.mjs +3 -0
- package/web-component.mjs +43 -31
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-
|
|
1
|
+
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-i9cta98X.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -871,6 +871,8 @@ interface BehaviorOptions {
|
|
|
871
871
|
showSources?: boolean;
|
|
872
872
|
/** Turn OFF the 👍/👎 feedback controls on assistant replies. Unset/`false` = shown (default). */
|
|
873
873
|
disableMessageFeedback?: boolean;
|
|
874
|
+
/** Auto-send a suggestion chip's text on tap. Unset/`false` = fill the composer to edit (default). */
|
|
875
|
+
autoSendSuggestions?: boolean;
|
|
874
876
|
}
|
|
875
877
|
/**
|
|
876
878
|
* Section: panel header actions — the enabled set (`history`/`close` buttons +
|
|
@@ -1187,6 +1189,8 @@ interface ResolvedOptions {
|
|
|
1187
1189
|
showSources: boolean;
|
|
1188
1190
|
/** Show 👍/👎 feedback controls on assistant replies. Default `true`. */
|
|
1189
1191
|
enableMessageFeedback: boolean;
|
|
1192
|
+
/** Auto-send a suggestion chip's text on tap (vs. filling the composer to edit). Default `false`. */
|
|
1193
|
+
autoSendSuggestions: boolean;
|
|
1190
1194
|
features: ResolvedFeatures;
|
|
1191
1195
|
/** Resolved event-driven forms — ordered list + trigger index. */
|
|
1192
1196
|
forms: ResolvedForms;
|
package/index.mjs
CHANGED
|
@@ -29,7 +29,7 @@ var BRAND = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
// src/core/version.ts
|
|
32
|
-
var ELEMENTS_VERSION = true ? "0.
|
|
32
|
+
var ELEMENTS_VERSION = true ? "0.62.0" : "0.0.0-dev";
|
|
33
33
|
var ELEMENTS_VERSION_PARAM = "_ev";
|
|
34
34
|
|
|
35
35
|
// src/i18n/strings.ts
|
|
@@ -1105,6 +1105,7 @@ function resolveOptions(rawOpts) {
|
|
|
1105
1105
|
showToolCalls: behavior.showToolCalls ?? false,
|
|
1106
1106
|
showSources: behavior.showSources ?? false,
|
|
1107
1107
|
enableMessageFeedback: !(behavior.disableMessageFeedback ?? false),
|
|
1108
|
+
autoSendSuggestions: behavior.autoSendSuggestions ?? false,
|
|
1108
1109
|
features: {
|
|
1109
1110
|
voice: opts.features?.voice ?? DEFAULT_FEATURES.voice,
|
|
1110
1111
|
fileUpload: !(opts.features?.disableFileUpload ?? false),
|
|
@@ -1433,7 +1434,8 @@ var BEHAVIOR_ATTRS = [
|
|
|
1433
1434
|
["show-reasoning", "showReasoning", boolAttr],
|
|
1434
1435
|
["show-tool-calls", "showToolCalls", boolAttr],
|
|
1435
1436
|
["show-sources", "showSources", boolAttr],
|
|
1436
|
-
["disable-message-feedback", "disableMessageFeedback", boolAttr]
|
|
1437
|
+
["disable-message-feedback", "disableMessageFeedback", boolAttr],
|
|
1438
|
+
["auto-send-suggestions", "autoSendSuggestions", boolAttr]
|
|
1437
1439
|
];
|
|
1438
1440
|
var I18N_ATTRS = [["locale", "locale"]];
|
|
1439
1441
|
var ACTION_NAMES = new Set(ACTION_NAME_LITERALS);
|
|
@@ -2254,15 +2256,6 @@ function retryAfterMs(headers) {
|
|
|
2254
2256
|
const ms = Number.isFinite(secs) ? secs * 1e3 : Date.parse(raw) - Date.now();
|
|
2255
2257
|
return Number.isFinite(ms) && ms >= 0 ? Math.min(ms, 3e4) : null;
|
|
2256
2258
|
}
|
|
2257
|
-
function followupsFromMessages(messages) {
|
|
2258
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2259
|
-
const m = messages[i];
|
|
2260
|
-
if (!m || m.role !== "assistant") continue;
|
|
2261
|
-
const part = m.parts.find((p36) => p36.type === "data-suggestions");
|
|
2262
|
-
return part?.type === "data-suggestions" ? parseSuggestions(part.data) : void 0;
|
|
2263
|
-
}
|
|
2264
|
-
return void 0;
|
|
2265
|
-
}
|
|
2266
2259
|
function sleep(ms, signal7) {
|
|
2267
2260
|
return new Promise((resolve) => {
|
|
2268
2261
|
if (signal7?.aborted) return resolve();
|
|
@@ -2509,10 +2502,10 @@ var AgentTransport = class {
|
|
|
2509
2502
|
canContinue: res.canContinue ?? true,
|
|
2510
2503
|
messages,
|
|
2511
2504
|
agent: res.agent,
|
|
2512
|
-
//
|
|
2513
|
-
//
|
|
2514
|
-
//
|
|
2515
|
-
suggestions:
|
|
2505
|
+
// Top-level STARTER chips (resume / new-chat), not turn-tied. A turn's own model follow-ups ride
|
|
2506
|
+
// ON its assistant message (`data-suggestions` part), lifted onto `message.suggestions` by
|
|
2507
|
+
// `fromWireMessage`; the App prefers the last turn's and falls back to these starters.
|
|
2508
|
+
suggestions: res.suggestions
|
|
2516
2509
|
};
|
|
2517
2510
|
}
|
|
2518
2511
|
/**
|
|
@@ -3014,9 +3007,11 @@ function fromWireMessage(w) {
|
|
|
3014
3007
|
}
|
|
3015
3008
|
return null;
|
|
3016
3009
|
}).filter((p36) => p36 !== null);
|
|
3010
|
+
const suggestionsPart = w.parts.find((p36) => p36.type === "data-suggestions");
|
|
3017
3011
|
return {
|
|
3018
3012
|
id: w.id,
|
|
3019
3013
|
role: w.role,
|
|
3014
|
+
suggestions: suggestionsPart?.type === "data-suggestions" ? parseSuggestions(suggestionsPart.data) : void 0,
|
|
3020
3015
|
// On reload the wire `id` IS the backend's id — keep it as `serverMessageId`
|
|
3021
3016
|
// too so a HITL re-POST after a reload still references the backend's message.
|
|
3022
3017
|
serverMessageId: w.id,
|
|
@@ -3239,6 +3234,7 @@ var StreamReducer = class {
|
|
|
3239
3234
|
case "data-conversation-rebind":
|
|
3240
3235
|
return;
|
|
3241
3236
|
case "data-suggestions":
|
|
3237
|
+
m.suggestions = parseSuggestions(chunk.data);
|
|
3242
3238
|
return;
|
|
3243
3239
|
default: {
|
|
3244
3240
|
const _exhaustive = chunk;
|
|
@@ -4532,6 +4528,13 @@ function Composer({ options, transport, feedback, bus, isStreaming, onSend, onSt
|
|
|
4532
4528
|
log11.info("attach (drop)", { count: result.accepted.length, totalBytes: totalBytes(result.accepted) });
|
|
4533
4529
|
bus.emit("attach", { count: result.accepted.length, totalBytes: totalBytes(result.accepted) });
|
|
4534
4530
|
setAtts((prev) => [...prev, ...result.accepted]);
|
|
4531
|
+
},
|
|
4532
|
+
fill: (value) => {
|
|
4533
|
+
setText(value);
|
|
4534
|
+
const el = taRef.current;
|
|
4535
|
+
if (!el) return;
|
|
4536
|
+
el.focus({ preventScroll: true });
|
|
4537
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
4535
4538
|
}
|
|
4536
4539
|
};
|
|
4537
4540
|
return () => {
|
|
@@ -6896,10 +6899,13 @@ function Panel(props2) {
|
|
|
6896
6899
|
el.removeEventListener("keydown", onKey);
|
|
6897
6900
|
};
|
|
6898
6901
|
}, [onClose]);
|
|
6899
|
-
const
|
|
6900
|
-
const onDropItems = useCallback2(
|
|
6901
|
-
|
|
6902
|
-
|
|
6902
|
+
const composerApiRef = props2.composerApiRef;
|
|
6903
|
+
const onDropItems = useCallback2(
|
|
6904
|
+
(items) => {
|
|
6905
|
+
composerApiRef.current?.attachFromDrop(items);
|
|
6906
|
+
},
|
|
6907
|
+
[composerApiRef]
|
|
6908
|
+
);
|
|
6903
6909
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
6904
6910
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
6905
6911
|
return /* @__PURE__ */ jsxs18(
|
|
@@ -6919,7 +6925,7 @@ function Panel(props2) {
|
|
|
6919
6925
|
...props2,
|
|
6920
6926
|
containerEl: containerRef.current,
|
|
6921
6927
|
dragOver,
|
|
6922
|
-
composerAttachApiRef
|
|
6928
|
+
composerAttachApiRef: composerApiRef
|
|
6923
6929
|
}
|
|
6924
6930
|
),
|
|
6925
6931
|
/* @__PURE__ */ jsx23(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
@@ -8236,6 +8242,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8236
8242
|
const resumeBubbleRef = useRef9(null);
|
|
8237
8243
|
const regenerateDanglingRef = useRef9(null);
|
|
8238
8244
|
const regenInFlightRef = useRef9(false);
|
|
8245
|
+
const composerApiRef = useRef9(null);
|
|
8239
8246
|
const markActiveConversationReadRef = useRef9(null);
|
|
8240
8247
|
const markReadTimerRef = useRef9();
|
|
8241
8248
|
useEffect16(() => () => clearTimeout(markReadTimerRef.current), []);
|
|
@@ -8305,7 +8312,8 @@ function App({ options, hostElement, bus }) {
|
|
|
8305
8312
|
if (loaded.length || tail.length) {
|
|
8306
8313
|
messagesSig.value = [...withWelcomeRows(loaded, markers), ...tail];
|
|
8307
8314
|
setCanSend(chat.canContinue ?? true);
|
|
8308
|
-
|
|
8315
|
+
const lastTurn = loaded.findLast((m) => m.role === "assistant" && !m.ephemeral);
|
|
8316
|
+
setSuggestions(lastTurn?.suggestions ?? chat.suggestions ?? []);
|
|
8309
8317
|
} else {
|
|
8310
8318
|
messagesSig.value = withWelcomeRows([], markers);
|
|
8311
8319
|
}
|
|
@@ -8439,11 +8447,10 @@ function App({ options, hostElement, bus }) {
|
|
|
8439
8447
|
useEffect16(() => {
|
|
8440
8448
|
if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
|
|
8441
8449
|
}, [effectiveLocale, activeLocale]);
|
|
8442
|
-
const
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
}, []);
|
|
8450
|
+
const settleSuggestions = useCallback6(
|
|
8451
|
+
(turn, starters = []) => setSuggestions(turn.suggestions ?? starters),
|
|
8452
|
+
[]
|
|
8453
|
+
);
|
|
8447
8454
|
const adoptConversationRebind = useCallback6(
|
|
8448
8455
|
(chunk) => {
|
|
8449
8456
|
if (chunk.type !== "data-conversation-rebind") return false;
|
|
@@ -8465,7 +8472,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8465
8472
|
let bubble = null;
|
|
8466
8473
|
try {
|
|
8467
8474
|
for await (const evt of handle.iter) {
|
|
8468
|
-
if (adoptConversationRebind(evt.chunk)
|
|
8475
|
+
if (adoptConversationRebind(evt.chunk)) continue;
|
|
8469
8476
|
if (!bubble) {
|
|
8470
8477
|
bubble = makeAssistantMessage();
|
|
8471
8478
|
resumeBubbleRef.current = bubble;
|
|
@@ -8491,6 +8498,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8491
8498
|
bubble.status = "complete";
|
|
8492
8499
|
feedback.play("messageReceived");
|
|
8493
8500
|
emitMessage(bus, options, "assistant", assistantText(bubble));
|
|
8501
|
+
settleSuggestions(bubble);
|
|
8494
8502
|
}
|
|
8495
8503
|
}
|
|
8496
8504
|
} catch (err) {
|
|
@@ -8635,7 +8643,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8635
8643
|
setActiveDetach(() => handle.detach);
|
|
8636
8644
|
try {
|
|
8637
8645
|
for await (const evt of handle.iter) {
|
|
8638
|
-
if (adoptConversationRebind(evt.chunk)
|
|
8646
|
+
if (adoptConversationRebind(evt.chunk)) continue;
|
|
8639
8647
|
reducer.apply(evt.chunk);
|
|
8640
8648
|
if (evt.chunk.type === "finish" && evt.chunk.canContinue === false) {
|
|
8641
8649
|
setCanSend(false);
|
|
@@ -8654,6 +8662,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8654
8662
|
assistantMsg.status = "complete";
|
|
8655
8663
|
feedback.play("messageReceived");
|
|
8656
8664
|
emitMessage(bus, options, "assistant", assistantText(assistantMsg));
|
|
8665
|
+
settleSuggestions(assistantMsg);
|
|
8657
8666
|
}
|
|
8658
8667
|
} catch (error) {
|
|
8659
8668
|
if (isAbortError(error)) {
|
|
@@ -9072,7 +9081,8 @@ function App({ options, hostElement, bus }) {
|
|
|
9072
9081
|
transport.primeIdentity(visitorId, res.conversationId);
|
|
9073
9082
|
if (res.agent) setAgent(res.agent);
|
|
9074
9083
|
setCanSend(res.canContinue);
|
|
9075
|
-
|
|
9084
|
+
const lastTurn = hydrated.findLast((m) => m.role === "assistant" && !m.ephemeral);
|
|
9085
|
+
setSuggestions(lastTurn?.suggestions ?? res.suggestions ?? []);
|
|
9076
9086
|
setView("chat");
|
|
9077
9087
|
void resumeInFlight();
|
|
9078
9088
|
await transport.markRead(targetConversationId);
|
|
@@ -9140,6 +9150,7 @@ function App({ options, hostElement, bus }) {
|
|
|
9140
9150
|
feedback,
|
|
9141
9151
|
bus,
|
|
9142
9152
|
persistence,
|
|
9153
|
+
composerApiRef,
|
|
9143
9154
|
view,
|
|
9144
9155
|
canSend,
|
|
9145
9156
|
isStreaming: streaming,
|
|
@@ -9165,9 +9176,10 @@ function App({ options, hostElement, bus }) {
|
|
|
9165
9176
|
onStop: handleStop,
|
|
9166
9177
|
onSuggestion: (s) => {
|
|
9167
9178
|
const text = s.text ?? s.label;
|
|
9168
|
-
log17.info("suggestion", { text });
|
|
9179
|
+
log17.info("suggestion", { text, autoSend: options.autoSendSuggestions });
|
|
9169
9180
|
bus.emit("suggestion", { text });
|
|
9170
|
-
void handleSend(text, []);
|
|
9181
|
+
if (options.autoSendSuggestions) void handleSend(text, []);
|
|
9182
|
+
else composerApiRef.current?.fill(text);
|
|
9171
9183
|
},
|
|
9172
9184
|
// Active form: replaces the composer as a gate and locks every chat action
|
|
9173
9185
|
// until the visitor submits or (when skippable) skips.
|
package/package.json
CHANGED
package/schema.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-
|
|
1
|
+
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-i9cta98X.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -85,6 +85,7 @@ declare const behaviorSchema: z.ZodObject<{
|
|
|
85
85
|
showToolCalls: z.ZodDefault<z.ZodBoolean>;
|
|
86
86
|
showSources: z.ZodDefault<z.ZodBoolean>;
|
|
87
87
|
disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
|
|
88
|
+
autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
|
|
88
89
|
}, z.core.$loose>;
|
|
89
90
|
type Behavior = z.infer<typeof behaviorSchema>;
|
|
90
91
|
|
package/schema.json
CHANGED
|
@@ -489,6 +489,11 @@
|
|
|
489
489
|
"default": false,
|
|
490
490
|
"description": "Turn OFF the 👍/👎 feedback controls under each assistant reply. Unset/`false` = shown (default), `true` = hidden. A choice fires the `messageFeedback` event and is POSTed best-effort to `/pai/message-feedback`.",
|
|
491
491
|
"type": "boolean"
|
|
492
|
+
},
|
|
493
|
+
"autoSendSuggestions": {
|
|
494
|
+
"default": false,
|
|
495
|
+
"description": "Auto-send a suggestion chip's text the moment it's tapped. `false` (default) fills the composer with the text so the visitor can edit before sending; `true` sends it immediately.",
|
|
496
|
+
"type": "boolean"
|
|
492
497
|
}
|
|
493
498
|
},
|
|
494
499
|
"required": [
|
|
@@ -497,7 +502,8 @@
|
|
|
497
502
|
"showReasoning",
|
|
498
503
|
"showToolCalls",
|
|
499
504
|
"showSources",
|
|
500
|
-
"disableMessageFeedback"
|
|
505
|
+
"disableMessageFeedback",
|
|
506
|
+
"autoSendSuggestions"
|
|
501
507
|
],
|
|
502
508
|
"additionalProperties": {},
|
|
503
509
|
"description": "Conversation behaviour — lifecycle, streaming, and the transcript surface (scroll, feedback).",
|
|
@@ -2360,6 +2366,11 @@
|
|
|
2360
2366
|
"default": false,
|
|
2361
2367
|
"description": "Turn OFF the 👍/👎 feedback controls under each assistant reply. Unset/`false` = shown (default), `true` = hidden. A choice fires the `messageFeedback` event and is POSTed best-effort to `/pai/message-feedback`.",
|
|
2362
2368
|
"type": "boolean"
|
|
2369
|
+
},
|
|
2370
|
+
"autoSendSuggestions": {
|
|
2371
|
+
"default": false,
|
|
2372
|
+
"description": "Auto-send a suggestion chip's text the moment it's tapped. `false` (default) fills the composer with the text so the visitor can edit before sending; `true` sends it immediately.",
|
|
2373
|
+
"type": "boolean"
|
|
2363
2374
|
}
|
|
2364
2375
|
},
|
|
2365
2376
|
"required": [
|
|
@@ -2368,7 +2379,8 @@
|
|
|
2368
2379
|
"showReasoning",
|
|
2369
2380
|
"showToolCalls",
|
|
2370
2381
|
"showSources",
|
|
2371
|
-
"disableMessageFeedback"
|
|
2382
|
+
"disableMessageFeedback",
|
|
2383
|
+
"autoSendSuggestions"
|
|
2372
2384
|
],
|
|
2373
2385
|
"additionalProperties": {},
|
|
2374
2386
|
"description": "Conversation behaviour — lifecycle, streaming, and the transcript surface (scroll, feedback).",
|
package/schema.mjs
CHANGED
|
@@ -133,6 +133,9 @@ var behaviorSchema = z4.object({
|
|
|
133
133
|
),
|
|
134
134
|
disableMessageFeedback: z4.boolean().default(false).describe(
|
|
135
135
|
"Turn OFF the \u{1F44D}/\u{1F44E} feedback controls under each assistant reply. Unset/`false` = shown (default), `true` = hidden. A choice fires the `messageFeedback` event and is POSTed best-effort to `/pai/message-feedback`."
|
|
136
|
+
),
|
|
137
|
+
autoSendSuggestions: z4.boolean().default(false).describe(
|
|
138
|
+
"Auto-send a suggestion chip's text the moment it's tapped. `false` (default) fills the composer with the text so the visitor can edit before sending; `true` sends it immediately."
|
|
136
139
|
)
|
|
137
140
|
}).loose().describe("Conversation behaviour \u2014 lifecycle, streaming, and the transcript surface (scroll, feedback).").meta({
|
|
138
141
|
examples: [
|
package/web-component.mjs
CHANGED
|
@@ -1086,6 +1086,7 @@ function resolveOptions(rawOpts) {
|
|
|
1086
1086
|
showToolCalls: behavior.showToolCalls ?? false,
|
|
1087
1087
|
showSources: behavior.showSources ?? false,
|
|
1088
1088
|
enableMessageFeedback: !(behavior.disableMessageFeedback ?? false),
|
|
1089
|
+
autoSendSuggestions: behavior.autoSendSuggestions ?? false,
|
|
1089
1090
|
features: {
|
|
1090
1091
|
voice: opts.features?.voice ?? DEFAULT_FEATURES.voice,
|
|
1091
1092
|
fileUpload: !(opts.features?.disableFileUpload ?? false),
|
|
@@ -1414,7 +1415,8 @@ var BEHAVIOR_ATTRS = [
|
|
|
1414
1415
|
["show-reasoning", "showReasoning", boolAttr],
|
|
1415
1416
|
["show-tool-calls", "showToolCalls", boolAttr],
|
|
1416
1417
|
["show-sources", "showSources", boolAttr],
|
|
1417
|
-
["disable-message-feedback", "disableMessageFeedback", boolAttr]
|
|
1418
|
+
["disable-message-feedback", "disableMessageFeedback", boolAttr],
|
|
1419
|
+
["auto-send-suggestions", "autoSendSuggestions", boolAttr]
|
|
1418
1420
|
];
|
|
1419
1421
|
var I18N_ATTRS = [["locale", "locale"]];
|
|
1420
1422
|
var ACTION_NAMES = new Set(ACTION_NAME_LITERALS);
|
|
@@ -1930,7 +1932,7 @@ function createAuth(opts) {
|
|
|
1930
1932
|
}
|
|
1931
1933
|
|
|
1932
1934
|
// src/core/version.ts
|
|
1933
|
-
var ELEMENTS_VERSION = true ? "0.
|
|
1935
|
+
var ELEMENTS_VERSION = true ? "0.62.0" : "0.0.0-dev";
|
|
1934
1936
|
var ELEMENTS_VERSION_PARAM = "_ev";
|
|
1935
1937
|
|
|
1936
1938
|
// src/stream/types.ts
|
|
@@ -2213,15 +2215,6 @@ function retryAfterMs(headers) {
|
|
|
2213
2215
|
const ms = Number.isFinite(secs) ? secs * 1e3 : Date.parse(raw) - Date.now();
|
|
2214
2216
|
return Number.isFinite(ms) && ms >= 0 ? Math.min(ms, 3e4) : null;
|
|
2215
2217
|
}
|
|
2216
|
-
function followupsFromMessages(messages) {
|
|
2217
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2218
|
-
const m = messages[i];
|
|
2219
|
-
if (!m || m.role !== "assistant") continue;
|
|
2220
|
-
const part = m.parts.find((p36) => p36.type === "data-suggestions");
|
|
2221
|
-
return part?.type === "data-suggestions" ? parseSuggestions(part.data) : void 0;
|
|
2222
|
-
}
|
|
2223
|
-
return void 0;
|
|
2224
|
-
}
|
|
2225
2218
|
function sleep(ms, signal7) {
|
|
2226
2219
|
return new Promise((resolve) => {
|
|
2227
2220
|
if (signal7?.aborted) return resolve();
|
|
@@ -2468,10 +2461,10 @@ var AgentTransport = class {
|
|
|
2468
2461
|
canContinue: res.canContinue ?? true,
|
|
2469
2462
|
messages,
|
|
2470
2463
|
agent: res.agent,
|
|
2471
|
-
//
|
|
2472
|
-
//
|
|
2473
|
-
//
|
|
2474
|
-
suggestions:
|
|
2464
|
+
// Top-level STARTER chips (resume / new-chat), not turn-tied. A turn's own model follow-ups ride
|
|
2465
|
+
// ON its assistant message (`data-suggestions` part), lifted onto `message.suggestions` by
|
|
2466
|
+
// `fromWireMessage`; the App prefers the last turn's and falls back to these starters.
|
|
2467
|
+
suggestions: res.suggestions
|
|
2475
2468
|
};
|
|
2476
2469
|
}
|
|
2477
2470
|
/**
|
|
@@ -2973,9 +2966,11 @@ function fromWireMessage(w) {
|
|
|
2973
2966
|
}
|
|
2974
2967
|
return null;
|
|
2975
2968
|
}).filter((p36) => p36 !== null);
|
|
2969
|
+
const suggestionsPart = w.parts.find((p36) => p36.type === "data-suggestions");
|
|
2976
2970
|
return {
|
|
2977
2971
|
id: w.id,
|
|
2978
2972
|
role: w.role,
|
|
2973
|
+
suggestions: suggestionsPart?.type === "data-suggestions" ? parseSuggestions(suggestionsPart.data) : void 0,
|
|
2979
2974
|
// On reload the wire `id` IS the backend's id — keep it as `serverMessageId`
|
|
2980
2975
|
// too so a HITL re-POST after a reload still references the backend's message.
|
|
2981
2976
|
serverMessageId: w.id,
|
|
@@ -3198,6 +3193,7 @@ var StreamReducer = class {
|
|
|
3198
3193
|
case "data-conversation-rebind":
|
|
3199
3194
|
return;
|
|
3200
3195
|
case "data-suggestions":
|
|
3196
|
+
m.suggestions = parseSuggestions(chunk.data);
|
|
3201
3197
|
return;
|
|
3202
3198
|
default: {
|
|
3203
3199
|
const _exhaustive = chunk;
|
|
@@ -4491,6 +4487,13 @@ function Composer({ options, transport, feedback, bus, isStreaming, onSend, onSt
|
|
|
4491
4487
|
log10.info("attach (drop)", { count: result.accepted.length, totalBytes: totalBytes(result.accepted) });
|
|
4492
4488
|
bus.emit("attach", { count: result.accepted.length, totalBytes: totalBytes(result.accepted) });
|
|
4493
4489
|
setAtts((prev) => [...prev, ...result.accepted]);
|
|
4490
|
+
},
|
|
4491
|
+
fill: (value) => {
|
|
4492
|
+
setText(value);
|
|
4493
|
+
const el = taRef.current;
|
|
4494
|
+
if (!el) return;
|
|
4495
|
+
el.focus({ preventScroll: true });
|
|
4496
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
4494
4497
|
}
|
|
4495
4498
|
};
|
|
4496
4499
|
return () => {
|
|
@@ -6855,10 +6858,13 @@ function Panel(props2) {
|
|
|
6855
6858
|
el.removeEventListener("keydown", onKey);
|
|
6856
6859
|
};
|
|
6857
6860
|
}, [onClose]);
|
|
6858
|
-
const
|
|
6859
|
-
const onDropItems = useCallback2(
|
|
6860
|
-
|
|
6861
|
-
|
|
6861
|
+
const composerApiRef = props2.composerApiRef;
|
|
6862
|
+
const onDropItems = useCallback2(
|
|
6863
|
+
(items) => {
|
|
6864
|
+
composerApiRef.current?.attachFromDrop(items);
|
|
6865
|
+
},
|
|
6866
|
+
[composerApiRef]
|
|
6867
|
+
);
|
|
6862
6868
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
6863
6869
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
6864
6870
|
return /* @__PURE__ */ jsxs18(
|
|
@@ -6878,7 +6884,7 @@ function Panel(props2) {
|
|
|
6878
6884
|
...props2,
|
|
6879
6885
|
containerEl: containerRef.current,
|
|
6880
6886
|
dragOver,
|
|
6881
|
-
composerAttachApiRef
|
|
6887
|
+
composerAttachApiRef: composerApiRef
|
|
6882
6888
|
}
|
|
6883
6889
|
),
|
|
6884
6890
|
/* @__PURE__ */ jsx23(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
@@ -8195,6 +8201,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8195
8201
|
const resumeBubbleRef = useRef9(null);
|
|
8196
8202
|
const regenerateDanglingRef = useRef9(null);
|
|
8197
8203
|
const regenInFlightRef = useRef9(false);
|
|
8204
|
+
const composerApiRef = useRef9(null);
|
|
8198
8205
|
const markActiveConversationReadRef = useRef9(null);
|
|
8199
8206
|
const markReadTimerRef = useRef9();
|
|
8200
8207
|
useEffect16(() => () => clearTimeout(markReadTimerRef.current), []);
|
|
@@ -8264,7 +8271,8 @@ function App({ options, hostElement, bus }) {
|
|
|
8264
8271
|
if (loaded.length || tail.length) {
|
|
8265
8272
|
messagesSig.value = [...withWelcomeRows(loaded, markers), ...tail];
|
|
8266
8273
|
setCanSend(chat.canContinue ?? true);
|
|
8267
|
-
|
|
8274
|
+
const lastTurn = loaded.findLast((m) => m.role === "assistant" && !m.ephemeral);
|
|
8275
|
+
setSuggestions(lastTurn?.suggestions ?? chat.suggestions ?? []);
|
|
8268
8276
|
} else {
|
|
8269
8277
|
messagesSig.value = withWelcomeRows([], markers);
|
|
8270
8278
|
}
|
|
@@ -8398,11 +8406,10 @@ function App({ options, hostElement, bus }) {
|
|
|
8398
8406
|
useEffect16(() => {
|
|
8399
8407
|
if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
|
|
8400
8408
|
}, [effectiveLocale, activeLocale]);
|
|
8401
|
-
const
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
}, []);
|
|
8409
|
+
const settleSuggestions = useCallback6(
|
|
8410
|
+
(turn, starters = []) => setSuggestions(turn.suggestions ?? starters),
|
|
8411
|
+
[]
|
|
8412
|
+
);
|
|
8406
8413
|
const adoptConversationRebind = useCallback6(
|
|
8407
8414
|
(chunk) => {
|
|
8408
8415
|
if (chunk.type !== "data-conversation-rebind") return false;
|
|
@@ -8424,7 +8431,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8424
8431
|
let bubble = null;
|
|
8425
8432
|
try {
|
|
8426
8433
|
for await (const evt of handle.iter) {
|
|
8427
|
-
if (adoptConversationRebind(evt.chunk)
|
|
8434
|
+
if (adoptConversationRebind(evt.chunk)) continue;
|
|
8428
8435
|
if (!bubble) {
|
|
8429
8436
|
bubble = makeAssistantMessage();
|
|
8430
8437
|
resumeBubbleRef.current = bubble;
|
|
@@ -8450,6 +8457,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8450
8457
|
bubble.status = "complete";
|
|
8451
8458
|
feedback.play("messageReceived");
|
|
8452
8459
|
emitMessage(bus, options, "assistant", assistantText(bubble));
|
|
8460
|
+
settleSuggestions(bubble);
|
|
8453
8461
|
}
|
|
8454
8462
|
}
|
|
8455
8463
|
} catch (err) {
|
|
@@ -8594,7 +8602,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8594
8602
|
setActiveDetach(() => handle.detach);
|
|
8595
8603
|
try {
|
|
8596
8604
|
for await (const evt of handle.iter) {
|
|
8597
|
-
if (adoptConversationRebind(evt.chunk)
|
|
8605
|
+
if (adoptConversationRebind(evt.chunk)) continue;
|
|
8598
8606
|
reducer.apply(evt.chunk);
|
|
8599
8607
|
if (evt.chunk.type === "finish" && evt.chunk.canContinue === false) {
|
|
8600
8608
|
setCanSend(false);
|
|
@@ -8613,6 +8621,7 @@ function App({ options, hostElement, bus }) {
|
|
|
8613
8621
|
assistantMsg.status = "complete";
|
|
8614
8622
|
feedback.play("messageReceived");
|
|
8615
8623
|
emitMessage(bus, options, "assistant", assistantText(assistantMsg));
|
|
8624
|
+
settleSuggestions(assistantMsg);
|
|
8616
8625
|
}
|
|
8617
8626
|
} catch (error) {
|
|
8618
8627
|
if (isAbortError(error)) {
|
|
@@ -9031,7 +9040,8 @@ function App({ options, hostElement, bus }) {
|
|
|
9031
9040
|
transport.primeIdentity(visitorId, res.conversationId);
|
|
9032
9041
|
if (res.agent) setAgent(res.agent);
|
|
9033
9042
|
setCanSend(res.canContinue);
|
|
9034
|
-
|
|
9043
|
+
const lastTurn = hydrated.findLast((m) => m.role === "assistant" && !m.ephemeral);
|
|
9044
|
+
setSuggestions(lastTurn?.suggestions ?? res.suggestions ?? []);
|
|
9035
9045
|
setView("chat");
|
|
9036
9046
|
void resumeInFlight();
|
|
9037
9047
|
await transport.markRead(targetConversationId);
|
|
@@ -9099,6 +9109,7 @@ function App({ options, hostElement, bus }) {
|
|
|
9099
9109
|
feedback,
|
|
9100
9110
|
bus,
|
|
9101
9111
|
persistence,
|
|
9112
|
+
composerApiRef,
|
|
9102
9113
|
view,
|
|
9103
9114
|
canSend,
|
|
9104
9115
|
isStreaming: streaming,
|
|
@@ -9124,9 +9135,10 @@ function App({ options, hostElement, bus }) {
|
|
|
9124
9135
|
onStop: handleStop,
|
|
9125
9136
|
onSuggestion: (s) => {
|
|
9126
9137
|
const text = s.text ?? s.label;
|
|
9127
|
-
log16.info("suggestion", { text });
|
|
9138
|
+
log16.info("suggestion", { text, autoSend: options.autoSendSuggestions });
|
|
9128
9139
|
bus.emit("suggestion", { text });
|
|
9129
|
-
void handleSend(text, []);
|
|
9140
|
+
if (options.autoSendSuggestions) void handleSend(text, []);
|
|
9141
|
+
else composerApiRef.current?.fill(text);
|
|
9130
9142
|
},
|
|
9131
9143
|
// Active form: replaces the composer as a gate and locks every chat action
|
|
9132
9144
|
// until the visitor submits or (when skippable) skips.
|