@webless/agent 0.3.2 → 0.4.1

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.
@@ -271,13 +271,15 @@ function emitWorkItem(item, handlers, workItems) {
271
271
  handlers.onWork?.(item);
272
272
  handlers.onStep?.(item.label, item.detail);
273
273
  }
274
- function completePlanning(handlers, workItems) {
274
+ function completePlanning(handlers, workItems, nextItems = []) {
275
275
  const planning = workItems.get("planning");
276
276
  if (!planning || planning.state !== "active") return;
277
+ const specialists = nextItems.filter((item) => item.kind === "specialist");
278
+ const detail = specialists.length === 1 ? `Delegating to ${specialists[0]?.label}` : specialists.length > 1 ? `Delegating to ${specialists.length} specialists` : nextItems.some((item) => item.kind === "search") ? "Using built-in Search & Discovery" : "Picked the best way to help";
277
279
  emitWorkItem(
278
280
  {
279
281
  ...planning,
280
- detail: "Picked the best way to help",
282
+ detail,
281
283
  state: "completed"
282
284
  },
283
285
  handlers,
@@ -327,11 +329,12 @@ function applyWorkEvent(event, handlers, workItems) {
327
329
  return;
328
330
  }
329
331
  if (event.type === "actions.requested") {
330
- completePlanning(handlers, workItems);
331
- for (const action of event.data.actions) {
332
+ const nextItems = event.data.actions.flatMap((action) => {
332
333
  const item = requestedWorkItem(action);
333
- if (item) emitWorkItem(item, handlers, workItems);
334
- }
334
+ return item ? [item] : [];
335
+ });
336
+ completePlanning(handlers, workItems, nextItems);
337
+ for (const item of nextItems) emitWorkItem(item, handlers, workItems);
335
338
  return;
336
339
  }
337
340
  if (event.type === "subagent.called") {
@@ -1053,6 +1056,37 @@ function useAgentChat({
1053
1056
  },
1054
1057
  [runTurn]
1055
1058
  );
1059
+ const retry = useCallback(async () => {
1060
+ const visitorMessage = [...state.messages].reverse().find((message) => message.role === "visitor");
1061
+ if (!visitorMessage) return;
1062
+ if (runRef.current) {
1063
+ runRef.current.abort();
1064
+ clientRef.current.cancelActive();
1065
+ }
1066
+ const controller = new AbortController();
1067
+ runRef.current = controller;
1068
+ setState((prev) => ({
1069
+ ...prev,
1070
+ phase: "thinking",
1071
+ toolSteps: [
1072
+ {
1073
+ id: "planning",
1074
+ kind: "planning",
1075
+ label: "Understanding your question",
1076
+ state: "active"
1077
+ }
1078
+ ],
1079
+ journey: null,
1080
+ followUps: [],
1081
+ streamingText: "",
1082
+ error: null
1083
+ }));
1084
+ await runTurn({
1085
+ controller,
1086
+ resume: false,
1087
+ visitorText: visitorMessage.text
1088
+ });
1089
+ }, [runTurn, state.messages]);
1056
1090
  useEffect(() => {
1057
1091
  const conversation = loadPersistedAgentConversation(
1058
1092
  resolvedStorageKeyPrefix,
@@ -1085,6 +1119,7 @@ function useAgentChat({
1085
1119
  return {
1086
1120
  state,
1087
1121
  reset,
1122
+ retry,
1088
1123
  submit,
1089
1124
  visitorSessionId: visitorId,
1090
1125
  sessionId: clientRef.current.getActiveSessionId()
@@ -1142,15 +1177,16 @@ var defaultAgentRailTheme = {
1142
1177
  };
1143
1178
 
1144
1179
  // src/react/components/AgentRail/AgentRail.tsx
1145
- import { useEffect as useEffect2, useRef as useRef3 } from "react";
1180
+ import { useEffect as useEffect2, useId, useRef as useRef3 } from "react";
1146
1181
 
1147
1182
  // src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
1148
- import { jsx, jsxs } from "react/jsx-runtime";
1149
- function workSummary(steps, failed) {
1183
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1184
+ function workSummary(steps, failed, brandLabel) {
1150
1185
  const active = [...steps].reverse().find((step) => step.state === "active");
1151
- if (active?.kind === "specialist") return `Working with ${active.label}`;
1186
+ if (active?.kind === "specialist")
1187
+ return `${active.label} is reviewing your question`;
1152
1188
  if (active?.kind === "search") return "Searching this site";
1153
- if (active) return active.label;
1189
+ if (active) return `${brandLabel} is choosing the best way to help`;
1154
1190
  if (failed) return "Couldn\u2019t complete this request";
1155
1191
  const hasError = steps.some((step) => step.state === "error");
1156
1192
  const specialists = steps.filter(
@@ -1161,16 +1197,60 @@ function workSummary(steps, failed) {
1161
1197
  );
1162
1198
  if (hasError) return "Answered with available information";
1163
1199
  if (specialists.length > 1)
1164
- return `Consulted ${specialists.length} specialists`;
1165
- if (specialists.length === 1) return `Consulted ${specialists[0]?.label}`;
1166
- if (searched) return "Searched this site";
1167
- return "Prepared a response";
1200
+ return `Answer prepared with ${specialists.length} specialists`;
1201
+ if (specialists.length === 1)
1202
+ return `Answer prepared with ${specialists[0]?.label}`;
1203
+ if (searched) return "Answer prepared from this site";
1204
+ return "Answer ready";
1205
+ }
1206
+ function stepLabel(step, brandLabel) {
1207
+ return step.kind === "planning" ? brandLabel : step.label;
1208
+ }
1209
+ function stepDetail(step, steps) {
1210
+ if (step.kind !== "planning" || step.state !== "completed") {
1211
+ return step.detail;
1212
+ }
1213
+ const specialists = steps.filter((item) => item.kind === "specialist");
1214
+ if (specialists.length === 1) return `Delegated to ${specialists[0]?.label}`;
1215
+ if (specialists.length > 1)
1216
+ return `Delegated to ${specialists.length} specialists`;
1217
+ if (steps.some((item) => item.kind === "search"))
1218
+ return "Used built-in Search & Discovery";
1219
+ return step.detail;
1220
+ }
1221
+ function SearchIcon() {
1222
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
1223
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "3.75", stroke: "currentColor", strokeWidth: "1.4" }),
1224
+ /* @__PURE__ */ jsx(
1225
+ "path",
1226
+ {
1227
+ d: "m10 10 3 3",
1228
+ stroke: "currentColor",
1229
+ strokeWidth: "1.4",
1230
+ strokeLinecap: "round"
1231
+ }
1232
+ )
1233
+ ] });
1234
+ }
1235
+ function PlanningIcon() {
1236
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
1237
+ "path",
1238
+ {
1239
+ d: "M4 4.5h8M4 8h5.5M4 11.5h7",
1240
+ stroke: "currentColor",
1241
+ strokeWidth: "1.4",
1242
+ strokeLinecap: "round"
1243
+ }
1244
+ ) });
1168
1245
  }
1169
1246
  function AgentActivityBubble({
1247
+ brandLabel = "Webless Guide",
1248
+ brandLogoUrl,
1170
1249
  failed = false,
1171
1250
  steps
1172
1251
  }) {
1173
1252
  const active = steps.some((step) => step.state === "active");
1253
+ const delegated = steps.some((step) => step.kind === "specialist");
1174
1254
  return /* @__PURE__ */ jsxs("article", { className: "agent-activity-bubble", children: [
1175
1255
  /* @__PURE__ */ jsxs("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
1176
1256
  /* @__PURE__ */ jsx(
@@ -1180,33 +1260,59 @@ function AgentActivityBubble({
1180
1260
  "aria-hidden": "true"
1181
1261
  }
1182
1262
  ),
1183
- workSummary(steps, failed)
1263
+ workSummary(steps, failed, brandLabel)
1184
1264
  ] }),
1185
- /* @__PURE__ */ jsxs("details", { className: "agent-activity-bubble__details", open: active, children: [
1186
- /* @__PURE__ */ jsx("summary", { children: "Work details" }),
1187
- /* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => /* @__PURE__ */ jsxs(
1188
- "li",
1189
- {
1190
- className: "agent-activity-bubble__step",
1191
- "data-state": step.state,
1192
- children: [
1193
- /* @__PURE__ */ jsx(
1194
- "span",
1265
+ /* @__PURE__ */ jsxs(
1266
+ "details",
1267
+ {
1268
+ className: "agent-activity-bubble__details",
1269
+ open: active || delegated,
1270
+ children: [
1271
+ /* @__PURE__ */ jsx("summary", { children: failed ? "What happened" : active ? "Working" : "How this answer was prepared" }),
1272
+ /* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => {
1273
+ const detail = stepDetail(step, steps);
1274
+ return /* @__PURE__ */ jsxs(
1275
+ "li",
1195
1276
  {
1196
- className: "agent-activity-bubble__step-icon",
1197
- "aria-hidden": "true",
1198
- children: step.state === "completed" ? "\u2713" : step.state === "error" ? "!" : ""
1199
- }
1200
- ),
1201
- /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
1202
- /* @__PURE__ */ jsx("strong", { children: step.label }),
1203
- step.detail ? /* @__PURE__ */ jsx("small", { children: step.detail }) : null
1204
- ] })
1205
- ]
1206
- },
1207
- step.id
1208
- )) })
1209
- ] })
1277
+ className: "agent-activity-bubble__step",
1278
+ "data-kind": step.kind,
1279
+ "data-state": step.state,
1280
+ children: [
1281
+ /* @__PURE__ */ jsx(
1282
+ "span",
1283
+ {
1284
+ className: "agent-activity-bubble__step-icon",
1285
+ "aria-hidden": "true",
1286
+ children: step.kind === "planning" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1287
+ /* @__PURE__ */ jsx(PlanningIcon, {}),
1288
+ brandLogoUrl ? /* @__PURE__ */ jsx(
1289
+ "img",
1290
+ {
1291
+ src: brandLogoUrl,
1292
+ alt: "",
1293
+ onError: (event) => {
1294
+ event.currentTarget.hidden = true;
1295
+ }
1296
+ }
1297
+ ) : null
1298
+ ] }) : step.kind === "search" ? /* @__PURE__ */ jsx(SearchIcon, {}) : step.label.slice(0, 1).toUpperCase()
1299
+ }
1300
+ ),
1301
+ /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
1302
+ /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-heading", children: [
1303
+ /* @__PURE__ */ jsx("strong", { children: stepLabel(step, brandLabel) }),
1304
+ /* @__PURE__ */ jsx("small", { children: step.kind === "specialist" ? "Specialist" : step.kind === "search" ? "Built-in capability" : "Supervisor" })
1305
+ ] }),
1306
+ detail ? /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null
1307
+ ] })
1308
+ ]
1309
+ },
1310
+ step.id
1311
+ );
1312
+ }) })
1313
+ ]
1314
+ }
1315
+ )
1210
1316
  ] });
