@webless/agent 0.2.14 → 0.2.15

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/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 import_react5 = require("react");
53
+ var import_react6 = require("react");
54
54
 
55
- // src/react/hooks/useAgentChat.ts
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");
@@ -733,7 +813,7 @@ function useAgentChat({
733
813
  visitorSessionId,
734
814
  storageKeyPrefix
735
815
  }) {
736
- const previewGrantProviderRef = (0, import_react.useRef)(getUnpublishedPreviewGrant);
816
+ const previewGrantProviderRef = (0, import_react2.useRef)(getUnpublishedPreviewGrant);
737
817
  previewGrantProviderRef.current = getUnpublishedPreviewGrant;
738
818
  const resolveUnpublishedPreviewGrant = () => {
739
819
  const provider = previewGrantProviderRef.current;
@@ -746,7 +826,7 @@ function useAgentChat({
746
826
  }
747
827
  return provider();
748
828
  };
749
- const resolvedStorageKeyPrefix = (0, import_react.useMemo)(
829
+ const resolvedStorageKeyPrefix = (0, import_react2.useMemo)(
750
830
  () => storageKeyPrefix?.trim() || buildAgentStorageKeyPrefix({
751
831
  customerId,
752
832
  indexId,
@@ -755,19 +835,19 @@ function useAgentChat({
755
835
  }),
756
836
  [customerId, indexId, runtimeOrigin, storageKeyPrefix, version]
757
837
  );
758
- const visitorId = (0, import_react.useMemo)(
838
+ const visitorId = (0, import_react2.useMemo)(
759
839
  () => visitorSessionId?.trim() || getOrCreateVisitorSessionId({
760
840
  storageKeyPrefix: resolvedStorageKeyPrefix
761
841
  }),
762
842
  [resolvedStorageKeyPrefix, visitorSessionId]
763
843
  );
764
- const [state, setState] = (0, import_react.useState)(
844
+ const [state, setState] = (0, import_react2.useState)(
765
845
  () => stateFromConversation(
766
846
  loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId)
767
847
  )
768
848
  );
769
- const runRef = (0, import_react.useRef)(null);
770
- const clientRef = (0, import_react.useRef)(
849
+ const runRef = (0, import_react2.useRef)(null);
850
+ const clientRef = (0, import_react2.useRef)(
771
851
  createAgentClient({
772
852
  customerId,
773
853
  getUnpublishedPreviewGrant: resolveUnpublishedPreviewGrant,
@@ -779,8 +859,8 @@ function useAgentChat({
779
859
  })
780
860
  );
781
861
  const identityKey = `${customerId ?? ""}|${indexId}|${version ?? "published"}|${runtimeOrigin ?? ""}|${resolvedStorageKeyPrefix}|${visitorId}`;
782
- const identityRef = (0, import_react.useRef)(identityKey);
783
- (0, import_react.useEffect)(() => {
862
+ const identityRef = (0, import_react2.useRef)(identityKey);
863
+ (0, import_react2.useEffect)(() => {
784
864
  if (identityRef.current === identityKey) {
785
865
  return;
786
866
  }
@@ -810,7 +890,7 @@ function useAgentChat({
810
890
  version,
811
891
  visitorId
812
892
  ]);
813
- (0, import_react.useEffect)(() => {
893
+ (0, import_react2.useEffect)(() => {
814
894
  if (!hasVisitorMessages(state.messages)) return;
815
895
  savePersistedAgentConversation(resolvedStorageKeyPrefix, visitorId, {
816
896
  messages: state.messages,
@@ -824,14 +904,14 @@ function useAgentChat({
824
904
  state.streamingText,
825
905
  visitorId
826
906
  ]);
827
- const reset = (0, import_react.useCallback)(() => {
907
+ const reset = (0, import_react2.useCallback)(() => {
828
908
  runRef.current?.abort();
829
909
  runRef.current = null;
830
910
  clientRef.current.reset();
831
911
  clearPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId);
832
912
  setState(INITIAL_STATE);
833
913
  }, [resolvedStorageKeyPrefix, visitorId]);
834
- const runTurn = (0, import_react.useCallback)(
914
+ const runTurn = (0, import_react2.useCallback)(
835
915
  async (input) => {
836
916
  const { controller, initialText = "", resume, visitorText } = input;
837
917
  const { signal } = controller;
@@ -932,7 +1012,7 @@ function useAgentChat({
932
1012
  },
933
1013
  []
934
1014
  );
935
- const submit = (0, import_react.useCallback)(
1015
+ const submit = (0, import_react2.useCallback)(
936
1016
  async (visitorText) => {
937
1017
  if (runRef.current) {
938
1018
  runRef.current.abort();
@@ -962,7 +1042,7 @@ function useAgentChat({
962
1042
  },
963
1043
  [runTurn]
964
1044
  );
965
- (0, import_react.useEffect)(() => {
1045
+ (0, import_react2.useEffect)(() => {
966
1046
  const conversation = loadPersistedAgentConversation(
967
1047
  resolvedStorageKeyPrefix,
968
1048
  visitorId
@@ -985,7 +1065,7 @@ function useAgentChat({
985
1065
  controller.abort();
986
1066
  };
987
1067
  }, [identityKey, resolvedStorageKeyPrefix, runTurn, visitorId]);
988
- (0, import_react.useEffect)(() => {
1068
+ (0, import_react2.useEffect)(() => {
989
1069
  return () => {
990
1070
  runRef.current?.abort();
991
1071
  runRef.current = null;
@@ -1014,12 +1094,12 @@ function isAgentBusy(phase) {
1014
1094
  }
1015
1095
 
1016
1096
  // src/react/hooks/useIsMobile.ts
1017
- var import_react2 = require("react");
1097
+ var import_react3 = require("react");
1018
1098
  function useIsMobile(breakpoint = 767) {
1019
- const [isMobile, setIsMobile] = (0, import_react2.useState)(
1099
+ const [isMobile, setIsMobile] = (0, import_react3.useState)(
1020
1100
  () => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
1021
1101
  );
1022
- (0, import_react2.useEffect)(() => {
1102
+ (0, import_react3.useEffect)(() => {
1023
1103
  const media = window.matchMedia(`(max-width: ${breakpoint}px)`);
1024
1104
  const onChange = () => setIsMobile(media.matches);
1025
1105
  onChange();
@@ -1047,7 +1127,7 @@ function normalizeAgentPlacement(placement) {
1047
1127
  }
1048
1128
 
1049
1129
  // src/react/components/AgentRail/AgentRail.tsx
1050
- var import_react4 = require("react");
1130
+ var import_react5 = require("react");
1051
1131
 
1052
1132
  // src/react/components/ToolTimeline/ToolTimeline.tsx
1053
1133
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1118,7 +1198,7 @@ function AgentActivityBubble({
1118
1198
  }
1119
1199
 
1120
1200
  // src/react/components/Composer/Composer.tsx
1121
- var import_react3 = require("react");
1201
+ var import_react4 = require("react");
1122
1202
  var import_jsx_runtime3 = require("react/jsx-runtime");
1123
1203
  function SendIcon() {
1124
1204
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
@@ -1129,8 +1209,8 @@ function Composer({
1129
1209
  variant = "default",
1130
1210
  onSubmit
1131
1211
  }) {
1132
- const [value, setValue] = (0, import_react3.useState)("");
1133
- const inputRef = (0, import_react3.useRef)(null);
1212
+ const [value, setValue] = (0, import_react4.useState)("");
1213
+ const inputRef = (0, import_react4.useRef)(null);
1134
1214
  function submitCurrent() {
1135
1215
  const trimmed = value.trim();
1136
1216
  if (!trimmed || disabled) return;
@@ -1282,7 +1362,7 @@ function AgentRail({
1282
1362
  onSubmit,
1283
1363
  onFollowUpSelect
1284
1364
  }) {
1285
- const transcriptRef = (0, import_react4.useRef)(null);
1365
+ const transcriptRef = (0, import_react5.useRef)(null);
1286
1366
  const railStyle = theme?.railMaxWidth ? { ["--rail-width"]: theme.railMaxWidth, ["--as-rail-max-width"]: theme.railMaxWidth } : void 0;
1287
1367
  const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
1288
1368
  const showActivity = state.toolSteps.length > 0 && (state.phase === "thinking" || state.phase === "running-tools");
@@ -1296,7 +1376,7 @@ function AgentRail({
1296
1376
  streaming: true,
1297
1377
  text: state.streamingText
1298
1378
  } : null;
1299
- (0, import_react4.useEffect)(() => {
1379
+ (0, import_react5.useEffect)(() => {
1300
1380
  const node = transcriptRef.current;
1301
1381
  if (!node) return;
1302
1382
  node.scrollTop = node.scrollHeight;
@@ -1465,12 +1545,24 @@ function AgentWidget({
1465
1545
  runtimeOrigin,
1466
1546
  placement: placementInput,
1467
1547
  defaultCollapsed = true,
1548
+ pageShift = true,
1468
1549
  registerPanelController = false
1469
1550
  }) {
1470
1551
  const isMobile = useIsMobile();
1471
1552
  const placement = normalizeAgentPlacement(placementInput);
1472
- const [railCollapsed, setRailCollapsed] = (0, import_react5.useState)(defaultCollapsed);
1473
- const [railExpanded, setRailExpanded] = (0, import_react5.useState)(false);
1553
+ const railSlotRef = (0, import_react6.useRef)(null);
1554
+ const [railCollapsed, setRailCollapsed] = (0, import_react6.useState)(defaultCollapsed);
1555
+ const [railExpanded, setRailExpanded] = (0, import_react6.useState)(false);
1556
+ const pageShiftActive = shouldApplyPageShift({
1557
+ pageShift,
1558
+ isMobile,
1559
+ railCollapsed,
1560
+ railExpanded
1561
+ });
1562
+ usePageShift({
1563
+ active: pageShiftActive,
1564
+ railSlotRef
1565
+ });
1474
1566
  const { state, submit } = useAgentChat({
1475
1567
  customerId,
1476
1568
  getUnpublishedPreviewGrant,
@@ -1479,7 +1571,7 @@ function AgentWidget({
1479
1571
  runtimeOrigin
1480
1572
  });
1481
1573
  const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
1482
- (0, import_react5.useEffect)(() => {
1574
+ (0, import_react6.useEffect)(() => {
1483
1575
  if (!registerPanelController) return;
1484
1576
  registerAgentPanelController(customerId, {
1485
1577
  open: () => setRailCollapsed(false),
@@ -1502,6 +1594,7 @@ function AgentWidget({
1502
1594
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1503
1595
  "div",
1504
1596
  {
1597
+ ref: railSlotRef,
1505
1598
  className: "webless-agent-root__rail-slot",
1506
1599
  inert: railCollapsed || void 0,
1507
1600
  "aria-hidden": railCollapsed,
@@ -1559,6 +1652,7 @@ function AgentWidget2({ manifest }) {
1559
1652
  version: manifest.version,
1560
1653
  runtimeOrigin: manifest.runtimeOrigin,
1561
1654
  placement: manifest.placement,
1655
+ pageShift: manifest.pageShift,
1562
1656
  defaultCollapsed: true,
1563
1657
  registerPanelController: true
1564
1658
  }
@@ -1593,7 +1687,8 @@ function normalizeAgentTagManifest(manifest) {
1593
1687
  selector: manifest.mount?.selector?.trim(),
1594
1688
  strategy: manifest.mount?.strategy ?? "body"
1595
1689
  },
1596
- placement: normalizeAgentPlacement(manifest.placement)
1690
+ placement: normalizeAgentPlacement(manifest.placement),
1691
+ pageShift: manifest.pageShift ?? true
1597
1692
  };
1598
1693
  }
1599
1694