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