1211
1317
  }
1212
1318
 
@@ -1345,6 +1451,29 @@ function MinimizeIcon() {
1345
1451
  }
1346
1452
  ) });
1347
1453
  }
1454
+ function CloseIcon() {
1455
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1456
+ "path",
1457
+ {
1458
+ d: "M4 4l8 8M12 4l-8 8",
1459
+ stroke: "currentColor",
1460
+ strokeWidth: "1.5",
1461
+ strokeLinecap: "round"
1462
+ }
1463
+ ) });
1464
+ }
1465
+ function NewChatIcon() {
1466
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1467
+ "path",
1468
+ {
1469
+ d: "M9.5 3.5h3v3M12.25 3.75 8 8M7 4H4.5A1.5 1.5 0 0 0 3 5.5v6A1.5 1.5 0 0 0 4.5 13h6a1.5 1.5 0 0 0 1.5-1.5V9",
1470
+ stroke: "currentColor",
1471
+ strokeWidth: "1.4",
1472
+ strokeLinecap: "round",
1473
+ strokeLinejoin: "round"
1474
+ }
1475
+ ) });
1476
+ }
1348
1477
  function ExpandIcon() {
1349
1478
  return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
1350
1479
  "path",
@@ -1381,10 +1510,13 @@ function AgentRail({
1381
1510
  onCollapse,
1382
1511
  onClose,
1383
1512
  onExpandToggle,
1513
+ onReset,
1514
+ onRetry,
1384
1515
  onSubmit,
1385
1516
  onFollowUpSelect
1386
1517
  }) {
1387
1518
  const transcriptRef = useRef3(null);
1519
+ const welcomeTitleId = useId();
1388
1520
  const resolvedTheme = { ...defaultAgentRailTheme, ...theme };
1389
1521
  const railStyle = {
1390
1522
  "--rail-width": resolvedTheme.railMaxWidth,
@@ -1411,7 +1543,13 @@ function AgentRail({
1411
1543
  (message) => message.role === "visitor"
1412
1544
  );
1413
1545
  const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
1414
- const showDockFollowUps = expanded && showIdleFollowUps;
1546
+ const greeting = state.messages.find(
1547
+ (message) => message.role === "agent" && message.id === "greeting"
1548
+ );
1549
+ const visibleMessages = hasVisitorMessages2 ? state.messages.filter((message) => message.id !== "greeting") : [];
1550
+ const lastMessage = visibleMessages.at(-1);
1551
+ const completedAnswer = showActivity && state.phase === "complete" && lastMessage?.role === "agent" ? lastMessage : null;
1552
+ const transcriptMessages = completedAnswer ? visibleMessages.slice(0, -1) : visibleMessages;
1415
1553
  const streamingMessage = state.phase === "streaming" && state.streamingText ? {
1416
1554
  createdAt: 0,
1417
1555
  id: "streaming-response",
@@ -1436,6 +1574,10 @@ function AgentRail({
1436
1574
  className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
1437
1575
  style: railStyle,
1438
1576
  "aria-label": "Agent conversation",
1577
+ "aria-modal": mobileFullscreen || expanded ? true : void 0,
1578
+ autoFocus: mobileFullscreen || expanded,
1579
+ role: mobileFullscreen || expanded ? "dialog" : void 0,
1580
+ tabIndex: mobileFullscreen || expanded ? -1 : void 0,
1439
1581
  children: [
1440
1582
  /* @__PURE__ */ jsx5("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs4("div", { className: "agent-rail__brand-row", children: [
1441
1583
  onCollapse ? /* @__PURE__ */ jsx5(
@@ -1454,7 +1596,7 @@ function AgentRail({
1454
1596
  className: "agent-rail__close",
1455
1597
  "aria-label": "Close agent",
1456
1598
  onClick: onClose,
1457
- children: /* @__PURE__ */ jsx5(MinimizeIcon, {})
1599
+ children: /* @__PURE__ */ jsx5(CloseIcon, {})
1458
1600
  }
1459
1601
  ) : /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
1460
1602
  /* @__PURE__ */ jsxs4("span", { className: "agent-rail__identity", children: [
@@ -1474,81 +1616,102 @@ function AgentRail({
1474
1616
  ] }),
1475
1617
  /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-label", children: brandLabel })
1476
1618
  ] }),
1477
- onExpandToggle ? /* @__PURE__ */ jsx5(
1478
- "button",
1619
+ /* @__PURE__ */ jsxs4("span", { className: "agent-rail__actions", children: [
1620
+ onReset ? /* @__PURE__ */ jsx5(
1621
+ "button",
1622
+ {
1623
+ type: "button",
1624
+ className: "agent-rail__new-chat",
1625
+ "aria-label": "Start a new conversation",
1626
+ disabled: !hasVisitorMessages2,
1627
+ onClick: onReset,
1628
+ children: /* @__PURE__ */ jsx5(NewChatIcon, {})
1629
+ }
1630
+ ) : null,
1631
+ onExpandToggle ? /* @__PURE__ */ jsx5(
1632
+ "button",
1633
+ {
1634
+ type: "button",
1635
+ className: "agent-rail__expand",
1636
+ "aria-label": expanded ? "Exit focus view" : "Open focus view",
1637
+ onClick: onExpandToggle,
1638
+ children: expanded ? /* @__PURE__ */ jsx5(RestoreIcon, {}) : /* @__PURE__ */ jsx5(ExpandIcon, {})
1639
+ }
1640
+ ) : null
1641
+ ] })
1642
+ ] }) }),
1643
+ /* @__PURE__ */ jsx5("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ jsxs4("div", { className: "agent-rail__thread", children: [
1644
+ !hasVisitorMessages2 ? /* @__PURE__ */ jsxs4(
1645
+ "section",
1479
1646
  {
1480
- type: "button",
1481
- className: "agent-rail__expand",
1482
- "aria-label": expanded ? "Restore assist panel" : "Expand assist panel",
1483
- onClick: onExpandToggle,
1484
- children: expanded ? /* @__PURE__ */ jsx5(RestoreIcon, {}) : /* @__PURE__ */ jsx5(ExpandIcon, {})
1647
+ className: "agent-rail__welcome",
1648
+ "aria-labelledby": welcomeTitleId,
1649
+ children: [
1650
+ /* @__PURE__ */ jsxs4("span", { className: "agent-rail__welcome-mark", "aria-hidden": "true", children: [
1651
+ brandLabel.slice(0, 1).toUpperCase(),
1652
+ brandLogoUrl ? /* @__PURE__ */ jsx5(
1653
+ "img",
1654
+ {
1655
+ className: "agent-rail__welcome-logo",
1656
+ src: brandLogoUrl,
1657
+ alt: "",
1658
+ onError: (event) => {
1659
+ event.currentTarget.hidden = true;
1660
+ }
1661
+ }
1662
+ ) : null
1663
+ ] }),
1664
+ /* @__PURE__ */ jsxs4("div", { className: "agent-rail__welcome-copy", children: [
1665
+ /* @__PURE__ */ jsx5("h2", { id: welcomeTitleId, children: "What can I help you find?" }),
1666
+ greeting?.role === "agent" ? /* @__PURE__ */ jsx5("p", { children: greeting.text }) : null
1667
+ ] }),
1668
+ showIdleFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx5(
1669
+ FollowUpChips,
1670
+ {
1671
+ suggestions: state.followUps,
1672
+ disabled: isBusy,
1673
+ label: "Start here",
1674
+ onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
1675
+ }
1676
+ ) }) : null
1677
+ ]
1485
1678
  }
1486
- ) : /* @__PURE__ */ jsx5("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" })
1487
- ] }) }),
1488
- /* @__PURE__ */ jsxs4("div", { ref: transcriptRef, className: "agent-rail__transcript", children: [
1489
- state.messages.map((message) => /* @__PURE__ */ jsx5(MessageBubble, { message }, message.id)),
1490
- streamingMessage ? /* @__PURE__ */ jsx5(MessageBubble, { message: streamingMessage }) : null,
1679
+ ) : null,
1680
+ transcriptMessages.map((message) => /* @__PURE__ */ jsx5(MessageBubble, { message }, message.id)),
1491
1681
  showActivity ? /* @__PURE__ */ jsx5(
1492
1682
  AgentActivityBubble,
1493
1683
  {
1684
+ brandLabel,
1685
+ brandLogoUrl,
1494
1686
  failed: state.phase === "error",
1495
1687
  steps: state.toolSteps
1496
1688
  }
1497
1689
  ) : null,
1498
- !expanded && showIdleFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx5(
1499
- FollowUpChips,
1500
- {
1501
- suggestions: state.followUps,
1502
- disabled: isBusy,
1503
- label: "Try asking",
1504
- onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
1505
- }
1506
- ) }) : null,
1507
- state.error ? /* @__PURE__ */ jsx5(
1508
- "p",
1509
- {
1510
- role: "alert",
1511
- style: { fontSize: 13, color: "var(--as-danger)", margin: 0 },
1512
- children: state.error
1513
- }
1514
- ) : null
1515
- ] }),
1516
- expanded ? /* @__PURE__ */ jsxs4("div", { className: "agent-rail__dock-wrap", children: [
1517
- showDockFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__dock-followups", children: /* @__PURE__ */ jsx5(
1518
- FollowUpChips,
1519
- {
1520
- variant: "dock",
1521
- suggestions: state.followUps,
1522
- disabled: isBusy,
1523
- onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
1524
- }
1525
- ) }) : null,
1526
- /* @__PURE__ */ jsx5("div", { className: "agent-rail__dock", children: /* @__PURE__ */ jsx5(
1527
- Composer,
1528
- {
1529
- variant: "dock",
1530
- disabled: isBusy,
1531
- placeholder: composerPlaceholder,
1532
- onSubmit
1533
- }
1534
- ) }),
1535
- /* @__PURE__ */ jsxs4("div", { className: "agent-rail__footer", children: [
1536
- /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1537
- /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1538
- ] })
1539
- ] }) : /* @__PURE__ */ jsxs4("div", { className: "agent-rail__composer-wrap", children: [
1690
+ streamingMessage ? /* @__PURE__ */ jsx5(MessageBubble, { message: streamingMessage }) : null,
1691
+ completedAnswer ? /* @__PURE__ */ jsx5(MessageBubble, { message: completedAnswer }) : null,
1692
+ state.error ? /* @__PURE__ */ jsxs4("section", { className: "agent-rail__error", role: "alert", children: [
1693
+ /* @__PURE__ */ jsxs4("div", { children: [
1694
+ /* @__PURE__ */ jsx5("strong", { children: "Something went wrong" }),
1695
+ /* @__PURE__ */ jsx5("p", { children: state.error })
1696
+ ] }),
1697
+ onRetry ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
1698
+ ] }) : null
1699
+ ] }) }),
1700
+ /* @__PURE__ */ jsxs4("div", { className: "agent-rail__composer-wrap", children: [
1540
1701
  /* @__PURE__ */ jsx5(
1541
1702
  Composer,
1542
1703
  {
1704
+ variant: expanded || mobileFullscreen ? "dock" : "default",
1543
1705
  disabled: isBusy,
1544
1706
  placeholder: composerPlaceholder,
1545
1707
  onSubmit
1546
1708
  }
1547
1709
  ),
1548
- /* @__PURE__ */ jsxs4("div", { className: "agent-rail__footer", children: [
1549
- /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-disclaimer", children: "AI can make mistakes. Check important info." }),
1550
- /* @__PURE__ */ jsx5("p", { className: "agent-rail__footer-note", children: poweredByLabel })
1551
- ] })
1710
+ /* @__PURE__ */ jsx5("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsxs4("p", { children: [
1711
+ /* @__PURE__ */ jsx5("span", { children: "AI can make mistakes." }),
1712
+ /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: " \xB7 " }),
1713
+ /* @__PURE__ */ jsx5("span", { children: poweredByLabel })
1714
+ ] }) })
1552
1715
  ] })
