@webless/agent 0.2.15 → 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.
@@ -220,9 +220,8 @@ function clearPersistedAgentSession(visitorSessionId, options) {
220
220
  function isTurnBoundary(event) {
221
221
  return event.type === "session.waiting" || event.type === "session.completed" || event.type === "session.failed";
222
222
  }
223
- function applyMessageEvent(event, rendered, handlers) {
224
- const step = mapStepLabel(event);
225
- if (step) handlers.onStep?.(step.label, step.detail);
223
+ function applyMessageEvent(event, rendered, handlers, workItems) {
224
+ applyWorkEvent(event, handlers, workItems);
226
225
  if (event.type === "session.failed") {
227
226
  throw new Error(event.data.message || event.data.code);
228
227
  }
@@ -265,13 +264,120 @@ function renderTurn(events) {
265
264
  }
266
265
  return rendered;
267
266
  }
268
- function mapStepLabel(event) {
269
- if (event.type !== "step.started") return null;
270
- const stepIndex = event.data.stepIndex;
271
- return {
272
- label: "Model step running",
273
- detail: typeof stepIndex === "number" ? `Step ${stepIndex + 1}` : void 0
274
- };
267
+ function emitWorkItem(item, handlers, workItems) {
268
+ workItems.set(item.id, item);
269
+ handlers.onWork?.(item);
270
+ handlers.onStep?.(item.label, item.detail);
271
+ }
272
+ function completePlanning(handlers, workItems) {
273
+ const planning = workItems.get("planning");
274
+ if (!planning || planning.state !== "active") return;
275
+ emitWorkItem(
276
+ {
277
+ ...planning,
278
+ detail: "Picked the best way to help",
279
+ state: "completed"
280
+ },
281
+ handlers,
282
+ workItems
283
+ );
284
+ }
285
+ function specialistNameFromInput(input) {
286
+ const message = input.message;
287
+ if (typeof message !== "string") return void 0;
288
+ const match = /^Webless-Agent-Name:\s*(.+)$/imu.exec(message);
289
+ return match?.[1]?.trim() || void 0;
290
+ }
291
+ function requestedWorkItem(action) {
292
+ if (action.kind === "tool-call" && action.toolName === "search_discovery") {
293
+ return {
294
+ id: action.callId,
295
+ kind: "search",
296
+ label: "Search & Discovery",
297
+ detail: "Searching this site",
298
+ state: "active"
299
+ };
300
+ }
301
+ if (action.kind === "subagent-call" || action.kind === "remote-agent-call" || action.kind === "tool-call" && action.toolName === "agent") {
302
+ const name = specialistNameFromInput(action.input) ?? "Specialist";
303
+ return {
304
+ id: action.callId,
305
+ kind: "specialist",
306
+ label: name,
307
+ detail: "Reviewing your question",
308
+ state: "active"
309
+ };
310
+ }
311
+ return null;
312
+ }
313
+ function applyWorkEvent(event, handlers, workItems) {
314
+ if (event.type === "step.started" && workItems.size === 0) {
315
+ emitWorkItem(
316
+ {
317
+ id: "planning",
318
+ kind: "planning",
319
+ label: "Understanding your question",
320
+ state: "active"
321
+ },
322
+ handlers,
323
+ workItems
324
+ );
325
+ return;
326
+ }
327
+ if (event.type === "actions.requested") {
328
+ completePlanning(handlers, workItems);
329
+ for (const action of event.data.actions) {
330
+ const item = requestedWorkItem(action);
331
+ if (item) emitWorkItem(item, handlers, workItems);
332
+ }
333
+ return;
334
+ }
335
+ if (event.type === "subagent.called") {
336
+ completePlanning(handlers, workItems);
337
+ const current2 = workItems.get(event.data.callId);
338
+ if (!current2) {
339
+ emitWorkItem(
340
+ {
341
+ id: event.data.callId,
342
+ kind: "specialist",
343
+ label: event.data.name || "Specialist",
344
+ detail: "Reviewing your question",
345
+ state: "active"
346
+ },
347
+ handlers,
348
+ workItems
349
+ );
350
+ }
351
+ return;
352
+ }
353
+ if (event.type === "subagent.completed") {
354
+ const current2 = workItems.get(event.data.callId);
355
+ if (!current2) return;
356
+ emitWorkItem(
357
+ {
358
+ ...current2,
359
+ detail: "Guidance received",
360
+ state: "completed"
361
+ },
362
+ handlers,
363
+ workItems
364
+ );
365
+ return;
366
+ }
367
+ if (event.type !== "action.result") return;
368
+ const { result, status } = event.data;
369
+ const current = workItems.get(result.callId);
370
+ if (!current) return;
371
+ const failed = status !== "completed" || result.isError === true;
372
+ emitWorkItem(
373
+ {
374
+ ...current,
375
+ detail: failed ? "Couldn\u2019t complete; continuing with available information" : current.kind === "search" ? "Found relevant site content" : "Guidance received",
376
+ state: failed ? "error" : "completed"
377
+ },
378
+ handlers,
379
+ workItems
380
+ );
275
381
  }
276
382
  var AgentSession = class {
277
383
  constructor(indexId, version, runtimeOrigin, visitorSessionId, storeOptions, getUnpublishedPreviewGrant) {
@@ -389,10 +495,11 @@ var AgentSession = class {
389
495
  this.activeResponse = response;
390
496
  let streamIndex = session?.state.streamIndex ?? 0;
391
497
  let rendered = "";
498
+ const workItems = /* @__PURE__ */ new Map();
392
499
  try {
393
500
  for await (const event of response) {
394
501
  if (signal.aborted) break;
395
- rendered = applyMessageEvent(event, rendered, handlers);
502
+ rendered = applyMessageEvent(event, rendered, handlers, workItems);
396
503
  streamIndex += 1;
397
504
  if (session) {
398
505
  savePersistedAgentSession(
@@ -434,6 +541,10 @@ var AgentSession = class {
434
541
  return null;
435
542
  }
436
543
  let rendered = renderTurn(turnEvents);
544
+ const workItems = /* @__PURE__ */ new Map();
545
+ for (const event of turnEvents) {
546
+ applyWorkEvent(event, handlers, workItems);
547
+ }
437
548
  if (rendered.startsWith(initialText)) {
438
549
  const missedText = rendered.slice(initialText.length);
439
550
  if (missedText) handlers.onDelta(missedText);
@@ -468,7 +579,7 @@ var AgentSession = class {
468
579
  let streamIndex = snapshot.session.streamIndex;
469
580
  for await (const event of session.stream({ signal })) {
470
581
  if (signal.aborted) break;
471
- rendered = applyMessageEvent(event, rendered, handlers);
582
+ rendered = applyMessageEvent(event, rendered, handlers, workItems);
472
583
  streamIndex += 1;
473
584
  savePersistedAgentSession(
474
585
  this.visitorSessionId,
@@ -621,57 +732,54 @@ function clearPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
621
732
  }
622
733
 
623
734
  // src/react/hooks/useAgentChat.ts
624
- var GREETING_MESSAGE = {
625
- id: "greeting",
626
- role: "agent",
627
- text: "Hi! I'm connected to the Webless Agent Runtime. Ask anything about your published site index.",
628
- createdAt: 0
629
- };
630
- var INITIAL_STATE = {
631
- phase: "idle",
632
- messages: [GREETING_MESSAGE],
633
- toolSteps: [],
634
- journey: null,
635
- followUps: [],
636
- streamingText: "",
637
- error: null
638
- };
639
- function stateFromConversation(conversation) {
640
- if (!conversation || conversation.messages.length === 0) return INITIAL_STATE;
735
+ var DEFAULT_GREETING = "Hi! I can search this site or bring in a specialist when it helps. What would you like to know?";
736
+ function createInitialState(greeting = DEFAULT_GREETING) {
737
+ return {
738
+ phase: "idle",
739
+ messages: [
740
+ {
741
+ id: "greeting",
742
+ role: "agent",
743
+ text: greeting,
744
+ createdAt: 0
745
+ }
746
+ ],
747
+ toolSteps: [],
748
+ journey: null,
749
+ followUps: [],
750
+ streamingText: "",
751
+ error: null
752
+ };
753
+ }
754
+ function stateFromConversation(conversation, initialState) {
755
+ if (!conversation || conversation.messages.length === 0) return initialState;
641
756
  return {
642
- ...INITIAL_STATE,
757
+ ...initialState,
643
758
  messages: conversation.messages,
644
759
  phase: conversation.pending ? conversation.streamingText ? "streaming" : "thinking" : "complete",
645
760
  streamingText: conversation.streamingText
646
761
  };
647
762
  }
648
- var STATUS_SEQUENCE = [
649
- { id: "s1", label: "Starting Eve session", ms: 400 },
650
- { id: "s2", label: "Connecting to runtime", ms: 500 }
651
- ];
652
- function delay(ms, signal) {
653
- return new Promise((resolve, reject) => {
654
- const timer = window.setTimeout(resolve, ms);
655
- signal.addEventListener(
656
- "abort",
657
- () => {
658
- window.clearTimeout(timer);
659
- reject(new DOMException("Aborted", "AbortError"));
660
- },
661
- { once: true }
662
- );
663
- });
664
- }
665
- async function runStatusSequence(signal, onStep) {
666
- for (const item of STATUS_SEQUENCE) {
667
- onStep({
668
- id: item.id,
669
- label: item.label,
670
- detail: item.detail,
671
- state: "active"
672
- });
673
- await delay(item.ms, signal);
674
- }
763
+ function upsertToolStep(steps, item) {
764
+ const next = {
765
+ id: item.id,
766
+ kind: item.kind,
767
+ label: item.label,
768
+ state: item.state,
769
+ ...item.detail ? { detail: item.detail } : {}
770
+ };
771
+ const index = steps.findIndex((step) => step.id === item.id);
772
+ if (index < 0) return [...steps, next];
773
+ return steps.map((step, stepIndex) => stepIndex === index ? next : step);
774
+ }
775
+ function completeActivePlanning(steps) {
776
+ return steps.map(
777
+ (step) => step.kind === "planning" && step.state === "active" ? {
778
+ ...step,
779
+ detail: "Prepared a response",
780
+ state: "completed"
781
+ } : step
782
+ );
675
783
  }
676
784
  function useAgentChat({
677
785
  customerId,
@@ -680,8 +788,13 @@ function useAgentChat({
680
788
  version,
681
789
  runtimeOrigin,
682
790
  visitorSessionId,
683
- storageKeyPrefix
791
+ storageKeyPrefix,
792
+ greeting
684
793
  }) {
794
+ const initialState = useMemo(
795
+ () => createInitialState(greeting?.trim() || DEFAULT_GREETING),
796
+ [greeting]
797
+ );
685
798
  const previewGrantProviderRef = useRef(getUnpublishedPreviewGrant);
686
799
  previewGrantProviderRef.current = getUnpublishedPreviewGrant;
687
800
  const resolveUnpublishedPreviewGrant = () => {
@@ -712,7 +825,8 @@ function useAgentChat({
712
825
  );
713
826
  const [state, setState] = useState(
714
827
  () => stateFromConversation(
715
- loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId)
828
+ loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
829
+ initialState
716
830
  )
717
831
  );
718
832
  const runRef = useRef(null);
@@ -727,7 +841,7 @@ function useAgentChat({
727
841
  storageKeyPrefix: resolvedStorageKeyPrefix
728
842
  })
729
843
  );
730
- const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}`;
844
+ const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}|${greeting ?? ""}`;
731
845
  const identityRef = useRef(identityKey);
732
846
  useEffect(() => {
733
847
  if (identityRef.current === identityKey) {
@@ -747,13 +861,15 @@ function useAgentChat({
747
861
  });
748
862
  setState(
749
863
  stateFromConversation(
750
- loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId)
864
+ loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
865
+ initialState
751
866
  )
752
867
  );
753
868
  }, [
754
869
  customerId,
755
870
  identityKey,
756
871
  indexId,
872
+ initialState,
757
873
  runtimeOrigin,
758
874
  resolvedStorageKeyPrefix,
759
875
  version,
@@ -778,8 +894,8 @@ function useAgentChat({
778
894
  runRef.current = null;
779
895
  clientRef.current.reset();
780
896
  clearPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId);
781
- setState(INITIAL_STATE);
782
- }, [resolvedStorageKeyPrefix, visitorId]);
897
+ setState(initialState);
898
+ }, [initialState, resolvedStorageKeyPrefix, visitorId]);
783
899
  const runTurn = useCallback(
784
900
  async (input) => {
785
901
  const { controller, initialText = "", resume, visitorText } = input;
@@ -788,35 +904,23 @@ function useAgentChat({
788
904
  try {
789
905
  let streamStarted = Boolean(initialText);
790
906
  let streamed = initialText;
791
- const planningPromise = resume ? Promise.resolve() : runStatusSequence(signal, (step) => {
792
- if (streamStarted || !isActiveRun()) return;
793
- setState((prev) => ({
794
- ...prev,
795
- phase: "running-tools",
796
- toolSteps: [step]
797
- }));
798
- });
799
907
  const handlers = {
800
- onStep: (label, detail) => {
801
- if (streamStarted || !isActiveRun()) return;
908
+ onWork: (item) => {
909
+ if (!isActiveRun()) return;
802
910
  setState((prev) => ({
803
911
  ...prev,
804
- phase: "running-tools",
805
- toolSteps: [
806
- { id: `step-${label}`, label, detail, state: "active" }
807
- ]
912
+ phase: item.state === "active" ? "running-tools" : prev.phase,
913
+ toolSteps: upsertToolStep(prev.toolSteps, item)
808
914
  }));
809
915
  },
810
916
  onDelta: (delta) => {
811
917
  if (!isActiveRun()) return;
812
- void planningPromise.catch(() => {
813
- });
814
918
  if (!streamStarted) {
815
919
  streamStarted = true;
816
920
  setState((prev) => ({
817
921
  ...prev,
818
922
  phase: "streaming",
819
- toolSteps: [],
923
+ toolSteps: completeActivePlanning(prev.toolSteps),
820
924
  streamingText: ""
821
925
  }));
822
926
  }
@@ -844,8 +948,6 @@ function useAgentChat({
844
948
  signal
845
949
  });
846
950
  }
847
- await planningPromise.catch(() => {
848
- });
849
951
  if (!isActiveRun() || finalText === null) return;
850
952
  const agentMessage = {
851
953
  id: `agent-${Date.now()}`,
@@ -857,7 +959,7 @@ function useAgentChat({
857
959
  ...prev,
858
960
  phase: "complete",
859
961
  messages: [...prev.messages, agentMessage],
860
- toolSteps: [],
962
+ toolSteps: completeActivePlanning(prev.toolSteps),
861
963
  streamingText: "",
862
964
  followUps: [],
863
965
  journey: null
@@ -872,7 +974,13 @@ function useAgentChat({
872
974
  setState((prev) => ({
873
975
  ...prev,
874
976
  phase: "complete",
875
- toolSteps: [],
977
+ toolSteps: prev.toolSteps.map(
978
+ (step) => step.state === "active" ? {
979
+ ...step,
980
+ detail: "Couldn\u2019t complete this step",
981
+ state: "error"
982
+ } : step
983
+ ),
876
984
  streamingText: "",
877
985
  error: message
878
986
  }));
@@ -900,7 +1008,12 @@ function useAgentChat({
900
1008
  phase: "thinking",
901
1009
  messages: [...prev.messages, visitorMessage],
902
1010
  toolSteps: [
903
- { id: "s1", label: "Starting Eve session", state: "active" }
1011
+ {
1012
+ id: "planning",
1013
+ kind: "planning",
1014
+ label: "Understanding your question",
1015
+ state: "active"
1016
+ }
904
1017
  ],
905
1018
  journey: null,
906
1019
  followUps: [],
@@ -979,82 +1092,96 @@ function normalizeAgentPlacement(placement) {
979
1092
  };
980
1093
  }
981
1094
 
1095
+ // src/react/types/conversation.ts
1096
+ var defaultAgentRailTheme = {
1097
+ railMaxWidth: "450px",
1098
+ brand: "#6f16ff",
1099
+ brandSoft: "#f3edff",
1100
+ brandDeep: "#12043e",
1101
+ surface: "#ffffff",
1102
+ surfaceMuted: "#f4f6fb",
1103
+ text: "#171b2a",
1104
+ textMuted: "#5a6378",
1105
+ textSubtle: "#8a94a8",
1106
+ border: "rgb(42 51 70 / 0.1)",
1107
+ visitorBubble: "#6f16ff",
1108
+ visitorText: "#ffffff",
1109
+ success: "#18794e",
1110
+ danger: "#c94b63",
1111
+ fontBody: '"Mulish", "Avenir Next", "Segoe UI", sans-serif',
1112
+ fontDisplay: '"Space Grotesk", sans-serif'
1113
+ };
1114
+
982
1115
  // src/react/components/AgentRail/AgentRail.tsx
983
1116
  import { useEffect as useEffect2, useRef as useRef3 } from "react";
984
1117
 
985
- // src/react/components/ToolTimeline/ToolTimeline.tsx
1118
+ // src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
986
1119
  import { jsx, jsxs } from "react/jsx-runtime";
987
- function SpinnerIcon() {
988
- return /* @__PURE__ */ jsxs("svg", { className: "agent-status__spinner", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
989
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.25" }),
990
- /* @__PURE__ */ jsx("path", { d: "M14 8a6 6 0 0 0-6-6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
991
- ] });
992
- }
993
- function getCurrentStep(steps) {
994
- const active = steps.find((step) => step.state === "active");
995
- if (active) return active;
996
- const error = steps.find((step) => step.state === "error");
997
- if (error) return error;
998
- const pending = steps.find((step) => step.state === "pending");
999
- if (pending) return pending;
1000
- return steps.at(-1) ?? null;
1001
- }
1002
- function ToolTimeline({
1003
- steps,
1004
- streamingText,
1005
- showStreaming = false,
1006
- inline = false
1007
- }) {
1008
- if (steps.length === 0 && !(showStreaming && streamingText)) return null;
1009
- const currentStep = getCurrentStep(steps);
1010
- const showStatus = currentStep && currentStep.state !== "completed" && !(showStreaming && streamingText);
1011
- return /* @__PURE__ */ jsxs(
1012
- "div",
1013
- {
1014
- className: `tool-timeline${inline ? " tool-timeline--inline" : ""}`,
1015
- role: "status",
1016
- "aria-live": "polite",
1017
- "aria-label": "Agent progress",
1018
- children: [
1019
- showStatus ? /* @__PURE__ */ jsxs("div", { className: "agent-status", children: [
1020
- currentStep.state === "error" ? /* @__PURE__ */ jsx("span", { className: "agent-status__icon agent-status__icon--error", "aria-hidden": "true", children: "!" }) : /* @__PURE__ */ jsx("span", { className: "agent-status__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(SpinnerIcon, {}) }),
1021
- /* @__PURE__ */ jsxs("div", { className: "agent-status__copy", children: [
1022
- /* @__PURE__ */ jsx("span", { className: "agent-status__label", children: currentStep.label }),
1023
- currentStep.detail ? /* @__PURE__ */ jsx("span", { className: "agent-status__detail", children: currentStep.detail }) : null
1024
- ] })
1025
- ] }, currentStep.id) : null,
1026
- showStreaming && streamingText ? /* @__PURE__ */ jsxs("p", { className: "tool-timeline__streaming-text", children: [
1027
- streamingText,
1028
- /* @__PURE__ */ jsx("span", { className: "tool-timeline__cursor", "aria-hidden": "true" })
1029
- ] }) : null
1030
- ]
1031
- }
1120
+ function workSummary(steps) {
1121
+ const active = [...steps].reverse().find((step) => step.state === "active");
1122
+ if (active?.kind === "specialist") return `Working with ${active.label}`;
1123
+ if (active?.kind === "search") return "Searching this site";
1124
+ if (active) return active.label;
1125
+ const hasError = steps.some((step) => step.state === "error");
1126
+ const specialists = steps.filter(
1127
+ (step) => step.kind === "specialist" && step.state === "completed"
1032
1128
  );
1033
- }
1034
-
1035
- // src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
1036
- import { jsx as jsx2 } from "react/jsx-runtime";
1037
- function AgentActivityBubble({
1038
- steps,
1039
- streamingText,
1040
- showStreaming = false
1041
- }) {
1042
- return /* @__PURE__ */ jsx2("article", { className: "agent-activity-bubble", children: /* @__PURE__ */ jsx2("div", { className: "agent-activity-bubble__shell", children: /* @__PURE__ */ jsx2(
1043
- ToolTimeline,
1044
- {
1045
- steps,
1046
- streamingText,
1047
- showStreaming,
1048
- inline: true
1049
- }
1050
- ) }) });
1129
+ const searched = steps.some(
1130
+ (step) => step.kind === "search" && step.state === "completed"
1131
+ );
1132
+ if (hasError) return "Answered with available information";
1133
+ if (specialists.length > 1)
1134
+ return `Consulted ${specialists.length} specialists`;
1135
+ if (specialists.length === 1) return `Consulted ${specialists[0]?.label}`;
1136
+ if (searched) return "Searched this site";
1137
+ return "Prepared a response";
1138
+ }
1139
+ function AgentActivityBubble({ steps }) {
1140
+ const active = steps.some((step) => step.state === "active");
1141
+ return /* @__PURE__ */ jsxs("article", { className: "agent-activity-bubble", children: [
1142
+ /* @__PURE__ */ jsxs("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
1143
+ /* @__PURE__ */ jsx(
1144
+ "span",
1145
+ {
1146
+ className: `agent-activity-bubble__pulse${active ? " is-active" : ""}`,
1147
+ "aria-hidden": "true"
1148
+ }
1149
+ ),
1150
+ workSummary(steps)
1151
+ ] }),
1152
+ /* @__PURE__ */ jsxs("details", { className: "agent-activity-bubble__details", open: active, children: [
1153
+ /* @__PURE__ */ jsx("summary", { children: "Work details" }),
1154
+ /* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => /* @__PURE__ */ jsxs(
1155
+ "li",
1156
+ {
1157
+ className: "agent-activity-bubble__step",
1158
+ "data-state": step.state,
1159
+ children: [
1160
+ /* @__PURE__ */ jsx(
1161
+ "span",
1162
+ {
1163
+ className: "agent-activity-bubble__step-icon",
1164
+ "aria-hidden": "true",
1165
+ children: step.state === "completed" ? "\u2713" : step.state === "error" ? "!" : ""
1166
+ }
1167
+ ),
1168
+ /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
1169
+ /* @__PURE__ */ jsx("strong", { children: step.label }),
1170
+ step.detail ? /* @__PURE__ */ jsx("small", { children: step.detail }) : null
1171
+ ] })
1172
+ ]
1173
+ },
1174
+ step.id
1175
+ )) })
1176
+ ] })
1177
+ ] });
1051
1178
  }
1052
1179
 
1053
1180
  // src/react/components/Composer/Composer.tsx
1054
1181
  import { useRef as useRef2, useState as useState2 } from "react";
1055
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1182
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1056
1183
  function SendIcon() {
1057
- return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx3("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1184
+ return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1058
1185
  }
1059
1186
  function Composer({
1060
1187
  disabled = false,
@@ -1081,8 +1208,8 @@ function Composer({
1081
1208
  submitCurrent();
1082
1209
  }
1083
1210
  }
1084
- return /* @__PURE__ */ jsx3("form", { className: `composer${variant === "dock" ? " composer--dock" : ""}`, onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2("div", { className: "composer__field", children: [
1085
- /* @__PURE__ */ jsx3(
1211
+ return /* @__PURE__ */ jsx2("form", { className: `composer${variant === "dock" ? " composer--dock" : ""}`, onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2("div", { className: "composer__field", children: [
1212
+ /* @__PURE__ */ jsx2(
1086
1213
  "textarea",
1087
1214
  {
1088
1215
  ref: inputRef,
@@ -1096,21 +1223,21 @@ function Composer({
1096
1223
  onKeyDown: handleKeyDown
1097
1224
  }
1098
1225
  ),
1099
- /* @__PURE__ */ jsx3(
1226
+ /* @__PURE__ */ jsx2(
1100
1227
  "button",
1101
1228
  {
1102
1229
  type: "submit",
1103
1230
  className: "composer__send",
1104
1231
  disabled: disabled || !value.trim(),
1105
1232
  "aria-label": "Send message",
1106
- children: /* @__PURE__ */ jsx3(SendIcon, {})
1233
+ children: /* @__PURE__ */ jsx2(SendIcon, {})
1107
1234
  }
1108
1235
  )
1109
1236
  ] }) });
1110
1237
  }
1111
1238
 
1112
1239
  // src/react/components/FollowUpChips/FollowUpChips.tsx
1113
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1240
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1114
1241
  function FollowUpChips({
1115
1242
  suggestions,
1116
1243
  disabled = false,
@@ -1120,7 +1247,7 @@ function FollowUpChips({
1120
1247
  }) {
1121
1248
  if (suggestions.length === 0) return null;
1122
1249
  if (variant === "dock") {
1123
- return /* @__PURE__ */ jsx4("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx4("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
1250
+ return /* @__PURE__ */ jsx3("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx3("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx3(
1124
1251
  "button",
1125
1252
  {
1126
1253
  type: "button",
@@ -1133,8 +1260,8 @@ function FollowUpChips({
1133
1260
  )) }) });
1134
1261
  }
1135
1262
  return /* @__PURE__ */ jsxs3("div", { className: "followups", children: [
1136
- /* @__PURE__ */ jsx4("span", { className: "followups__label", children: label }),
1137
- /* @__PURE__ */ jsx4("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx4(
1263
+ /* @__PURE__ */ jsx3("span", { className: "followups__label", children: label }),
1264
+ /* @__PURE__ */ jsx3("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx3(
1138
1265
  "button",
1139
1266
  {
1140
1267
  type: "button",
@@ -1151,12 +1278,12 @@ function FollowUpChips({
1151
1278
  // src/react/components/MessageBubble/MessageBubble.tsx
1152
1279
  import { Streamdown } from "streamdown";
1153
1280
  import "streamdown/styles.css";
1154
- import { jsx as jsx5 } from "react/jsx-runtime";
1281
+ import { jsx as jsx4 } from "react/jsx-runtime";
1155
1282
  function MessageBubble({ message }) {
1156
1283
  if (message.role === "visitor") {
1157
- return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx5("p", { className: "message-bubble__text", children: message.text }) });
1284
+ return /* @__PURE__ */ jsx4("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx4("p", { className: "message-bubble__text", children: message.text }) });
1158
1285
  }
1159
- return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--agent", children: /* @__PURE__ */ jsx5("div", { className: "message-bubble__text", children: /* @__PURE__ */ jsx5(
1286
+ return /* @__PURE__ */ jsx4("article", { className: "message-bubble message-bubble--agent", children: /* @__PURE__ */ jsx4("div", { className: "message-bubble__text", children: /* @__PURE__ */ jsx4(
1160
1287
  Streamdown,
1161
1288
  {
1162
1289
  animated: true,
@@ -1173,12 +1300,20 @@ function MessageBubble({ message }) {
1173
1300
  }
1174
1301
 
1175
1302
  // src/react/components/AgentRail/AgentRail.tsx
1176
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1303
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1177
1304
  function MinimizeIcon() {
1178
- return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("path", { d: "M3.5 8h9", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round" }) });
1305
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1306
+ "path",
1307
+ {
1308
+ d: "M3.5 8h9",
1309
+ stroke: "currentColor",
1310
+ strokeWidth: "1.7",
1311
+ strokeLinecap: "round"
1312
+ }
1313
+ ) });
1179
1314
  }
1180
1315
  function ExpandIcon() {
1181
- return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
1316
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1182
1317
  "path",
1183
1318
  {
1184
1319
  d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
@@ -1190,7 +1325,7 @@ function ExpandIcon() {
1190
1325
  ) });
1191
1326
  }
1192
1327
  function RestoreIcon() {
1193
- return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
1328
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1194
1329
  "path",
1195
1330
  {
1196
1331
  d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
@@ -1205,6 +1340,7 @@ function AgentRail({
1205
1340
  state,
1206
1341
  theme,
1207
1342
  brandLabel = "Webless Assist",
1343
+ brandLogoUrl,
1208
1344
  poweredByLabel = "Powered by Webless",
1209
1345
  composerPlaceholder = "Ask anything\u2026",
1210
1346
  mobileFullscreen = false,
@@ -1216,10 +1352,31 @@ function AgentRail({
1216
1352
  onFollowUpSelect
1217
1353
  }) {
1218
1354
  const transcriptRef = useRef3(null);
1219
- const railStyle = theme?.railMaxWidth ? { ["--rail-width"]: theme.railMaxWidth, ["--as-rail-max-width"]: theme.railMaxWidth } : void 0;
1355
+ const resolvedTheme = { ...defaultAgentRailTheme, ...theme };
1356
+ const railStyle = {
1357
+ "--rail-width": resolvedTheme.railMaxWidth,
1358
+ "--as-rail-max-width": resolvedTheme.railMaxWidth,
1359
+ "--as-brand": resolvedTheme.brand,
1360
+ "--as-brand-soft": resolvedTheme.brandSoft,
1361
+ "--as-brand-deep": resolvedTheme.brandDeep,
1362
+ "--as-surface": resolvedTheme.surface,
1363
+ "--as-surface-muted": resolvedTheme.surfaceMuted,
1364
+ "--as-text": resolvedTheme.text,
1365
+ "--as-text-muted": resolvedTheme.textMuted,
1366
+ "--as-text-subtle": resolvedTheme.textSubtle,
1367
+ "--as-border": resolvedTheme.border,
1368
+ "--as-visitor-bubble": resolvedTheme.visitorBubble,
1369
+ "--as-visitor-text": resolvedTheme.visitorText,
1370
+ "--as-success": resolvedTheme.success,
1371
+ "--as-danger": resolvedTheme.danger,
1372
+ "--as-font-body": resolvedTheme.fontBody,
1373
+ "--as-font-display": resolvedTheme.fontDisplay
1374
+ };
1220
1375
  const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
1221
- const showActivity = state.toolSteps.length > 0 && (state.phase === "thinking" || state.phase === "running-tools");
1222
- const hasVisitorMessages2 = state.messages.some((message) => message.role === "visitor");
1376
+ const showActivity = state.toolSteps.length > 0;
1377
+ const hasVisitorMessages2 = state.messages.some(
1378
+ (message) => message.role === "visitor"
1379
+ );
1223
1380
  const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
1224
1381
  const showDockFollowUps = expanded && showIdleFollowUps;
1225
1382
  const streamingMessage = state.phase === "streaming" && state.streamingText ? {
@@ -1233,7 +1390,13 @@ function AgentRail({
1233
1390
  const node = transcriptRef.current;
1234
1391
  if (!node) return;
1235
1392
  node.scrollTop = node.scrollHeight;
1236
- }, [state.messages, state.toolSteps, state.streamingText, state.followUps, state.journey]);
1393
+ }, [
1394
+ state.messages,
1395
+ state.toolSteps,
1396
+ state.streamingText,
1397
+ state.followUps,
1398
+ state.journey
1399
+ ]);
1237
1400
  return /* @__PURE__ */ jsxs4(
1238
1401
  "aside",
1239
1402
  {
@@ -1241,34 +1404,59 @@ function AgentRail({
1241
1404
  style: railStyle,
1242
1405
  "aria-label": "Agent conversation",
1243
1406
  children: [
1244
- /* @__PURE__ */ jsx6("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs4("div", { className: "agent-rail__brand-row", children: [
1245
- onCollapse ? /* @__PURE__ */ jsx6(
1407
+ /* @__PURE__ */ jsx5("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs4("div", { className: "agent-rail__brand-row", children: [
1408
+ onCollapse ? /* @__PURE__ */ jsx5(
1246
1409
  "button",
1247
1410
  {
1248
1411
  type: "button",
1249
1412
  className: "agent-rail__collapse",
1250
1413
  "aria-label": "Collapse assist",
1251
1414
  onClick: onCollapse,
1252
- children: /* @__PURE__ */ jsx6(MinimizeIcon, {})
1415
+ children: /* @__PURE__ */ jsx5(MinimizeIcon, {})
1253
1416
  }
1254
- ) : onClose ? /* @__PURE__ */ jsx6("button", { type: "button", className: "agent-rail__close", "aria-label": "Close agent", onClick: onClose, children: /* @__PURE__ */ jsx6(MinimizeIcon, {}) }) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
1255
- /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-label", children: brandLabel }),
1256
- onExpandToggle ? /* @__PURE__ */ jsx6(
1417
+ ) : onClose ? /* @__PURE__ */ jsx5(
1418
+ "button",
1419
+ {
1420
+ type: "button",
1421
+ className: "agent-rail__close",
1422
+ "aria-label": "Close agent",
1423
+ onClick: onClose,
1424
+ children: /* @__PURE__ */ jsx5(MinimizeIcon, {})
1425
+ }
1426
+ ) : /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
1427
+ /* @__PURE__ */ jsxs4("span", { className: "agent-rail__identity", children: [
1428
+ /* @__PURE__ */ jsxs4("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: [
1429
+ brandLabel.slice(0, 1).toUpperCase(),
1430
+ brandLogoUrl ? /* @__PURE__ */ jsx5(
1431
+ "img",
1432
+ {
1433
+ className: "agent-rail__brand-logo",
1434
+ src: brandLogoUrl,
1435
+ alt: "",
1436
+ onError: (event) => {
1437
+ event.currentTarget.hidden = true;
1438
+ }
1439
+ }
1440
+ ) : null
1441
+ ] }),
1442
+ /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-label", children: brandLabel })
1443
+ ] }),
1444
+ onExpandToggle ? /* @__PURE__ */ jsx5(
1257
1445
  "button",
1258
1446
  {
1259
1447
  type: "button",
1260
1448
  className: "agent-rail__expand",
1261
1449
  "aria-label": expanded ? "Restore assist panel" : "Expand assist panel",
1262
1450
  onClick: onExpandToggle,
1263
- children: expanded ? /* @__PURE__ */ jsx6(RestoreIcon, {}) : /* @__PURE__ */ jsx6(ExpandIcon, {})
1451
+ children: expanded ? /* @__PURE__ */ jsx5(RestoreIcon, {}) : /* @__PURE__ */ jsx5(ExpandIcon, {})
1264
1452
  }
1265
- ) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
1453
+ ) : /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
1266
1454
  ] }) }),
1267
1455
  /* @__PURE__ */ jsxs4("div", { ref: transcriptRef, className: "agent-rail__transcript", children: [
1268
- state.messages.map((message) => /* @__PURE__ */ jsx6(MessageBubble, { message }, message.id)),
1269
- streamingMessage ? /* @__PURE__ */ jsx6(MessageBubble, { message: streamingMessage }) : null,
1270
- showActivity ? /* @__PURE__ */ jsx6(AgentActivityBubble, { steps: state.toolSteps }) : null,
1271
- !expanded && showIdleFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
1456
+ state.messages.map((message) => /* @__PURE__ */ jsx5(MessageBubble, { message }, message.id)),
1457
+ streamingMessage ? /* @__PURE__ */ jsx5(MessageBubble, { message: streamingMessage }) : null,
1458
+ showActivity ? /* @__PURE__ */ jsx5(AgentActivityBubble, { steps: state.toolSteps }) : null,
1459
+ !expanded && showIdleFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx5(
1272
1460
  FollowUpChips,
1273
1461
  {
1274
1462
  suggestions: state.followUps,
@@ -1277,10 +1465,17 @@ function AgentRail({
1277
1465
  onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
1278
1466
  }
1279
1467
  ) }) : null,
1280
- state.error ? /* @__PURE__ */ jsx6("p", { role: "alert", style: { fontSize: 13, color: "var(--as-danger)", margin: 0 }, children: state.error }) : null
1468
+ state.error ? /* @__PURE__ */ jsx5(
1469
+ "p",
1470
+ {
1471
+ role: "alert",
1472
+ style: { fontSize: 13, color: "var(--as-danger)", margin: 0 },
1473
+ children: state.error
1474
+ }
1475
+ ) : null
1281
1476
  ] }),
1282
1477
  expanded ? /* @__PURE__ */ jsxs4("div", { className: "agent-rail__dock-wrap", children: [
1283
- showDockFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ jsx6(
1478
+ showDockFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ jsx5(
1284
1479
  FollowUpChips,
1285
1480
  {
1286
1481
  variant: "dock",
@@ -1289,7 +1484,7 @@ function AgentRail({
1289
1484
  onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
1290
1485
  }
1291
1486
  ) }) : null,
1292
- /* @__PURE__ */ jsx6("div", { className: "agent-rail__dock", children: /* @__PURE__ */ jsx6(
1487
+ /* @__PURE__ */ jsx5("div", { className: "agent-rail__dock", children: /* @__PURE__ */ jsx5(
1293
1488
  Composer,
1294
1489
  {
1295
1490
  variant: "dock",
@@ -1299,11 +1494,11 @@ function AgentRail({
1299
1494
  }
1300
1495
  ) }),
1301
1496
  /* @__PURE__ */ jsxs4("div", { className: "agent-rail__footer", children: [
1302
- /* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1303
- /* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1497
+ /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1498
+ /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1304
1499
  ] })
1305
1500
  ] }) : /* @__PURE__ */ jsxs4("div", { className: "agent-rail__composer-wrap", children: [
1306
- /* @__PURE__ */ jsx6(
1501
+ /* @__PURE__ */ jsx5(
1307
1502
  Composer,
1308
1503
  {
1309
1504
  disabled: isBusy,
@@ -1312,8 +1507,8 @@ function AgentRail({
1312
1507
  }
1313
1508
  ),
1314
1509
  /* @__PURE__ */ jsxs4("div", { className: "agent-rail__footer", children: [
1315
- /* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1316
- /* @__PURE__ */ jsx6("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1510
+ /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1511
+ /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1317
1512
  ] })
1318
1513
  ] })
1319
1514
  ]
@@ -1322,22 +1517,67 @@ function AgentRail({
1322
1517
  }
1323
1518
 
1324
1519
  // src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
1325
- import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1520
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1326
1521
  function SparklesIcon() {
1327
- return /* @__PURE__ */ jsxs5("svg", { className: "assist-edge-tab__sparkles", viewBox: "0 0 18 16", fill: "none", "aria-hidden": "true", children: [
1328
- /* @__PURE__ */ jsx7("path", { d: "M8 1.2l.95 2.7 2.85.05-2.25 1.75.8 2.75L8 6.7 5.65 8.45l.8-2.75L4.2 3.95l2.85-.05L8 1.2z", fill: "currentColor" }),
1329
- /* @__PURE__ */ jsx7("path", { d: "M14.2 6.4l.55 1.55 1.65.03-1.3 1 .46 1.58-1.36-1-1.36 1 .46-1.58-1.3-1 1.65-.03.55-1.55z", fill: "currentColor" }),
1330
- /* @__PURE__ */ jsx7("path", { d: "M3.1 9.1l.4 1.15 1.22.02-.96.74.34 1.17-1-.74-1 .74.34-1.17-.96-.74 1.22-.02.4-1.15z", fill: "currentColor" })
1331
- ] });
1522
+ return /* @__PURE__ */ jsxs5(
1523
+ "svg",
1524
+ {
1525
+ className: "assist-edge-tab__sparkles",
1526
+ viewBox: "0 0 18 16",
1527
+ fill: "none",
1528
+ "aria-hidden": "true",
1529
+ children: [
1530
+ /* @__PURE__ */ jsx6(
1531
+ "path",
1532
+ {
1533
+ 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",
1534
+ fill: "currentColor"
1535
+ }
1536
+ ),
1537
+ /* @__PURE__ */ jsx6(
1538
+ "path",
1539
+ {
1540
+ 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",
1541
+ fill: "currentColor"
1542
+ }
1543
+ ),
1544
+ /* @__PURE__ */ jsx6(
1545
+ "path",
1546
+ {
1547
+ 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",
1548
+ fill: "currentColor"
1549
+ }
1550
+ )
1551
+ ]
1552
+ }
1553
+ );
1332
1554
  }
1333
1555
  function ChevronLeftIcon() {
1334
- return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
1556
+ return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
1557
+ "path",
1558
+ {
1559
+ d: "M10 4L6 8l4 4",
1560
+ stroke: "currentColor",
1561
+ strokeWidth: "1.6",
1562
+ strokeLinecap: "round",
1563
+ strokeLinejoin: "round"
1564
+ }
1565
+ ) });
1335
1566
  }
1336
1567
  function ChevronDownIcon() {
1337
- return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
1568
+ return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
1569
+ "path",
1570
+ {
1571
+ d: "M4 6l4 4 4-4",
1572
+ stroke: "currentColor",
1573
+ strokeWidth: "1.6",
1574
+ strokeLinecap: "round",
1575
+ strokeLinejoin: "round"
1576
+ }
1577
+ ) });
1338
1578
  }
1339
1579
  function DragDots() {
1340
- return /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx7("i", {}, index)) });
1580
+ return /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx6("i", {}, index)) });
1341
1581
  }
1342
1582
  var VARIANT_COPY = {
1343
1583
  outline: { label: "Assist", aria: "Open Assist" },
@@ -1350,12 +1590,19 @@ function AssistEdgeTab({
1350
1590
  along,
1351
1591
  inset,
1352
1592
  visible,
1593
+ label,
1594
+ logoUrl,
1595
+ brandColor,
1596
+ fontFamily,
1353
1597
  onOpen
1354
1598
  }) {
1355
1599
  const copy = VARIANT_COPY[variant];
1600
+ const visibleLabel = label?.trim() || copy.label;
1356
1601
  const style = {
1357
1602
  "--tab-along": `${along}%`,
1358
- "--tab-inset": `${inset}px`
1603
+ "--tab-inset": `${inset}px`,
1604
+ ...brandColor ? { "--as-brand": brandColor } : {},
1605
+ ...fontFamily ? { "--as-font-display": fontFamily } : {}
1359
1606
  };
1360
1607
  return /* @__PURE__ */ jsxs5(
1361
1608
  "button",
@@ -1363,25 +1610,51 @@ function AssistEdgeTab({
1363
1610
  type: "button",
1364
1611
  className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${visible ? " is-visible" : ""}`,
1365
1612
  style,
1366
- "aria-label": copy.aria,
1613
+ "aria-label": `Open ${visibleLabel}`,
1367
1614
  "aria-hidden": !visible,
1368
1615
  tabIndex: visible ? 0 : -1,
1369
1616
  onClick: onOpen,
1370
1617
  children: [
1371
1618
  variant === "outline" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1372
- /* @__PURE__ */ jsx7(SparklesIcon, {}),
1373
- /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
1374
- /* @__PURE__ */ jsx7(ChevronDownIcon, {})
1619
+ /* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
1620
+ /* @__PURE__ */ jsx6(SparklesIcon, {}),
1621
+ logoUrl ? /* @__PURE__ */ jsx6(
1622
+ "img",
1623
+ {
1624
+ className: "assist-edge-tab__logo",
1625
+ src: logoUrl,
1626
+ alt: "",
1627
+ onError: (event) => {
1628
+ event.currentTarget.hidden = true;
1629
+ }
1630
+ }
1631
+ ) : null
1632
+ ] }),
1633
+ /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__label", children: visibleLabel }),
1634
+ /* @__PURE__ */ jsx6(ChevronDownIcon, {})
1375
1635
  ] }) : null,
1376
1636
  variant === "ask" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1377
- /* @__PURE__ */ jsx7(ChevronLeftIcon, {}),
1378
- /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
1379
- /* @__PURE__ */ jsx7(DragDots, {})
1637
+ /* @__PURE__ */ jsx6(ChevronLeftIcon, {}),
1638
+ /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__label", children: visibleLabel }),
1639
+ /* @__PURE__ */ jsx6(DragDots, {})
1380
1640
  ] }) : null,
1381
1641
  variant === "fill" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1382
- /* @__PURE__ */ jsx7(SparklesIcon, {}),
1383
- /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: copy.label }),
1384
- /* @__PURE__ */ jsx7(ChevronLeftIcon, {})
1642
+ /* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
1643
+ /* @__PURE__ */ jsx6(SparklesIcon, {}),
1644
+ logoUrl ? /* @__PURE__ */ jsx6(
1645
+ "img",
1646
+ {
1647
+ className: "assist-edge-tab__logo",
1648
+ src: logoUrl,
1649
+ alt: "",
1650
+ onError: (event) => {
1651
+ event.currentTarget.hidden = true;
1652
+ }
1653
+ }
1654
+ ) : null
1655
+ ] }),
1656
+ /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__label", children: visibleLabel }),
1657
+ /* @__PURE__ */ jsx6(ChevronLeftIcon, {})
1385
1658
  ] }) : null
1386
1659
  ]
1387
1660
  }
@@ -1503,7 +1776,7 @@ function closeAgentPanel(customerId) {
1503
1776
  }
1504
1777
 
1505
1778
  // src/react/components/AgentWidget/AgentWidget.tsx
1506
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1779
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1507
1780
  function AgentWidget({
1508
1781
  indexId,
1509
1782
  customerId,
@@ -1513,7 +1786,8 @@ function AgentWidget({
1513
1786
  placement: placementInput,
1514
1787
  defaultCollapsed = true,
1515
1788
  pageShift = true,
1516
- registerPanelController = false
1789
+ registerPanelController = false,
1790
+ branding
1517
1791
  }) {
1518
1792
  const isMobile = useIsMobile();
1519
1793
  const placement = normalizeAgentPlacement(placementInput);
@@ -1535,8 +1809,27 @@ function AgentWidget({
1535
1809
  getUnpublishedPreviewGrant,
1536
1810
  indexId,
1537
1811
  version,
1538
- runtimeOrigin
1812
+ runtimeOrigin,
1813
+ greeting: branding?.greeting
1539
1814
  });
1815
+ const agentName = branding?.agentName ?? "Webless Guide";
1816
+ const theme = {
1817
+ ...branding?.fontFamily ? { fontBody: branding.fontFamily, fontDisplay: branding.fontFamily } : {},
1818
+ ...branding?.colors?.primary ? {
1819
+ brand: branding.colors.primary,
1820
+ visitorBubble: branding.colors.primary
1821
+ } : {},
1822
+ ...branding?.colors?.primarySoft ? { brandSoft: branding.colors.primarySoft } : {},
1823
+ ...branding?.colors?.primaryForeground ? { visitorText: branding.colors.primaryForeground } : {},
1824
+ ...branding?.colors?.surface ? { surface: branding.colors.surface } : {},
1825
+ ...branding?.colors?.surfaceMuted ? { surfaceMuted: branding.colors.surfaceMuted } : {},
1826
+ ...branding?.colors?.text ? { text: branding.colors.text } : {},
1827
+ ...branding?.colors?.textMuted ? {
1828
+ textMuted: branding.colors.textMuted,
1829
+ textSubtle: branding.colors.textMuted
1830
+ } : {},
1831
+ ...branding?.colors?.border ? { border: branding.colors.border } : {}
1832
+ };
1540
1833
  const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
1541
1834
  useEffect5(() => {
1542
1835
  if (!registerPanelController) return;
@@ -1554,47 +1847,55 @@ function AgentWidget({
1554
1847
  await submit(message);
1555
1848
  }
1556
1849
  return /* @__PURE__ */ jsxs6("div", { className: "webless-agent-root", children: [
1557
- /* @__PURE__ */ jsx8(
1850
+ /* @__PURE__ */ jsxs6(
1558
1851
  "div",
1559
1852
  {
1560
1853
  className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
1561
- children: /* @__PURE__ */ jsx8(
1562
- "div",
1563
- {
1564
- ref: railSlotRef,
1565
- className: "webless-agent-root__rail-slot",
1566
- inert: railCollapsed || void 0,
1567
- "aria-hidden": railCollapsed,
1568
- children: /* @__PURE__ */ jsx8(
1569
- AgentRail,
1570
- {
1571
- state: idle ? {
1572
- ...state,
1573
- followUps: createIdleSuggestions()
1574
- } : state,
1575
- mobileFullscreen: isMobile && !railCollapsed,
1576
- expanded: railExpanded,
1577
- onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
1578
- onClose: isMobile ? () => setRailCollapsed(true) : void 0,
1579
- onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
1580
- onSubmit: handleSubmit,
1581
- onFollowUpSelect: (label) => void handleSubmit(label)
1582
- }
1583
- )
1584
- }
1585
- )
1854
+ children: [
1855
+ /* @__PURE__ */ jsx7(
1856
+ "div",
1857
+ {
1858
+ ref: railSlotRef,
1859
+ className: "webless-agent-root__rail-slot",
1860
+ inert: railCollapsed || void 0,
1861
+ "aria-hidden": railCollapsed,
1862
+ children: /* @__PURE__ */ jsx7(
1863
+ AgentRail,
1864
+ {
1865
+ theme,
1866
+ brandLabel: agentName,
1867
+ brandLogoUrl: branding?.logoUrl,
1868
+ composerPlaceholder: branding?.composerPlaceholder ?? `Ask ${agentName}\u2026`,
1869
+ poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
1870
+ state: idle ? {
1871
+ ...state,
1872
+ followUps: createIdleSuggestions()
1873
+ } : state,
1874
+ mobileFullscreen: isMobile && !railCollapsed,
1875
+ expanded: railExpanded,
1876
+ onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
1877
+ onClose: isMobile ? () => setRailCollapsed(true) : void 0,
1878
+ onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
1879
+ onSubmit: handleSubmit,
1880
+ onFollowUpSelect: (label) => void handleSubmit(label)
1881
+ }
1882
+ )
1883
+ }
1884
+ ),
1885
+ !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx7(
1886
+ "button",
1887
+ {
1888
+ type: "button",
1889
+ className: "webless-agent-root__backdrop",
1890
+ tabIndex: -1,
1891
+ "aria-label": "Close expanded assist",
1892
+ onClick: () => setRailExpanded(false)
1893
+ }
1894
+ ) : null
1895
+ ]
1586
1896
  }
1587
1897
  ),
1588
- !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx8(
1589
- "button",
1590
- {
1591
- type: "button",
1592
- className: "webless-agent-root__backdrop",
1593
- "aria-label": "Close expanded assist",
1594
- onClick: () => setRailExpanded(false)
1595
- }
1596
- ) : null,
1597
- railCollapsed ? /* @__PURE__ */ jsx8(
1898
+ railCollapsed ? /* @__PURE__ */ jsx7(
1598
1899
  AssistEdgeTab,
1599
1900
  {
1600
1901
  variant: placement.variant,
@@ -1602,6 +1903,10 @@ function AgentWidget({
1602
1903
  along: placement.along,
1603
1904
  inset: placement.inset,
1604
1905
  visible: true,
1906
+ label: agentName,
1907
+ logoUrl: branding?.logoUrl,
1908
+ brandColor: branding?.colors?.primary,
1909
+ fontFamily: branding?.fontFamily,
1605
1910
  onOpen: () => setRailCollapsed(false)
1606
1911
  }
1607
1912
  ) : null
@@ -1619,8 +1924,9 @@ export {
1619
1924
  normalizeAgentPlacement,
1620
1925
  openAgentPanel,
1621
1926
  closeAgentPanel,
1927
+ defaultAgentRailTheme,
1622
1928
  AgentRail,
1623
1929
  AssistEdgeTab,
1624
1930
  AgentWidget
1625
1931
  };
1626
- //# sourceMappingURL=chunk-7IR64MFS.js.map
1932
+ //# sourceMappingURL=chunk-MRSLWREA.js.map