@webless/agent 0.2.14 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/{chunk-6FNE65AR.js → chunk-MRSLWREA.js} +650 -251
- package/dist/chunk-MRSLWREA.js.map +1 -0
- package/dist/embed.cjs +722 -294
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.css +199 -21
- package/dist/embed.css.map +1 -1
- package/dist/embed.d.cts +3 -31
- package/dist/embed.d.ts +3 -31
- package/dist/embed.js +33 -3
- package/dist/embed.js.map +1 -1
- package/dist/index.cjs +123 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +123 -12
- package/dist/index.js.map +1 -1
- package/dist/manifest-oc_3zCSC.d.cts +79 -0
- package/dist/manifest-oc_3zCSC.d.ts +79 -0
- package/dist/react.cjs +684 -304
- package/dist/react.cjs.map +1 -1
- package/dist/react.css +199 -21
- package/dist/react.css.map +1 -1
- package/dist/react.d.cts +12 -5
- package/dist/react.d.ts +12 -5
- package/dist/react.js +2 -19
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6FNE65AR.js.map +0 -1
- package/dist/placement-CXW_83AF.d.cts +0 -25
- package/dist/placement-CXW_83AF.d.ts +0 -25
package/dist/embed.cjs
CHANGED
|
@@ -50,10 +50,90 @@ function closeAgentPanel(customerId) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
53
|
-
var
|
|
53
|
+
var import_react6 = require("react");
|
|
54
54
|
|
|
55
|
-
// src/react/
|
|
55
|
+
// src/react/page-shift.ts
|
|
56
56
|
var import_react = require("react");
|
|
57
|
+
var PAGE_SHIFT_CLASS = "webless-agent-page-shift";
|
|
58
|
+
var DEFAULT_RAIL_WIDTH_PX = 450;
|
|
59
|
+
function shouldApplyPageShift(input) {
|
|
60
|
+
return input.pageShift && !input.isMobile && !input.railCollapsed && !input.railExpanded;
|
|
61
|
+
}
|
|
62
|
+
function resolvePageShiftWidth(railWidth) {
|
|
63
|
+
if (typeof railWidth === "number" && railWidth > 0) {
|
|
64
|
+
return railWidth;
|
|
65
|
+
}
|
|
66
|
+
if (typeof document !== "undefined") {
|
|
67
|
+
const token = getComputedStyle(document.documentElement).getPropertyValue("--as-rail-max-width").trim();
|
|
68
|
+
const parsed = Number.parseFloat(token);
|
|
69
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
70
|
+
return parsed;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return DEFAULT_RAIL_WIDTH_PX;
|
|
74
|
+
}
|
|
75
|
+
var savedPageMargin = null;
|
|
76
|
+
function readPageMarginSnapshot(style) {
|
|
77
|
+
return {
|
|
78
|
+
value: style.getPropertyValue("margin-right"),
|
|
79
|
+
priority: style.getPropertyPriority("margin-right")
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function restorePageMargin(style, snapshot) {
|
|
83
|
+
if (snapshot.value) {
|
|
84
|
+
style.setProperty("margin-right", snapshot.value, snapshot.priority || void 0);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
style.removeProperty("margin-right");
|
|
88
|
+
}
|
|
89
|
+
function snapshotPageMarginIfNeeded() {
|
|
90
|
+
if (savedPageMargin !== null) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
savedPageMargin = readPageMarginSnapshot(document.documentElement.style);
|
|
94
|
+
}
|
|
95
|
+
function setPageMargin(margin) {
|
|
96
|
+
snapshotPageMarginIfNeeded();
|
|
97
|
+
document.documentElement.style.setProperty("margin-right", margin, "important");
|
|
98
|
+
}
|
|
99
|
+
function clearPageMargin() {
|
|
100
|
+
if (savedPageMargin === null) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
restorePageMargin(document.documentElement.style, savedPageMargin);
|
|
104
|
+
savedPageMargin = null;
|
|
105
|
+
}
|
|
106
|
+
function usePageShift(input) {
|
|
107
|
+
const { active, railSlotRef } = input;
|
|
108
|
+
(0, import_react.useEffect)(() => {
|
|
109
|
+
if (typeof document === "undefined") {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!active) {
|
|
113
|
+
document.documentElement.classList.remove(PAGE_SHIFT_CLASS);
|
|
114
|
+
clearPageMargin();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
document.documentElement.classList.add(PAGE_SHIFT_CLASS);
|
|
118
|
+
function applyMargin() {
|
|
119
|
+
const rail = railSlotRef.current?.querySelector(".agent-rail");
|
|
120
|
+
const width = resolvePageShiftWidth(
|
|
121
|
+
rail instanceof HTMLElement ? rail.offsetWidth : null
|
|
122
|
+
);
|
|
123
|
+
setPageMargin(`${width}px`);
|
|
124
|
+
}
|
|
125
|
+
applyMargin();
|
|
126
|
+
const frame = requestAnimationFrame(applyMargin);
|
|
127
|
+
return () => {
|
|
128
|
+
cancelAnimationFrame(frame);
|
|
129
|
+
document.documentElement.classList.remove(PAGE_SHIFT_CLASS);
|
|
130
|
+
clearPageMargin();
|
|
131
|
+
};
|
|
132
|
+
}, [active, railSlotRef]);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/react/hooks/useAgentChat.ts
|
|
136
|
+
var import_react2 = require("react");
|
|
57
137
|
|
|
58
138
|
// src/runtime/client.ts
|
|
59
139
|
var import_client2 = require("eve/client");
|
|
@@ -271,9 +351,8 @@ function clearPersistedAgentSession(visitorSessionId, options) {
|
|
|
271
351
|
function isTurnBoundary(event) {
|
|
272
352
|
return event.type === "session.waiting" || event.type === "session.completed" || event.type === "session.failed";
|
|
273
353
|
}
|
|
274
|
-
function applyMessageEvent(event, rendered, handlers) {
|
|
275
|
-
|
|
276
|
-
if (step) handlers.onStep?.(step.label, step.detail);
|
|
354
|
+
function applyMessageEvent(event, rendered, handlers, workItems) {
|
|
355
|
+
applyWorkEvent(event, handlers, workItems);
|
|
277
356
|
if (event.type === "session.failed") {
|
|
278
357
|
throw new Error(event.data.message || event.data.code);
|
|
279
358
|
}
|
|
@@ -316,13 +395,120 @@ function renderTurn(events) {
|
|
|
316
395
|
}
|
|
317
396
|
return rendered;
|
|
318
397
|
}
|
|
319
|
-
function
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
398
|
+
function emitWorkItem(item, handlers, workItems) {
|
|
399
|
+
workItems.set(item.id, item);
|
|
400
|
+
handlers.onWork?.(item);
|
|
401
|
+
handlers.onStep?.(item.label, item.detail);
|
|
402
|
+
}
|
|
403
|
+
function completePlanning(handlers, workItems) {
|
|
404
|
+
const planning = workItems.get("planning");
|
|
405
|
+
if (!planning || planning.state !== "active") return;
|
|
406
|
+
emitWorkItem(
|
|
407
|
+
{
|
|
408
|
+
...planning,
|
|
409
|
+
detail: "Picked the best way to help",
|
|
410
|
+
state: "completed"
|
|
411
|
+
},
|
|
412
|
+
handlers,
|
|
413
|
+
workItems
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
function specialistNameFromInput(input) {
|
|
417
|
+
const message = input.message;
|
|
418
|
+
if (typeof message !== "string") return void 0;
|
|
419
|
+
const match = /^Webless-Agent-Name:\s*(.+)$/imu.exec(message);
|
|
420
|
+
return match?.[1]?.trim() || void 0;
|
|
421
|
+
}
|
|
422
|
+
function requestedWorkItem(action) {
|
|
423
|
+
if (action.kind === "tool-call" && action.toolName === "search_discovery") {
|
|
424
|
+
return {
|
|
425
|
+
id: action.callId,
|
|
426
|
+
kind: "search",
|
|
427
|
+
label: "Search & Discovery",
|
|
428
|
+
detail: "Searching this site",
|
|
429
|
+
state: "active"
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (action.kind === "subagent-call" || action.kind === "remote-agent-call" || action.kind === "tool-call" && action.toolName === "agent") {
|
|
433
|
+
const name = specialistNameFromInput(action.input) ?? "Specialist";
|
|
434
|
+
return {
|
|
435
|
+
id: action.callId,
|
|
436
|
+
kind: "specialist",
|
|
437
|
+
label: name,
|
|
438
|
+
detail: "Reviewing your question",
|
|
439
|
+
state: "active"
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
function applyWorkEvent(event, handlers, workItems) {
|
|
445
|
+
if (event.type === "step.started" && workItems.size === 0) {
|
|
446
|
+
emitWorkItem(
|
|
447
|
+
{
|
|
448
|
+
id: "planning",
|
|
449
|
+
kind: "planning",
|
|
450
|
+
label: "Understanding your question",
|
|
451
|
+
state: "active"
|
|
452
|
+
},
|
|
453
|
+
handlers,
|
|
454
|
+
workItems
|
|
455
|
+
);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
if (event.type === "actions.requested") {
|
|
459
|
+
completePlanning(handlers, workItems);
|
|
460
|
+
for (const action of event.data.actions) {
|
|
461
|
+
const item = requestedWorkItem(action);
|
|
462
|
+
if (item) emitWorkItem(item, handlers, workItems);
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (event.type === "subagent.called") {
|
|
467
|
+
completePlanning(handlers, workItems);
|
|
468
|
+
const current2 = workItems.get(event.data.callId);
|
|
469
|
+
if (!current2) {
|
|
470
|
+
emitWorkItem(
|
|
471
|
+
{
|
|
472
|
+
id: event.data.callId,
|
|
473
|
+
kind: "specialist",
|
|
474
|
+
label: event.data.name || "Specialist",
|
|
475
|
+
detail: "Reviewing your question",
|
|
476
|
+
state: "active"
|
|
477
|
+
},
|
|
478
|
+
handlers,
|
|
479
|
+
workItems
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
if (event.type === "subagent.completed") {
|
|
485
|
+
const current2 = workItems.get(event.data.callId);
|
|
486
|
+
if (!current2) return;
|
|
487
|
+
emitWorkItem(
|
|
488
|
+
{
|
|
489
|
+
...current2,
|
|
490
|
+
detail: "Guidance received",
|
|
491
|
+
state: "completed"
|
|
492
|
+
},
|
|
493
|
+
handlers,
|
|
494
|
+
workItems
|
|
495
|
+
);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (event.type !== "action.result") return;
|
|
499
|
+
const { result, status } = event.data;
|
|
500
|
+
const current = workItems.get(result.callId);
|
|
501
|
+
if (!current) return;
|
|
502
|
+
const failed = status !== "completed" || result.isError === true;
|
|
503
|
+
emitWorkItem(
|
|
504
|
+
{
|
|
505
|
+
...current,
|
|
506
|
+
detail: failed ? "Couldn\u2019t complete; continuing with available information" : current.kind === "search" ? "Found relevant site content" : "Guidance received",
|
|
507
|
+
state: failed ? "error" : "completed"
|
|
508
|
+
},
|
|
509
|
+
handlers,
|
|
510
|
+
workItems
|
|
511
|
+
);
|
|
326
512
|
}
|
|
327
513
|
var AgentSession = class {
|
|
328
514
|
constructor(indexId, version, runtimeOrigin, visitorSessionId, storeOptions, getUnpublishedPreviewGrant) {
|
|
@@ -440,10 +626,11 @@ var AgentSession = class {
|
|
|
440
626
|
this.activeResponse = response;
|
|
441
627
|
let streamIndex = session?.state.streamIndex ?? 0;
|
|
442
628
|
let rendered = "";
|
|
629
|
+
const workItems = /* @__PURE__ */ new Map();
|
|
443
630
|
try {
|
|
444
631
|
for await (const event of response) {
|
|
445
632
|
if (signal.aborted) break;
|
|
446
|
-
rendered = applyMessageEvent(event, rendered, handlers);
|
|
633
|
+
rendered = applyMessageEvent(event, rendered, handlers, workItems);
|
|
447
634
|
streamIndex += 1;
|
|
448
635
|
if (session) {
|
|
449
636
|
savePersistedAgentSession(
|
|
@@ -485,6 +672,10 @@ var AgentSession = class {
|
|
|
485
672
|
return null;
|
|
486
673
|
}
|
|
487
674
|
let rendered = renderTurn(turnEvents);
|
|
675
|
+
const workItems = /* @__PURE__ */ new Map();
|
|
676
|
+
for (const event of turnEvents) {
|
|
677
|
+
applyWorkEvent(event, handlers, workItems);
|
|
678
|
+
}
|
|
488
679
|
if (rendered.startsWith(initialText)) {
|
|
489
680
|
const missedText = rendered.slice(initialText.length);
|
|
490
681
|
if (missedText) handlers.onDelta(missedText);
|
|
@@ -519,7 +710,7 @@ var AgentSession = class {
|
|
|
519
710
|
let streamIndex = snapshot.session.streamIndex;
|
|
520
711
|
for await (const event of session.stream({ signal })) {
|
|
521
712
|
if (signal.aborted) break;
|
|
522
|
-
rendered = applyMessageEvent(event, rendered, handlers);
|
|
713
|
+
rendered = applyMessageEvent(event, rendered, handlers, workItems);
|
|
523
714
|
streamIndex += 1;
|
|
524
715
|
savePersistedAgentSession(
|
|
525
716
|
this.visitorSessionId,
|
|
@@ -672,57 +863,54 @@ function clearPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
|
672
863
|
}
|
|
673
864
|
|
|
674
865
|
// src/react/hooks/useAgentChat.ts
|
|
675
|
-
var
|
|
676
|
-
|
|
677
|
-
role: "agent",
|
|
678
|
-
text: "Hi! I'm connected to the Webless Agent Runtime. Ask anything about your published site index.",
|
|
679
|
-
createdAt: 0
|
|
680
|
-
};
|
|
681
|
-
var INITIAL_STATE = {
|
|
682
|
-
phase: "idle",
|
|
683
|
-
messages: [GREETING_MESSAGE],
|
|
684
|
-
toolSteps: [],
|
|
685
|
-
journey: null,
|
|
686
|
-
followUps: [],
|
|
687
|
-
streamingText: "",
|
|
688
|
-
error: null
|
|
689
|
-
};
|
|
690
|
-
function stateFromConversation(conversation) {
|
|
691
|
-
if (!conversation || conversation.messages.length === 0) return INITIAL_STATE;
|
|
866
|
+
var DEFAULT_GREETING = "Hi! I can search this site or bring in a specialist when it helps. What would you like to know?";
|
|
867
|
+
function createInitialState(greeting = DEFAULT_GREETING) {
|
|
692
868
|
return {
|
|
693
|
-
|
|
869
|
+
phase: "idle",
|
|
870
|
+
messages: [
|
|
871
|
+
{
|
|
872
|
+
id: "greeting",
|
|
873
|
+
role: "agent",
|
|
874
|
+
text: greeting,
|
|
875
|
+
createdAt: 0
|
|
876
|
+
}
|
|
877
|
+
],
|
|
878
|
+
toolSteps: [],
|
|
879
|
+
journey: null,
|
|
880
|
+
followUps: [],
|
|
881
|
+
streamingText: "",
|
|
882
|
+
error: null
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
function stateFromConversation(conversation, initialState) {
|
|
886
|
+
if (!conversation || conversation.messages.length === 0) return initialState;
|
|
887
|
+
return {
|
|
888
|
+
...initialState,
|
|
694
889
|
messages: conversation.messages,
|
|
695
890
|
phase: conversation.pending ? conversation.streamingText ? "streaming" : "thinking" : "complete",
|
|
696
891
|
streamingText: conversation.streamingText
|
|
697
892
|
};
|
|
698
893
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
)
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
id: item.id,
|
|
720
|
-
label: item.label,
|
|
721
|
-
detail: item.detail,
|
|
722
|
-
state: "active"
|
|
723
|
-
});
|
|
724
|
-
await delay(item.ms, signal);
|
|
725
|
-
}
|
|
894
|
+
function upsertToolStep(steps, item) {
|
|
895
|
+
const next = {
|
|
896
|
+
id: item.id,
|
|
897
|
+
kind: item.kind,
|
|
898
|
+
label: item.label,
|
|
899
|
+
state: item.state,
|
|
900
|
+
...item.detail ? { detail: item.detail } : {}
|
|
901
|
+
};
|
|
902
|
+
const index = steps.findIndex((step) => step.id === item.id);
|
|
903
|
+
if (index < 0) return [...steps, next];
|
|
904
|
+
return steps.map((step, stepIndex) => stepIndex === index ? next : step);
|
|
905
|
+
}
|
|
906
|
+
function completeActivePlanning(steps) {
|
|
907
|
+
return steps.map(
|
|
908
|
+
(step) => step.kind === "planning" && step.state === "active" ? {
|
|
909
|
+
...step,
|
|
910
|
+
detail: "Prepared a response",
|
|
911
|
+
state: "completed"
|
|
912
|
+
} : step
|
|
913
|
+
);
|
|
726
914
|
}
|
|
727
915
|
function useAgentChat({
|
|
728
916
|
customerId,
|
|
@@ -731,9 +919,14 @@ function useAgentChat({
|
|
|
731
919
|
version,
|
|
732
920
|
runtimeOrigin,
|
|
733
921
|
visitorSessionId,
|
|
734
|
-
storageKeyPrefix
|
|
922
|
+
storageKeyPrefix,
|
|
923
|
+
greeting
|
|
735
924
|
}) {
|
|
736
|
-
const
|
|
925
|
+
const initialState = (0, import_react2.useMemo)(
|
|
926
|
+
() => createInitialState(greeting?.trim() || DEFAULT_GREETING),
|
|
927
|
+
[greeting]
|
|
928
|
+
);
|
|
929
|
+
const previewGrantProviderRef = (0, import_react2.useRef)(getUnpublishedPreviewGrant);
|
|
737
930
|
previewGrantProviderRef.current = getUnpublishedPreviewGrant;
|
|
738
931
|
const resolveUnpublishedPreviewGrant = () => {
|
|
739
932
|
const provider = previewGrantProviderRef.current;
|
|
@@ -746,7 +939,7 @@ function useAgentChat({
|
|
|
746
939
|
}
|
|
747
940
|
return provider();
|
|
748
941
|
};
|
|
749
|
-
const resolvedStorageKeyPrefix = (0,
|
|
942
|
+
const resolvedStorageKeyPrefix = (0, import_react2.useMemo)(
|
|
750
943
|
() => storageKeyPrefix?.trim() || buildAgentStorageKeyPrefix({
|
|
751
944
|
customerId,
|
|
752
945
|
indexId,
|
|
@@ -755,19 +948,20 @@ function useAgentChat({
|
|
|
755
948
|
}),
|
|
756
949
|
[customerId, indexId, runtimeOrigin, storageKeyPrefix, version]
|
|
757
950
|
);
|
|
758
|
-
const visitorId = (0,
|
|
951
|
+
const visitorId = (0, import_react2.useMemo)(
|
|
759
952
|
() => visitorSessionId?.trim() || getOrCreateVisitorSessionId({
|
|
760
953
|
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
761
954
|
}),
|
|
762
955
|
[resolvedStorageKeyPrefix, visitorSessionId]
|
|
763
956
|
);
|
|
764
|
-
const [state, setState] = (0,
|
|
957
|
+
const [state, setState] = (0, import_react2.useState)(
|
|
765
958
|
() => stateFromConversation(
|
|
766
|
-
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId)
|
|
959
|
+
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
|
|
960
|
+
initialState
|
|
767
961
|
)
|
|
768
962
|
);
|
|
769
|
-
const runRef = (0,
|
|
770
|
-
const clientRef = (0,
|
|
963
|
+
const runRef = (0, import_react2.useRef)(null);
|
|
964
|
+
const clientRef = (0, import_react2.useRef)(
|
|
771
965
|
createAgentClient({
|
|
772
966
|
customerId,
|
|
773
967
|
getUnpublishedPreviewGrant: resolveUnpublishedPreviewGrant,
|
|
@@ -778,9 +972,9 @@ function useAgentChat({
|
|
|
778
972
|
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
779
973
|
})
|
|
780
974
|
);
|
|
781
|
-
const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}`;
|
|
782
|
-
const identityRef = (0,
|
|
783
|
-
(0,
|
|
975
|
+
const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}|${greeting ?? ""}`;
|
|
976
|
+
const identityRef = (0, import_react2.useRef)(identityKey);
|
|
977
|
+
(0, import_react2.useEffect)(() => {
|
|
784
978
|
if (identityRef.current === identityKey) {
|
|
785
979
|
return;
|
|
786
980
|
}
|
|
@@ -798,19 +992,21 @@ function useAgentChat({
|
|
|
798
992
|
});
|
|
799
993
|
setState(
|
|
800
994
|
stateFromConversation(
|
|
801
|
-
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId)
|
|
995
|
+
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
|
|
996
|
+
initialState
|
|
802
997
|
)
|
|
803
998
|
);
|
|
804
999
|
}, [
|
|
805
1000
|
customerId,
|
|
806
1001
|
identityKey,
|
|
807
1002
|
indexId,
|
|
1003
|
+
initialState,
|
|
808
1004
|
runtimeOrigin,
|
|
809
1005
|
resolvedStorageKeyPrefix,
|
|
810
1006
|
version,
|
|
811
1007
|
visitorId
|
|
812
1008
|
]);
|
|
813
|
-
(0,
|
|
1009
|
+
(0, import_react2.useEffect)(() => {
|
|
814
1010
|
if (!hasVisitorMessages(state.messages)) return;
|
|
815
1011
|
savePersistedAgentConversation(resolvedStorageKeyPrefix, visitorId, {
|
|
816
1012
|
messages: state.messages,
|
|
@@ -824,14 +1020,14 @@ function useAgentChat({
|
|
|
824
1020
|
state.streamingText,
|
|
825
1021
|
visitorId
|
|
826
1022
|
]);
|
|
827
|
-
const reset = (0,
|
|
1023
|
+
const reset = (0, import_react2.useCallback)(() => {
|
|
828
1024
|
runRef.current?.abort();
|
|
829
1025
|
runRef.current = null;
|
|
830
1026
|
clientRef.current.reset();
|
|
831
1027
|
clearPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId);
|
|
832
|
-
setState(
|
|
833
|
-
}, [resolvedStorageKeyPrefix, visitorId]);
|
|
834
|
-
const runTurn = (0,
|
|
1028
|
+
setState(initialState);
|
|
1029
|
+
}, [initialState, resolvedStorageKeyPrefix, visitorId]);
|
|
1030
|
+
const runTurn = (0, import_react2.useCallback)(
|
|
835
1031
|
async (input) => {
|
|
836
1032
|
const { controller, initialText = "", resume, visitorText } = input;
|
|
837
1033
|
const { signal } = controller;
|
|
@@ -839,35 +1035,23 @@ function useAgentChat({
|
|
|
839
1035
|
try {
|
|
840
1036
|
let streamStarted = Boolean(initialText);
|
|
841
1037
|
let streamed = initialText;
|
|
842
|
-
const planningPromise = resume ? Promise.resolve() : runStatusSequence(signal, (step) => {
|
|
843
|
-
if (streamStarted || !isActiveRun()) return;
|
|
844
|
-
setState((prev) => ({
|
|
845
|
-
...prev,
|
|
846
|
-
phase: "running-tools",
|
|
847
|
-
toolSteps: [step]
|
|
848
|
-
}));
|
|
849
|
-
});
|
|
850
1038
|
const handlers = {
|
|
851
|
-
|
|
852
|
-
if (
|
|
1039
|
+
onWork: (item) => {
|
|
1040
|
+
if (!isActiveRun()) return;
|
|
853
1041
|
setState((prev) => ({
|
|
854
1042
|
...prev,
|
|
855
|
-
phase: "running-tools",
|
|
856
|
-
toolSteps:
|
|
857
|
-
{ id: `step-${label}`, label, detail, state: "active" }
|
|
858
|
-
]
|
|
1043
|
+
phase: item.state === "active" ? "running-tools" : prev.phase,
|
|
1044
|
+
toolSteps: upsertToolStep(prev.toolSteps, item)
|
|
859
1045
|
}));
|
|
860
1046
|
},
|
|
861
1047
|
onDelta: (delta) => {
|
|
862
1048
|
if (!isActiveRun()) return;
|
|
863
|
-
void planningPromise.catch(() => {
|
|
864
|
-
});
|
|
865
1049
|
if (!streamStarted) {
|
|
866
1050
|
streamStarted = true;
|
|
867
1051
|
setState((prev) => ({
|
|
868
1052
|
...prev,
|
|
869
1053
|
phase: "streaming",
|
|
870
|
-
toolSteps:
|
|
1054
|
+
toolSteps: completeActivePlanning(prev.toolSteps),
|
|
871
1055
|
streamingText: ""
|
|
872
1056
|
}));
|
|
873
1057
|
}
|
|
@@ -895,8 +1079,6 @@ function useAgentChat({
|
|
|
895
1079
|
signal
|
|
896
1080
|
});
|
|
897
1081
|
}
|
|
898
|
-
await planningPromise.catch(() => {
|
|
899
|
-
});
|
|
900
1082
|
if (!isActiveRun() || finalText === null) return;
|
|
901
1083
|
const agentMessage = {
|
|
902
1084
|
id: `agent-${Date.now()}`,
|
|
@@ -908,7 +1090,7 @@ function useAgentChat({
|
|
|
908
1090
|
...prev,
|
|
909
1091
|
phase: "complete",
|
|
910
1092
|
messages: [...prev.messages, agentMessage],
|
|
911
|
-
toolSteps:
|
|
1093
|
+
toolSteps: completeActivePlanning(prev.toolSteps),
|
|
912
1094
|
streamingText: "",
|
|
913
1095
|
followUps: [],
|
|
914
1096
|
journey: null
|
|
@@ -923,7 +1105,13 @@ function useAgentChat({
|
|
|
923
1105
|
setState((prev) => ({
|
|
924
1106
|
...prev,
|
|
925
1107
|
phase: "complete",
|
|
926
|
-
toolSteps:
|
|
1108
|
+
toolSteps: prev.toolSteps.map(
|
|
1109
|
+
(step) => step.state === "active" ? {
|
|
1110
|
+
...step,
|
|
1111
|
+
detail: "Couldn\u2019t complete this step",
|
|
1112
|
+
state: "error"
|
|
1113
|
+
} : step
|
|
1114
|
+
),
|
|
927
1115
|
streamingText: "",
|
|
928
1116
|
error: message
|
|
929
1117
|
}));
|
|
@@ -932,7 +1120,7 @@ function useAgentChat({
|
|
|
932
1120
|
},
|
|
933
1121
|
[]
|
|
934
1122
|
);
|
|
935
|
-
const submit = (0,
|
|
1123
|
+
const submit = (0, import_react2.useCallback)(
|
|
936
1124
|
async (visitorText) => {
|
|
937
1125
|
if (runRef.current) {
|
|
938
1126
|
runRef.current.abort();
|
|
@@ -951,7 +1139,12 @@ function useAgentChat({
|
|
|
951
1139
|
phase: "thinking",
|
|
952
1140
|
messages: [...prev.messages, visitorMessage],
|
|
953
1141
|
toolSteps: [
|
|
954
|
-
{
|
|
1142
|
+
{
|
|
1143
|
+
id: "planning",
|
|
1144
|
+
kind: "planning",
|
|
1145
|
+
label: "Understanding your question",
|
|
1146
|
+
state: "active"
|
|
1147
|
+
}
|
|
955
1148
|
],
|
|
956
1149
|
journey: null,
|
|
957
1150
|
followUps: [],
|
|
@@ -962,7 +1155,7 @@ function useAgentChat({
|
|
|
962
1155
|
},
|
|
963
1156
|
[runTurn]
|
|
964
1157
|
);
|
|
965
|
-
(0,
|
|
1158
|
+
(0, import_react2.useEffect)(() => {
|
|
966
1159
|
const conversation = loadPersistedAgentConversation(
|
|
967
1160
|
resolvedStorageKeyPrefix,
|
|
968
1161
|
visitorId
|
|
@@ -985,7 +1178,7 @@ function useAgentChat({
|
|
|
985
1178
|
controller.abort();
|
|
986
1179
|
};
|
|
987
1180
|
}, [identityKey, resolvedStorageKeyPrefix, runTurn, visitorId]);
|
|
988
|
-
(0,
|
|
1181
|
+
(0, import_react2.useEffect)(() => {
|
|
989
1182
|
return () => {
|
|
990
1183
|
runRef.current?.abort();
|
|
991
1184
|
runRef.current = null;
|
|
@@ -1014,12 +1207,12 @@ function isAgentBusy(phase) {
|
|
|
1014
1207
|
}
|
|
1015
1208
|
|
|
1016
1209
|
// src/react/hooks/useIsMobile.ts
|
|
1017
|
-
var
|
|
1210
|
+
var import_react3 = require("react");
|
|
1018
1211
|
function useIsMobile(breakpoint = 767) {
|
|
1019
|
-
const [isMobile, setIsMobile] = (0,
|
|
1212
|
+
const [isMobile, setIsMobile] = (0, import_react3.useState)(
|
|
1020
1213
|
() => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1021
1214
|
);
|
|
1022
|
-
(0,
|
|
1215
|
+
(0, import_react3.useEffect)(() => {
|
|
1023
1216
|
const media = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
1024
1217
|
const onChange = () => setIsMobile(media.matches);
|
|
1025
1218
|
onChange();
|
|
@@ -1047,81 +1240,95 @@ function normalizeAgentPlacement(placement) {
|
|
|
1047
1240
|
}
|
|
1048
1241
|
|
|
1049
1242
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1050
|
-
var
|
|
1243
|
+
var import_react5 = require("react");
|
|
1051
1244
|
|
|
1052
|
-
// src/react/
|
|
1053
|
-
var
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
streamingText,
|
|
1072
|
-
showStreaming = false,
|
|
1073
|
-
inline = false
|
|
1074
|
-
}) {
|
|
1075
|
-
if (steps.length === 0 && !(showStreaming && streamingText)) return null;
|
|
1076
|
-
const currentStep = getCurrentStep(steps);
|
|
1077
|
-
const showStatus = currentStep && currentStep.state !== "completed" && !(showStreaming && streamingText);
|
|
1078
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1079
|
-
"div",
|
|
1080
|
-
{
|
|
1081
|
-
className: `tool-timeline${inline ? " tool-timeline--inline" : ""}`,
|
|
1082
|
-
role: "status",
|
|
1083
|
-
"aria-live": "polite",
|
|
1084
|
-
"aria-label": "Agent progress",
|
|
1085
|
-
children: [
|
|
1086
|
-
showStatus ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "agent-status", children: [
|
|
1087
|
-
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, {}) }),
|
|
1088
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "agent-status__copy", children: [
|
|
1089
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-status__label", children: currentStep.label }),
|
|
1090
|
-
currentStep.detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-status__detail", children: currentStep.detail }) : null
|
|
1091
|
-
] })
|
|
1092
|
-
] }, currentStep.id) : null,
|
|
1093
|
-
showStreaming && streamingText ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "tool-timeline__streaming-text", children: [
|
|
1094
|
-
streamingText,
|
|
1095
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tool-timeline__cursor", "aria-hidden": "true" })
|
|
1096
|
-
] }) : null
|
|
1097
|
-
]
|
|
1098
|
-
}
|
|
1099
|
-
);
|
|
1100
|
-
}
|
|
1245
|
+
// src/react/types/conversation.ts
|
|
1246
|
+
var defaultAgentRailTheme = {
|
|
1247
|
+
railMaxWidth: "450px",
|
|
1248
|
+
brand: "#6f16ff",
|
|
1249
|
+
brandSoft: "#f3edff",
|
|
1250
|
+
brandDeep: "#12043e",
|
|
1251
|
+
surface: "#ffffff",
|
|
1252
|
+
surfaceMuted: "#f4f6fb",
|
|
1253
|
+
text: "#171b2a",
|
|
1254
|
+
textMuted: "#5a6378",
|
|
1255
|
+
textSubtle: "#8a94a8",
|
|
1256
|
+
border: "rgb(42 51 70 / 0.1)",
|
|
1257
|
+
visitorBubble: "#6f16ff",
|
|
1258
|
+
visitorText: "#ffffff",
|
|
1259
|
+
success: "#18794e",
|
|
1260
|
+
danger: "#c94b63",
|
|
1261
|
+
fontBody: '"Mulish", "Avenir Next", "Segoe UI", sans-serif',
|
|
1262
|
+
fontDisplay: '"Space Grotesk", sans-serif'
|
|
1263
|
+
};
|
|
1101
1264
|
|
|
1102
1265
|
// src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
|
|
1103
|
-
var
|
|
1104
|
-
function
|
|
1105
|
-
steps
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1266
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1267
|
+
function workSummary(steps) {
|
|
1268
|
+
const active = [...steps].reverse().find((step) => step.state === "active");
|
|
1269
|
+
if (active?.kind === "specialist") return `Working with ${active.label}`;
|
|
1270
|
+
if (active?.kind === "search") return "Searching this site";
|
|
1271
|
+
if (active) return active.label;
|
|
1272
|
+
const hasError = steps.some((step) => step.state === "error");
|
|
1273
|
+
const specialists = steps.filter(
|
|
1274
|
+
(step) => step.kind === "specialist" && step.state === "completed"
|
|
1275
|
+
);
|
|
1276
|
+
const searched = steps.some(
|
|
1277
|
+
(step) => step.kind === "search" && step.state === "completed"
|
|
1278
|
+
);
|
|
1279
|
+
if (hasError) return "Answered with available information";
|
|
1280
|
+
if (specialists.length > 1)
|
|
1281
|
+
return `Consulted ${specialists.length} specialists`;
|
|
1282
|
+
if (specialists.length === 1) return `Consulted ${specialists[0]?.label}`;
|
|
1283
|
+
if (searched) return "Searched this site";
|
|
1284
|
+
return "Prepared a response";
|
|
1285
|
+
}
|
|
1286
|
+
function AgentActivityBubble({ steps }) {
|
|
1287
|
+
const active = steps.some((step) => step.state === "active");
|
|
1288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { className: "agent-activity-bubble", children: [
|
|
1289
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1291
|
+
"span",
|
|
1292
|
+
{
|
|
1293
|
+
className: `agent-activity-bubble__pulse${active ? " is-active" : ""}`,
|
|
1294
|
+
"aria-hidden": "true"
|
|
1295
|
+
}
|
|
1296
|
+
),
|
|
1297
|
+
workSummary(steps)
|
|
1298
|
+
] }),
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "agent-activity-bubble__details", open: active, children: [
|
|
1300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "Work details" }),
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1302
|
+
"li",
|
|
1303
|
+
{
|
|
1304
|
+
className: "agent-activity-bubble__step",
|
|
1305
|
+
"data-state": step.state,
|
|
1306
|
+
children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1308
|
+
"span",
|
|
1309
|
+
{
|
|
1310
|
+
className: "agent-activity-bubble__step-icon",
|
|
1311
|
+
"aria-hidden": "true",
|
|
1312
|
+
children: step.state === "completed" ? "\u2713" : step.state === "error" ? "!" : ""
|
|
1313
|
+
}
|
|
1314
|
+
),
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "agent-activity-bubble__step-copy", children: [
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: step.label }),
|
|
1317
|
+
step.detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: step.detail }) : null
|
|
1318
|
+
] })
|
|
1319
|
+
]
|
|
1320
|
+
},
|
|
1321
|
+
step.id
|
|
1322
|
+
)) })
|
|
1323
|
+
] })
|
|
1324
|
+
] });
|
|
1118
1325
|
}
|
|
1119
1326
|
|
|
1120
1327
|
// src/react/components/Composer/Composer.tsx
|
|
1121
|
-
var
|
|
1122
|
-
var
|
|
1328
|
+
var import_react4 = require("react");
|
|
1329
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1123
1330
|
function SendIcon() {
|
|
1124
|
-
return /* @__PURE__ */ (0,
|
|
1331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1125
1332
|
}
|
|
1126
1333
|
function Composer({
|
|
1127
1334
|
disabled = false,
|
|
@@ -1129,8 +1336,8 @@ function Composer({
|
|
|
1129
1336
|
variant = "default",
|
|
1130
1337
|
onSubmit
|
|
1131
1338
|
}) {
|
|
1132
|
-
const [value, setValue] = (0,
|
|
1133
|
-
const inputRef = (0,
|
|
1339
|
+
const [value, setValue] = (0, import_react4.useState)("");
|
|
1340
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
1134
1341
|
function submitCurrent() {
|
|
1135
1342
|
const trimmed = value.trim();
|
|
1136
1343
|
if (!trimmed || disabled) return;
|
|
@@ -1148,8 +1355,8 @@ function Composer({
|
|
|
1148
1355
|
submitCurrent();
|
|
1149
1356
|
}
|
|
1150
1357
|
}
|
|
1151
|
-
return /* @__PURE__ */ (0,
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("form", { className: `composer${variant === "dock" ? " composer--dock" : ""}`, onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "composer__field", children: [
|
|
1359
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1153
1360
|
"textarea",
|
|
1154
1361
|
{
|
|
1155
1362
|
ref: inputRef,
|
|
@@ -1163,21 +1370,21 @@ function Composer({
|
|
|
1163
1370
|
onKeyDown: handleKeyDown
|
|
1164
1371
|
}
|
|
1165
1372
|
),
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1167
1374
|
"button",
|
|
1168
1375
|
{
|
|
1169
1376
|
type: "submit",
|
|
1170
1377
|
className: "composer__send",
|
|
1171
1378
|
disabled: disabled || !value.trim(),
|
|
1172
1379
|
"aria-label": "Send message",
|
|
1173
|
-
children: /* @__PURE__ */ (0,
|
|
1380
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SendIcon, {})
|
|
1174
1381
|
}
|
|
1175
1382
|
)
|
|
1176
1383
|
] }) });
|
|
1177
1384
|
}
|
|
1178
1385
|
|
|
1179
1386
|
// src/react/components/FollowUpChips/FollowUpChips.tsx
|
|
1180
|
-
var
|
|
1387
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1181
1388
|
function FollowUpChips({
|
|
1182
1389
|
suggestions,
|
|
1183
1390
|
disabled = false,
|
|
@@ -1187,7 +1394,7 @@ function FollowUpChips({
|
|
|
1187
1394
|
}) {
|
|
1188
1395
|
if (suggestions.length === 0) return null;
|
|
1189
1396
|
if (variant === "dock") {
|
|
1190
|
-
return /* @__PURE__ */ (0,
|
|
1397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups followups--dock", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1191
1398
|
"button",
|
|
1192
1399
|
{
|
|
1193
1400
|
type: "button",
|
|
@@ -1199,9 +1406,9 @@ function FollowUpChips({
|
|
|
1199
1406
|
suggestion.id
|
|
1200
1407
|
)) }) });
|
|
1201
1408
|
}
|
|
1202
|
-
return /* @__PURE__ */ (0,
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1204
|
-
/* @__PURE__ */ (0,
|
|
1409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "followups", children: [
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "followups__label", children: label }),
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1205
1412
|
"button",
|
|
1206
1413
|
{
|
|
1207
1414
|
type: "button",
|
|
@@ -1218,12 +1425,12 @@ function FollowUpChips({
|
|
|
1218
1425
|
// src/react/components/MessageBubble/MessageBubble.tsx
|
|
1219
1426
|
var import_streamdown = require("streamdown");
|
|
1220
1427
|
var import_styles = require("streamdown/styles.css");
|
|
1221
|
-
var
|
|
1428
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1222
1429
|
function MessageBubble({ message }) {
|
|
1223
1430
|
if (message.role === "visitor") {
|
|
1224
|
-
return /* @__PURE__ */ (0,
|
|
1431
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "message-bubble__text", children: message.text }) });
|
|
1225
1432
|
}
|
|
1226
|
-
return /* @__PURE__ */ (0,
|
|
1433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("article", { className: "message-bubble message-bubble--agent", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "message-bubble__text", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1227
1434
|
import_streamdown.Streamdown,
|
|
1228
1435
|
{
|
|
1229
1436
|
animated: true,
|
|
@@ -1240,12 +1447,20 @@ function MessageBubble({ message }) {
|
|
|
1240
1447
|
}
|
|
1241
1448
|
|
|
1242
1449
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1243
|
-
var
|
|
1450
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1244
1451
|
function MinimizeIcon() {
|
|
1245
|
-
return /* @__PURE__ */ (0,
|
|
1452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1453
|
+
"path",
|
|
1454
|
+
{
|
|
1455
|
+
d: "M3.5 8h9",
|
|
1456
|
+
stroke: "currentColor",
|
|
1457
|
+
strokeWidth: "1.7",
|
|
1458
|
+
strokeLinecap: "round"
|
|
1459
|
+
}
|
|
1460
|
+
) });
|
|
1246
1461
|
}
|
|
1247
1462
|
function ExpandIcon() {
|
|
1248
|
-
return /* @__PURE__ */ (0,
|
|
1463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1249
1464
|
"path",
|
|
1250
1465
|
{
|
|
1251
1466
|
d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
|
|
@@ -1257,7 +1472,7 @@ function ExpandIcon() {
|
|
|
1257
1472
|
) });
|
|
1258
1473
|
}
|
|
1259
1474
|
function RestoreIcon() {
|
|
1260
|
-
return /* @__PURE__ */ (0,
|
|
1475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1261
1476
|
"path",
|
|
1262
1477
|
{
|
|
1263
1478
|
d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
|
|
@@ -1272,6 +1487,7 @@ function AgentRail({
|
|
|
1272
1487
|
state,
|
|
1273
1488
|
theme,
|
|
1274
1489
|
brandLabel = "Webless Assist",
|
|
1490
|
+
brandLogoUrl,
|
|
1275
1491
|
poweredByLabel = "Powered by Webless",
|
|
1276
1492
|
composerPlaceholder = "Ask anything\u2026",
|
|
1277
1493
|
mobileFullscreen = false,
|
|
@@ -1282,11 +1498,32 @@ function AgentRail({
|
|
|
1282
1498
|
onSubmit,
|
|
1283
1499
|
onFollowUpSelect
|
|
1284
1500
|
}) {
|
|
1285
|
-
const transcriptRef = (0,
|
|
1286
|
-
const
|
|
1501
|
+
const transcriptRef = (0, import_react5.useRef)(null);
|
|
1502
|
+
const resolvedTheme = { ...defaultAgentRailTheme, ...theme };
|
|
1503
|
+
const railStyle = {
|
|
1504
|
+
"--rail-width": resolvedTheme.railMaxWidth,
|
|
1505
|
+
"--as-rail-max-width": resolvedTheme.railMaxWidth,
|
|
1506
|
+
"--as-brand": resolvedTheme.brand,
|
|
1507
|
+
"--as-brand-soft": resolvedTheme.brandSoft,
|
|
1508
|
+
"--as-brand-deep": resolvedTheme.brandDeep,
|
|
1509
|
+
"--as-surface": resolvedTheme.surface,
|
|
1510
|
+
"--as-surface-muted": resolvedTheme.surfaceMuted,
|
|
1511
|
+
"--as-text": resolvedTheme.text,
|
|
1512
|
+
"--as-text-muted": resolvedTheme.textMuted,
|
|
1513
|
+
"--as-text-subtle": resolvedTheme.textSubtle,
|
|
1514
|
+
"--as-border": resolvedTheme.border,
|
|
1515
|
+
"--as-visitor-bubble": resolvedTheme.visitorBubble,
|
|
1516
|
+
"--as-visitor-text": resolvedTheme.visitorText,
|
|
1517
|
+
"--as-success": resolvedTheme.success,
|
|
1518
|
+
"--as-danger": resolvedTheme.danger,
|
|
1519
|
+
"--as-font-body": resolvedTheme.fontBody,
|
|
1520
|
+
"--as-font-display": resolvedTheme.fontDisplay
|
|
1521
|
+
};
|
|
1287
1522
|
const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
|
|
1288
|
-
const showActivity = state.toolSteps.length > 0
|
|
1289
|
-
const hasVisitorMessages2 = state.messages.some(
|
|
1523
|
+
const showActivity = state.toolSteps.length > 0;
|
|
1524
|
+
const hasVisitorMessages2 = state.messages.some(
|
|
1525
|
+
(message) => message.role === "visitor"
|
|
1526
|
+
);
|
|
1290
1527
|
const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
|
|
1291
1528
|
const showDockFollowUps = expanded && showIdleFollowUps;
|
|
1292
1529
|
const streamingMessage = state.phase === "streaming" && state.streamingText ? {
|
|
@@ -1296,46 +1533,77 @@ function AgentRail({
|
|
|
1296
1533
|
streaming: true,
|
|
1297
1534
|
text: state.streamingText
|
|
1298
1535
|
} : null;
|
|
1299
|
-
(0,
|
|
1536
|
+
(0, import_react5.useEffect)(() => {
|
|
1300
1537
|
const node = transcriptRef.current;
|
|
1301
1538
|
if (!node) return;
|
|
1302
1539
|
node.scrollTop = node.scrollHeight;
|
|
1303
|
-
}, [
|
|
1304
|
-
|
|
1540
|
+
}, [
|
|
1541
|
+
state.messages,
|
|
1542
|
+
state.toolSteps,
|
|
1543
|
+
state.streamingText,
|
|
1544
|
+
state.followUps,
|
|
1545
|
+
state.journey
|
|
1546
|
+
]);
|
|
1547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1305
1548
|
"aside",
|
|
1306
1549
|
{
|
|
1307
1550
|
className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
|
|
1308
1551
|
style: railStyle,
|
|
1309
1552
|
"aria-label": "Agent conversation",
|
|
1310
1553
|
children: [
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
onCollapse ? /* @__PURE__ */ (0,
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("header", { className: "agent-rail__header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "agent-rail__brand-row", children: [
|
|
1555
|
+
onCollapse ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1313
1556
|
"button",
|
|
1314
1557
|
{
|
|
1315
1558
|
type: "button",
|
|
1316
1559
|
className: "agent-rail__collapse",
|
|
1317
1560
|
"aria-label": "Collapse assist",
|
|
1318
1561
|
onClick: onCollapse,
|
|
1319
|
-
children: /* @__PURE__ */ (0,
|
|
1562
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MinimizeIcon, {})
|
|
1563
|
+
}
|
|
1564
|
+
) : onClose ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1565
|
+
"button",
|
|
1566
|
+
{
|
|
1567
|
+
type: "button",
|
|
1568
|
+
className: "agent-rail__close",
|
|
1569
|
+
"aria-label": "Close agent",
|
|
1570
|
+
onClick: onClose,
|
|
1571
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MinimizeIcon, {})
|
|
1320
1572
|
}
|
|
1321
|
-
) :
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1323
|
-
|
|
1573
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
|
|
1574
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "agent-rail__identity", children: [
|
|
1575
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: [
|
|
1576
|
+
brandLabel.slice(0, 1).toUpperCase(),
|
|
1577
|
+
brandLogoUrl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1578
|
+
"img",
|
|
1579
|
+
{
|
|
1580
|
+
className: "agent-rail__brand-logo",
|
|
1581
|
+
src: brandLogoUrl,
|
|
1582
|
+
alt: "",
|
|
1583
|
+
onError: (event) => {
|
|
1584
|
+
event.currentTarget.hidden = true;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
) : null
|
|
1588
|
+
] }),
|
|
1589
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "agent-rail__brand-label", children: brandLabel })
|
|
1590
|
+
] }),
|
|
1591
|
+
onExpandToggle ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1324
1592
|
"button",
|
|
1325
1593
|
{
|
|
1326
1594
|
type: "button",
|
|
1327
1595
|
className: "agent-rail__expand",
|
|
1328
1596
|
"aria-label": expanded ? "Restore assist panel" : "Expand assist panel",
|
|
1329
1597
|
onClick: onExpandToggle,
|
|
1330
|
-
children: expanded ? /* @__PURE__ */ (0,
|
|
1598
|
+
children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RestoreIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExpandIcon, {})
|
|
1331
1599
|
}
|
|
1332
|
-
) : /* @__PURE__ */ (0,
|
|
1600
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
|
|
1333
1601
|
] }) }),
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1335
|
-
state.messages.map((message) => /* @__PURE__ */ (0,
|
|
1336
|
-
streamingMessage ? /* @__PURE__ */ (0,
|
|
1337
|
-
showActivity ? /* @__PURE__ */ (0,
|
|
1338
|
-
!expanded && showIdleFollowUps ? /* @__PURE__ */ (0,
|
|
1602
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: transcriptRef, className: "agent-rail__transcript", children: [
|
|
1603
|
+
state.messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageBubble, { message }, message.id)),
|
|
1604
|
+
streamingMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageBubble, { message: streamingMessage }) : null,
|
|
1605
|
+
showActivity ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AgentActivityBubble, { steps: state.toolSteps }) : null,
|
|
1606
|
+
!expanded && showIdleFollowUps ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1339
1607
|
FollowUpChips,
|
|
1340
1608
|
{
|
|
1341
1609
|
suggestions: state.followUps,
|
|
@@ -1344,10 +1612,17 @@ function AgentRail({
|
|
|
1344
1612
|
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
1345
1613
|
}
|
|
1346
1614
|
) }) : null,
|
|
1347
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1615
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1616
|
+
"p",
|
|
1617
|
+
{
|
|
1618
|
+
role: "alert",
|
|
1619
|
+
style: { fontSize: 13, color: "var(--as-danger)", margin: 0 },
|
|
1620
|
+
children: state.error
|
|
1621
|
+
}
|
|
1622
|
+
) : null
|
|
1348
1623
|
] }),
|
|
1349
|
-
expanded ? /* @__PURE__ */ (0,
|
|
1350
|
-
showDockFollowUps ? /* @__PURE__ */ (0,
|
|
1624
|
+
expanded ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "agent-rail__dock-wrap", children: [
|
|
1625
|
+
showDockFollowUps ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1351
1626
|
FollowUpChips,
|
|
1352
1627
|
{
|
|
1353
1628
|
variant: "dock",
|
|
@@ -1356,7 +1631,7 @@ function AgentRail({
|
|
|
1356
1631
|
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
1357
1632
|
}
|
|
1358
1633
|
) }) : null,
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1634
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "agent-rail__dock", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1360
1635
|
Composer,
|
|
1361
1636
|
{
|
|
1362
1637
|
variant: "dock",
|
|
@@ -1365,12 +1640,12 @@ function AgentRail({
|
|
|
1365
1640
|
onSubmit
|
|
1366
1641
|
}
|
|
1367
1642
|
) }),
|
|
1368
|
-
/* @__PURE__ */ (0,
|
|
1369
|
-
/* @__PURE__ */ (0,
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1643
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "agent-rail__footer", children: [
|
|
1644
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
1371
1646
|
] })
|
|
1372
|
-
] }) : /* @__PURE__ */ (0,
|
|
1373
|
-
/* @__PURE__ */ (0,
|
|
1647
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "agent-rail__composer-wrap", children: [
|
|
1648
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1374
1649
|
Composer,
|
|
1375
1650
|
{
|
|
1376
1651
|
disabled: isBusy,
|
|
@@ -1378,9 +1653,9 @@ function AgentRail({
|
|
|
1378
1653
|
onSubmit
|
|
1379
1654
|
}
|
|
1380
1655
|
),
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1382
|
-
/* @__PURE__ */ (0,
|
|
1383
|
-
/* @__PURE__ */ (0,
|
|
1656
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "agent-rail__footer", children: [
|
|
1657
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
|
|
1658
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "agent-rail__footer-note", children: poweredByLabel })
|
|
1384
1659
|
] })
|
|
1385
1660
|
] })
|
|
1386
1661
|
]
|
|
@@ -1389,22 +1664,67 @@ function AgentRail({
|
|
|
1389
1664
|
}
|
|
1390
1665
|
|
|
1391
1666
|
// src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
|
|
1392
|
-
var
|
|
1667
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1393
1668
|
function SparklesIcon() {
|
|
1394
|
-
return /* @__PURE__ */ (0,
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1670
|
+
"svg",
|
|
1671
|
+
{
|
|
1672
|
+
className: "assist-edge-tab__sparkles",
|
|
1673
|
+
viewBox: "0 0 18 16",
|
|
1674
|
+
fill: "none",
|
|
1675
|
+
"aria-hidden": "true",
|
|
1676
|
+
children: [
|
|
1677
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1678
|
+
"path",
|
|
1679
|
+
{
|
|
1680
|
+
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",
|
|
1681
|
+
fill: "currentColor"
|
|
1682
|
+
}
|
|
1683
|
+
),
|
|
1684
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1685
|
+
"path",
|
|
1686
|
+
{
|
|
1687
|
+
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",
|
|
1688
|
+
fill: "currentColor"
|
|
1689
|
+
}
|
|
1690
|
+
),
|
|
1691
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1692
|
+
"path",
|
|
1693
|
+
{
|
|
1694
|
+
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",
|
|
1695
|
+
fill: "currentColor"
|
|
1696
|
+
}
|
|
1697
|
+
)
|
|
1698
|
+
]
|
|
1699
|
+
}
|
|
1700
|
+
);
|
|
1399
1701
|
}
|
|
1400
1702
|
function ChevronLeftIcon() {
|
|
1401
|
-
return /* @__PURE__ */ (0,
|
|
1703
|
+
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)(
|
|
1704
|
+
"path",
|
|
1705
|
+
{
|
|
1706
|
+
d: "M10 4L6 8l4 4",
|
|
1707
|
+
stroke: "currentColor",
|
|
1708
|
+
strokeWidth: "1.6",
|
|
1709
|
+
strokeLinecap: "round",
|
|
1710
|
+
strokeLinejoin: "round"
|
|
1711
|
+
}
|
|
1712
|
+
) });
|
|
1402
1713
|
}
|
|
1403
1714
|
function ChevronDownIcon() {
|
|
1404
|
-
return /* @__PURE__ */ (0,
|
|
1715
|
+
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)(
|
|
1716
|
+
"path",
|
|
1717
|
+
{
|
|
1718
|
+
d: "M4 6l4 4 4-4",
|
|
1719
|
+
stroke: "currentColor",
|
|
1720
|
+
strokeWidth: "1.6",
|
|
1721
|
+
strokeLinecap: "round",
|
|
1722
|
+
strokeLinejoin: "round"
|
|
1723
|
+
}
|
|
1724
|
+
) });
|
|
1405
1725
|
}
|
|
1406
1726
|
function DragDots() {
|
|
1407
|
-
return /* @__PURE__ */ (0,
|
|
1727
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", {}, index)) });
|
|
1408
1728
|
}
|
|
1409
1729
|
var VARIANT_COPY = {
|
|
1410
1730
|
outline: { label: "Assist", aria: "Open Assist" },
|
|
@@ -1417,38 +1737,71 @@ function AssistEdgeTab({
|
|
|
1417
1737
|
along,
|
|
1418
1738
|
inset,
|
|
1419
1739
|
visible,
|
|
1740
|
+
label,
|
|
1741
|
+
logoUrl,
|
|
1742
|
+
brandColor,
|
|
1743
|
+
fontFamily,
|
|
1420
1744
|
onOpen
|
|
1421
1745
|
}) {
|
|
1422
1746
|
const copy = VARIANT_COPY[variant];
|
|
1747
|
+
const visibleLabel = label?.trim() || copy.label;
|
|
1423
1748
|
const style = {
|
|
1424
1749
|
"--tab-along": `${along}%`,
|
|
1425
|
-
"--tab-inset": `${inset}px
|
|
1750
|
+
"--tab-inset": `${inset}px`,
|
|
1751
|
+
...brandColor ? { "--as-brand": brandColor } : {},
|
|
1752
|
+
...fontFamily ? { "--as-font-display": fontFamily } : {}
|
|
1426
1753
|
};
|
|
1427
|
-
return /* @__PURE__ */ (0,
|
|
1754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1428
1755
|
"button",
|
|
1429
1756
|
{
|
|
1430
1757
|
type: "button",
|
|
1431
1758
|
className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${visible ? " is-visible" : ""}`,
|
|
1432
1759
|
style,
|
|
1433
|
-
"aria-label":
|
|
1760
|
+
"aria-label": `Open ${visibleLabel}`,
|
|
1434
1761
|
"aria-hidden": !visible,
|
|
1435
1762
|
tabIndex: visible ? 0 : -1,
|
|
1436
1763
|
onClick: onOpen,
|
|
1437
1764
|
children: [
|
|
1438
|
-
variant === "outline" ? /* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1440
|
-
|
|
1441
|
-
|
|
1765
|
+
variant === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
1767
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparklesIcon, {}),
|
|
1768
|
+
logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1769
|
+
"img",
|
|
1770
|
+
{
|
|
1771
|
+
className: "assist-edge-tab__logo",
|
|
1772
|
+
src: logoUrl,
|
|
1773
|
+
alt: "",
|
|
1774
|
+
onError: (event) => {
|
|
1775
|
+
event.currentTarget.hidden = true;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
) : null
|
|
1779
|
+
] }),
|
|
1780
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
1781
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChevronDownIcon, {})
|
|
1442
1782
|
] }) : null,
|
|
1443
|
-
variant === "ask" ? /* @__PURE__ */ (0,
|
|
1444
|
-
/* @__PURE__ */ (0,
|
|
1445
|
-
/* @__PURE__ */ (0,
|
|
1446
|
-
/* @__PURE__ */ (0,
|
|
1783
|
+
variant === "ask" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1784
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChevronLeftIcon, {}),
|
|
1785
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
1786
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DragDots, {})
|
|
1447
1787
|
] }) : null,
|
|
1448
|
-
variant === "fill" ? /* @__PURE__ */ (0,
|
|
1449
|
-
/* @__PURE__ */ (0,
|
|
1450
|
-
|
|
1451
|
-
|
|
1788
|
+
variant === "fill" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1789
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
1790
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparklesIcon, {}),
|
|
1791
|
+
logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1792
|
+
"img",
|
|
1793
|
+
{
|
|
1794
|
+
className: "assist-edge-tab__logo",
|
|
1795
|
+
src: logoUrl,
|
|
1796
|
+
alt: "",
|
|
1797
|
+
onError: (event) => {
|
|
1798
|
+
event.currentTarget.hidden = true;
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
) : null
|
|
1802
|
+
] }),
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
1804
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChevronLeftIcon, {})
|
|
1452
1805
|
] }) : null
|
|
1453
1806
|
]
|
|
1454
1807
|
}
|
|
@@ -1456,7 +1809,7 @@ function AssistEdgeTab({
|
|
|
1456
1809
|
}
|
|
1457
1810
|
|
|
1458
1811
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
1459
|
-
var
|
|
1812
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1460
1813
|
function AgentWidget({
|
|
1461
1814
|
indexId,
|
|
1462
1815
|
customerId,
|
|
@@ -1465,21 +1818,53 @@ function AgentWidget({
|
|
|
1465
1818
|
runtimeOrigin,
|
|
1466
1819
|
placement: placementInput,
|
|
1467
1820
|
defaultCollapsed = true,
|
|
1468
|
-
|
|
1821
|
+
pageShift = true,
|
|
1822
|
+
registerPanelController = false,
|
|
1823
|
+
branding
|
|
1469
1824
|
}) {
|
|
1470
1825
|
const isMobile = useIsMobile();
|
|
1471
1826
|
const placement = normalizeAgentPlacement(placementInput);
|
|
1472
|
-
const
|
|
1473
|
-
const [
|
|
1827
|
+
const railSlotRef = (0, import_react6.useRef)(null);
|
|
1828
|
+
const [railCollapsed, setRailCollapsed] = (0, import_react6.useState)(defaultCollapsed);
|
|
1829
|
+
const [railExpanded, setRailExpanded] = (0, import_react6.useState)(false);
|
|
1830
|
+
const pageShiftActive = shouldApplyPageShift({
|
|
1831
|
+
pageShift,
|
|
1832
|
+
isMobile,
|
|
1833
|
+
railCollapsed,
|
|
1834
|
+
railExpanded
|
|
1835
|
+
});
|
|
1836
|
+
usePageShift({
|
|
1837
|
+
active: pageShiftActive,
|
|
1838
|
+
railSlotRef
|
|
1839
|
+
});
|
|
1474
1840
|
const { state, submit } = useAgentChat({
|
|
1475
1841
|
customerId,
|
|
1476
1842
|
getUnpublishedPreviewGrant,
|
|
1477
1843
|
indexId,
|
|
1478
1844
|
version,
|
|
1479
|
-
runtimeOrigin
|
|
1845
|
+
runtimeOrigin,
|
|
1846
|
+
greeting: branding?.greeting
|
|
1480
1847
|
});
|
|
1848
|
+
const agentName = branding?.agentName ?? "Webless Guide";
|
|
1849
|
+
const theme = {
|
|
1850
|
+
...branding?.fontFamily ? { fontBody: branding.fontFamily, fontDisplay: branding.fontFamily } : {},
|
|
1851
|
+
...branding?.colors?.primary ? {
|
|
1852
|
+
brand: branding.colors.primary,
|
|
1853
|
+
visitorBubble: branding.colors.primary
|
|
1854
|
+
} : {},
|
|
1855
|
+
...branding?.colors?.primarySoft ? { brandSoft: branding.colors.primarySoft } : {},
|
|
1856
|
+
...branding?.colors?.primaryForeground ? { visitorText: branding.colors.primaryForeground } : {},
|
|
1857
|
+
...branding?.colors?.surface ? { surface: branding.colors.surface } : {},
|
|
1858
|
+
...branding?.colors?.surfaceMuted ? { surfaceMuted: branding.colors.surfaceMuted } : {},
|
|
1859
|
+
...branding?.colors?.text ? { text: branding.colors.text } : {},
|
|
1860
|
+
...branding?.colors?.textMuted ? {
|
|
1861
|
+
textMuted: branding.colors.textMuted,
|
|
1862
|
+
textSubtle: branding.colors.textMuted
|
|
1863
|
+
} : {},
|
|
1864
|
+
...branding?.colors?.border ? { border: branding.colors.border } : {}
|
|
1865
|
+
};
|
|
1481
1866
|
const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
|
|
1482
|
-
(0,
|
|
1867
|
+
(0, import_react6.useEffect)(() => {
|
|
1483
1868
|
if (!registerPanelController) return;
|
|
1484
1869
|
registerAgentPanelController(customerId, {
|
|
1485
1870
|
open: () => setRailCollapsed(false),
|
|
@@ -1494,47 +1879,56 @@ function AgentWidget({
|
|
|
1494
1879
|
if (isMobile) setRailCollapsed(false);
|
|
1495
1880
|
await submit(message);
|
|
1496
1881
|
}
|
|
1497
|
-
return /* @__PURE__ */ (0,
|
|
1498
|
-
/* @__PURE__ */ (0,
|
|
1882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "webless-agent-root", children: [
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1499
1884
|
"div",
|
|
1500
1885
|
{
|
|
1501
1886
|
className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
|
|
1502
|
-
children:
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1887
|
+
children: [
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1889
|
+
"div",
|
|
1890
|
+
{
|
|
1891
|
+
ref: railSlotRef,
|
|
1892
|
+
className: "webless-agent-root__rail-slot",
|
|
1893
|
+
inert: railCollapsed || void 0,
|
|
1894
|
+
"aria-hidden": railCollapsed,
|
|
1895
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1896
|
+
AgentRail,
|
|
1897
|
+
{
|
|
1898
|
+
theme,
|
|
1899
|
+
brandLabel: agentName,
|
|
1900
|
+
brandLogoUrl: branding?.logoUrl,
|
|
1901
|
+
composerPlaceholder: branding?.composerPlaceholder ?? `Ask ${agentName}\u2026`,
|
|
1902
|
+
poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
|
|
1903
|
+
state: idle ? {
|
|
1904
|
+
...state,
|
|
1905
|
+
followUps: createIdleSuggestions()
|
|
1906
|
+
} : state,
|
|
1907
|
+
mobileFullscreen: isMobile && !railCollapsed,
|
|
1908
|
+
expanded: railExpanded,
|
|
1909
|
+
onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
|
|
1910
|
+
onClose: isMobile ? () => setRailCollapsed(true) : void 0,
|
|
1911
|
+
onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
|
|
1912
|
+
onSubmit: handleSubmit,
|
|
1913
|
+
onFollowUpSelect: (label) => void handleSubmit(label)
|
|
1914
|
+
}
|
|
1915
|
+
)
|
|
1916
|
+
}
|
|
1917
|
+
),
|
|
1918
|
+
!isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1919
|
+
"button",
|
|
1920
|
+
{
|
|
1921
|
+
type: "button",
|
|
1922
|
+
className: "webless-agent-root__backdrop",
|
|
1923
|
+
tabIndex: -1,
|
|
1924
|
+
"aria-label": "Close expanded assist",
|
|
1925
|
+
onClick: () => setRailExpanded(false)
|
|
1926
|
+
}
|
|
1927
|
+
) : null
|
|
1928
|
+
]
|
|
1526
1929
|
}
|
|
1527
1930
|
),
|
|
1528
|
-
|
|
1529
|
-
"button",
|
|
1530
|
-
{
|
|
1531
|
-
type: "button",
|
|
1532
|
-
className: "webless-agent-root__backdrop",
|
|
1533
|
-
"aria-label": "Close expanded assist",
|
|
1534
|
-
onClick: () => setRailExpanded(false)
|
|
1535
|
-
}
|
|
1536
|
-
) : null,
|
|
1537
|
-
railCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1931
|
+
railCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1538
1932
|
AssistEdgeTab,
|
|
1539
1933
|
{
|
|
1540
1934
|
variant: placement.variant,
|
|
@@ -1542,6 +1936,10 @@ function AgentWidget({
|
|
|
1542
1936
|
along: placement.along,
|
|
1543
1937
|
inset: placement.inset,
|
|
1544
1938
|
visible: true,
|
|
1939
|
+
label: agentName,
|
|
1940
|
+
logoUrl: branding?.logoUrl,
|
|
1941
|
+
brandColor: branding?.colors?.primary,
|
|
1942
|
+
fontFamily: branding?.fontFamily,
|
|
1545
1943
|
onOpen: () => setRailCollapsed(false)
|
|
1546
1944
|
}
|
|
1547
1945
|
) : null
|
|
@@ -1549,9 +1947,11 @@ function AgentWidget({
|
|
|
1549
1947
|
}
|
|
1550
1948
|
|
|
1551
1949
|
// src/embed/AgentWidget.tsx
|
|
1552
|
-
var
|
|
1553
|
-
function AgentWidget2({
|
|
1554
|
-
|
|
1950
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1951
|
+
function AgentWidget2({
|
|
1952
|
+
manifest
|
|
1953
|
+
}) {
|
|
1954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1555
1955
|
AgentWidget,
|
|
1556
1956
|
{
|
|
1557
1957
|
indexId: manifest.indexId,
|
|
@@ -1559,6 +1959,8 @@ function AgentWidget2({ manifest }) {
|
|
|
1559
1959
|
version: manifest.version,
|
|
1560
1960
|
runtimeOrigin: manifest.runtimeOrigin,
|
|
1561
1961
|
placement: manifest.placement,
|
|
1962
|
+
pageShift: manifest.pageShift,
|
|
1963
|
+
branding: manifest.branding,
|
|
1562
1964
|
defaultCollapsed: true,
|
|
1563
1965
|
registerPanelController: true
|
|
1564
1966
|
}
|
|
@@ -1584,6 +1986,7 @@ function normalizeAgentTagManifest(manifest) {
|
|
|
1584
1986
|
version,
|
|
1585
1987
|
runtimeOrigin: manifest.runtimeOrigin?.trim() || DEFAULT_RUNTIME_ORIGIN
|
|
1586
1988
|
});
|
|
1989
|
+
const branding = normalizeAgentBranding(manifest.branding);
|
|
1587
1990
|
return {
|
|
1588
1991
|
customerId,
|
|
1589
1992
|
indexId,
|
|
@@ -1593,12 +1996,37 @@ function normalizeAgentTagManifest(manifest) {
|
|
|
1593
1996
|
selector: manifest.mount?.selector?.trim(),
|
|
1594
1997
|
strategy: manifest.mount?.strategy ?? "body"
|
|
1595
1998
|
},
|
|
1596
|
-
placement: normalizeAgentPlacement(manifest.placement)
|
|
1999
|
+
placement: normalizeAgentPlacement(manifest.placement),
|
|
2000
|
+
pageShift: manifest.pageShift ?? true,
|
|
2001
|
+
...branding ? { branding } : {}
|
|
1597
2002
|
};
|
|
1598
2003
|
}
|
|
2004
|
+
function normalizeOptionalValue(value) {
|
|
2005
|
+
const normalized = value?.trim();
|
|
2006
|
+
return normalized || void 0;
|
|
2007
|
+
}
|
|
2008
|
+
function normalizeAgentBranding(branding) {
|
|
2009
|
+
if (!branding) return void 0;
|
|
2010
|
+
const colors = branding.colors ? Object.fromEntries(
|
|
2011
|
+
Object.entries(branding.colors).flatMap(([key, value]) => {
|
|
2012
|
+
const normalized2 = normalizeOptionalValue(value);
|
|
2013
|
+
return normalized2 ? [[key, normalized2]] : [];
|
|
2014
|
+
})
|
|
2015
|
+
) : void 0;
|
|
2016
|
+
const normalized = {
|
|
2017
|
+
agentName: normalizeOptionalValue(branding.agentName),
|
|
2018
|
+
logoUrl: normalizeOptionalValue(branding.logoUrl),
|
|
2019
|
+
greeting: normalizeOptionalValue(branding.greeting),
|
|
2020
|
+
composerPlaceholder: normalizeOptionalValue(branding.composerPlaceholder),
|
|
2021
|
+
poweredByLabel: normalizeOptionalValue(branding.poweredByLabel),
|
|
2022
|
+
fontFamily: normalizeOptionalValue(branding.fontFamily),
|
|
2023
|
+
colors: colors && Object.keys(colors).length > 0 ? colors : void 0
|
|
2024
|
+
};
|
|
2025
|
+
return Object.values(normalized).some((value) => value !== void 0) ? normalized : void 0;
|
|
2026
|
+
}
|
|
1599
2027
|
|
|
1600
2028
|
// src/embed/mount.tsx
|
|
1601
|
-
var
|
|
2029
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1602
2030
|
var mountedHandles = /* @__PURE__ */ new Map();
|
|
1603
2031
|
var latestCustomerId = null;
|
|
1604
2032
|
function resolveMountHost(manifest, script) {
|
|
@@ -1628,7 +2056,7 @@ function mountAgent(input) {
|
|
|
1628
2056
|
const host = createHost(manifest.customerId);
|
|
1629
2057
|
mountTarget.append(host);
|
|
1630
2058
|
const root = (0, import_client5.createRoot)(host);
|
|
1631
|
-
root.render(/* @__PURE__ */ (0,
|
|
2059
|
+
root.render(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AgentWidget2, { manifest }));
|
|
1632
2060
|
const handle = {
|
|
1633
2061
|
customerId: manifest.customerId,
|
|
1634
2062
|
manifest,
|