@webless/agent 0.2.0 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -106
- package/dist/{chunk-WLQDMWO6.js → chunk-4QGS7UZY.js} +899 -736
- package/dist/chunk-4QGS7UZY.js.map +1 -0
- package/dist/embed.cjs +709 -612
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.css +156 -148
- package/dist/embed.css.map +1 -1
- package/dist/embed.d.cts +23 -13
- package/dist/embed.d.ts +23 -13
- package/dist/embed.js +72 -131
- package/dist/embed.js.map +1 -1
- package/dist/index.cjs +19 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +19 -6
- package/dist/index.js.map +1 -1
- package/dist/placement-CXW_83AF.d.cts +25 -0
- package/dist/placement-CXW_83AF.d.ts +25 -0
- package/dist/react.cjs +876 -718
- package/dist/react.cjs.map +1 -1
- package/dist/react.css +156 -1
- package/dist/react.css.map +1 -1
- package/dist/react.d.cts +16 -13
- package/dist/react.d.ts +16 -13
- package/dist/react.js +8 -1
- package/dist/react.js.map +1 -1
- package/package.json +5 -5
- package/scripts/build-agent-manifest-bundle-impl.mjs +32 -32
- package/scripts/ensure-css-imports.mjs +53 -0
- package/dist/chunk-WLQDMWO6.js.map +0 -1
|
@@ -1,524 +1,127 @@
|
|
|
1
|
-
// src/react/
|
|
2
|
-
import { useEffect, useRef
|
|
1
|
+
// src/react/hooks/useAgentChat.ts
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
|
|
4
|
-
// src/
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/* @__PURE__ */ jsx("path", { d: "M14 8a6 6 0 0 0-6-6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
10
|
-
] });
|
|
11
|
-
}
|
|
12
|
-
function getCurrentStep(steps) {
|
|
13
|
-
const active = steps.find((step) => step.state === "active");
|
|
14
|
-
if (active) return active;
|
|
15
|
-
const error = steps.find((step) => step.state === "error");
|
|
16
|
-
if (error) return error;
|
|
17
|
-
const pending = steps.find((step) => step.state === "pending");
|
|
18
|
-
if (pending) return pending;
|
|
19
|
-
return steps.at(-1) ?? null;
|
|
20
|
-
}
|
|
21
|
-
function ToolTimeline({
|
|
22
|
-
steps,
|
|
23
|
-
streamingText,
|
|
24
|
-
showStreaming = false,
|
|
25
|
-
inline = false
|
|
26
|
-
}) {
|
|
27
|
-
if (steps.length === 0 && !(showStreaming && streamingText)) return null;
|
|
28
|
-
const currentStep = getCurrentStep(steps);
|
|
29
|
-
const showStatus = currentStep && currentStep.state !== "completed" && !(showStreaming && streamingText);
|
|
30
|
-
return /* @__PURE__ */ jsxs(
|
|
31
|
-
"div",
|
|
32
|
-
{
|
|
33
|
-
className: `tool-timeline${inline ? " tool-timeline--inline" : ""}`,
|
|
34
|
-
role: "status",
|
|
35
|
-
"aria-live": "polite",
|
|
36
|
-
"aria-label": "Agent progress",
|
|
37
|
-
children: [
|
|
38
|
-
showStatus ? /* @__PURE__ */ jsxs("div", { className: "agent-status", children: [
|
|
39
|
-
currentStep.state === "error" ? /* @__PURE__ */ jsx("span", { className: "agent-status__icon agent-status__icon--error", "aria-hidden": "true", children: "!" }) : /* @__PURE__ */ jsx("span", { className: "agent-status__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(SpinnerIcon, {}) }),
|
|
40
|
-
/* @__PURE__ */ jsxs("div", { className: "agent-status__copy", children: [
|
|
41
|
-
/* @__PURE__ */ jsx("span", { className: "agent-status__label", children: currentStep.label }),
|
|
42
|
-
currentStep.detail ? /* @__PURE__ */ jsx("span", { className: "agent-status__detail", children: currentStep.detail }) : null
|
|
43
|
-
] })
|
|
44
|
-
] }, currentStep.id) : null,
|
|
45
|
-
showStreaming && streamingText ? /* @__PURE__ */ jsxs("p", { className: "tool-timeline__streaming-text", children: [
|
|
46
|
-
streamingText,
|
|
47
|
-
/* @__PURE__ */ jsx("span", { className: "tool-timeline__cursor", "aria-hidden": "true" })
|
|
48
|
-
] }) : null
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
}
|
|
4
|
+
// src/runtime/client.ts
|
|
5
|
+
import {
|
|
6
|
+
Client,
|
|
7
|
+
ClientError
|
|
8
|
+
} from "eve/client";
|
|
53
9
|
|
|
54
|
-
// src/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
10
|
+
// src/runtime/config.ts
|
|
11
|
+
var DEFAULT_RUNTIME_ORIGIN = "https://runtime.staging.webless.ai";
|
|
12
|
+
var trimTrailingSlash = (value) => value.replace(/\/+$/, "");
|
|
13
|
+
function buildEveHost(origin, indexId, version = "published") {
|
|
14
|
+
const base = trimTrailingSlash(origin);
|
|
15
|
+
const searchParams = new URLSearchParams({ indexId: indexId.trim() });
|
|
16
|
+
if (version === "unpublished") {
|
|
17
|
+
searchParams.set("version", version);
|
|
18
|
+
}
|
|
19
|
+
return `${base}?${searchParams.toString()}`;
|
|
20
|
+
}
|
|
21
|
+
function resolveAgentRuntimeConfig(input) {
|
|
22
|
+
const origin = trimTrailingSlash(input.runtimeOrigin?.trim() || DEFAULT_RUNTIME_ORIGIN);
|
|
23
|
+
const resolvedIndexId = input.indexId.trim();
|
|
24
|
+
const version = input.version ?? "published";
|
|
25
|
+
return {
|
|
26
|
+
origin,
|
|
27
|
+
indexId: resolvedIndexId,
|
|
28
|
+
version,
|
|
29
|
+
host: resolvedIndexId ? buildEveHost(origin, resolvedIndexId, version) : origin
|
|
30
|
+
};
|
|
70
31
|
}
|
|
71
32
|
|
|
72
|
-
// src/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
33
|
+
// src/runtime/session-store.ts
|
|
34
|
+
var DEFAULT_STORAGE_KEY_PREFIX = "webless:agent";
|
|
35
|
+
function normalizeRuntimeOrigin(runtimeOrigin) {
|
|
36
|
+
const trimmed = runtimeOrigin?.trim();
|
|
37
|
+
if (!trimmed) return "_";
|
|
38
|
+
return trimmed.replace(/\/+$/, "");
|
|
77
39
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}) {
|
|
84
|
-
const [value, setValue] = useState("");
|
|
85
|
-
const inputRef = useRef(null);
|
|
86
|
-
function submitCurrent() {
|
|
87
|
-
const trimmed = value.trim();
|
|
88
|
-
if (!trimmed || disabled) return;
|
|
89
|
-
onSubmit?.(trimmed);
|
|
90
|
-
setValue("");
|
|
91
|
-
inputRef.current?.focus();
|
|
92
|
-
}
|
|
93
|
-
function handleSubmit(event) {
|
|
94
|
-
event.preventDefault();
|
|
95
|
-
submitCurrent();
|
|
96
|
-
}
|
|
97
|
-
function handleKeyDown(event) {
|
|
98
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
99
|
-
event.preventDefault();
|
|
100
|
-
submitCurrent();
|
|
101
|
-
}
|
|
40
|
+
function buildAgentStorageKeyPrefix(input) {
|
|
41
|
+
const customerId = input.customerId?.trim() || "_";
|
|
42
|
+
const indexId = input.indexId.trim();
|
|
43
|
+
if (!indexId) {
|
|
44
|
+
throw new Error("indexId is required to build agent storage keys.");
|
|
102
45
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"textarea",
|
|
106
|
-
{
|
|
107
|
-
ref: inputRef,
|
|
108
|
-
className: "composer__input",
|
|
109
|
-
rows: 1,
|
|
110
|
-
value,
|
|
111
|
-
placeholder,
|
|
112
|
-
disabled,
|
|
113
|
-
"aria-label": "Message",
|
|
114
|
-
onChange: (event) => setValue(event.target.value),
|
|
115
|
-
onKeyDown: handleKeyDown
|
|
116
|
-
}
|
|
117
|
-
),
|
|
118
|
-
/* @__PURE__ */ jsx3(
|
|
119
|
-
"button",
|
|
120
|
-
{
|
|
121
|
-
type: "submit",
|
|
122
|
-
className: "composer__send",
|
|
123
|
-
disabled: disabled || !value.trim(),
|
|
124
|
-
"aria-label": "Send message",
|
|
125
|
-
children: /* @__PURE__ */ jsx3(SendIcon, {})
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
] }) });
|
|
46
|
+
const versionSuffix = input.version === "unpublished" ? ":unpublished" : "";
|
|
47
|
+
return `${DEFAULT_STORAGE_KEY_PREFIX}:${customerId}:${indexId}${versionSuffix}:${normalizeRuntimeOrigin(input.runtimeOrigin)}`;
|
|
129
48
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
function FollowUpChips({
|
|
134
|
-
suggestions,
|
|
135
|
-
disabled = false,
|
|
136
|
-
label = "Follow up",
|
|
137
|
-
variant = "default",
|
|
138
|
-
onSelect
|
|
139
|
-
}) {
|
|
140
|
-
if (suggestions.length === 0) return null;
|
|
141
|
-
if (variant === "dock") {
|
|
142
|
-
return /* @__PURE__ */ jsx4("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx4("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
|
|
143
|
-
"button",
|
|
144
|
-
{
|
|
145
|
-
type: "button",
|
|
146
|
-
className: "followups__chip followups__chip--dock",
|
|
147
|
-
disabled,
|
|
148
|
-
onClick: () => onSelect?.(suggestion),
|
|
149
|
-
children: suggestion.label
|
|
150
|
-
},
|
|
151
|
-
suggestion.id
|
|
152
|
-
)) }) });
|
|
49
|
+
function createSessionId() {
|
|
50
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
51
|
+
return crypto.randomUUID();
|
|
153
52
|
}
|
|
154
|
-
return
|
|
155
|
-
/* @__PURE__ */ jsx4("span", { className: "followups__label", children: label }),
|
|
156
|
-
/* @__PURE__ */ jsx4("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
|
|
157
|
-
"button",
|
|
158
|
-
{
|
|
159
|
-
type: "button",
|
|
160
|
-
className: "followups__chip",
|
|
161
|
-
disabled,
|
|
162
|
-
onClick: () => onSelect?.(suggestion),
|
|
163
|
-
children: suggestion.label
|
|
164
|
-
},
|
|
165
|
-
suggestion.id
|
|
166
|
-
)) })
|
|
167
|
-
] });
|
|
53
|
+
return `sess_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
168
54
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
function
|
|
173
|
-
|
|
174
|
-
|
|
55
|
+
function resolvePrefix(options) {
|
|
56
|
+
return options?.storageKeyPrefix?.trim() || DEFAULT_STORAGE_KEY_PREFIX;
|
|
57
|
+
}
|
|
58
|
+
function getOrCreateVisitorSessionId(options) {
|
|
59
|
+
const prefix = resolvePrefix(options);
|
|
60
|
+
const visitorKey = `${prefix}:visitorSessionId`;
|
|
61
|
+
if (typeof sessionStorage === "undefined") {
|
|
62
|
+
return createSessionId();
|
|
175
63
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
64
|
+
const existing = sessionStorage.getItem(visitorKey)?.trim();
|
|
65
|
+
if (existing) return existing;
|
|
66
|
+
const next = createSessionId();
|
|
67
|
+
sessionStorage.setItem(visitorKey, next);
|
|
68
|
+
return next;
|
|
180
69
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
184
|
-
function MinimizeIcon() {
|
|
185
|
-
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("path", { d: "M3.5 8h9", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round" }) });
|
|
70
|
+
function runtimeSessionIdKey(visitorSessionId, prefix) {
|
|
71
|
+
return `${prefix}:eve:${visitorSessionId}:sessionId`;
|
|
186
72
|
}
|
|
187
|
-
function
|
|
188
|
-
return
|
|
189
|
-
"path",
|
|
190
|
-
{
|
|
191
|
-
d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
|
|
192
|
-
stroke: "currentColor",
|
|
193
|
-
strokeWidth: "1.5",
|
|
194
|
-
strokeLinecap: "round",
|
|
195
|
-
strokeLinejoin: "round"
|
|
196
|
-
}
|
|
197
|
-
) });
|
|
73
|
+
function runtimeStreamIndexKey(visitorSessionId, prefix) {
|
|
74
|
+
return `${prefix}:eve:${visitorSessionId}:streamIndex`;
|
|
198
75
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
76
|
+
function loadPersistedAgentSession(visitorSessionId, options) {
|
|
77
|
+
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return null;
|
|
78
|
+
const prefix = resolvePrefix(options);
|
|
79
|
+
const sessionId = sessionStorage.getItem(runtimeSessionIdKey(visitorSessionId, prefix))?.trim();
|
|
80
|
+
if (!sessionId) return null;
|
|
81
|
+
const rawIndex = sessionStorage.getItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
82
|
+
const streamIndex = rawIndex ? Number.parseInt(rawIndex, 10) : 0;
|
|
83
|
+
return {
|
|
84
|
+
sessionId,
|
|
85
|
+
streamIndex: Number.isFinite(streamIndex) && streamIndex >= 0 ? streamIndex : 0
|
|
86
|
+
};
|
|
210
87
|
}
|
|
211
|
-
function
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
onClose,
|
|
221
|
-
onExpandToggle,
|
|
222
|
-
onSubmit,
|
|
223
|
-
onFollowUpSelect
|
|
224
|
-
}) {
|
|
225
|
-
const transcriptRef = useRef2(null);
|
|
226
|
-
const railStyle = theme?.railMaxWidth ? { ["--rail-width"]: theme.railMaxWidth, ["--as-rail-max-width"]: theme.railMaxWidth } : void 0;
|
|
227
|
-
const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
|
|
228
|
-
const showActivity = state.toolSteps.length > 0 && (state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming");
|
|
229
|
-
const showStreamingInActivity = state.phase === "streaming" && Boolean(state.streamingText);
|
|
230
|
-
const hasVisitorMessages2 = state.messages.some((message) => message.role === "visitor");
|
|
231
|
-
const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
|
|
232
|
-
const showCompleteFollowUps = state.phase === "complete" && state.followUps.length > 0 && hasVisitorMessages2;
|
|
233
|
-
const showDockFollowUps = expanded && (showIdleFollowUps || showCompleteFollowUps);
|
|
234
|
-
useEffect(() => {
|
|
235
|
-
const node = transcriptRef.current;
|
|
236
|
-
if (!node) return;
|
|
237
|
-
node.scrollTop = node.scrollHeight;
|
|
238
|
-
}, [state.messages, state.toolSteps, state.streamingText, state.followUps, state.journey]);
|
|
239
|
-
return /* @__PURE__ */ jsxs5(
|
|
240
|
-
"aside",
|
|
241
|
-
{
|
|
242
|
-
className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
|
|
243
|
-
style: railStyle,
|
|
244
|
-
"aria-label": "Agent conversation",
|
|
245
|
-
children: [
|
|
246
|
-
/* @__PURE__ */ jsx6("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs5("div", { className: "agent-rail__brand-row", children: [
|
|
247
|
-
onCollapse ? /* @__PURE__ */ jsx6(
|
|
248
|
-
"button",
|
|
249
|
-
{
|
|
250
|
-
type: "button",
|
|
251
|
-
className: "agent-rail__collapse",
|
|
252
|
-
"aria-label": "Collapse assist",
|
|
253
|
-
onClick: onCollapse,
|
|
254
|
-
children: /* @__PURE__ */ jsx6(MinimizeIcon, {})
|
|
255
|
-
}
|
|
256
|
-
) : onClose ? /* @__PURE__ */ jsx6("button", { type: "button", className: "agent-rail__close", "aria-label": "Close agent", onClick: onClose, children: /* @__PURE__ */ jsx6(MinimizeIcon, {}) }) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
|
|
257
|
-
/* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-label", children: brandLabel }),
|
|
258
|
-
onExpandToggle ? /* @__PURE__ */ jsx6(
|
|
259
|
-
"button",
|
|
260
|
-
{
|
|
261
|
-
type: "button",
|
|
262
|
-
className: "agent-rail__expand",
|
|
263
|
-
"aria-label": expanded ? "Restore assist panel" : "Expand assist panel",
|
|
264
|
-
onClick: onExpandToggle,
|
|
265
|
-
children: expanded ? /* @__PURE__ */ jsx6(RestoreIcon, {}) : /* @__PURE__ */ jsx6(ExpandIcon, {})
|
|
266
|
-
}
|
|
267
|
-
) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
|
|
268
|
-
] }) }),
|
|
269
|
-
/* @__PURE__ */ jsxs5("div", { ref: transcriptRef, className: "agent-rail__transcript", children: [
|
|
270
|
-
state.messages.map((message) => /* @__PURE__ */ jsx6(MessageBubble, { message }, message.id)),
|
|
271
|
-
showActivity ? /* @__PURE__ */ jsx6(
|
|
272
|
-
AgentActivityBubble,
|
|
273
|
-
{
|
|
274
|
-
steps: state.toolSteps,
|
|
275
|
-
streamingText: state.streamingText,
|
|
276
|
-
showStreaming: showStreamingInActivity
|
|
277
|
-
}
|
|
278
|
-
) : null,
|
|
279
|
-
!expanded && showIdleFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
280
|
-
FollowUpChips,
|
|
281
|
-
{
|
|
282
|
-
suggestions: state.followUps,
|
|
283
|
-
disabled: isBusy,
|
|
284
|
-
label: "Try asking",
|
|
285
|
-
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
286
|
-
}
|
|
287
|
-
) }) : null,
|
|
288
|
-
!expanded && showCompleteFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
289
|
-
FollowUpChips,
|
|
290
|
-
{
|
|
291
|
-
suggestions: state.followUps,
|
|
292
|
-
disabled: isBusy,
|
|
293
|
-
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
294
|
-
}
|
|
295
|
-
) }) : null,
|
|
296
|
-
state.error ? /* @__PURE__ */ jsx6("p", { role: "alert", style: { fontSize: 13, color: "var(--as-danger)", margin: 0 }, children: state.error }) : null
|
|
297
|
-
] }),
|
|
298
|
-
expanded ? /* @__PURE__ */ jsxs5("div", { className: "agent-rail__dock-wrap", children: [
|
|
299
|
-
showDockFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ jsx6(
|
|
300
|
-
FollowUpChips,
|
|
301
|
-
{
|
|
302
|
-
variant: "dock",
|
|
303
|
-
suggestions: state.followUps,
|
|
304
|
-
disabled: isBusy,
|
|
305
|
-
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
306
|
-
}
|
|
307
|
-
) }) : null,
|
|
308
|
-
/* @__PURE__ */ jsx6("div", { className: "agent-rail__dock", children: /* @__PURE__ */ jsx6(
|
|
309
|
-
Composer,
|
|
310
|
-
{
|
|
311
|
-
variant: "dock",
|
|
312
|
-
disabled: isBusy,
|
|
313
|
-
placeholder: composerPlaceholder,
|
|
314
|
-
onSubmit
|
|
315
|
-
}
|
|
316
|
-
) }),
|
|
317
|
-
/* @__PURE__ */ jsxs5("div", { className: "agent-rail__footer", children: [
|
|
318
|
-
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
319
|
-
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
320
|
-
] })
|
|
321
|
-
] }) : /* @__PURE__ */ jsxs5("div", { className: "agent-rail__composer-wrap", children: [
|
|
322
|
-
/* @__PURE__ */ jsx6(
|
|
323
|
-
Composer,
|
|
324
|
-
{
|
|
325
|
-
disabled: isBusy,
|
|
326
|
-
placeholder: composerPlaceholder,
|
|
327
|
-
onSubmit
|
|
328
|
-
}
|
|
329
|
-
),
|
|
330
|
-
/* @__PURE__ */ jsxs5("div", { className: "agent-rail__footer", children: [
|
|
331
|
-
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
332
|
-
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
333
|
-
] })
|
|
334
|
-
] })
|
|
335
|
-
]
|
|
336
|
-
}
|
|
88
|
+
function savePersistedAgentSession(visitorSessionId, sessionId, streamIndex, options) {
|
|
89
|
+
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim() || !sessionId.trim()) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const prefix = resolvePrefix(options);
|
|
93
|
+
sessionStorage.setItem(runtimeSessionIdKey(visitorSessionId, prefix), sessionId);
|
|
94
|
+
sessionStorage.setItem(
|
|
95
|
+
runtimeStreamIndexKey(visitorSessionId, prefix),
|
|
96
|
+
String(Math.max(0, streamIndex))
|
|
337
97
|
);
|
|
338
98
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
/* @__PURE__ */ jsx7("path", { d: "M8 1.2l.95 2.7 2.85.05-2.25 1.75.8 2.75L8 6.7 5.65 8.45l.8-2.75L4.2 3.95l2.85-.05L8 1.2z", fill: "currentColor" }),
|
|
345
|
-
/* @__PURE__ */ jsx7("path", { d: "M14.2 6.4l.55 1.55 1.65.03-1.3 1 .46 1.58-1.36-1-1.36 1 .46-1.58-1.3-1 1.65-.03.55-1.55z", fill: "currentColor" }),
|
|
346
|
-
/* @__PURE__ */ jsx7("path", { d: "M3.1 9.1l.4 1.15 1.22.02-.96.74.34 1.17-1-.74-1 .74.34-1.17-.96-.74 1.22-.02.4-1.15z", fill: "currentColor" })
|
|
347
|
-
] });
|
|
348
|
-
}
|
|
349
|
-
function ChevronLeftIcon() {
|
|
350
|
-
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
351
|
-
}
|
|
352
|
-
function ChevronDownIcon() {
|
|
353
|
-
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
354
|
-
}
|
|
355
|
-
function DragDots() {
|
|
356
|
-
return /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx7("i", {}, index)) });
|
|
357
|
-
}
|
|
358
|
-
var VARIANT_COPY = {
|
|
359
|
-
outline: { label: "Assist", aria: "Open Assist" },
|
|
360
|
-
ask: { label: "Ask anything", aria: "Ask anything" },
|
|
361
|
-
fill: { label: "Assist", aria: "Open Assist" }
|
|
362
|
-
};
|
|
363
|
-
function AssistEdgeTab({
|
|
364
|
-
variant,
|
|
365
|
-
side,
|
|
366
|
-
along,
|
|
367
|
-
inset,
|
|
368
|
-
visible,
|
|
369
|
-
onOpen
|
|
370
|
-
}) {
|
|
371
|
-
const copy = VARIANT_COPY[variant];
|
|
372
|
-
const style = {
|
|
373
|
-
"--tab-along": `${along}%`,
|
|
374
|
-
"--tab-inset": `${inset}px`
|
|
375
|
-
};
|
|
376
|
-
return /* @__PURE__ */ jsxs6(
|
|
377
|
-
"button",
|
|
378
|
-
{
|
|
379
|
-
type: "button",
|
|
380
|
-
className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${visible ? " is-visible" : ""}`,
|
|
381
|
-
style,
|
|
382
|
-
"aria-label": copy.aria,
|
|
383
|
-
"aria-hidden": !visible,
|
|
384
|
-
tabIndex: visible ? 0 : -1,
|
|
385
|
-
onClick: onOpen,
|
|
386
|
-
children: [
|
|
387
|
-
variant === "outline" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
388
|
-
/* @__PURE__ */ jsx7(SparklesIcon, {}),
|
|
389
|
-
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
390
|
-
/* @__PURE__ */ jsx7(ChevronDownIcon, {})
|
|
391
|
-
] }) : null,
|
|
392
|
-
variant === "ask" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
393
|
-
/* @__PURE__ */ jsx7(ChevronLeftIcon, {}),
|
|
394
|
-
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
395
|
-
/* @__PURE__ */ jsx7(DragDots, {})
|
|
396
|
-
] }) : null,
|
|
397
|
-
variant === "fill" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
398
|
-
/* @__PURE__ */ jsx7(SparklesIcon, {}),
|
|
399
|
-
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
400
|
-
/* @__PURE__ */ jsx7(ChevronLeftIcon, {})
|
|
401
|
-
] }) : null
|
|
402
|
-
]
|
|
403
|
-
}
|
|
404
|
-
);
|
|
99
|
+
function clearPersistedAgentSession(visitorSessionId, options) {
|
|
100
|
+
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return;
|
|
101
|
+
const prefix = resolvePrefix(options);
|
|
102
|
+
sessionStorage.removeItem(runtimeSessionIdKey(visitorSessionId, prefix));
|
|
103
|
+
sessionStorage.removeItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
405
104
|
}
|
|
406
105
|
|
|
407
|
-
// src/react/hooks/useAgentChat.ts
|
|
408
|
-
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef3, useState as useState2 } from "react";
|
|
409
|
-
|
|
410
106
|
// src/runtime/client.ts
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
} from "eve/client";
|
|
415
|
-
|
|
416
|
-
// src/runtime/config.ts
|
|
417
|
-
var DEFAULT_RUNTIME_ORIGIN = "https://runtime.staging.webless.ai";
|
|
418
|
-
var trimTrailingSlash = (value) => value.replace(/\/+$/, "");
|
|
419
|
-
function buildEveHost(origin, indexId) {
|
|
420
|
-
const base = trimTrailingSlash(origin);
|
|
421
|
-
return `${base}?indexId=${encodeURIComponent(indexId.trim())}`;
|
|
422
|
-
}
|
|
423
|
-
function resolveAgentRuntimeConfig(input) {
|
|
424
|
-
const origin = trimTrailingSlash(input.runtimeOrigin?.trim() || DEFAULT_RUNTIME_ORIGIN);
|
|
425
|
-
const resolvedIndexId = input.indexId.trim();
|
|
107
|
+
function mapStepLabel(event) {
|
|
108
|
+
if (event.type !== "step.started") return null;
|
|
109
|
+
const stepIndex = event.data.stepIndex;
|
|
426
110
|
return {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
host: resolvedIndexId ? buildEveHost(origin, resolvedIndexId) : origin
|
|
111
|
+
label: "Model step running",
|
|
112
|
+
detail: typeof stepIndex === "number" ? `Step ${stepIndex + 1}` : void 0
|
|
430
113
|
};
|
|
431
114
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
function buildAgentStorageKeyPrefix(input) {
|
|
441
|
-
const customerId = input.customerId?.trim() || "_";
|
|
442
|
-
const indexId = input.indexId.trim();
|
|
443
|
-
if (!indexId) {
|
|
444
|
-
throw new Error("indexId is required to build agent storage keys.");
|
|
445
|
-
}
|
|
446
|
-
return `${DEFAULT_STORAGE_KEY_PREFIX}:${customerId}:${indexId}:${normalizeRuntimeOrigin(input.runtimeOrigin)}`;
|
|
447
|
-
}
|
|
448
|
-
function createSessionId() {
|
|
449
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
450
|
-
return crypto.randomUUID();
|
|
451
|
-
}
|
|
452
|
-
return `sess_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
453
|
-
}
|
|
454
|
-
function resolvePrefix(options) {
|
|
455
|
-
return options?.storageKeyPrefix?.trim() || DEFAULT_STORAGE_KEY_PREFIX;
|
|
456
|
-
}
|
|
457
|
-
function getOrCreateVisitorSessionId(options) {
|
|
458
|
-
const prefix = resolvePrefix(options);
|
|
459
|
-
const visitorKey = `${prefix}:visitorSessionId`;
|
|
460
|
-
if (typeof sessionStorage === "undefined") {
|
|
461
|
-
return createSessionId();
|
|
462
|
-
}
|
|
463
|
-
const existing = sessionStorage.getItem(visitorKey)?.trim();
|
|
464
|
-
if (existing) return existing;
|
|
465
|
-
const next = createSessionId();
|
|
466
|
-
sessionStorage.setItem(visitorKey, next);
|
|
467
|
-
return next;
|
|
468
|
-
}
|
|
469
|
-
function runtimeSessionIdKey(visitorSessionId, prefix) {
|
|
470
|
-
return `${prefix}:eve:${visitorSessionId}:sessionId`;
|
|
471
|
-
}
|
|
472
|
-
function runtimeStreamIndexKey(visitorSessionId, prefix) {
|
|
473
|
-
return `${prefix}:eve:${visitorSessionId}:streamIndex`;
|
|
474
|
-
}
|
|
475
|
-
function loadPersistedAgentSession(visitorSessionId, options) {
|
|
476
|
-
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return null;
|
|
477
|
-
const prefix = resolvePrefix(options);
|
|
478
|
-
const sessionId = sessionStorage.getItem(runtimeSessionIdKey(visitorSessionId, prefix))?.trim();
|
|
479
|
-
if (!sessionId) return null;
|
|
480
|
-
const rawIndex = sessionStorage.getItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
481
|
-
const streamIndex = rawIndex ? Number.parseInt(rawIndex, 10) : 0;
|
|
482
|
-
return {
|
|
483
|
-
sessionId,
|
|
484
|
-
streamIndex: Number.isFinite(streamIndex) && streamIndex >= 0 ? streamIndex : 0
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
function savePersistedAgentSession(visitorSessionId, sessionId, streamIndex, options) {
|
|
488
|
-
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim() || !sessionId.trim()) {
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
const prefix = resolvePrefix(options);
|
|
492
|
-
sessionStorage.setItem(runtimeSessionIdKey(visitorSessionId, prefix), sessionId);
|
|
493
|
-
sessionStorage.setItem(
|
|
494
|
-
runtimeStreamIndexKey(visitorSessionId, prefix),
|
|
495
|
-
String(Math.max(0, streamIndex))
|
|
496
|
-
);
|
|
497
|
-
}
|
|
498
|
-
function clearPersistedAgentSession(visitorSessionId, options) {
|
|
499
|
-
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return;
|
|
500
|
-
const prefix = resolvePrefix(options);
|
|
501
|
-
sessionStorage.removeItem(runtimeSessionIdKey(visitorSessionId, prefix));
|
|
502
|
-
sessionStorage.removeItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// src/runtime/client.ts
|
|
506
|
-
function mapStepLabel(event) {
|
|
507
|
-
if (event.type !== "step.started") return null;
|
|
508
|
-
const stepIndex = event.data.stepIndex;
|
|
509
|
-
return {
|
|
510
|
-
label: "Model step running",
|
|
511
|
-
detail: typeof stepIndex === "number" ? `Step ${stepIndex + 1}` : void 0
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
var AgentSession = class {
|
|
515
|
-
constructor(indexId, runtimeOrigin, visitorSessionId, storeOptions) {
|
|
516
|
-
this.indexId = indexId;
|
|
517
|
-
this.runtimeOrigin = runtimeOrigin;
|
|
518
|
-
this.visitorSessionId = visitorSessionId;
|
|
519
|
-
this.storeOptions = storeOptions;
|
|
115
|
+
var AgentSession = class {
|
|
116
|
+
constructor(indexId, version, runtimeOrigin, visitorSessionId, storeOptions) {
|
|
117
|
+
this.indexId = indexId;
|
|
118
|
+
this.version = version;
|
|
119
|
+
this.runtimeOrigin = runtimeOrigin;
|
|
120
|
+
this.visitorSessionId = visitorSessionId;
|
|
121
|
+
this.storeOptions = storeOptions;
|
|
520
122
|
}
|
|
521
123
|
indexId;
|
|
124
|
+
version;
|
|
522
125
|
runtimeOrigin;
|
|
523
126
|
visitorSessionId;
|
|
524
127
|
storeOptions;
|
|
@@ -549,6 +152,7 @@ var AgentSession = class {
|
|
|
549
152
|
ensureClient() {
|
|
550
153
|
const config = resolveAgentRuntimeConfig({
|
|
551
154
|
indexId: this.indexId,
|
|
155
|
+
version: this.version,
|
|
552
156
|
runtimeOrigin: this.runtimeOrigin
|
|
553
157
|
});
|
|
554
158
|
if (!config.indexId) {
|
|
@@ -648,17 +252,20 @@ function createAgentClient(options) {
|
|
|
648
252
|
throw new Error("indexId is required.");
|
|
649
253
|
}
|
|
650
254
|
const runtimeOrigin = options.runtimeOrigin?.trim() || resolveAgentRuntimeConfig({ indexId }).origin;
|
|
255
|
+
const version = options.version ?? "published";
|
|
651
256
|
const storeOptions = {
|
|
652
257
|
storageKeyPrefix: options.storageKeyPrefix?.trim() || buildAgentStorageKeyPrefix({
|
|
653
258
|
customerId: options.customerId,
|
|
654
259
|
indexId,
|
|
260
|
+
version,
|
|
655
261
|
runtimeOrigin
|
|
656
262
|
})
|
|
657
263
|
};
|
|
658
264
|
const visitorSessionId = options.visitorSessionId?.trim() || getOrCreateVisitorSessionId(storeOptions);
|
|
659
|
-
const session = new AgentSession(indexId, runtimeOrigin, visitorSessionId, storeOptions);
|
|
265
|
+
const session = new AgentSession(indexId, version, runtimeOrigin, visitorSessionId, storeOptions);
|
|
660
266
|
return {
|
|
661
267
|
indexId,
|
|
268
|
+
version,
|
|
662
269
|
runtimeOrigin,
|
|
663
270
|
visitorSessionId,
|
|
664
271
|
sendTurn: (message, sendOptions) => session.sendTurn(
|
|
@@ -672,261 +279,817 @@ function createAgentClient(options) {
|
|
|
672
279
|
};
|
|
673
280
|
}
|
|
674
281
|
|
|
675
|
-
// src/runtime/errors.ts
|
|
676
|
-
import { ClientError as ClientError2 } from "eve/client";
|
|
677
|
-
function formatAgentError(error) {
|
|
678
|
-
if (error instanceof ClientError2) {
|
|
679
|
-
if (error.status === 401 && error.code === "index_required") {
|
|
680
|
-
return "Missing indexId \u2014 pass a published index id to createAgentClient().";
|
|
681
|
-
}
|
|
682
|
-
if (error.status === 403 && error.code === "agent_unavailable") {
|
|
683
|
-
return "Agent unavailable for this index (disabled or unpublished).";
|
|
684
|
-
}
|
|
685
|
-
if (error.status === 409 && error.code === "session_not_active") {
|
|
686
|
-
return "Session expired \u2014 send a new message to start again.";
|
|
687
|
-
}
|
|
688
|
-
return error.message || `Runtime error (${error.status})`;
|
|
689
|
-
}
|
|
690
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
691
|
-
return "";
|
|
692
|
-
}
|
|
693
|
-
if (error instanceof Error) return error.message;
|
|
694
|
-
return "Runtime request failed";
|
|
282
|
+
// src/runtime/errors.ts
|
|
283
|
+
import { ClientError as ClientError2 } from "eve/client";
|
|
284
|
+
function formatAgentError(error) {
|
|
285
|
+
if (error instanceof ClientError2) {
|
|
286
|
+
if (error.status === 401 && error.code === "index_required") {
|
|
287
|
+
return "Missing indexId \u2014 pass a published index id to createAgentClient().";
|
|
288
|
+
}
|
|
289
|
+
if (error.status === 403 && error.code === "agent_unavailable") {
|
|
290
|
+
return "Agent unavailable for this index (disabled or unpublished).";
|
|
291
|
+
}
|
|
292
|
+
if (error.status === 409 && error.code === "session_not_active") {
|
|
293
|
+
return "Session expired \u2014 send a new message to start again.";
|
|
294
|
+
}
|
|
295
|
+
return error.message || `Runtime error (${error.status})`;
|
|
296
|
+
}
|
|
297
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
298
|
+
return "";
|
|
299
|
+
}
|
|
300
|
+
if (error instanceof Error) return error.message;
|
|
301
|
+
return "Runtime request failed";
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/react/hooks/useAgentChat.ts
|
|
305
|
+
var GREETING_MESSAGE = {
|
|
306
|
+
id: "greeting",
|
|
307
|
+
role: "agent",
|
|
308
|
+
text: "Hi! I'm connected to the Webless Agent Runtime. Ask anything about your published site index.",
|
|
309
|
+
createdAt: 0
|
|
310
|
+
};
|
|
311
|
+
var INITIAL_STATE = {
|
|
312
|
+
phase: "idle",
|
|
313
|
+
messages: [GREETING_MESSAGE],
|
|
314
|
+
toolSteps: [],
|
|
315
|
+
journey: null,
|
|
316
|
+
followUps: [],
|
|
317
|
+
streamingText: "",
|
|
318
|
+
error: null
|
|
319
|
+
};
|
|
320
|
+
var STATUS_SEQUENCE = [
|
|
321
|
+
{ id: "s1", label: "Starting Eve session", ms: 400 },
|
|
322
|
+
{ id: "s2", label: "Connecting to runtime", ms: 500 }
|
|
323
|
+
];
|
|
324
|
+
var DEFAULT_FOLLOW_UPS = [
|
|
325
|
+
{ id: "fu-1", label: "What can you help me with?" },
|
|
326
|
+
{ id: "fu-2", label: "Summarize your capabilities" },
|
|
327
|
+
{ id: "fu-3", label: "What should I ask next?" }
|
|
328
|
+
];
|
|
329
|
+
function delay(ms, signal) {
|
|
330
|
+
return new Promise((resolve, reject) => {
|
|
331
|
+
const timer = window.setTimeout(resolve, ms);
|
|
332
|
+
signal.addEventListener(
|
|
333
|
+
"abort",
|
|
334
|
+
() => {
|
|
335
|
+
window.clearTimeout(timer);
|
|
336
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
337
|
+
},
|
|
338
|
+
{ once: true }
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
async function runStatusSequence(signal, onStep) {
|
|
343
|
+
for (const item of STATUS_SEQUENCE) {
|
|
344
|
+
onStep({ id: item.id, label: item.label, detail: item.detail, state: "active" });
|
|
345
|
+
await delay(item.ms, signal);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function useAgentChat({
|
|
349
|
+
customerId,
|
|
350
|
+
indexId,
|
|
351
|
+
version,
|
|
352
|
+
runtimeOrigin,
|
|
353
|
+
visitorSessionId,
|
|
354
|
+
storageKeyPrefix
|
|
355
|
+
}) {
|
|
356
|
+
const [state, setState] = useState(INITIAL_STATE);
|
|
357
|
+
const runRef = useRef(null);
|
|
358
|
+
const resolvedStorageKeyPrefix = useMemo(
|
|
359
|
+
() => storageKeyPrefix?.trim() || buildAgentStorageKeyPrefix({ customerId, indexId, version, runtimeOrigin }),
|
|
360
|
+
[customerId, indexId, runtimeOrigin, storageKeyPrefix, version]
|
|
361
|
+
);
|
|
362
|
+
const visitorId = useMemo(
|
|
363
|
+
() => visitorSessionId?.trim() || getOrCreateVisitorSessionId({ storageKeyPrefix: resolvedStorageKeyPrefix }),
|
|
364
|
+
[resolvedStorageKeyPrefix, visitorSessionId]
|
|
365
|
+
);
|
|
366
|
+
const clientRef = useRef(
|
|
367
|
+
createAgentClient({
|
|
368
|
+
customerId,
|
|
369
|
+
indexId,
|
|
370
|
+
version,
|
|
371
|
+
runtimeOrigin,
|
|
372
|
+
visitorSessionId: visitorId,
|
|
373
|
+
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
374
|
+
})
|
|
375
|
+
);
|
|
376
|
+
const identityRef = useRef(null);
|
|
377
|
+
const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}`;
|
|
378
|
+
useEffect(() => {
|
|
379
|
+
if (identityRef.current === null) {
|
|
380
|
+
identityRef.current = identityKey;
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (identityRef.current === identityKey) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
identityRef.current = identityKey;
|
|
387
|
+
runRef.current?.abort();
|
|
388
|
+
runRef.current = null;
|
|
389
|
+
clientRef.current.reset();
|
|
390
|
+
clientRef.current = createAgentClient({
|
|
391
|
+
customerId,
|
|
392
|
+
indexId,
|
|
393
|
+
version,
|
|
394
|
+
runtimeOrigin,
|
|
395
|
+
visitorSessionId: visitorId,
|
|
396
|
+
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
397
|
+
});
|
|
398
|
+
setState(INITIAL_STATE);
|
|
399
|
+
}, [customerId, identityKey, indexId, runtimeOrigin, resolvedStorageKeyPrefix, version, visitorId]);
|
|
400
|
+
const reset = useCallback(() => {
|
|
401
|
+
runRef.current?.abort();
|
|
402
|
+
runRef.current = null;
|
|
403
|
+
clientRef.current.reset();
|
|
404
|
+
setState(INITIAL_STATE);
|
|
405
|
+
}, []);
|
|
406
|
+
const submit = useCallback(
|
|
407
|
+
async (visitorText) => {
|
|
408
|
+
runRef.current?.abort();
|
|
409
|
+
clientRef.current.cancelActive();
|
|
410
|
+
const controller = new AbortController();
|
|
411
|
+
runRef.current = controller;
|
|
412
|
+
const { signal } = controller;
|
|
413
|
+
const isActiveRun = () => runRef.current === controller && !signal.aborted;
|
|
414
|
+
const visitorMessage = {
|
|
415
|
+
id: `visitor-${Date.now()}`,
|
|
416
|
+
role: "visitor",
|
|
417
|
+
text: visitorText,
|
|
418
|
+
createdAt: Date.now()
|
|
419
|
+
};
|
|
420
|
+
setState((prev) => ({
|
|
421
|
+
...prev,
|
|
422
|
+
phase: "thinking",
|
|
423
|
+
messages: [...prev.messages, visitorMessage],
|
|
424
|
+
toolSteps: [{ id: "s1", label: "Starting Eve session", state: "active" }],
|
|
425
|
+
journey: null,
|
|
426
|
+
followUps: [],
|
|
427
|
+
streamingText: "",
|
|
428
|
+
error: null
|
|
429
|
+
}));
|
|
430
|
+
try {
|
|
431
|
+
let streamStarted = false;
|
|
432
|
+
const planningPromise = runStatusSequence(signal, (step) => {
|
|
433
|
+
if (streamStarted || !isActiveRun()) return;
|
|
434
|
+
setState((prev) => ({ ...prev, phase: "running-tools", toolSteps: [step] }));
|
|
435
|
+
});
|
|
436
|
+
let streamed = "";
|
|
437
|
+
const finalText = await clientRef.current.sendTurn(visitorText, {
|
|
438
|
+
signal,
|
|
439
|
+
handlers: {
|
|
440
|
+
onStep: (label, detail) => {
|
|
441
|
+
if (streamStarted || !isActiveRun()) return;
|
|
442
|
+
setState((prev) => ({
|
|
443
|
+
...prev,
|
|
444
|
+
phase: "running-tools",
|
|
445
|
+
toolSteps: [{ id: `step-${label}`, label, detail, state: "active" }]
|
|
446
|
+
}));
|
|
447
|
+
},
|
|
448
|
+
onDelta: (delta) => {
|
|
449
|
+
if (!isActiveRun()) return;
|
|
450
|
+
void planningPromise.catch(() => {
|
|
451
|
+
});
|
|
452
|
+
if (!streamStarted) {
|
|
453
|
+
streamStarted = true;
|
|
454
|
+
setState((prev) => ({
|
|
455
|
+
...prev,
|
|
456
|
+
phase: "streaming",
|
|
457
|
+
toolSteps: [],
|
|
458
|
+
streamingText: ""
|
|
459
|
+
}));
|
|
460
|
+
}
|
|
461
|
+
streamed += delta;
|
|
462
|
+
setState((prev) => ({ ...prev, phase: "streaming", streamingText: streamed }));
|
|
463
|
+
},
|
|
464
|
+
onComplete: () => {
|
|
465
|
+
if (!isActiveRun()) return;
|
|
466
|
+
streamStarted = true;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
await planningPromise.catch(() => {
|
|
471
|
+
});
|
|
472
|
+
if (!isActiveRun()) return;
|
|
473
|
+
const agentMessage = {
|
|
474
|
+
id: `agent-${Date.now()}`,
|
|
475
|
+
role: "agent",
|
|
476
|
+
text: finalText,
|
|
477
|
+
createdAt: Date.now()
|
|
478
|
+
};
|
|
479
|
+
setState((prev) => ({
|
|
480
|
+
...prev,
|
|
481
|
+
phase: "complete",
|
|
482
|
+
messages: [...prev.messages, agentMessage],
|
|
483
|
+
toolSteps: [],
|
|
484
|
+
streamingText: "",
|
|
485
|
+
followUps: DEFAULT_FOLLOW_UPS,
|
|
486
|
+
journey: null
|
|
487
|
+
}));
|
|
488
|
+
} catch (error) {
|
|
489
|
+
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
490
|
+
if (!isActiveRun()) return;
|
|
491
|
+
const message = formatAgentError(error);
|
|
492
|
+
if (!message) return;
|
|
493
|
+
setState((prev) => ({
|
|
494
|
+
...prev,
|
|
495
|
+
phase: "complete",
|
|
496
|
+
toolSteps: [],
|
|
497
|
+
streamingText: "",
|
|
498
|
+
error: message
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
[customerId, indexId, runtimeOrigin, resolvedStorageKeyPrefix, version, visitorId]
|
|
503
|
+
);
|
|
504
|
+
useEffect(() => {
|
|
505
|
+
return () => {
|
|
506
|
+
runRef.current?.abort();
|
|
507
|
+
clientRef.current.cancelActive();
|
|
508
|
+
};
|
|
509
|
+
}, []);
|
|
510
|
+
return {
|
|
511
|
+
state,
|
|
512
|
+
reset,
|
|
513
|
+
submit,
|
|
514
|
+
visitorSessionId: visitorId,
|
|
515
|
+
sessionId: clientRef.current.getActiveSessionId()
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
function hasVisitorMessages(messages) {
|
|
519
|
+
return messages.some((message) => message.role === "visitor");
|
|
520
|
+
}
|
|
521
|
+
function createIdleSuggestions() {
|
|
522
|
+
return [
|
|
523
|
+
{ id: "idle-1", label: "Hello \u2014 what can you do?" },
|
|
524
|
+
{ id: "idle-2", label: "Help me evaluate this product" },
|
|
525
|
+
{ id: "idle-3", label: "What should I ask you?" }
|
|
526
|
+
];
|
|
527
|
+
}
|
|
528
|
+
function isAgentBusy(phase) {
|
|
529
|
+
return phase === "thinking" || phase === "running-tools" || phase === "streaming";
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// src/react/placement.ts
|
|
533
|
+
var DEFAULT_AGENT_PLACEMENT = {
|
|
534
|
+
side: "right",
|
|
535
|
+
along: 50,
|
|
536
|
+
inset: 0,
|
|
537
|
+
variant: "outline"
|
|
538
|
+
};
|
|
539
|
+
function normalizeAgentPlacement(placement) {
|
|
540
|
+
const along = placement?.along ?? DEFAULT_AGENT_PLACEMENT.along;
|
|
541
|
+
return {
|
|
542
|
+
side: placement?.side ?? DEFAULT_AGENT_PLACEMENT.side,
|
|
543
|
+
along: Math.min(100, Math.max(0, along)),
|
|
544
|
+
inset: Math.max(0, placement?.inset ?? DEFAULT_AGENT_PLACEMENT.inset),
|
|
545
|
+
variant: placement?.variant ?? DEFAULT_AGENT_PLACEMENT.variant
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// src/react/components/AgentRail/AgentRail.tsx
|
|
550
|
+
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
551
|
+
|
|
552
|
+
// src/react/components/ToolTimeline/ToolTimeline.tsx
|
|
553
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
554
|
+
function SpinnerIcon() {
|
|
555
|
+
return /* @__PURE__ */ jsxs("svg", { className: "agent-status__spinner", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
556
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.25" }),
|
|
557
|
+
/* @__PURE__ */ jsx("path", { d: "M14 8a6 6 0 0 0-6-6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
558
|
+
] });
|
|
559
|
+
}
|
|
560
|
+
function getCurrentStep(steps) {
|
|
561
|
+
const active = steps.find((step) => step.state === "active");
|
|
562
|
+
if (active) return active;
|
|
563
|
+
const error = steps.find((step) => step.state === "error");
|
|
564
|
+
if (error) return error;
|
|
565
|
+
const pending = steps.find((step) => step.state === "pending");
|
|
566
|
+
if (pending) return pending;
|
|
567
|
+
return steps.at(-1) ?? null;
|
|
568
|
+
}
|
|
569
|
+
function ToolTimeline({
|
|
570
|
+
steps,
|
|
571
|
+
streamingText,
|
|
572
|
+
showStreaming = false,
|
|
573
|
+
inline = false
|
|
574
|
+
}) {
|
|
575
|
+
if (steps.length === 0 && !(showStreaming && streamingText)) return null;
|
|
576
|
+
const currentStep = getCurrentStep(steps);
|
|
577
|
+
const showStatus = currentStep && currentStep.state !== "completed" && !(showStreaming && streamingText);
|
|
578
|
+
return /* @__PURE__ */ jsxs(
|
|
579
|
+
"div",
|
|
580
|
+
{
|
|
581
|
+
className: `tool-timeline${inline ? " tool-timeline--inline" : ""}`,
|
|
582
|
+
role: "status",
|
|
583
|
+
"aria-live": "polite",
|
|
584
|
+
"aria-label": "Agent progress",
|
|
585
|
+
children: [
|
|
586
|
+
showStatus ? /* @__PURE__ */ jsxs("div", { className: "agent-status", children: [
|
|
587
|
+
currentStep.state === "error" ? /* @__PURE__ */ jsx("span", { className: "agent-status__icon agent-status__icon--error", "aria-hidden": "true", children: "!" }) : /* @__PURE__ */ jsx("span", { className: "agent-status__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(SpinnerIcon, {}) }),
|
|
588
|
+
/* @__PURE__ */ jsxs("div", { className: "agent-status__copy", children: [
|
|
589
|
+
/* @__PURE__ */ jsx("span", { className: "agent-status__label", children: currentStep.label }),
|
|
590
|
+
currentStep.detail ? /* @__PURE__ */ jsx("span", { className: "agent-status__detail", children: currentStep.detail }) : null
|
|
591
|
+
] })
|
|
592
|
+
] }, currentStep.id) : null,
|
|
593
|
+
showStreaming && streamingText ? /* @__PURE__ */ jsxs("p", { className: "tool-timeline__streaming-text", children: [
|
|
594
|
+
streamingText,
|
|
595
|
+
/* @__PURE__ */ jsx("span", { className: "tool-timeline__cursor", "aria-hidden": "true" })
|
|
596
|
+
] }) : null
|
|
597
|
+
]
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
|
|
603
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
604
|
+
function AgentActivityBubble({
|
|
605
|
+
steps,
|
|
606
|
+
streamingText,
|
|
607
|
+
showStreaming = false
|
|
608
|
+
}) {
|
|
609
|
+
return /* @__PURE__ */ jsx2("article", { className: "agent-activity-bubble", children: /* @__PURE__ */ jsx2("div", { className: "agent-activity-bubble__shell", children: /* @__PURE__ */ jsx2(
|
|
610
|
+
ToolTimeline,
|
|
611
|
+
{
|
|
612
|
+
steps,
|
|
613
|
+
streamingText,
|
|
614
|
+
showStreaming,
|
|
615
|
+
inline: true
|
|
616
|
+
}
|
|
617
|
+
) }) });
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/react/components/Composer/Composer.tsx
|
|
621
|
+
import { useRef as useRef2, useState as useState2 } from "react";
|
|
622
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
623
|
+
function SendIcon() {
|
|
624
|
+
return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx3("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
625
|
+
}
|
|
626
|
+
function Composer({
|
|
627
|
+
disabled = false,
|
|
628
|
+
placeholder = "Ask anything\u2026",
|
|
629
|
+
variant = "default",
|
|
630
|
+
onSubmit
|
|
631
|
+
}) {
|
|
632
|
+
const [value, setValue] = useState2("");
|
|
633
|
+
const inputRef = useRef2(null);
|
|
634
|
+
function submitCurrent() {
|
|
635
|
+
const trimmed = value.trim();
|
|
636
|
+
if (!trimmed || disabled) return;
|
|
637
|
+
onSubmit?.(trimmed);
|
|
638
|
+
setValue("");
|
|
639
|
+
inputRef.current?.focus();
|
|
640
|
+
}
|
|
641
|
+
function handleSubmit(event) {
|
|
642
|
+
event.preventDefault();
|
|
643
|
+
submitCurrent();
|
|
644
|
+
}
|
|
645
|
+
function handleKeyDown(event) {
|
|
646
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
647
|
+
event.preventDefault();
|
|
648
|
+
submitCurrent();
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return /* @__PURE__ */ jsx3("form", { className: `composer${variant === "dock" ? " composer--dock" : ""}`, onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2("div", { className: "composer__field", children: [
|
|
652
|
+
/* @__PURE__ */ jsx3(
|
|
653
|
+
"textarea",
|
|
654
|
+
{
|
|
655
|
+
ref: inputRef,
|
|
656
|
+
className: "composer__input",
|
|
657
|
+
rows: 1,
|
|
658
|
+
value,
|
|
659
|
+
placeholder,
|
|
660
|
+
disabled,
|
|
661
|
+
"aria-label": "Message",
|
|
662
|
+
onChange: (event) => setValue(event.target.value),
|
|
663
|
+
onKeyDown: handleKeyDown
|
|
664
|
+
}
|
|
665
|
+
),
|
|
666
|
+
/* @__PURE__ */ jsx3(
|
|
667
|
+
"button",
|
|
668
|
+
{
|
|
669
|
+
type: "submit",
|
|
670
|
+
className: "composer__send",
|
|
671
|
+
disabled: disabled || !value.trim(),
|
|
672
|
+
"aria-label": "Send message",
|
|
673
|
+
children: /* @__PURE__ */ jsx3(SendIcon, {})
|
|
674
|
+
}
|
|
675
|
+
)
|
|
676
|
+
] }) });
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// src/react/components/FollowUpChips/FollowUpChips.tsx
|
|
680
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
681
|
+
function FollowUpChips({
|
|
682
|
+
suggestions,
|
|
683
|
+
disabled = false,
|
|
684
|
+
label = "Follow up",
|
|
685
|
+
variant = "default",
|
|
686
|
+
onSelect
|
|
687
|
+
}) {
|
|
688
|
+
if (suggestions.length === 0) return null;
|
|
689
|
+
if (variant === "dock") {
|
|
690
|
+
return /* @__PURE__ */ jsx4("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx4("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
|
|
691
|
+
"button",
|
|
692
|
+
{
|
|
693
|
+
type: "button",
|
|
694
|
+
className: "followups__chip followups__chip--dock",
|
|
695
|
+
disabled,
|
|
696
|
+
onClick: () => onSelect?.(suggestion),
|
|
697
|
+
children: suggestion.label
|
|
698
|
+
},
|
|
699
|
+
suggestion.id
|
|
700
|
+
)) }) });
|
|
701
|
+
}
|
|
702
|
+
return /* @__PURE__ */ jsxs3("div", { className: "followups", children: [
|
|
703
|
+
/* @__PURE__ */ jsx4("span", { className: "followups__label", children: label }),
|
|
704
|
+
/* @__PURE__ */ jsx4("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
|
|
705
|
+
"button",
|
|
706
|
+
{
|
|
707
|
+
type: "button",
|
|
708
|
+
className: "followups__chip",
|
|
709
|
+
disabled,
|
|
710
|
+
onClick: () => onSelect?.(suggestion),
|
|
711
|
+
children: suggestion.label
|
|
712
|
+
},
|
|
713
|
+
suggestion.id
|
|
714
|
+
)) })
|
|
715
|
+
] });
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// src/react/components/MessageBubble/MessageBubble.tsx
|
|
719
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
720
|
+
function MessageBubble({ message }) {
|
|
721
|
+
if (message.role === "visitor") {
|
|
722
|
+
return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx5("p", { className: "message-bubble__text", children: message.text }) });
|
|
723
|
+
}
|
|
724
|
+
return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--agent", children: /* @__PURE__ */ jsxs4("p", { className: "message-bubble__text", children: [
|
|
725
|
+
message.text,
|
|
726
|
+
message.streaming ? /* @__PURE__ */ jsx5("span", { className: "tool-timeline__cursor", "aria-hidden": "true" }) : null
|
|
727
|
+
] }) });
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/react/components/AgentRail/AgentRail.tsx
|
|
731
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
732
|
+
function MinimizeIcon() {
|
|
733
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("path", { d: "M3.5 8h9", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round" }) });
|
|
734
|
+
}
|
|
735
|
+
function ExpandIcon() {
|
|
736
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
737
|
+
"path",
|
|
738
|
+
{
|
|
739
|
+
d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
|
|
740
|
+
stroke: "currentColor",
|
|
741
|
+
strokeWidth: "1.5",
|
|
742
|
+
strokeLinecap: "round",
|
|
743
|
+
strokeLinejoin: "round"
|
|
744
|
+
}
|
|
745
|
+
) });
|
|
746
|
+
}
|
|
747
|
+
function RestoreIcon() {
|
|
748
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
749
|
+
"path",
|
|
750
|
+
{
|
|
751
|
+
d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
|
|
752
|
+
stroke: "currentColor",
|
|
753
|
+
strokeWidth: "1.5",
|
|
754
|
+
strokeLinecap: "round",
|
|
755
|
+
strokeLinejoin: "round"
|
|
756
|
+
}
|
|
757
|
+
) });
|
|
758
|
+
}
|
|
759
|
+
function AgentRail({
|
|
760
|
+
state,
|
|
761
|
+
theme,
|
|
762
|
+
brandLabel = "Webless Assist",
|
|
763
|
+
poweredByLabel = "Powered by Webless",
|
|
764
|
+
composerPlaceholder = "Ask anything\u2026",
|
|
765
|
+
mobileFullscreen = false,
|
|
766
|
+
expanded = false,
|
|
767
|
+
onCollapse,
|
|
768
|
+
onClose,
|
|
769
|
+
onExpandToggle,
|
|
770
|
+
onSubmit,
|
|
771
|
+
onFollowUpSelect
|
|
772
|
+
}) {
|
|
773
|
+
const transcriptRef = useRef3(null);
|
|
774
|
+
const railStyle = theme?.railMaxWidth ? { ["--rail-width"]: theme.railMaxWidth, ["--as-rail-max-width"]: theme.railMaxWidth } : void 0;
|
|
775
|
+
const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
|
|
776
|
+
const showActivity = state.toolSteps.length > 0 && (state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming");
|
|
777
|
+
const showStreamingInActivity = state.phase === "streaming" && Boolean(state.streamingText);
|
|
778
|
+
const hasVisitorMessages2 = state.messages.some((message) => message.role === "visitor");
|
|
779
|
+
const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
|
|
780
|
+
const showCompleteFollowUps = state.phase === "complete" && state.followUps.length > 0 && hasVisitorMessages2;
|
|
781
|
+
const showDockFollowUps = expanded && (showIdleFollowUps || showCompleteFollowUps);
|
|
782
|
+
useEffect2(() => {
|
|
783
|
+
const node = transcriptRef.current;
|
|
784
|
+
if (!node) return;
|
|
785
|
+
node.scrollTop = node.scrollHeight;
|
|
786
|
+
}, [state.messages, state.toolSteps, state.streamingText, state.followUps, state.journey]);
|
|
787
|
+
return /* @__PURE__ */ jsxs5(
|
|
788
|
+
"aside",
|
|
789
|
+
{
|
|
790
|
+
className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
|
|
791
|
+
style: railStyle,
|
|
792
|
+
"aria-label": "Agent conversation",
|
|
793
|
+
children: [
|
|
794
|
+
/* @__PURE__ */ jsx6("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs5("div", { className: "agent-rail__brand-row", children: [
|
|
795
|
+
onCollapse ? /* @__PURE__ */ jsx6(
|
|
796
|
+
"button",
|
|
797
|
+
{
|
|
798
|
+
type: "button",
|
|
799
|
+
className: "agent-rail__collapse",
|
|
800
|
+
"aria-label": "Collapse assist",
|
|
801
|
+
onClick: onCollapse,
|
|
802
|
+
children: /* @__PURE__ */ jsx6(MinimizeIcon, {})
|
|
803
|
+
}
|
|
804
|
+
) : onClose ? /* @__PURE__ */ jsx6("button", { type: "button", className: "agent-rail__close", "aria-label": "Close agent", onClick: onClose, children: /* @__PURE__ */ jsx6(MinimizeIcon, {}) }) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
|
|
805
|
+
/* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-label", children: brandLabel }),
|
|
806
|
+
onExpandToggle ? /* @__PURE__ */ jsx6(
|
|
807
|
+
"button",
|
|
808
|
+
{
|
|
809
|
+
type: "button",
|
|
810
|
+
className: "agent-rail__expand",
|
|
811
|
+
"aria-label": expanded ? "Restore assist panel" : "Expand assist panel",
|
|
812
|
+
onClick: onExpandToggle,
|
|
813
|
+
children: expanded ? /* @__PURE__ */ jsx6(RestoreIcon, {}) : /* @__PURE__ */ jsx6(ExpandIcon, {})
|
|
814
|
+
}
|
|
815
|
+
) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
|
|
816
|
+
] }) }),
|
|
817
|
+
/* @__PURE__ */ jsxs5("div", { ref: transcriptRef, className: "agent-rail__transcript", children: [
|
|
818
|
+
state.messages.map((message) => /* @__PURE__ */ jsx6(MessageBubble, { message }, message.id)),
|
|
819
|
+
showActivity ? /* @__PURE__ */ jsx6(
|
|
820
|
+
AgentActivityBubble,
|
|
821
|
+
{
|
|
822
|
+
steps: state.toolSteps,
|
|
823
|
+
streamingText: state.streamingText,
|
|
824
|
+
showStreaming: showStreamingInActivity
|
|
825
|
+
}
|
|
826
|
+
) : null,
|
|
827
|
+
!expanded && showIdleFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
828
|
+
FollowUpChips,
|
|
829
|
+
{
|
|
830
|
+
suggestions: state.followUps,
|
|
831
|
+
disabled: isBusy,
|
|
832
|
+
label: "Try asking",
|
|
833
|
+
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
834
|
+
}
|
|
835
|
+
) }) : null,
|
|
836
|
+
!expanded && showCompleteFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
837
|
+
FollowUpChips,
|
|
838
|
+
{
|
|
839
|
+
suggestions: state.followUps,
|
|
840
|
+
disabled: isBusy,
|
|
841
|
+
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
842
|
+
}
|
|
843
|
+
) }) : null,
|
|
844
|
+
state.error ? /* @__PURE__ */ jsx6("p", { role: "alert", style: { fontSize: 13, color: "var(--as-danger)", margin: 0 }, children: state.error }) : null
|
|
845
|
+
] }),
|
|
846
|
+
expanded ? /* @__PURE__ */ jsxs5("div", { className: "agent-rail__dock-wrap", children: [
|
|
847
|
+
showDockFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ jsx6(
|
|
848
|
+
FollowUpChips,
|
|
849
|
+
{
|
|
850
|
+
variant: "dock",
|
|
851
|
+
suggestions: state.followUps,
|
|
852
|
+
disabled: isBusy,
|
|
853
|
+
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
854
|
+
}
|
|
855
|
+
) }) : null,
|
|
856
|
+
/* @__PURE__ */ jsx6("div", { className: "agent-rail__dock", children: /* @__PURE__ */ jsx6(
|
|
857
|
+
Composer,
|
|
858
|
+
{
|
|
859
|
+
variant: "dock",
|
|
860
|
+
disabled: isBusy,
|
|
861
|
+
placeholder: composerPlaceholder,
|
|
862
|
+
onSubmit
|
|
863
|
+
}
|
|
864
|
+
) }),
|
|
865
|
+
/* @__PURE__ */ jsxs5("div", { className: "agent-rail__footer", children: [
|
|
866
|
+
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
867
|
+
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
868
|
+
] })
|
|
869
|
+
] }) : /* @__PURE__ */ jsxs5("div", { className: "agent-rail__composer-wrap", children: [
|
|
870
|
+
/* @__PURE__ */ jsx6(
|
|
871
|
+
Composer,
|
|
872
|
+
{
|
|
873
|
+
disabled: isBusy,
|
|
874
|
+
placeholder: composerPlaceholder,
|
|
875
|
+
onSubmit
|
|
876
|
+
}
|
|
877
|
+
),
|
|
878
|
+
/* @__PURE__ */ jsxs5("div", { className: "agent-rail__footer", children: [
|
|
879
|
+
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
880
|
+
/* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
881
|
+
] })
|
|
882
|
+
] })
|
|
883
|
+
]
|
|
884
|
+
}
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
|
|
889
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
890
|
+
function SparklesIcon() {
|
|
891
|
+
return /* @__PURE__ */ jsxs6("svg", { className: "assist-edge-tab__sparkles", viewBox: "0 0 18 16", fill: "none", "aria-hidden": "true", children: [
|
|
892
|
+
/* @__PURE__ */ jsx7("path", { d: "M8 1.2l.95 2.7 2.85.05-2.25 1.75.8 2.75L8 6.7 5.65 8.45l.8-2.75L4.2 3.95l2.85-.05L8 1.2z", fill: "currentColor" }),
|
|
893
|
+
/* @__PURE__ */ jsx7("path", { d: "M14.2 6.4l.55 1.55 1.65.03-1.3 1 .46 1.58-1.36-1-1.36 1 .46-1.58-1.3-1 1.65-.03.55-1.55z", fill: "currentColor" }),
|
|
894
|
+
/* @__PURE__ */ jsx7("path", { d: "M3.1 9.1l.4 1.15 1.22.02-.96.74.34 1.17-1-.74-1 .74.34-1.17-.96-.74 1.22-.02.4-1.15z", fill: "currentColor" })
|
|
895
|
+
] });
|
|
896
|
+
}
|
|
897
|
+
function ChevronLeftIcon() {
|
|
898
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
899
|
+
}
|
|
900
|
+
function ChevronDownIcon() {
|
|
901
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
902
|
+
}
|
|
903
|
+
function DragDots() {
|
|
904
|
+
return /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx7("i", {}, index)) });
|
|
905
|
+
}
|
|
906
|
+
var VARIANT_COPY = {
|
|
907
|
+
outline: { label: "Assist", aria: "Open Assist" },
|
|
908
|
+
ask: { label: "Ask anything", aria: "Ask anything" },
|
|
909
|
+
fill: { label: "Assist", aria: "Open Assist" }
|
|
910
|
+
};
|
|
911
|
+
function AssistEdgeTab({
|
|
912
|
+
variant,
|
|
913
|
+
side,
|
|
914
|
+
along,
|
|
915
|
+
inset,
|
|
916
|
+
visible,
|
|
917
|
+
onOpen
|
|
918
|
+
}) {
|
|
919
|
+
const copy = VARIANT_COPY[variant];
|
|
920
|
+
const style = {
|
|
921
|
+
"--tab-along": `${along}%`,
|
|
922
|
+
"--tab-inset": `${inset}px`
|
|
923
|
+
};
|
|
924
|
+
return /* @__PURE__ */ jsxs6(
|
|
925
|
+
"button",
|
|
926
|
+
{
|
|
927
|
+
type: "button",
|
|
928
|
+
className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${visible ? " is-visible" : ""}`,
|
|
929
|
+
style,
|
|
930
|
+
"aria-label": copy.aria,
|
|
931
|
+
"aria-hidden": !visible,
|
|
932
|
+
tabIndex: visible ? 0 : -1,
|
|
933
|
+
onClick: onOpen,
|
|
934
|
+
children: [
|
|
935
|
+
variant === "outline" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
936
|
+
/* @__PURE__ */ jsx7(SparklesIcon, {}),
|
|
937
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
938
|
+
/* @__PURE__ */ jsx7(ChevronDownIcon, {})
|
|
939
|
+
] }) : null,
|
|
940
|
+
variant === "ask" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
941
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {}),
|
|
942
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
943
|
+
/* @__PURE__ */ jsx7(DragDots, {})
|
|
944
|
+
] }) : null,
|
|
945
|
+
variant === "fill" ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
946
|
+
/* @__PURE__ */ jsx7(SparklesIcon, {}),
|
|
947
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
|
|
948
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {})
|
|
949
|
+
] }) : null
|
|
950
|
+
]
|
|
951
|
+
}
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
956
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
957
|
+
|
|
958
|
+
// src/react/hooks/useIsMobile.ts
|
|
959
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
960
|
+
function useIsMobile(breakpoint = 767) {
|
|
961
|
+
const [isMobile, setIsMobile] = useState3(
|
|
962
|
+
() => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
963
|
+
);
|
|
964
|
+
useEffect3(() => {
|
|
965
|
+
const media = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
966
|
+
const onChange = () => setIsMobile(media.matches);
|
|
967
|
+
onChange();
|
|
968
|
+
media.addEventListener("change", onChange);
|
|
969
|
+
return () => media.removeEventListener("change", onChange);
|
|
970
|
+
}, [breakpoint]);
|
|
971
|
+
return isMobile;
|
|
695
972
|
}
|
|
696
973
|
|
|
697
|
-
// src/react/
|
|
698
|
-
var
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
text: "Hi! I'm connected to the Webless Agent Runtime. Ask anything about your published site index.",
|
|
702
|
-
createdAt: 0
|
|
703
|
-
};
|
|
704
|
-
var INITIAL_STATE = {
|
|
705
|
-
phase: "idle",
|
|
706
|
-
messages: [GREETING_MESSAGE],
|
|
707
|
-
toolSteps: [],
|
|
708
|
-
journey: null,
|
|
709
|
-
followUps: [],
|
|
710
|
-
streamingText: "",
|
|
711
|
-
error: null
|
|
712
|
-
};
|
|
713
|
-
var STATUS_SEQUENCE = [
|
|
714
|
-
{ id: "s1", label: "Starting Eve session", ms: 400 },
|
|
715
|
-
{ id: "s2", label: "Connecting to runtime", ms: 500 }
|
|
716
|
-
];
|
|
717
|
-
var DEFAULT_FOLLOW_UPS = [
|
|
718
|
-
{ id: "fu-1", label: "What can you help me with?" },
|
|
719
|
-
{ id: "fu-2", label: "Summarize your capabilities" },
|
|
720
|
-
{ id: "fu-3", label: "What should I ask next?" }
|
|
721
|
-
];
|
|
722
|
-
function delay(ms, signal) {
|
|
723
|
-
return new Promise((resolve, reject) => {
|
|
724
|
-
const timer = window.setTimeout(resolve, ms);
|
|
725
|
-
signal.addEventListener(
|
|
726
|
-
"abort",
|
|
727
|
-
() => {
|
|
728
|
-
window.clearTimeout(timer);
|
|
729
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
730
|
-
},
|
|
731
|
-
{ once: true }
|
|
732
|
-
);
|
|
733
|
-
});
|
|
974
|
+
// src/react/panel-controller.ts
|
|
975
|
+
var controllers = /* @__PURE__ */ new Map();
|
|
976
|
+
function registerAgentPanelController(customerId, controller) {
|
|
977
|
+
controllers.set(customerId, controller);
|
|
734
978
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
onStep({ id: item.id, label: item.label, detail: item.detail, state: "active" });
|
|
738
|
-
await delay(item.ms, signal);
|
|
739
|
-
}
|
|
979
|
+
function unregisterAgentPanelController(customerId) {
|
|
980
|
+
controllers.delete(customerId);
|
|
740
981
|
}
|
|
741
|
-
function
|
|
742
|
-
customerId
|
|
982
|
+
function openAgentPanel(customerId) {
|
|
983
|
+
controllers.get(customerId)?.open();
|
|
984
|
+
}
|
|
985
|
+
function closeAgentPanel(customerId) {
|
|
986
|
+
controllers.get(customerId)?.close();
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
990
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
991
|
+
function AgentWidget({
|
|
743
992
|
indexId,
|
|
993
|
+
customerId,
|
|
994
|
+
version,
|
|
744
995
|
runtimeOrigin,
|
|
745
|
-
|
|
746
|
-
|
|
996
|
+
placement: placementInput,
|
|
997
|
+
defaultCollapsed = true,
|
|
998
|
+
registerPanelController = false
|
|
747
999
|
}) {
|
|
748
|
-
const
|
|
749
|
-
const
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
);
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const identityRef = useRef3(null);
|
|
768
|
-
const identityKey = `${customerId ?? ""}|${indexId}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}`;
|
|
769
|
-
useEffect2(() => {
|
|
770
|
-
if (identityRef.current === null) {
|
|
771
|
-
identityRef.current = identityKey;
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
if (identityRef.current === identityKey) {
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
777
|
-
identityRef.current = identityKey;
|
|
778
|
-
runRef.current?.abort();
|
|
779
|
-
runRef.current = null;
|
|
780
|
-
clientRef.current.reset();
|
|
781
|
-
clientRef.current = createAgentClient({
|
|
782
|
-
customerId,
|
|
783
|
-
indexId,
|
|
784
|
-
runtimeOrigin,
|
|
785
|
-
visitorSessionId: visitorId,
|
|
786
|
-
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
1000
|
+
const isMobile = useIsMobile();
|
|
1001
|
+
const placement = normalizeAgentPlacement(placementInput);
|
|
1002
|
+
const [railCollapsed, setRailCollapsed] = useState4(defaultCollapsed);
|
|
1003
|
+
const [railExpanded, setRailExpanded] = useState4(false);
|
|
1004
|
+
const { state, submit } = useAgentChat({
|
|
1005
|
+
customerId,
|
|
1006
|
+
indexId,
|
|
1007
|
+
version,
|
|
1008
|
+
runtimeOrigin
|
|
1009
|
+
});
|
|
1010
|
+
const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
|
|
1011
|
+
useEffect4(() => {
|
|
1012
|
+
if (!registerPanelController) return;
|
|
1013
|
+
registerAgentPanelController(customerId, {
|
|
1014
|
+
open: () => setRailCollapsed(false),
|
|
1015
|
+
close: () => {
|
|
1016
|
+
setRailCollapsed(true);
|
|
1017
|
+
setRailExpanded(false);
|
|
1018
|
+
}
|
|
787
1019
|
});
|
|
788
|
-
|
|
789
|
-
}, [customerId,
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}));
|
|
820
|
-
try {
|
|
821
|
-
let streamStarted = false;
|
|
822
|
-
const planningPromise = runStatusSequence(signal, (step) => {
|
|
823
|
-
if (streamStarted || !isActiveRun()) return;
|
|
824
|
-
setState((prev) => ({ ...prev, phase: "running-tools", toolSteps: [step] }));
|
|
825
|
-
});
|
|
826
|
-
let streamed = "";
|
|
827
|
-
const finalText = await clientRef.current.sendTurn(visitorText, {
|
|
828
|
-
signal,
|
|
829
|
-
handlers: {
|
|
830
|
-
onStep: (label, detail) => {
|
|
831
|
-
if (streamStarted || !isActiveRun()) return;
|
|
832
|
-
setState((prev) => ({
|
|
833
|
-
...prev,
|
|
834
|
-
phase: "running-tools",
|
|
835
|
-
toolSteps: [{ id: `step-${label}`, label, detail, state: "active" }]
|
|
836
|
-
}));
|
|
837
|
-
},
|
|
838
|
-
onDelta: (delta) => {
|
|
839
|
-
if (!isActiveRun()) return;
|
|
840
|
-
void planningPromise.catch(() => {
|
|
841
|
-
});
|
|
842
|
-
if (!streamStarted) {
|
|
843
|
-
streamStarted = true;
|
|
844
|
-
setState((prev) => ({
|
|
845
|
-
...prev,
|
|
846
|
-
phase: "streaming",
|
|
847
|
-
toolSteps: [],
|
|
848
|
-
streamingText: ""
|
|
849
|
-
}));
|
|
1020
|
+
return () => unregisterAgentPanelController(customerId);
|
|
1021
|
+
}, [customerId, registerPanelController]);
|
|
1022
|
+
async function handleSubmit(message) {
|
|
1023
|
+
if (isMobile) setRailCollapsed(false);
|
|
1024
|
+
await submit(message);
|
|
1025
|
+
}
|
|
1026
|
+
return /* @__PURE__ */ jsxs7("div", { className: "webless-agent-root", children: [
|
|
1027
|
+
/* @__PURE__ */ jsx8(
|
|
1028
|
+
"div",
|
|
1029
|
+
{
|
|
1030
|
+
className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
|
|
1031
|
+
children: /* @__PURE__ */ jsx8(
|
|
1032
|
+
"div",
|
|
1033
|
+
{
|
|
1034
|
+
className: "webless-agent-root__rail-slot",
|
|
1035
|
+
inert: railCollapsed || void 0,
|
|
1036
|
+
"aria-hidden": railCollapsed,
|
|
1037
|
+
children: /* @__PURE__ */ jsx8(
|
|
1038
|
+
AgentRail,
|
|
1039
|
+
{
|
|
1040
|
+
state: idle ? {
|
|
1041
|
+
...state,
|
|
1042
|
+
followUps: createIdleSuggestions()
|
|
1043
|
+
} : state,
|
|
1044
|
+
mobileFullscreen: isMobile && !railCollapsed,
|
|
1045
|
+
expanded: railExpanded,
|
|
1046
|
+
onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
|
|
1047
|
+
onClose: isMobile ? () => setRailCollapsed(true) : void 0,
|
|
1048
|
+
onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
|
|
1049
|
+
onSubmit: handleSubmit,
|
|
1050
|
+
onFollowUpSelect: (label) => void handleSubmit(label)
|
|
850
1051
|
}
|
|
851
|
-
|
|
852
|
-
setState((prev) => ({ ...prev, phase: "streaming", streamingText: streamed }));
|
|
853
|
-
},
|
|
854
|
-
onComplete: () => {
|
|
855
|
-
if (!isActiveRun()) return;
|
|
856
|
-
streamStarted = true;
|
|
857
|
-
}
|
|
1052
|
+
)
|
|
858
1053
|
}
|
|
859
|
-
|
|
860
|
-
await planningPromise.catch(() => {
|
|
861
|
-
});
|
|
862
|
-
if (!isActiveRun()) return;
|
|
863
|
-
const agentMessage = {
|
|
864
|
-
id: `agent-${Date.now()}`,
|
|
865
|
-
role: "agent",
|
|
866
|
-
text: finalText,
|
|
867
|
-
createdAt: Date.now()
|
|
868
|
-
};
|
|
869
|
-
setState((prev) => ({
|
|
870
|
-
...prev,
|
|
871
|
-
phase: "complete",
|
|
872
|
-
messages: [...prev.messages, agentMessage],
|
|
873
|
-
toolSteps: [],
|
|
874
|
-
streamingText: "",
|
|
875
|
-
followUps: DEFAULT_FOLLOW_UPS,
|
|
876
|
-
journey: null
|
|
877
|
-
}));
|
|
878
|
-
} catch (error) {
|
|
879
|
-
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
880
|
-
if (!isActiveRun()) return;
|
|
881
|
-
const message = formatAgentError(error);
|
|
882
|
-
if (!message) return;
|
|
883
|
-
setState((prev) => ({
|
|
884
|
-
...prev,
|
|
885
|
-
phase: "complete",
|
|
886
|
-
toolSteps: [],
|
|
887
|
-
streamingText: "",
|
|
888
|
-
error: message
|
|
889
|
-
}));
|
|
1054
|
+
)
|
|
890
1055
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
{ id: "idle-1", label: "Hello \u2014 what can you do?" },
|
|
914
|
-
{ id: "idle-2", label: "Help me evaluate this product" },
|
|
915
|
-
{ id: "idle-3", label: "What should I ask you?" }
|
|
916
|
-
];
|
|
917
|
-
}
|
|
918
|
-
function isAgentBusy(phase) {
|
|
919
|
-
return phase === "thinking" || phase === "running-tools" || phase === "streaming";
|
|
1056
|
+
),
|
|
1057
|
+
!isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx8(
|
|
1058
|
+
"button",
|
|
1059
|
+
{
|
|
1060
|
+
type: "button",
|
|
1061
|
+
className: "webless-agent-root__backdrop",
|
|
1062
|
+
"aria-label": "Close expanded assist",
|
|
1063
|
+
onClick: () => setRailExpanded(false)
|
|
1064
|
+
}
|
|
1065
|
+
) : null,
|
|
1066
|
+
railCollapsed ? /* @__PURE__ */ jsx8(
|
|
1067
|
+
AssistEdgeTab,
|
|
1068
|
+
{
|
|
1069
|
+
variant: placement.variant,
|
|
1070
|
+
side: placement.side,
|
|
1071
|
+
along: placement.along,
|
|
1072
|
+
inset: placement.inset,
|
|
1073
|
+
visible: true,
|
|
1074
|
+
onOpen: () => setRailCollapsed(false)
|
|
1075
|
+
}
|
|
1076
|
+
) : null
|
|
1077
|
+
] });
|
|
920
1078
|
}
|
|
921
1079
|
|
|
922
1080
|
export {
|
|
923
|
-
AgentRail,
|
|
924
|
-
AssistEdgeTab,
|
|
925
1081
|
DEFAULT_RUNTIME_ORIGIN,
|
|
926
1082
|
resolveAgentRuntimeConfig,
|
|
927
1083
|
useAgentChat,
|
|
928
1084
|
hasVisitorMessages,
|
|
929
1085
|
createIdleSuggestions,
|
|
930
|
-
isAgentBusy
|
|
1086
|
+
isAgentBusy,
|
|
1087
|
+
DEFAULT_AGENT_PLACEMENT,
|
|
1088
|
+
normalizeAgentPlacement,
|
|
1089
|
+
openAgentPanel,
|
|
1090
|
+
closeAgentPanel,
|
|
1091
|
+
AgentRail,
|
|
1092
|
+
AssistEdgeTab,
|
|
1093
|
+
AgentWidget
|
|
931
1094
|
};
|
|
932
|
-
//# sourceMappingURL=chunk-
|
|
1095
|
+
//# sourceMappingURL=chunk-4QGS7UZY.js.map
|