1553
1716
  ]
1554
1717
  }
@@ -1556,7 +1719,7 @@ function AgentRail({
1556
1719
  }
1557
1720
 
1558
1721
  // src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
1559
- import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1722
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1560
1723
  function SparklesIcon() {
1561
1724
  return /* @__PURE__ */ jsxs5(
1562
1725
  "svg",
@@ -1632,7 +1795,12 @@ function AssistEdgeTab({
1632
1795
  label,
1633
1796
  logoUrl,
1634
1797
  brandColor,
1798
+ brandForeground,
1799
+ borderColor,
1635
1800
  fontFamily,
1801
+ mobile = false,
1802
+ surfaceColor,
1803
+ textColor,
1636
1804
  onOpen
1637
1805
  }) {
1638
1806
  const copy = VARIANT_COPY[variant];
@@ -1641,20 +1809,50 @@ function AssistEdgeTab({
1641
1809
  "--tab-along": `${along}%`,
1642
1810
  "--tab-inset": `${inset}px`,
1643
1811
  ...brandColor ? { "--as-brand": brandColor } : {},
1644
- ...fontFamily ? { "--as-font-display": fontFamily } : {}
1812
+ ...brandForeground ? { "--as-visitor-text": brandForeground } : {},
1813
+ ...borderColor ? { "--as-border": borderColor } : {},
1814
+ ...fontFamily ? { "--as-font-display": fontFamily } : {},
1815
+ ...surfaceColor ? { "--as-surface": surfaceColor } : {},
1816
+ ...textColor ? { "--as-text": textColor } : {}
1645
1817
  };
1646
1818
  return /* @__PURE__ */ jsxs5(
1647
1819
  "button",
1648
1820
  {
1649
1821
  type: "button",
1650
- className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${visible ? " is-visible" : ""}`,
1822
+ className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${mobile ? " assist-edge-tab--mobile" : ""}${visible ? " is-visible" : ""}`,
1651
1823
  style,
1652
1824
  "aria-label": `Open ${visibleLabel}`,
1653
1825
  "aria-hidden": !visible,
1654
1826
  tabIndex: visible ? 0 : -1,
1655
1827
  onClick: onOpen,
1656
1828
  children: [
1657
- variant === "outline" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1829
+ mobile ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1830
+ /* @__PURE__ */ jsxs5(
1831
+ "span",
1832
+ {
1833
+ className: "assist-edge-tab__mark assist-edge-tab__mark--mobile",
1834
+ "aria-hidden": "true",
1835
+ children: [
1836
+ visibleLabel.slice(0, 1).toUpperCase(),
1837
+ logoUrl ? /* @__PURE__ */ jsx6(
1838
+ "img",
1839
+ {
1840
+ className: "assist-edge-tab__logo",
1841
+ src: logoUrl,
1842
+ alt: "",
1843
+ onError: (event) => {
1844
+ event.currentTarget.hidden = true;
1845
+ }
1846
+ }
1847
+ ) : null
1848
+ ]
1849
+ }
1850
+ ),
1851
+ /* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__label", children: [
1852
+ "Ask ",
1853
+ visibleLabel
1854
+ ] })
1855
+ ] }) : variant === "outline" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1658
1856
  /* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
1659
1857
  /* @__PURE__ */ jsx6(SparklesIcon, {}),
1660
1858
  logoUrl ? /* @__PURE__ */ jsx6(
@@ -1672,12 +1870,12 @@ function AssistEdgeTab({
1672
1870
  /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__label", children: visibleLabel }),
1673
1871
  /* @__PURE__ */ jsx6(ChevronDownIcon, {})
1674
1872
  ] }) : null,
1675
- variant === "ask" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1873
+ variant === "ask" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1676
1874
  /* @__PURE__ */ jsx6(ChevronLeftIcon, {}),
1677
1875
  /* @__PURE__ */ jsx6("span", { className: "assist-edge-tab__label", children: visibleLabel }),
1678
1876
  /* @__PURE__ */ jsx6(DragDots, {})
1679
1877
  ] }) : null,
1680
- variant === "fill" ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1878
+ variant === "fill" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1681
1879
  /* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
1682
1880
  /* @__PURE__ */ jsx6(SparklesIcon, {}),
1683
1881
  logoUrl ? /* @__PURE__ */ jsx6(
@@ -1844,7 +2042,7 @@ function AgentWidget({
1844
2042
  active: pageShiftActive,
1845
2043
  railSlotRef
1846
2044
  });
1847
- const { state, submit } = useAgentChat({
2045
+ const { state, reset, retry, submit } = useAgentChat({
1848
2046
  customerId,
1849
2047
  getUnpublishedPreviewGrant,
1850
2048
  indexId,
@@ -1887,6 +2085,40 @@ function AgentWidget({
1887
2085
  if (isMobile) setRailCollapsed(false);
1888
2086
  await submit(message);
1889
2087
  }
2088
+ useEffect5(() => {
2089
+ if (railCollapsed) return;
2090
+ const handleKeyDown = (event) => {
2091
+ if (event.key === "Tab" && (isMobile || railExpanded)) {
2092
+ const focusable = railSlotRef.current?.querySelectorAll(
2093
+ 'button:not(:disabled), a[href], textarea:not(:disabled), input:not(:disabled), [tabindex]:not([tabindex="-1"])'
2094
+ );
2095
+ if (!focusable || focusable.length === 0) return;
2096
+ const first = focusable.item(0);
2097
+ const last = focusable.item(focusable.length - 1);
2098
+ const dialog = railSlotRef.current?.querySelector(".agent-rail");
2099
+ if (document.activeElement === dialog) {
2100
+ event.preventDefault();
2101
+ (event.shiftKey ? last : first).focus();
2102
+ } else if (event.shiftKey && document.activeElement === first) {
2103
+ event.preventDefault();
2104
+ last.focus();
2105
+ } else if (!event.shiftKey && document.activeElement === last) {
2106
+ event.preventDefault();
2107
+ first.focus();
2108
+ }
2109
+ return;
2110
+ }
2111
+ if (event.key === "Escape") {
2112
+ if (railExpanded) {
2113
+ setRailExpanded(false);
2114
+ return;
2115
+ }
2116
+ setRailCollapsed(true);
2117
+ }
2118
+ };
2119
+ window.addEventListener("keydown", handleKeyDown);
2120
+ return () => window.removeEventListener("keydown", handleKeyDown);
2121
+ }, [isMobile, railCollapsed, railExpanded]);
1890
2122
  return /* @__PURE__ */ jsxs6("div", { className: "webless-agent-root", children: [
1891
2123
  /* @__PURE__ */ jsxs6(
1892
2124
  "div",
@@ -1918,19 +2150,27 @@ function AgentWidget({
1918
2150
  onClose: isMobile ? () => setRailCollapsed(true) : void 0,
1919
2151
  onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
1920
2152
  onSubmit: handleSubmit,
2153
+ onReset: reset,
2154
+ onRetry: () => void retry(),
1921
2155
  onFollowUpSelect: (label) => void handleSubmit(label)
1922
2156
  }
1923
2157
  )
1924
2158
  }
1925
2159
  ),
1926
- !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx7(
2160
+ !railCollapsed && isMobile || !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx7(
1927
2161
  "button",
1928
2162
  {
1929
2163
  type: "button",
1930
- className: "webless-agent-root__backdrop",
2164
+ className: `webless-agent-root__backdrop${isMobile ? " webless-agent-root__backdrop--mobile" : ""}`,
1931
2165
  tabIndex: -1,
1932
- "aria-label": "Close expanded assist",
1933
- onClick: () => setRailExpanded(false)
2166
+ "aria-label": isMobile ? "Close agent" : "Exit focus view",
2167
+ onClick: () => {
2168
+ if (isMobile) {
2169
+ setRailCollapsed(true);
2170
+ } else {
2171
+ setRailExpanded(false);
2172
+ }
2173
+ }
1934
2174
  }
1935
2175
  ) : null
1936
2176
  ]
@@ -1947,7 +2187,12 @@ function AgentWidget({
1947
2187
  label: agentName,
1948
2188
  logoUrl: branding?.logoUrl,
1949
2189
  brandColor: branding?.colors?.primary,
2190
+ brandForeground: branding?.colors?.primaryForeground,
2191
+ borderColor: branding?.colors?.border,
1950
2192
  fontFamily: branding?.fontFamily,
2193
+ mobile: isMobile,
2194
+ surfaceColor: branding?.colors?.surface,
2195
+ textColor: branding?.colors?.text,
1951
2196
  onOpen: () => setRailCollapsed(false)
1952
2197
  }
1953
2198
  ) : null
@@ -1970,4 +2215,4 @@ export {
1970
2215
  AssistEdgeTab,
1971
2216
  AgentWidget
1972
2217
  };
1973
- //# sourceMappingURL=chunk-APNF27K2.js.map
2218
+ //# sourceMappingURL=chunk-SVWXFDV3.js.map