@flamingo-stack/openframe-frontend-core 0.0.444 → 0.0.445-snapshot.20260717185124
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/{chunk-BYTJNRJW.cjs → chunk-3AFV2YIC.cjs} +40 -40
- package/dist/{chunk-BYTJNRJW.cjs.map → chunk-3AFV2YIC.cjs.map} +1 -1
- package/dist/{chunk-MG4AMIFX.js → chunk-5NYXGWBN.js} +2 -2
- package/dist/{chunk-Q6XOEVPH.cjs → chunk-5WX2V6CY.cjs} +12 -12
- package/dist/{chunk-Q6XOEVPH.cjs.map → chunk-5WX2V6CY.cjs.map} +1 -1
- package/dist/{chunk-CE3AITV2.js → chunk-5YQSRQHP.js} +6 -6
- package/dist/{chunk-OXZLBIR7.cjs → chunk-6XZNIPXP.cjs} +18 -18
- package/dist/{chunk-OXZLBIR7.cjs.map → chunk-6XZNIPXP.cjs.map} +1 -1
- package/dist/{chunk-VI2QQIGR.cjs → chunk-7IC2QCOL.cjs} +73 -73
- package/dist/{chunk-VI2QQIGR.cjs.map → chunk-7IC2QCOL.cjs.map} +1 -1
- package/dist/{chunk-4R3SVOKH.cjs → chunk-BAUWT7PV.cjs} +1101 -700
- package/dist/chunk-BAUWT7PV.cjs.map +1 -0
- package/dist/{chunk-37ZZQXHK.js → chunk-BNYI2FVM.js} +4 -4
- package/dist/{chunk-2PLNDTRG.cjs → chunk-DH3DUY6Q.cjs} +32 -32
- package/dist/{chunk-2PLNDTRG.cjs.map → chunk-DH3DUY6Q.cjs.map} +1 -1
- package/dist/{chunk-FQASXKBK.js → chunk-G2KXNMFQ.js} +2 -2
- package/dist/{chunk-PMTR5W5G.js → chunk-GTHA2SYB.js} +5 -5
- package/dist/{chunk-LCJGOV6P.js → chunk-I7IOEXRJ.js} +2 -2
- package/dist/{chunk-H7H3AFLF.js → chunk-K6JIBV3X.js} +2 -2
- package/dist/{chunk-YP7VJPCJ.cjs → chunk-L276GOMD.cjs} +40 -40
- package/dist/{chunk-YP7VJPCJ.cjs.map → chunk-L276GOMD.cjs.map} +1 -1
- package/dist/{chunk-NDWIFCLS.js → chunk-MAB4TQCO.js} +731 -330
- package/dist/{chunk-NDWIFCLS.js.map → chunk-MAB4TQCO.js.map} +1 -1
- package/dist/{chunk-ABIRMYG5.js → chunk-MR7BMJHI.js} +6 -6
- package/dist/{chunk-FO4CI4R5.cjs → chunk-MS5CEBBQ.cjs} +5 -5
- package/dist/{chunk-FO4CI4R5.cjs.map → chunk-MS5CEBBQ.cjs.map} +1 -1
- package/dist/{chunk-RALJEQWM.cjs → chunk-N3Y6JYH5.cjs} +15 -15
- package/dist/{chunk-RALJEQWM.cjs.map → chunk-N3Y6JYH5.cjs.map} +1 -1
- package/dist/{chunk-DCDB3SM4.js → chunk-N4CCB33C.js} +3 -3
- package/dist/{chunk-WXU6A6CA.cjs → chunk-NQLY27GH.cjs} +73 -73
- package/dist/{chunk-WXU6A6CA.cjs.map → chunk-NQLY27GH.cjs.map} +1 -1
- package/dist/{chunk-PHWQLKVE.js → chunk-P47NN7RY.js} +29 -31
- package/dist/chunk-P47NN7RY.js.map +1 -0
- package/dist/{chunk-2CJ734N2.cjs → chunk-PTT4J5GF.cjs} +3 -3
- package/dist/{chunk-2CJ734N2.cjs.map → chunk-PTT4J5GF.cjs.map} +1 -1
- package/dist/{chunk-DSW6FIEF.cjs → chunk-SA7AHDS6.cjs} +7 -7
- package/dist/{chunk-DSW6FIEF.cjs.map → chunk-SA7AHDS6.cjs.map} +1 -1
- package/dist/{chunk-F2XHBAHT.js → chunk-SAV4U37G.js} +2 -2
- package/dist/{chunk-3SCNEGL2.js → chunk-SCKAD2MY.js} +5 -5
- package/dist/{chunk-7CZ4MJSI.cjs → chunk-VIJARDBM.cjs} +3 -3
- package/dist/{chunk-7CZ4MJSI.cjs.map → chunk-VIJARDBM.cjs.map} +1 -1
- package/dist/{chunk-PXXS27EE.cjs → chunk-W24U7ZUV.cjs} +40 -42
- package/dist/chunk-W24U7ZUV.cjs.map +1 -0
- package/dist/{chunk-U7U2CZBZ.js → chunk-XB6D7B3I.js} +3 -3
- package/dist/{chunk-DTMJWBDQ.js → chunk-YLMD4UFA.js} +3 -3
- package/dist/{chunk-F6NMMPDL.cjs → chunk-ZKYEMGMD.cjs} +29 -29
- package/dist/{chunk-F6NMMPDL.cjs.map → chunk-ZKYEMGMD.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +10 -10
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/hooks/use-chunk-catchup.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +44 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-dialog-subscription.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +10 -4
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +9 -3
- package/dist/components/chat/utils/message-segment-accumulator.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +4 -4
- package/dist/components/features/index.js +3 -3
- package/dist/components/features/policy-configuration-panel.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/index.cjs +142 -136
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +18 -12
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +8 -8
- package/dist/components/onboarding-guides/index.js +7 -7
- package/dist/components/related-content/index.cjs +6 -6
- package/dist/components/related-content/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +10 -4
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +9 -3
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +10 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -3
- package/dist/nats/index.cjs +2 -2
- package/dist/nats/index.js +1 -1
- package/dist/nats/shared-connection.d.ts +6 -0
- package/dist/nats/shared-connection.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/hooks/__tests__/nats-adapter-message-updaters.test.ts +270 -0
- package/src/components/chat/hooks/use-chunk-catchup.ts +212 -57
- package/src/components/chat/hooks/use-jetstream-dialog-subscription.ts +12 -8
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +574 -9
- package/src/components/chat/hooks/use-nats-dialog-subscription.ts +12 -6
- package/src/components/chat/hooks/use-realtime-chunk-processor.ts +40 -3
- package/src/components/chat/utils/__tests__/process-historical-messages-approvals.test.ts +62 -0
- package/src/components/chat/utils/message-segment-accumulator.ts +6 -0
- package/src/components/chat/utils/process-historical-messages.ts +25 -3
- package/src/components/features/policy-configuration-panel.tsx +34 -49
- package/src/nats/shared-connection.ts +42 -29
- package/src/stories/PolicyConfigurationPanel.stories.tsx +8 -6
- package/dist/chunk-4R3SVOKH.cjs.map +0 -1
- package/dist/chunk-PHWQLKVE.js.map +0 -1
- package/dist/chunk-PXXS27EE.cjs.map +0 -1
- /package/dist/{chunk-MG4AMIFX.js.map → chunk-5NYXGWBN.js.map} +0 -0
- /package/dist/{chunk-CE3AITV2.js.map → chunk-5YQSRQHP.js.map} +0 -0
- /package/dist/{chunk-37ZZQXHK.js.map → chunk-BNYI2FVM.js.map} +0 -0
- /package/dist/{chunk-FQASXKBK.js.map → chunk-G2KXNMFQ.js.map} +0 -0
- /package/dist/{chunk-PMTR5W5G.js.map → chunk-GTHA2SYB.js.map} +0 -0
- /package/dist/{chunk-LCJGOV6P.js.map → chunk-I7IOEXRJ.js.map} +0 -0
- /package/dist/{chunk-H7H3AFLF.js.map → chunk-K6JIBV3X.js.map} +0 -0
- /package/dist/{chunk-ABIRMYG5.js.map → chunk-MR7BMJHI.js.map} +0 -0
- /package/dist/{chunk-DCDB3SM4.js.map → chunk-N4CCB33C.js.map} +0 -0
- /package/dist/{chunk-F2XHBAHT.js.map → chunk-SAV4U37G.js.map} +0 -0
- /package/dist/{chunk-3SCNEGL2.js.map → chunk-SCKAD2MY.js.map} +0 -0
- /package/dist/{chunk-U7U2CZBZ.js.map → chunk-XB6D7B3I.js.map} +0 -0
- /package/dist/{chunk-DTMJWBDQ.js.map → chunk-YLMD4UFA.js.map} +0 -0
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
useOgPlaceholderUrl,
|
|
28
28
|
useOnboardingState,
|
|
29
29
|
useToast
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-5NYXGWBN.js";
|
|
31
31
|
import {
|
|
32
32
|
AlertCircleIcon,
|
|
33
33
|
AnthropicLogoGreyIcon,
|
|
@@ -249,7 +249,7 @@ import {
|
|
|
249
249
|
acquireClient,
|
|
250
250
|
releaseClient,
|
|
251
251
|
startConnectionLifecycle
|
|
252
|
-
} from "./chunk-
|
|
252
|
+
} from "./chunk-P47NN7RY.js";
|
|
253
253
|
import {
|
|
254
254
|
__esm
|
|
255
255
|
} from "./chunk-GGWZFCYS.js";
|
|
@@ -31939,23 +31939,22 @@ function ViewToggle({
|
|
|
31939
31939
|
|
|
31940
31940
|
// src/components/features/policy-configuration-panel.tsx
|
|
31941
31941
|
init_cn();
|
|
31942
|
-
import {
|
|
31942
|
+
import { useEffect as useEffect52, useState as useState71 } from "react";
|
|
31943
31943
|
import { ChevronDown as ChevronDown8, Shield as Shield2 } from "lucide-react";
|
|
31944
31944
|
init_button2();
|
|
31945
31945
|
import { Fragment as Fragment43, jsx as jsx253, jsxs as jsxs197 } from "react/jsx-runtime";
|
|
31946
|
-
var
|
|
31947
|
-
|
|
31948
|
-
|
|
31949
|
-
|
|
31950
|
-
|
|
31951
|
-
];
|
|
31952
|
-
var getApprovalLevelLabel = (level, editMode = false) => {
|
|
31953
|
-
if (!level) {
|
|
31954
|
-
return editMode ? "Set Global Permission" : "";
|
|
31955
|
-
}
|
|
31956
|
-
const option = approvalLevelOptions.find((opt) => opt.value === level);
|
|
31957
|
-
return option?.label || level;
|
|
31946
|
+
var approvalLevelLabels = {
|
|
31947
|
+
ALLOW: "Allow",
|
|
31948
|
+
ASK_USER: "Ask User",
|
|
31949
|
+
ASK_TECHNICIAN: "Ask Technician",
|
|
31950
|
+
DENY: "Restrict"
|
|
31958
31951
|
};
|
|
31952
|
+
var approvalLevelOptions = Object.keys(approvalLevelLabels).map(
|
|
31953
|
+
(value) => ({ value, label: approvalLevelLabels[value] })
|
|
31954
|
+
);
|
|
31955
|
+
var POLICY_LEVEL_WIDTH = "w-[180px]";
|
|
31956
|
+
var CATEGORY_LEVEL_WIDTH = "w-[256px]";
|
|
31957
|
+
var getApprovalLevelLabel = (level) => approvalLevelLabels[level] ?? level;
|
|
31959
31958
|
var ApprovalLevelDropdown = ({ value, onChange, allowClear = false, triggerClassName, contentClassName }) => /* @__PURE__ */ jsxs197(DropdownMenu, { children: [
|
|
31960
31959
|
/* @__PURE__ */ jsx253(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx253(
|
|
31961
31960
|
Button,
|
|
@@ -31967,7 +31966,7 @@ var ApprovalLevelDropdown = ({ value, onChange, allowClear = false, triggerClass
|
|
|
31967
31966
|
value ? "text-ods-text-primary" : "text-ods-text-secondary",
|
|
31968
31967
|
triggerClassName
|
|
31969
31968
|
),
|
|
31970
|
-
children: getApprovalLevelLabel(value
|
|
31969
|
+
children: value ? getApprovalLevelLabel(value) : "Set Global Permission"
|
|
31971
31970
|
}
|
|
31972
31971
|
) }),
|
|
31973
31972
|
/* @__PURE__ */ jsxs197(DropdownMenuContent, { align: "end", className: contentClassName, children: [
|
|
@@ -31998,7 +31997,7 @@ var PolicyRow = ({ policy, categoryId, editMode, onPermissionChange }) => {
|
|
|
31998
31997
|
value: policy.approvalLevel,
|
|
31999
31998
|
onChange: handleChange,
|
|
32000
31999
|
triggerClassName: "w-full",
|
|
32001
|
-
contentClassName:
|
|
32000
|
+
contentClassName: POLICY_LEVEL_WIDTH
|
|
32002
32001
|
}
|
|
32003
32002
|
) }) : policy.approvalLevel ? /* @__PURE__ */ jsx253("span", { className: "md:hidden text-h4 text-ods-text-primary", children: getApprovalLevelLabel(policy.approvalLevel) }) : null
|
|
32004
32003
|
] }),
|
|
@@ -32007,23 +32006,12 @@ var PolicyRow = ({ policy, categoryId, editMode, onPermissionChange }) => {
|
|
|
32007
32006
|
{
|
|
32008
32007
|
value: policy.approvalLevel,
|
|
32009
32008
|
onChange: handleChange,
|
|
32010
|
-
triggerClassName:
|
|
32011
|
-
contentClassName:
|
|
32009
|
+
triggerClassName: POLICY_LEVEL_WIDTH,
|
|
32010
|
+
contentClassName: POLICY_LEVEL_WIDTH
|
|
32012
32011
|
}
|
|
32013
|
-
) : /* @__PURE__ */ jsx253("div", { className: "px-[var(--spacing-system-sf)] py-[var(--spacing-system-xsf)]
|
|
32012
|
+
) : /* @__PURE__ */ jsx253("div", { className: cn("px-[var(--spacing-system-sf)] py-[var(--spacing-system-xsf)]", POLICY_LEVEL_WIDTH), children: policy.approvalLevel && /* @__PURE__ */ jsx253("span", { className: "text-h4 text-ods-text-primary", children: getApprovalLevelLabel(policy.approvalLevel) }) }) })
|
|
32014
32013
|
] });
|
|
32015
32014
|
};
|
|
32016
|
-
var useAnimatedHeight = (isExpanded) => {
|
|
32017
|
-
const [height, setHeight] = useState71(0);
|
|
32018
|
-
const contentRef = useRef37(null);
|
|
32019
|
-
useEffect52(() => {
|
|
32020
|
-
if (contentRef.current) {
|
|
32021
|
-
const contentHeight = contentRef.current.scrollHeight;
|
|
32022
|
-
setHeight(isExpanded ? contentHeight : 0);
|
|
32023
|
-
}
|
|
32024
|
-
}, [isExpanded]);
|
|
32025
|
-
return { contentRef, height };
|
|
32026
|
-
};
|
|
32027
32015
|
var CategorySection = ({
|
|
32028
32016
|
category,
|
|
32029
32017
|
editMode,
|
|
@@ -32033,7 +32021,7 @@ var CategorySection = ({
|
|
|
32033
32021
|
onBulkLevelChange,
|
|
32034
32022
|
onPolicyPermissionChange
|
|
32035
32023
|
}) => {
|
|
32036
|
-
const {
|
|
32024
|
+
const { innerRef, containerStyle } = useCollapsible({ expanded: isExpanded, durationMs: 300 });
|
|
32037
32025
|
const handleBulkChange = (level) => onBulkLevelChange(category.id, level);
|
|
32038
32026
|
return /* @__PURE__ */ jsxs197(Fragment43, { children: [
|
|
32039
32027
|
/* @__PURE__ */ jsxs197(
|
|
@@ -32056,7 +32044,7 @@ var CategorySection = ({
|
|
|
32056
32044
|
onChange: handleBulkChange,
|
|
32057
32045
|
allowClear: true,
|
|
32058
32046
|
triggerClassName: "w-full",
|
|
32059
|
-
contentClassName:
|
|
32047
|
+
contentClassName: CATEGORY_LEVEL_WIDTH
|
|
32060
32048
|
}
|
|
32061
32049
|
) })
|
|
32062
32050
|
] }),
|
|
@@ -32066,16 +32054,10 @@ var CategorySection = ({
|
|
|
32066
32054
|
value: bulkLevel,
|
|
32067
32055
|
onChange: handleBulkChange,
|
|
32068
32056
|
allowClear: true,
|
|
32069
|
-
triggerClassName:
|
|
32070
|
-
contentClassName:
|
|
32057
|
+
triggerClassName: CATEGORY_LEVEL_WIDTH,
|
|
32058
|
+
contentClassName: CATEGORY_LEVEL_WIDTH
|
|
32071
32059
|
}
|
|
32072
|
-
) }) : /* @__PURE__ */ jsx253(
|
|
32073
|
-
"div",
|
|
32074
|
-
{
|
|
32075
|
-
className: "hidden md:block px-[var(--spacing-system-sf)] py-[var(--spacing-system-xsf)] w-[256px] shrink-0",
|
|
32076
|
-
onClick: (e) => e.stopPropagation()
|
|
32077
|
-
}
|
|
32078
|
-
),
|
|
32060
|
+
) }) : /* @__PURE__ */ jsx253("div", { className: cn("hidden md:block px-[var(--spacing-system-sf)] py-[var(--spacing-system-xsf)] shrink-0", CATEGORY_LEVEL_WIDTH) }),
|
|
32079
32061
|
/* @__PURE__ */ jsx253(
|
|
32080
32062
|
Button,
|
|
32081
32063
|
{
|
|
@@ -32104,16 +32086,15 @@ var CategorySection = ({
|
|
|
32104
32086
|
/* @__PURE__ */ jsx253(
|
|
32105
32087
|
"div",
|
|
32106
32088
|
{
|
|
32107
|
-
ref: contentRef,
|
|
32108
32089
|
style: {
|
|
32109
|
-
|
|
32110
|
-
transition:
|
|
32090
|
+
...containerStyle,
|
|
32091
|
+
transition: `${containerStyle.transition}, opacity 300ms ease-in-out, visibility 300ms`,
|
|
32092
|
+
// visibility drops collapsed content from the tab order and a11y
|
|
32093
|
+
// tree; its discrete transition delays hiding until the fade ends.
|
|
32094
|
+
visibility: isExpanded ? "visible" : "hidden"
|
|
32111
32095
|
},
|
|
32112
|
-
className:
|
|
32113
|
-
|
|
32114
|
-
isExpanded ? "opacity-100" : "opacity-0"
|
|
32115
|
-
),
|
|
32116
|
-
children: /* @__PURE__ */ jsx253("div", { className: "px-[var(--spacing-system-mf)] pb-[var(--spacing-system-mf)] pt-0", children: /* @__PURE__ */ jsx253("div", { className: "border border-ods-border rounded-md overflow-hidden", children: category.policies.map((policy) => /* @__PURE__ */ jsx253(
|
|
32096
|
+
className: isExpanded ? "opacity-100" : "opacity-0",
|
|
32097
|
+
children: /* @__PURE__ */ jsx253("div", { ref: innerRef, className: "px-[var(--spacing-system-mf)] pb-[var(--spacing-system-mf)] pt-0", children: /* @__PURE__ */ jsx253("div", { className: "border border-ods-border rounded-md overflow-hidden", children: category.policies.map((policy) => /* @__PURE__ */ jsx253(
|
|
32117
32098
|
PolicyRow,
|
|
32118
32099
|
{
|
|
32119
32100
|
policy,
|
|
@@ -32176,7 +32157,7 @@ PolicyConfigurationPanel.displayName = "PolicyConfigurationPanel";
|
|
|
32176
32157
|
init_button2();
|
|
32177
32158
|
|
|
32178
32159
|
// src/components/ui/phone-input.tsx
|
|
32179
|
-
import { useCallback as useCallback28, useEffect as useEffect53, useMemo as useMemo27, useRef as
|
|
32160
|
+
import { useCallback as useCallback28, useEffect as useEffect53, useMemo as useMemo27, useRef as useRef37, useState as useState72 } from "react";
|
|
32180
32161
|
import { jsx as jsx254, jsxs as jsxs198 } from "react/jsx-runtime";
|
|
32181
32162
|
function PhoneInput({
|
|
32182
32163
|
value,
|
|
@@ -32194,7 +32175,7 @@ function PhoneInput({
|
|
|
32194
32175
|
[countryCode, priority, others]
|
|
32195
32176
|
);
|
|
32196
32177
|
const [isInvalid, setIsInvalid] = useState72(false);
|
|
32197
|
-
const debounceRef =
|
|
32178
|
+
const debounceRef = useRef37(null);
|
|
32198
32179
|
const digitCount = useCallback28((val) => val.replace(/[^0-9]/g, "").length, []);
|
|
32199
32180
|
const runValidation = useCallback28((phone) => {
|
|
32200
32181
|
if (!phone || digitCount(phone) === 0) {
|
|
@@ -32700,7 +32681,7 @@ function useOptionalNotifications() {
|
|
|
32700
32681
|
}
|
|
32701
32682
|
|
|
32702
32683
|
// src/components/features/notifications/notification-drawer.tsx
|
|
32703
|
-
import { useEffect as useEffect58, useRef as
|
|
32684
|
+
import { useEffect as useEffect58, useRef as useRef40 } from "react";
|
|
32704
32685
|
|
|
32705
32686
|
// src/components/navigation/app-layout-context.ts
|
|
32706
32687
|
import { createContext as createContext8, useContext as useContext8 } from "react";
|
|
@@ -33468,9 +33449,9 @@ function DrawerScrollList({
|
|
|
33468
33449
|
loadMoreRootMargin,
|
|
33469
33450
|
renderTile
|
|
33470
33451
|
}) {
|
|
33471
|
-
const scrollRef =
|
|
33472
|
-
const sentinelRef =
|
|
33473
|
-
const loadMoreRef =
|
|
33452
|
+
const scrollRef = useRef40(null);
|
|
33453
|
+
const sentinelRef = useRef40(null);
|
|
33454
|
+
const loadMoreRef = useRef40(loadMore);
|
|
33474
33455
|
loadMoreRef.current = loadMore;
|
|
33475
33456
|
useEffect58(() => {
|
|
33476
33457
|
if (!loadMore || !hasMore || isLoadingMore) return;
|
|
@@ -34339,7 +34320,7 @@ function LastEntryRow({ entry, onClick }) {
|
|
|
34339
34320
|
// src/components/features/time-tracker/time-tracker-header-button.tsx
|
|
34340
34321
|
init_cn();
|
|
34341
34322
|
import * as PopoverPrimitive5 from "@radix-ui/react-popover";
|
|
34342
|
-
import { useEffect as useEffect61, useRef as
|
|
34323
|
+
import { useEffect as useEffect61, useRef as useRef41 } from "react";
|
|
34343
34324
|
|
|
34344
34325
|
// src/components/navigation/header-button.tsx
|
|
34345
34326
|
init_cn();
|
|
@@ -34378,11 +34359,11 @@ function TimeTrackerHeaderButton({ className, disabled }) {
|
|
|
34378
34359
|
const layoutContainer = useAppLayoutDrawerContainer();
|
|
34379
34360
|
const coordination = useAppLayoutDrawerCoordination();
|
|
34380
34361
|
const isOpen = ctx?.isOpen ?? false;
|
|
34381
|
-
const isOpenRef =
|
|
34362
|
+
const isOpenRef = useRef41(isOpen);
|
|
34382
34363
|
isOpenRef.current = isOpen;
|
|
34383
|
-
const closeRef =
|
|
34364
|
+
const closeRef = useRef41(ctx?.close);
|
|
34384
34365
|
closeRef.current = ctx?.close;
|
|
34385
|
-
const selfHandleRef =
|
|
34366
|
+
const selfHandleRef = useRef41(null);
|
|
34386
34367
|
if (!selfHandleRef.current) {
|
|
34387
34368
|
selfHandleRef.current = {
|
|
34388
34369
|
close: () => {
|
|
@@ -35407,18 +35388,18 @@ function SortableRow({
|
|
|
35407
35388
|
|
|
35408
35389
|
// src/components/navigation/header.tsx
|
|
35409
35390
|
init_next_link();
|
|
35410
|
-
import React108, { useEffect as useEffect64, useRef as
|
|
35391
|
+
import React108, { useEffect as useEffect64, useRef as useRef45, useState as useState84 } from "react";
|
|
35411
35392
|
init_button2();
|
|
35412
35393
|
|
|
35413
35394
|
// src/components/navigation/mobile-nav-panel.tsx
|
|
35414
|
-
import { useRef as
|
|
35395
|
+
import { useRef as useRef44 } from "react";
|
|
35415
35396
|
import { usePreventScroll as usePreventScroll3 } from "@react-aria/overlays";
|
|
35416
35397
|
init_button2();
|
|
35417
35398
|
import { X as X10 } from "lucide-react";
|
|
35418
35399
|
import { Fragment as Fragment51, jsx as jsx273, jsxs as jsxs212 } from "react/jsx-runtime";
|
|
35419
35400
|
var MOBILE_NAV_PANEL_ID = "mobile-nav-panel";
|
|
35420
35401
|
function MobileNavPanel({ isOpen, config }) {
|
|
35421
|
-
const panelRef =
|
|
35402
|
+
const panelRef = useRef44(null);
|
|
35422
35403
|
usePreventScroll3({ isDisabled: !isOpen });
|
|
35423
35404
|
useFocusTrap(panelRef, isOpen, { onEscape: config.onClose });
|
|
35424
35405
|
const headerHeight = useHeaderHeight(64, { enabled: isOpen });
|
|
@@ -35579,8 +35560,8 @@ function Header2({ config, platform }) {
|
|
|
35579
35560
|
const [show, setShow] = useState84(true);
|
|
35580
35561
|
const [lastScrollY, setLastScrollY] = useState84(0);
|
|
35581
35562
|
const [openDropdowns, setOpenDropdowns] = useState84({});
|
|
35582
|
-
const dropdownRefs =
|
|
35583
|
-
const triggerRefs =
|
|
35563
|
+
const dropdownRefs = useRef45({});
|
|
35564
|
+
const triggerRefs = useRef45({});
|
|
35584
35565
|
useEffect64(() => {
|
|
35585
35566
|
const handleClickOutside = (event) => {
|
|
35586
35567
|
const target = event.target;
|
|
@@ -35906,7 +35887,7 @@ function ClientOnlyHeader({ config, skeleton }) {
|
|
|
35906
35887
|
}
|
|
35907
35888
|
|
|
35908
35889
|
// src/components/navigation/sliding-sidebar.tsx
|
|
35909
|
-
import { useState as useState86, useEffect as useEffect66, useRef as
|
|
35890
|
+
import { useState as useState86, useEffect as useEffect66, useRef as useRef46 } from "react";
|
|
35910
35891
|
import { motion as motion2, AnimatePresence, useReducedMotion } from "framer-motion";
|
|
35911
35892
|
import { usePreventScroll as usePreventScroll4 } from "@react-aria/overlays";
|
|
35912
35893
|
init_button2();
|
|
@@ -35915,7 +35896,7 @@ function SlidingSidebar({ config }) {
|
|
|
35915
35896
|
const [expandedItems, setExpandedItems] = useState86(/* @__PURE__ */ new Set());
|
|
35916
35897
|
const [mounted, setMounted] = useState86(false);
|
|
35917
35898
|
const headerHeight = useHeaderHeight();
|
|
35918
|
-
const asideRef =
|
|
35899
|
+
const asideRef = useRef46(null);
|
|
35919
35900
|
const prefersReducedMotion2 = useReducedMotion();
|
|
35920
35901
|
usePreventScroll4({ isDisabled: !config.isOpen });
|
|
35921
35902
|
useFocusTrap(asideRef, config.isOpen, { onEscape: config.onClose, contain: false });
|
|
@@ -36087,7 +36068,7 @@ function SlidingSidebar({ config }) {
|
|
|
36087
36068
|
}
|
|
36088
36069
|
|
|
36089
36070
|
// src/components/navigation/sticky-section-nav.tsx
|
|
36090
|
-
import { useEffect as useEffect67, useState as useState87, useCallback as useCallback35, useRef as
|
|
36071
|
+
import { useEffect as useEffect67, useState as useState87, useCallback as useCallback35, useRef as useRef47 } from "react";
|
|
36091
36072
|
import { jsx as jsx279, jsxs as jsxs217 } from "react/jsx-runtime";
|
|
36092
36073
|
function StickySectionNav({
|
|
36093
36074
|
sections,
|
|
@@ -36149,7 +36130,7 @@ function StickySectionNav({
|
|
|
36149
36130
|
}
|
|
36150
36131
|
function useSectionNavigation(sections, options) {
|
|
36151
36132
|
const [activeSection, setActiveSection] = useState87(sections[0]?.id || "");
|
|
36152
|
-
const isScrollingFromClick =
|
|
36133
|
+
const isScrollingFromClick = useRef47(false);
|
|
36153
36134
|
const { offset: offset2 = 100 } = options || {};
|
|
36154
36135
|
const handleSectionClick = useCallback35((sectionId) => {
|
|
36155
36136
|
const targetElement = document.getElementById(sectionId);
|
|
@@ -36849,10 +36830,10 @@ function NotificationsHeaderButton({
|
|
|
36849
36830
|
}
|
|
36850
36831
|
|
|
36851
36832
|
// src/components/navigation/app-layout.tsx
|
|
36852
|
-
import { Suspense as Suspense2, useCallback as useCallback38, useMemo as useMemo35, useRef as
|
|
36833
|
+
import { Suspense as Suspense2, useCallback as useCallback38, useMemo as useMemo35, useRef as useRef49, useState as useState89 } from "react";
|
|
36853
36834
|
|
|
36854
36835
|
// src/components/navigation/mobile-burger-menu.tsx
|
|
36855
|
-
import React113, { useCallback as useCallback37, useRef as
|
|
36836
|
+
import React113, { useCallback as useCallback37, useRef as useRef48 } from "react";
|
|
36856
36837
|
import { usePreventScroll as usePreventScroll5 } from "@react-aria/overlays";
|
|
36857
36838
|
import { Fragment as Fragment55, jsx as jsx288, jsxs as jsxs226 } from "react/jsx-runtime";
|
|
36858
36839
|
var HEADER_HEIGHT = 48;
|
|
@@ -36866,7 +36847,7 @@ var MobileBurgerMenu = React113.memo(function MobileBurgerMenu2({
|
|
|
36866
36847
|
onLogout,
|
|
36867
36848
|
disabled = false
|
|
36868
36849
|
}) {
|
|
36869
|
-
const panelRef =
|
|
36850
|
+
const panelRef = useRef48(null);
|
|
36870
36851
|
usePreventScroll5({ isDisabled: !isOpen });
|
|
36871
36852
|
useFocusTrap(panelRef, isOpen, { onEscape: onClose });
|
|
36872
36853
|
const handleItemClick = useCallback37((item) => {
|
|
@@ -37051,9 +37032,9 @@ function AppLayout({
|
|
|
37051
37032
|
}) {
|
|
37052
37033
|
const [mobileMenuOpen, setMobileMenuOpen] = useState89(false);
|
|
37053
37034
|
const [drawerContainer, setDrawerContainer] = useState89(null);
|
|
37054
|
-
const mobileMenuOpenRef =
|
|
37035
|
+
const mobileMenuOpenRef = useRef49(mobileMenuOpen);
|
|
37055
37036
|
mobileMenuOpenRef.current = mobileMenuOpen;
|
|
37056
|
-
const drawerHandlesRef =
|
|
37037
|
+
const drawerHandlesRef = useRef49(/* @__PURE__ */ new Set());
|
|
37057
37038
|
const handleToggleMobileMenu = useCallback38(() => {
|
|
37058
37039
|
const opening = !mobileMenuOpenRef.current;
|
|
37059
37040
|
if (opening) {
|
|
@@ -37680,7 +37661,7 @@ ScriptArguments.displayName = "ScriptArguments";
|
|
|
37680
37661
|
|
|
37681
37662
|
// src/components/shared/onboarding/onboarding-walkthrough.tsx
|
|
37682
37663
|
init_button2();
|
|
37683
|
-
import React115, { useRef as
|
|
37664
|
+
import React115, { useRef as useRef50, useCallback as useCallback39 } from "react";
|
|
37684
37665
|
|
|
37685
37666
|
// src/components/shared/onboarding/onboarding-step-card.tsx
|
|
37686
37667
|
import React114 from "react";
|
|
@@ -37804,10 +37785,10 @@ function OnboardingWalkthrough({
|
|
|
37804
37785
|
allStepsComplete,
|
|
37805
37786
|
markMultipleComplete
|
|
37806
37787
|
} = useOnboardingState(storageKey);
|
|
37807
|
-
const hasAutoMarkedRef =
|
|
37808
|
-
const autoMarkingInProgressRef =
|
|
37809
|
-
const lastCompletionStatusRef =
|
|
37810
|
-
const actionInProgressRef =
|
|
37788
|
+
const hasAutoMarkedRef = useRef50(false);
|
|
37789
|
+
const autoMarkingInProgressRef = useRef50(false);
|
|
37790
|
+
const lastCompletionStatusRef = useRef50(null);
|
|
37791
|
+
const actionInProgressRef = useRef50(/* @__PURE__ */ new Set());
|
|
37811
37792
|
React115.useEffect(() => {
|
|
37812
37793
|
if (isLoadingCompletion) {
|
|
37813
37794
|
hasAutoMarkedRef.current = false;
|
|
@@ -38495,7 +38476,7 @@ var ListLoader = (props) => /* @__PURE__ */ jsx307(ContentLoader, { ...props, va
|
|
|
38495
38476
|
|
|
38496
38477
|
// src/components/ui/table/table.tsx
|
|
38497
38478
|
init_cn();
|
|
38498
|
-
import { useEffect as useEffect70, useRef as
|
|
38479
|
+
import { useEffect as useEffect70, useRef as useRef52 } from "react";
|
|
38499
38480
|
init_pagination();
|
|
38500
38481
|
init_button2();
|
|
38501
38482
|
|
|
@@ -39255,8 +39236,8 @@ function Table({
|
|
|
39255
39236
|
};
|
|
39256
39237
|
const allSelected = selectedRows.length > 0 && selectedRows.length === data.length;
|
|
39257
39238
|
const someSelected = selectedRows.length > 0 && selectedRows.length < data.length;
|
|
39258
|
-
const sentinelRef =
|
|
39259
|
-
const onLoadMoreRef =
|
|
39239
|
+
const sentinelRef = useRef52(null);
|
|
39240
|
+
const onLoadMoreRef = useRef52(infiniteScroll?.onLoadMore);
|
|
39260
39241
|
onLoadMoreRef.current = infiniteScroll?.onLoadMore;
|
|
39261
39242
|
useEffect70(() => {
|
|
39262
39243
|
if (!infiniteScroll?.hasNextPage || infiniteScroll.isFetchingNextPage) return;
|
|
@@ -39476,7 +39457,7 @@ import { useMemo as useMemo37 } from "react";
|
|
|
39476
39457
|
|
|
39477
39458
|
// src/components/ui/query-report-table/query-report-table-header.tsx
|
|
39478
39459
|
init_cn();
|
|
39479
|
-
import { useRef as
|
|
39460
|
+
import { useRef as useRef53, useState as useState92, useCallback as useCallback40 } from "react";
|
|
39480
39461
|
import { jsx as jsx319, jsxs as jsxs252 } from "react/jsx-runtime";
|
|
39481
39462
|
function QueryReportTableHeader({
|
|
39482
39463
|
columns,
|
|
@@ -39505,7 +39486,7 @@ function QueryReportTableHeader({
|
|
|
39505
39486
|
);
|
|
39506
39487
|
}
|
|
39507
39488
|
function TruncatedHeaderCell({ value, width }) {
|
|
39508
|
-
const textRef =
|
|
39489
|
+
const textRef = useRef53(null);
|
|
39509
39490
|
const [isTruncated, setIsTruncated] = useState92(false);
|
|
39510
39491
|
const checkTruncation = useCallback40(() => {
|
|
39511
39492
|
const el = textRef.current;
|
|
@@ -39535,7 +39516,7 @@ function TruncatedHeaderCell({ value, width }) {
|
|
|
39535
39516
|
|
|
39536
39517
|
// src/components/ui/query-report-table/query-report-table-row.tsx
|
|
39537
39518
|
init_cn();
|
|
39538
|
-
import { useRef as
|
|
39519
|
+
import { useRef as useRef54, useState as useState93, useCallback as useCallback41 } from "react";
|
|
39539
39520
|
import { jsx as jsx320, jsxs as jsxs253 } from "react/jsx-runtime";
|
|
39540
39521
|
function QueryReportTableRow({
|
|
39541
39522
|
row,
|
|
@@ -39581,7 +39562,7 @@ function QueryReportTableRow({
|
|
|
39581
39562
|
);
|
|
39582
39563
|
}
|
|
39583
39564
|
function TruncatedCell({ value, className }) {
|
|
39584
|
-
const textRef =
|
|
39565
|
+
const textRef = useRef54(null);
|
|
39585
39566
|
const [isTruncated, setIsTruncated] = useState93(false);
|
|
39586
39567
|
const checkTruncation = useCallback41(() => {
|
|
39587
39568
|
const el = textRef.current;
|
|
@@ -40083,7 +40064,7 @@ function DataTableEmpty({ className, ...props }) {
|
|
|
40083
40064
|
// src/components/ui/data-table/data-table-row.tsx
|
|
40084
40065
|
init_next_link();
|
|
40085
40066
|
init_cn();
|
|
40086
|
-
import { memo as memo5, useCallback as useCallback43, useRef as
|
|
40067
|
+
import { memo as memo5, useCallback as useCallback43, useRef as useRef55 } from "react";
|
|
40087
40068
|
import { flexRender as flexRender2 } from "@tanstack/react-table";
|
|
40088
40069
|
|
|
40089
40070
|
// src/components/ui/data-table/data-table-skeleton.tsx
|
|
@@ -40168,7 +40149,7 @@ function DataTableRowImpl({
|
|
|
40168
40149
|
const hasSubRow = subRow != null && subRow !== false;
|
|
40169
40150
|
const isLinkMode = Boolean(href) && !onClick;
|
|
40170
40151
|
const isWholeCardLink = isLinkMode && !hasSubRow;
|
|
40171
|
-
const containerRef =
|
|
40152
|
+
const containerRef = useRef55(null);
|
|
40172
40153
|
const handleClick = useCallback43(
|
|
40173
40154
|
(e) => {
|
|
40174
40155
|
const target = e.target;
|
|
@@ -40336,7 +40317,7 @@ function DataTableBody({
|
|
|
40336
40317
|
}
|
|
40337
40318
|
|
|
40338
40319
|
// src/components/ui/data-table/data-table-infinite-footer.tsx
|
|
40339
|
-
import { useEffect as useEffect71, useRef as
|
|
40320
|
+
import { useEffect as useEffect71, useRef as useRef56 } from "react";
|
|
40340
40321
|
import { Fragment as Fragment63, jsx as jsx330, jsxs as jsxs261 } from "react/jsx-runtime";
|
|
40341
40322
|
function DataTableInfiniteFooter({
|
|
40342
40323
|
hasNextPage,
|
|
@@ -40345,8 +40326,8 @@ function DataTableInfiniteFooter({
|
|
|
40345
40326
|
skeletonRows = 3,
|
|
40346
40327
|
rootMargin = "200px"
|
|
40347
40328
|
}) {
|
|
40348
|
-
const sentinelRef =
|
|
40349
|
-
const onLoadMoreRef =
|
|
40329
|
+
const sentinelRef = useRef56(null);
|
|
40330
|
+
const onLoadMoreRef = useRef56(onLoadMore);
|
|
40350
40331
|
onLoadMoreRef.current = onLoadMore;
|
|
40351
40332
|
useEffect71(() => {
|
|
40352
40333
|
if (!hasNextPage || isFetchingNextPage) return;
|
|
@@ -40983,7 +40964,7 @@ function FilterList({
|
|
|
40983
40964
|
// src/components/ui/tag-search-input.tsx
|
|
40984
40965
|
import {
|
|
40985
40966
|
useEffect as useEffect73,
|
|
40986
|
-
useRef as
|
|
40967
|
+
useRef as useRef58,
|
|
40987
40968
|
useState as useState95
|
|
40988
40969
|
} from "react";
|
|
40989
40970
|
init_cn();
|
|
@@ -41018,9 +40999,9 @@ function TagSearchInput({
|
|
|
41018
40999
|
limitTags,
|
|
41019
41000
|
placeholder: currentPlaceholder
|
|
41020
41001
|
});
|
|
41021
|
-
const wrapperRef =
|
|
41022
|
-
const hiddenTagsRef =
|
|
41023
|
-
const hiddenTagsPopupRef =
|
|
41002
|
+
const wrapperRef = useRef58(null);
|
|
41003
|
+
const hiddenTagsRef = useRef58(null);
|
|
41004
|
+
const hiddenTagsPopupRef = useRef58(null);
|
|
41024
41005
|
const [showHiddenTags, setShowHiddenTags] = useState95(false);
|
|
41025
41006
|
useEffect73(() => {
|
|
41026
41007
|
if (!showHiddenTags) return;
|
|
@@ -41177,7 +41158,7 @@ function TagSearchInput({
|
|
|
41177
41158
|
}
|
|
41178
41159
|
|
|
41179
41160
|
// src/components/ui/markdown-editor.tsx
|
|
41180
|
-
import { useRef as
|
|
41161
|
+
import { useRef as useRef59, useCallback as useCallback44, useState as useState96, useEffect as useEffect74 } from "react";
|
|
41181
41162
|
init_cn();
|
|
41182
41163
|
import { Loader2 as Loader29, Upload as Upload8 } from "lucide-react";
|
|
41183
41164
|
import { jsx as jsx335, jsxs as jsxs266 } from "react/jsx-runtime";
|
|
@@ -41232,7 +41213,7 @@ function MarkdownEditor({
|
|
|
41232
41213
|
onFileUploaded,
|
|
41233
41214
|
renderPreview
|
|
41234
41215
|
}) {
|
|
41235
|
-
const fileInputRef =
|
|
41216
|
+
const fileInputRef = useRef59(null);
|
|
41236
41217
|
const [isUploading, setIsUploading] = useState96(false);
|
|
41237
41218
|
const [uploadProgress, setUploadProgress] = useState96("");
|
|
41238
41219
|
const [defaultExtraCommands, setDefaultExtraCommands] = useState96([]);
|
|
@@ -41325,11 +41306,11 @@ function MarkdownEditor({
|
|
|
41325
41306
|
}
|
|
41326
41307
|
} : null;
|
|
41327
41308
|
const extraCommands = uploadCommand ? [...defaultExtraCommands, uploadCommand] : defaultExtraCommands;
|
|
41328
|
-
const wrapperRef =
|
|
41329
|
-
const isDraggingRef =
|
|
41330
|
-
const mouseYRef =
|
|
41331
|
-
const rafRef =
|
|
41332
|
-
const scrollParentRef =
|
|
41309
|
+
const wrapperRef = useRef59(null);
|
|
41310
|
+
const isDraggingRef = useRef59(false);
|
|
41311
|
+
const mouseYRef = useRef59(0);
|
|
41312
|
+
const rafRef = useRef59(0);
|
|
41313
|
+
const scrollParentRef = useRef59(window);
|
|
41333
41314
|
const EDGE_ZONE = 60;
|
|
41334
41315
|
const MAX_SCROLL_SPEED = 15;
|
|
41335
41316
|
const findScrollParent = useCallback44((el) => {
|
|
@@ -46932,7 +46913,7 @@ function renderChatInlineEntityCard(chatRef, options = {}) {
|
|
|
46932
46913
|
}
|
|
46933
46914
|
|
|
46934
46915
|
// src/components/chat/hooks/use-chunk-catchup.ts
|
|
46935
|
-
import { useCallback as useCallback46, useRef as
|
|
46916
|
+
import { useCallback as useCallback46, useRef as useRef63 } from "react";
|
|
46936
46917
|
function makeSeqKey(messageType, chunkType, sequenceId) {
|
|
46937
46918
|
return `${messageType}:${chunkType}:${sequenceId}`;
|
|
46938
46919
|
}
|
|
@@ -46954,20 +46935,22 @@ function useChunkCatchup({
|
|
|
46954
46935
|
chatTypes = [CHAT_TYPE.CLIENT],
|
|
46955
46936
|
fetchChunks
|
|
46956
46937
|
}) {
|
|
46957
|
-
const processedSequenceKeys =
|
|
46958
|
-
const lastSequenceId =
|
|
46959
|
-
const
|
|
46960
|
-
const
|
|
46961
|
-
const
|
|
46962
|
-
const
|
|
46963
|
-
const
|
|
46964
|
-
const
|
|
46938
|
+
const processedSequenceKeys = useRef63(/* @__PURE__ */ new Set());
|
|
46939
|
+
const lastSequenceId = useRef63(null);
|
|
46940
|
+
const lastSequenceIdByType = useRef63(/* @__PURE__ */ new Map());
|
|
46941
|
+
const fetchingInProgress = useRef63(false);
|
|
46942
|
+
const lastFetchParams = useRef63(null);
|
|
46943
|
+
const pendingCatchupRef = useRef63(null);
|
|
46944
|
+
const chunkBuffer = useRef63([]);
|
|
46945
|
+
const bufferUntilInitialCatchupComplete = useRef63(false);
|
|
46946
|
+
const hasCompletedInitialCatchup = useRef63(false);
|
|
46947
|
+
const dialogIdRef = useRef63(dialogId);
|
|
46965
46948
|
dialogIdRef.current = dialogId;
|
|
46966
|
-
const chatTypesRef =
|
|
46949
|
+
const chatTypesRef = useRef63(chatTypes);
|
|
46967
46950
|
chatTypesRef.current = chatTypes;
|
|
46968
|
-
const fetchChunksRef =
|
|
46951
|
+
const fetchChunksRef = useRef63(fetchChunks);
|
|
46969
46952
|
fetchChunksRef.current = fetchChunks;
|
|
46970
|
-
const onChunkReceivedRef =
|
|
46953
|
+
const onChunkReceivedRef = useRef63(onChunkReceived);
|
|
46971
46954
|
onChunkReceivedRef.current = onChunkReceived;
|
|
46972
46955
|
const processChunk = useCallback46((chunk, messageType, forceProcess = false) => {
|
|
46973
46956
|
if (bufferUntilInitialCatchupComplete.current && !forceProcess) {
|
|
@@ -46976,8 +46959,14 @@ function useChunkCatchup({
|
|
|
46976
46959
|
}
|
|
46977
46960
|
if (chunk.sequenceId !== void 0 && chunk.sequenceId !== null) {
|
|
46978
46961
|
const chunkType = typeof chunk.type === "string" ? chunk.type : "";
|
|
46979
|
-
|
|
46962
|
+
const key = makeSeqKey(messageType, chunkType, chunk.sequenceId);
|
|
46963
|
+
if (processedSequenceKeys.current.has(key)) return true;
|
|
46964
|
+
processedSequenceKeys.current.add(key);
|
|
46980
46965
|
lastSequenceId.current = chunk.sequenceId;
|
|
46966
|
+
const prevTypeSeq = lastSequenceIdByType.current.get(messageType);
|
|
46967
|
+
if (prevTypeSeq === void 0 || chunk.sequenceId > prevTypeSeq) {
|
|
46968
|
+
lastSequenceIdByType.current.set(messageType, chunk.sequenceId);
|
|
46969
|
+
}
|
|
46981
46970
|
}
|
|
46982
46971
|
onChunkReceivedRef.current(chunk, messageType);
|
|
46983
46972
|
return true;
|
|
@@ -46987,8 +46976,8 @@ function useChunkCatchup({
|
|
|
46987
46976
|
const buffered = [...chunkBuffer.current];
|
|
46988
46977
|
chunkBuffer.current = [];
|
|
46989
46978
|
buffered.sort((a, b) => {
|
|
46990
|
-
const seqA = a.chunk.sequenceId ??
|
|
46991
|
-
const seqB = b.chunk.sequenceId ??
|
|
46979
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
46980
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
46992
46981
|
return seqA - seqB;
|
|
46993
46982
|
});
|
|
46994
46983
|
buffered.forEach(({ chunk, messageType }) => {
|
|
@@ -47003,9 +46992,14 @@ function useChunkCatchup({
|
|
|
47003
46992
|
return;
|
|
47004
46993
|
}
|
|
47005
46994
|
if (hasCompletedInitialCatchup.current) {
|
|
46995
|
+
if (bufferUntilInitialCatchupComplete.current) {
|
|
46996
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
46997
|
+
flushBufferedRealtimeChunks();
|
|
46998
|
+
}
|
|
47006
46999
|
return;
|
|
47007
47000
|
}
|
|
47008
47001
|
if (fetchingInProgress.current) {
|
|
47002
|
+
pendingCatchupRef.current = { dialogId: dialogId2, fromSequenceId: fromSequenceId ?? lastSequenceId.current };
|
|
47009
47003
|
return;
|
|
47010
47004
|
}
|
|
47011
47005
|
if (lastFetchParams.current && lastFetchParams.current.dialogId === dialogId2 && lastFetchParams.current.fromSequenceId === fromSequenceId) {
|
|
@@ -47022,7 +47016,8 @@ function useChunkCatchup({
|
|
|
47022
47016
|
try {
|
|
47023
47017
|
const chunkPromises = chatTypes2.map(async (chatType) => {
|
|
47024
47018
|
try {
|
|
47025
|
-
const
|
|
47019
|
+
const typeFromSequenceId = fromSequenceId === void 0 ? void 0 : lastSequenceIdByType.current.get(getChatTypeMessageType(chatType)) ?? null;
|
|
47020
|
+
const chunks = await fetchChunks2(dialogId2, chatType, typeFromSequenceId);
|
|
47026
47021
|
const messageType = getChatTypeMessageType(chatType);
|
|
47027
47022
|
return chunks.map((chunk) => ({ chunk, messageType }));
|
|
47028
47023
|
} catch (error) {
|
|
@@ -47042,49 +47037,66 @@ function useChunkCatchup({
|
|
|
47042
47037
|
chunkBuffer.current = [];
|
|
47043
47038
|
const allChunks = [...allCatchupChunks, ...bufferedNatsChunks];
|
|
47044
47039
|
allChunks.sort((a, b) => {
|
|
47045
|
-
const seqA = a.chunk.sequenceId ??
|
|
47046
|
-
const seqB = b.chunk.sequenceId ??
|
|
47040
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47041
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47047
47042
|
return seqA - seqB;
|
|
47048
47043
|
});
|
|
47049
47044
|
const uniqueAllChunks = [];
|
|
47050
47045
|
const seenInBatch = /* @__PURE__ */ new Set();
|
|
47051
47046
|
for (const item of allChunks) {
|
|
47052
|
-
const
|
|
47053
|
-
if (
|
|
47054
|
-
|
|
47055
|
-
|
|
47056
|
-
|
|
47057
|
-
let lastMessageStartSeqId = null;
|
|
47058
|
-
let lastMessageEndSeqId = null;
|
|
47059
|
-
for (let i = uniqueAllChunks.length - 1; i >= 0; i--) {
|
|
47060
|
-
const seq = uniqueAllChunks[i].chunk.sequenceId;
|
|
47061
|
-
if (uniqueAllChunks[i].chunk.type === MESSAGE_TYPE.MESSAGE_END && seq !== void 0 && seq !== null) {
|
|
47062
|
-
lastMessageEndSeqId = seq;
|
|
47063
|
-
break;
|
|
47047
|
+
const hasSeq = item.chunk.sequenceId !== void 0 && item.chunk.sequenceId !== null;
|
|
47048
|
+
if (hasSeq) {
|
|
47049
|
+
const k = makeBatchDedupKey(item);
|
|
47050
|
+
if (seenInBatch.has(k)) continue;
|
|
47051
|
+
seenInBatch.add(k);
|
|
47064
47052
|
}
|
|
47053
|
+
uniqueAllChunks.push(item);
|
|
47065
47054
|
}
|
|
47066
|
-
|
|
47067
|
-
|
|
47068
|
-
|
|
47069
|
-
|
|
47070
|
-
|
|
47071
|
-
|
|
47055
|
+
const hasNoSeq = (item) => item.chunk.sequenceId === void 0 || item.chunk.sequenceId === null;
|
|
47056
|
+
const byType = /* @__PURE__ */ new Map();
|
|
47057
|
+
for (const item of uniqueAllChunks) {
|
|
47058
|
+
const list = byType.get(item.messageType);
|
|
47059
|
+
if (list) list.push(item);
|
|
47060
|
+
else byType.set(item.messageType, [item]);
|
|
47061
|
+
}
|
|
47062
|
+
const chunksToProcess = [];
|
|
47063
|
+
for (const items of byType.values()) {
|
|
47064
|
+
let lastMessageStartSeqId = null;
|
|
47065
|
+
let lastMessageEndSeqId = null;
|
|
47066
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
47067
|
+
const seq = items[i].chunk.sequenceId;
|
|
47068
|
+
if (items[i].chunk.type === MESSAGE_TYPE.MESSAGE_END && seq !== void 0 && seq !== null) {
|
|
47069
|
+
lastMessageEndSeqId = seq;
|
|
47072
47070
|
break;
|
|
47073
47071
|
}
|
|
47074
47072
|
}
|
|
47073
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
47074
|
+
const chunk = items[i].chunk;
|
|
47075
|
+
const seq = chunk.sequenceId;
|
|
47076
|
+
if (chunk.type === MESSAGE_TYPE.MESSAGE_START && seq !== void 0 && seq !== null) {
|
|
47077
|
+
if (lastMessageEndSeqId === null || seq > lastMessageEndSeqId) {
|
|
47078
|
+
lastMessageStartSeqId = seq;
|
|
47079
|
+
break;
|
|
47080
|
+
}
|
|
47081
|
+
}
|
|
47082
|
+
}
|
|
47083
|
+
if (lastMessageStartSeqId !== null) {
|
|
47084
|
+
chunksToProcess.push(
|
|
47085
|
+
...items.filter((item) => hasNoSeq(item) || item.chunk.sequenceId >= lastMessageStartSeqId)
|
|
47086
|
+
);
|
|
47087
|
+
} else if (lastMessageEndSeqId !== null) {
|
|
47088
|
+
chunksToProcess.push(
|
|
47089
|
+
...items.filter((item) => hasNoSeq(item) || item.chunk.sequenceId > lastMessageEndSeqId)
|
|
47090
|
+
);
|
|
47091
|
+
} else {
|
|
47092
|
+
chunksToProcess.push(...items);
|
|
47093
|
+
}
|
|
47075
47094
|
}
|
|
47076
|
-
|
|
47077
|
-
|
|
47078
|
-
|
|
47079
|
-
|
|
47080
|
-
|
|
47081
|
-
} else if (lastMessageEndSeqId !== null) {
|
|
47082
|
-
chunksToProcess = uniqueAllChunks.filter(
|
|
47083
|
-
(item) => item.chunk.sequenceId !== void 0 && item.chunk.sequenceId > lastMessageEndSeqId
|
|
47084
|
-
);
|
|
47085
|
-
} else {
|
|
47086
|
-
chunksToProcess = uniqueAllChunks;
|
|
47087
|
-
}
|
|
47095
|
+
chunksToProcess.sort((a, b) => {
|
|
47096
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47097
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47098
|
+
return seqA - seqB;
|
|
47099
|
+
});
|
|
47088
47100
|
chunksToProcess.forEach(({ chunk, messageType }) => {
|
|
47089
47101
|
if (chunk.sequenceId !== void 0 && chunk.sequenceId !== null) {
|
|
47090
47102
|
const chunkType = typeof chunk.type === "string" ? chunk.type : "";
|
|
@@ -47092,6 +47104,10 @@ function useChunkCatchup({
|
|
|
47092
47104
|
if (processedSequenceKeys.current.has(key)) return;
|
|
47093
47105
|
processedSequenceKeys.current.add(key);
|
|
47094
47106
|
lastSequenceId.current = chunk.sequenceId;
|
|
47107
|
+
const prevTypeSeq = lastSequenceIdByType.current.get(messageType);
|
|
47108
|
+
if (prevTypeSeq === void 0 || chunk.sequenceId > prevTypeSeq) {
|
|
47109
|
+
lastSequenceIdByType.current.set(messageType, chunk.sequenceId);
|
|
47110
|
+
}
|
|
47095
47111
|
}
|
|
47096
47112
|
onChunkReceivedRef.current(chunk, messageType);
|
|
47097
47113
|
});
|
|
@@ -47100,26 +47116,55 @@ function useChunkCatchup({
|
|
|
47100
47116
|
} catch (error) {
|
|
47101
47117
|
console.error("Error during chunk catchup:", error);
|
|
47102
47118
|
} finally {
|
|
47103
|
-
|
|
47104
|
-
|
|
47105
|
-
|
|
47106
|
-
|
|
47107
|
-
|
|
47119
|
+
if (dialogId2 !== dialogIdRef.current) {
|
|
47120
|
+
if (pendingCatchupRef.current?.dialogId === dialogId2) {
|
|
47121
|
+
pendingCatchupRef.current = null;
|
|
47122
|
+
}
|
|
47123
|
+
} else {
|
|
47124
|
+
fetchingInProgress.current = false;
|
|
47125
|
+
const pending = pendingCatchupRef.current;
|
|
47126
|
+
if (pending) {
|
|
47127
|
+
pendingCatchupRef.current = null;
|
|
47128
|
+
if (pending.dialogId === dialogId2) {
|
|
47129
|
+
hasCompletedInitialCatchup.current = false;
|
|
47130
|
+
lastFetchParams.current = null;
|
|
47131
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47132
|
+
try {
|
|
47133
|
+
await catchUpChunksRef.current?.(pending.fromSequenceId);
|
|
47134
|
+
} catch (rerunError) {
|
|
47135
|
+
console.error("Queued catch-up re-run failed:", rerunError);
|
|
47136
|
+
}
|
|
47137
|
+
} else if (bufferUntilInitialCatchupComplete.current) {
|
|
47138
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
47139
|
+
hasCompletedInitialCatchup.current = true;
|
|
47140
|
+
flushBufferedRealtimeChunks();
|
|
47141
|
+
}
|
|
47142
|
+
} else if (bufferUntilInitialCatchupComplete.current) {
|
|
47143
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
47144
|
+
hasCompletedInitialCatchup.current = true;
|
|
47145
|
+
flushBufferedRealtimeChunks();
|
|
47146
|
+
}
|
|
47108
47147
|
}
|
|
47109
47148
|
}
|
|
47110
47149
|
}, [flushBufferedRealtimeChunks]);
|
|
47150
|
+
const catchUpChunksRef = useRef63(null);
|
|
47151
|
+
catchUpChunksRef.current = catchUpChunks;
|
|
47111
47152
|
const resetChunkTracking = useCallback46(() => {
|
|
47112
47153
|
processedSequenceKeys.current.clear();
|
|
47113
47154
|
lastSequenceId.current = null;
|
|
47155
|
+
lastSequenceIdByType.current.clear();
|
|
47114
47156
|
fetchingInProgress.current = false;
|
|
47115
47157
|
lastFetchParams.current = null;
|
|
47158
|
+
pendingCatchupRef.current = null;
|
|
47116
47159
|
chunkBuffer.current = [];
|
|
47117
47160
|
bufferUntilInitialCatchupComplete.current = false;
|
|
47118
47161
|
hasCompletedInitialCatchup.current = false;
|
|
47119
47162
|
}, []);
|
|
47120
47163
|
const startInitialBuffering = useCallback46(() => {
|
|
47121
|
-
|
|
47122
|
-
|
|
47164
|
+
if (!bufferUntilInitialCatchupComplete.current) {
|
|
47165
|
+
chunkBuffer.current = [];
|
|
47166
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47167
|
+
}
|
|
47123
47168
|
hasCompletedInitialCatchup.current = false;
|
|
47124
47169
|
}, []);
|
|
47125
47170
|
const isBufferingActive = useCallback46(() => bufferUntilInitialCatchupComplete.current, []);
|
|
@@ -47128,8 +47173,10 @@ function useChunkCatchup({
|
|
|
47128
47173
|
const fromSeq = lastSequenceId.current;
|
|
47129
47174
|
hasCompletedInitialCatchup.current = false;
|
|
47130
47175
|
lastFetchParams.current = null;
|
|
47131
|
-
bufferUntilInitialCatchupComplete.current
|
|
47132
|
-
|
|
47176
|
+
if (!bufferUntilInitialCatchupComplete.current) {
|
|
47177
|
+
chunkBuffer.current = [];
|
|
47178
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47179
|
+
}
|
|
47133
47180
|
await catchUpChunks(fromSeq);
|
|
47134
47181
|
}, [catchUpChunks]);
|
|
47135
47182
|
return {
|
|
@@ -47179,7 +47226,7 @@ function useScriptedStream(frames, resetKey, enabled = true) {
|
|
|
47179
47226
|
}
|
|
47180
47227
|
|
|
47181
47228
|
// src/components/chat/hooks/use-jetstream-dialog-subscription.ts
|
|
47182
|
-
import { useEffect as useEffect79, useRef as
|
|
47229
|
+
import { useEffect as useEffect79, useRef as useRef64, useState as useState107 } from "react";
|
|
47183
47230
|
var DEFAULT_INACTIVE_THRESHOLD_MS = 5 * 6e4;
|
|
47184
47231
|
var DEFAULT_STREAM_NAME = "CHAT_CHUNKS";
|
|
47185
47232
|
function useJetStreamDialogSubscription({
|
|
@@ -47202,51 +47249,51 @@ function useJetStreamDialogSubscription({
|
|
|
47202
47249
|
const [isSubscribed, setIsSubscribed] = useState107(false);
|
|
47203
47250
|
const [reconnectionCount, setReconnectionCount] = useState107(0);
|
|
47204
47251
|
const [currentStreamSeq, setCurrentStreamSeq] = useState107(null);
|
|
47205
|
-
const clientRef =
|
|
47206
|
-
const subscriptionRef =
|
|
47207
|
-
const highestStreamSeqRef =
|
|
47208
|
-
const onEventRef =
|
|
47252
|
+
const clientRef = useRef64(null);
|
|
47253
|
+
const subscriptionRef = useRef64(null);
|
|
47254
|
+
const highestStreamSeqRef = useRef64(null);
|
|
47255
|
+
const onEventRef = useRef64(onEvent);
|
|
47209
47256
|
useEffect79(() => {
|
|
47210
47257
|
onEventRef.current = onEvent;
|
|
47211
47258
|
}, [onEvent]);
|
|
47212
|
-
const onConnectRef =
|
|
47259
|
+
const onConnectRef = useRef64(onConnect);
|
|
47213
47260
|
useEffect79(() => {
|
|
47214
47261
|
onConnectRef.current = onConnect;
|
|
47215
47262
|
}, [onConnect]);
|
|
47216
|
-
const onDisconnectRef =
|
|
47263
|
+
const onDisconnectRef = useRef64(onDisconnect);
|
|
47217
47264
|
useEffect79(() => {
|
|
47218
47265
|
onDisconnectRef.current = onDisconnect;
|
|
47219
47266
|
}, [onDisconnect]);
|
|
47220
|
-
const onSubscribedRef =
|
|
47267
|
+
const onSubscribedRef = useRef64(onSubscribed);
|
|
47221
47268
|
useEffect79(() => {
|
|
47222
47269
|
onSubscribedRef.current = onSubscribed;
|
|
47223
47270
|
}, [onSubscribed]);
|
|
47224
|
-
const onBeforeReconnectRef =
|
|
47271
|
+
const onBeforeReconnectRef = useRef64(onBeforeReconnect);
|
|
47225
47272
|
useEffect79(() => {
|
|
47226
47273
|
onBeforeReconnectRef.current = onBeforeReconnect;
|
|
47227
47274
|
}, [onBeforeReconnect]);
|
|
47228
|
-
const getNatsWsUrlRef =
|
|
47275
|
+
const getNatsWsUrlRef = useRef64(getNatsWsUrl);
|
|
47229
47276
|
useEffect79(() => {
|
|
47230
47277
|
getNatsWsUrlRef.current = getNatsWsUrl;
|
|
47231
47278
|
}, [getNatsWsUrl]);
|
|
47232
|
-
const reconnectionBackoffRef =
|
|
47279
|
+
const reconnectionBackoffRef = useRef64(reconnectionBackoff);
|
|
47233
47280
|
useEffect79(() => {
|
|
47234
47281
|
reconnectionBackoffRef.current = reconnectionBackoff;
|
|
47235
47282
|
}, [reconnectionBackoff]);
|
|
47236
|
-
const optStartSeqRef =
|
|
47283
|
+
const optStartSeqRef = useRef64(optStartSeq);
|
|
47237
47284
|
useEffect79(() => {
|
|
47238
47285
|
optStartSeqRef.current = optStartSeq;
|
|
47239
47286
|
}, [optStartSeq]);
|
|
47240
|
-
const inactiveThresholdRef =
|
|
47287
|
+
const inactiveThresholdRef = useRef64(inactiveThresholdMs);
|
|
47241
47288
|
useEffect79(() => {
|
|
47242
47289
|
inactiveThresholdRef.current = inactiveThresholdMs;
|
|
47243
47290
|
}, [inactiveThresholdMs]);
|
|
47244
|
-
const hadConnectionBeforeRef =
|
|
47245
|
-
const clientConfigRef =
|
|
47291
|
+
const hadConnectionBeforeRef = useRef64(false);
|
|
47292
|
+
const clientConfigRef = useRef64(clientConfig);
|
|
47246
47293
|
useEffect79(() => {
|
|
47247
47294
|
clientConfigRef.current = clientConfig;
|
|
47248
47295
|
}, [clientConfig]);
|
|
47249
|
-
const currentWsUrlRef =
|
|
47296
|
+
const currentWsUrlRef = useRef64("");
|
|
47250
47297
|
const wsUrl = getNatsWsUrl();
|
|
47251
47298
|
useEffect79(() => {
|
|
47252
47299
|
if (!enabled || !wsUrl) {
|
|
@@ -47329,6 +47376,10 @@ function useJetStreamDialogSubscription({
|
|
|
47329
47376
|
}
|
|
47330
47377
|
};
|
|
47331
47378
|
}, [enabled, wsUrl]);
|
|
47379
|
+
useEffect79(() => {
|
|
47380
|
+
highestStreamSeqRef.current = null;
|
|
47381
|
+
setCurrentStreamSeq(null);
|
|
47382
|
+
}, [dialogId]);
|
|
47332
47383
|
useEffect79(() => {
|
|
47333
47384
|
if (!enabled || !dialogId || !isConnected) {
|
|
47334
47385
|
if (subscriptionRef.current) {
|
|
@@ -47412,15 +47463,11 @@ function useJetStreamDialogSubscription({
|
|
|
47412
47463
|
setIsSubscribed(false);
|
|
47413
47464
|
};
|
|
47414
47465
|
}, [enabled, dialogId, isConnected, streamName, topic, reconnectionCount]);
|
|
47415
|
-
useEffect79(() => {
|
|
47416
|
-
highestStreamSeqRef.current = null;
|
|
47417
|
-
setCurrentStreamSeq(null);
|
|
47418
|
-
}, [dialogId]);
|
|
47419
47466
|
return { isConnected, isSubscribed, reconnectionCount, currentStreamSeq };
|
|
47420
47467
|
}
|
|
47421
47468
|
|
|
47422
47469
|
// src/components/chat/hooks/use-nats-dialog-subscription.ts
|
|
47423
|
-
import { useEffect as useEffect80, useRef as
|
|
47470
|
+
import { useEffect as useEffect80, useRef as useRef65, useState as useState108 } from "react";
|
|
47424
47471
|
function useNatsDialogSubscription({
|
|
47425
47472
|
enabled,
|
|
47426
47473
|
dialogId,
|
|
@@ -47437,42 +47484,42 @@ function useNatsDialogSubscription({
|
|
|
47437
47484
|
const [isConnected, setIsConnected] = useState108(false);
|
|
47438
47485
|
const [isSubscribed, setIsSubscribed] = useState108(false);
|
|
47439
47486
|
const [reconnectionCount, setReconnectionCount] = useState108(0);
|
|
47440
|
-
const clientRef =
|
|
47441
|
-
const subscriptionRefs =
|
|
47442
|
-
const onEventRef =
|
|
47487
|
+
const clientRef = useRef65(null);
|
|
47488
|
+
const subscriptionRefs = useRef65(/* @__PURE__ */ new Map());
|
|
47489
|
+
const onEventRef = useRef65(onEvent);
|
|
47443
47490
|
useEffect80(() => {
|
|
47444
47491
|
onEventRef.current = onEvent;
|
|
47445
47492
|
}, [onEvent]);
|
|
47446
|
-
const onConnectRef =
|
|
47493
|
+
const onConnectRef = useRef65(onConnect);
|
|
47447
47494
|
useEffect80(() => {
|
|
47448
47495
|
onConnectRef.current = onConnect;
|
|
47449
47496
|
}, [onConnect]);
|
|
47450
|
-
const onDisconnectRef =
|
|
47497
|
+
const onDisconnectRef = useRef65(onDisconnect);
|
|
47451
47498
|
useEffect80(() => {
|
|
47452
47499
|
onDisconnectRef.current = onDisconnect;
|
|
47453
47500
|
}, [onDisconnect]);
|
|
47454
|
-
const onSubscribedRef =
|
|
47501
|
+
const onSubscribedRef = useRef65(onSubscribed);
|
|
47455
47502
|
useEffect80(() => {
|
|
47456
47503
|
onSubscribedRef.current = onSubscribed;
|
|
47457
47504
|
}, [onSubscribed]);
|
|
47458
|
-
const onBeforeReconnectRef =
|
|
47505
|
+
const onBeforeReconnectRef = useRef65(onBeforeReconnect);
|
|
47459
47506
|
useEffect80(() => {
|
|
47460
47507
|
onBeforeReconnectRef.current = onBeforeReconnect;
|
|
47461
47508
|
}, [onBeforeReconnect]);
|
|
47462
|
-
const hadConnectionBeforeRef =
|
|
47463
|
-
const getNatsWsUrlRef =
|
|
47509
|
+
const hadConnectionBeforeRef = useRef65(false);
|
|
47510
|
+
const getNatsWsUrlRef = useRef65(getNatsWsUrl);
|
|
47464
47511
|
useEffect80(() => {
|
|
47465
47512
|
getNatsWsUrlRef.current = getNatsWsUrl;
|
|
47466
47513
|
}, [getNatsWsUrl]);
|
|
47467
|
-
const reconnectionBackoffRef =
|
|
47514
|
+
const reconnectionBackoffRef = useRef65(reconnectionBackoff);
|
|
47468
47515
|
useEffect80(() => {
|
|
47469
47516
|
reconnectionBackoffRef.current = reconnectionBackoff;
|
|
47470
47517
|
}, [reconnectionBackoff]);
|
|
47471
|
-
const clientConfigRef =
|
|
47518
|
+
const clientConfigRef = useRef65(clientConfig);
|
|
47472
47519
|
useEffect80(() => {
|
|
47473
47520
|
clientConfigRef.current = clientConfig;
|
|
47474
47521
|
}, [clientConfig]);
|
|
47475
|
-
const currentWsUrlRef =
|
|
47522
|
+
const currentWsUrlRef = useRef65("");
|
|
47476
47523
|
const wsUrl = getNatsWsUrl();
|
|
47477
47524
|
useEffect80(() => {
|
|
47478
47525
|
if (!enabled || !wsUrl) {
|
|
@@ -47556,13 +47603,15 @@ function useNatsDialogSubscription({
|
|
|
47556
47603
|
};
|
|
47557
47604
|
}, [enabled, wsUrl]);
|
|
47558
47605
|
const topicsKey = topics.join(",");
|
|
47559
|
-
const
|
|
47560
|
-
|
|
47606
|
+
const topicsRef = useRef65(topics);
|
|
47607
|
+
topicsRef.current = topics;
|
|
47608
|
+
const lastSubscribedDialogIdRef = useRef65(null);
|
|
47609
|
+
const isConnectedRef = useRef65(isConnected);
|
|
47561
47610
|
useEffect80(() => {
|
|
47562
47611
|
isConnectedRef.current = isConnected;
|
|
47563
47612
|
}, [isConnected]);
|
|
47564
|
-
const currentDialogIdRef =
|
|
47565
|
-
const abortControllerRef =
|
|
47613
|
+
const currentDialogIdRef = useRef65(null);
|
|
47614
|
+
const abortControllerRef = useRef65(null);
|
|
47566
47615
|
useEffect80(() => {
|
|
47567
47616
|
currentDialogIdRef.current = dialogId;
|
|
47568
47617
|
if (!enabled || !dialogId) {
|
|
@@ -47615,7 +47664,7 @@ function useNatsDialogSubscription({
|
|
|
47615
47664
|
} catch {
|
|
47616
47665
|
}
|
|
47617
47666
|
};
|
|
47618
|
-
|
|
47667
|
+
topicsRef.current.forEach((topic) => {
|
|
47619
47668
|
const subscription = client.subscribeBytes(
|
|
47620
47669
|
`chat.${dialogId}.${topic}`,
|
|
47621
47670
|
handleMessage(topic),
|
|
@@ -47643,7 +47692,7 @@ function useNatsDialogSubscription({
|
|
|
47643
47692
|
lastSubscribedDialogIdRef.current = null;
|
|
47644
47693
|
abortControllerRef.current = null;
|
|
47645
47694
|
};
|
|
47646
|
-
}, [enabled, dialogId, topicsKey
|
|
47695
|
+
}, [enabled, dialogId, topicsKey]);
|
|
47647
47696
|
useEffect80(() => {
|
|
47648
47697
|
if (!enabled || !currentDialogIdRef.current || !isConnected) {
|
|
47649
47698
|
return;
|
|
@@ -47666,7 +47715,7 @@ function useNatsDialogSubscription({
|
|
|
47666
47715
|
} catch {
|
|
47667
47716
|
}
|
|
47668
47717
|
};
|
|
47669
|
-
|
|
47718
|
+
topicsRef.current.forEach((topic) => {
|
|
47670
47719
|
const subscription = client.subscribeBytes(
|
|
47671
47720
|
`chat.${dialogId2}.${topic}`,
|
|
47672
47721
|
handleMessage(topic),
|
|
@@ -47680,7 +47729,7 @@ function useNatsDialogSubscription({
|
|
|
47680
47729
|
} else if (subscriptionRefs.current.size > 0) {
|
|
47681
47730
|
setIsSubscribed(true);
|
|
47682
47731
|
}
|
|
47683
|
-
}, [isConnected, enabled,
|
|
47732
|
+
}, [isConnected, enabled, topicsKey]);
|
|
47684
47733
|
return { isConnected, isSubscribed, reconnectionCount };
|
|
47685
47734
|
}
|
|
47686
47735
|
function buildNatsWsUrl(apiBaseUrl, options) {
|
|
@@ -47694,7 +47743,7 @@ function buildNatsWsUrl(apiBaseUrl, options) {
|
|
|
47694
47743
|
}
|
|
47695
47744
|
|
|
47696
47745
|
// src/components/chat/hooks/use-realtime-chunk-processor.ts
|
|
47697
|
-
import { useCallback as useCallback47, useRef as
|
|
47746
|
+
import { useCallback as useCallback47, useRef as useRef66, useEffect as useEffect81 } from "react";
|
|
47698
47747
|
|
|
47699
47748
|
// src/components/chat/utils/chunk-parser.ts
|
|
47700
47749
|
function normalizeToolCalls(raw) {
|
|
@@ -48041,6 +48090,10 @@ var MessageSegmentAccumulator = class {
|
|
|
48041
48090
|
const hasCall = seg.data.toolCalls.some((c) => c.toolExecutionRequestId === execId);
|
|
48042
48091
|
if (!hasCall) return seg;
|
|
48043
48092
|
const prev = seg.data.executions?.[execId];
|
|
48093
|
+
if (toolData.type === "EXECUTING_TOOL" && prev?.status === "done") {
|
|
48094
|
+
matched = true;
|
|
48095
|
+
return seg;
|
|
48096
|
+
}
|
|
48044
48097
|
const next = toolData.type === "EXECUTED_TOOL" ? { status: "done", result: toolData.result, success: toolData.success } : { status: "executing", result: prev?.result, success: prev?.success };
|
|
48045
48098
|
matched = true;
|
|
48046
48099
|
return {
|
|
@@ -48345,13 +48398,13 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48345
48398
|
batchApprovalsEnabled = true,
|
|
48346
48399
|
isDirectMode = false
|
|
48347
48400
|
} = options;
|
|
48348
|
-
const accumulatorRef =
|
|
48401
|
+
const accumulatorRef = useRef66(
|
|
48349
48402
|
createMessageSegmentAccumulator({
|
|
48350
48403
|
onApprove: callbacks.onApprove,
|
|
48351
48404
|
onReject: callbacks.onReject
|
|
48352
48405
|
})
|
|
48353
48406
|
);
|
|
48354
|
-
const hasInitializedWithData =
|
|
48407
|
+
const hasInitializedWithData = useRef66(false);
|
|
48355
48408
|
useEffect81(() => {
|
|
48356
48409
|
if (initialState && !hasInitializedWithData.current) {
|
|
48357
48410
|
accumulatorRef.current.initializeWithState(initialState);
|
|
@@ -48365,15 +48418,15 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48365
48418
|
hasInitializedWithData.current = true;
|
|
48366
48419
|
}
|
|
48367
48420
|
}, [initialState, callbacks]);
|
|
48368
|
-
const isInStreamRef =
|
|
48369
|
-
const hasEverStreamedRef =
|
|
48370
|
-
const directModeFlagRef =
|
|
48371
|
-
const sawDirectMessageRef =
|
|
48372
|
-
const directTeardownFiredRef =
|
|
48421
|
+
const isInStreamRef = useRef66(false);
|
|
48422
|
+
const hasEverStreamedRef = useRef66(false);
|
|
48423
|
+
const directModeFlagRef = useRef66(isDirectMode);
|
|
48424
|
+
const sawDirectMessageRef = useRef66(false);
|
|
48425
|
+
const directTeardownFiredRef = useRef66(false);
|
|
48373
48426
|
useEffect81(() => {
|
|
48374
48427
|
directModeFlagRef.current = isDirectMode;
|
|
48375
48428
|
}, [isDirectMode]);
|
|
48376
|
-
const pendingEscalatedRef =
|
|
48429
|
+
const pendingEscalatedRef = useRef66(/* @__PURE__ */ new Map());
|
|
48377
48430
|
const processChunk = useCallback47(
|
|
48378
48431
|
(chunk) => {
|
|
48379
48432
|
const action = parseChunkToAction(chunk);
|
|
@@ -48504,6 +48557,16 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48504
48557
|
explanation: escalatedData.explanation,
|
|
48505
48558
|
approvalType: escalatedData.approvalType
|
|
48506
48559
|
});
|
|
48560
|
+
const emitResolved = (segments) => {
|
|
48561
|
+
if (isInStreamRef.current) {
|
|
48562
|
+
emitSegments(segments);
|
|
48563
|
+
return;
|
|
48564
|
+
}
|
|
48565
|
+
const delta = segments.filter(
|
|
48566
|
+
(s) => s.type === "approval_request" && s.data.requestId === requestId || s.type === "approval_batch" && s.data.approvalRequestId === requestId
|
|
48567
|
+
);
|
|
48568
|
+
emitSegments(delta, { append: true });
|
|
48569
|
+
};
|
|
48507
48570
|
if (escalatedData.toolCalls && escalatedData.toolCalls.length > 0) {
|
|
48508
48571
|
if (batchApprovalsEnabled) {
|
|
48509
48572
|
const segments = accumulator.addApprovalBatch(
|
|
@@ -48514,7 +48577,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48514
48577
|
void 0,
|
|
48515
48578
|
resolvedByName
|
|
48516
48579
|
);
|
|
48517
|
-
|
|
48580
|
+
emitResolved(segments);
|
|
48518
48581
|
} else {
|
|
48519
48582
|
let segments = accumulator.getSegments();
|
|
48520
48583
|
for (const call of escalatedData.toolCalls) {
|
|
@@ -48527,7 +48590,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48527
48590
|
status
|
|
48528
48591
|
);
|
|
48529
48592
|
}
|
|
48530
|
-
|
|
48593
|
+
emitResolved(segments);
|
|
48531
48594
|
}
|
|
48532
48595
|
} else {
|
|
48533
48596
|
const segments = accumulator.addApprovalRequest(
|
|
@@ -48537,7 +48600,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48537
48600
|
escalatedData.approvalType,
|
|
48538
48601
|
status
|
|
48539
48602
|
);
|
|
48540
|
-
|
|
48603
|
+
emitResolved(segments);
|
|
48541
48604
|
}
|
|
48542
48605
|
} else {
|
|
48543
48606
|
accumulator.updateApprovalStatus(requestId, status, resolvedByName);
|
|
@@ -48617,6 +48680,8 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48617
48680
|
hasInitializedWithData.current = false;
|
|
48618
48681
|
sawDirectMessageRef.current = false;
|
|
48619
48682
|
directTeardownFiredRef.current = false;
|
|
48683
|
+
isInStreamRef.current = false;
|
|
48684
|
+
hasEverStreamedRef.current = false;
|
|
48620
48685
|
}, []);
|
|
48621
48686
|
const updateApprovalStatus = useCallback47(
|
|
48622
48687
|
(requestId, status, resolvedByName) => {
|
|
@@ -48762,7 +48827,7 @@ function useEmptyStateConfig(emptyStateUrl, options) {
|
|
|
48762
48827
|
}
|
|
48763
48828
|
|
|
48764
48829
|
// src/components/chat/hooks/use-chat-attachments.ts
|
|
48765
|
-
import { useCallback as useCallback48, useMemo as useMemo41, useRef as
|
|
48830
|
+
import { useCallback as useCallback48, useMemo as useMemo41, useRef as useRef67, useState as useState110 } from "react";
|
|
48766
48831
|
import { fileTypeFromBlob } from "file-type";
|
|
48767
48832
|
var CHAT_ATTACHMENTS_BUCKET = "chat-attachments";
|
|
48768
48833
|
var CHAT_ATTACHMENTS_FOLDER = "chat";
|
|
@@ -48839,7 +48904,7 @@ function useChatAttachments() {
|
|
|
48839
48904
|
const runtime = useRequiredChatRuntime();
|
|
48840
48905
|
const uploadUrlEndpoint = runtime.endpoints.attachmentUploadUrl;
|
|
48841
48906
|
const [attachments, setAttachments] = useState110([]);
|
|
48842
|
-
const controllersRef =
|
|
48907
|
+
const controllersRef = useRef67(/* @__PURE__ */ new Map());
|
|
48843
48908
|
const updateOne = useCallback48((id, patch) => {
|
|
48844
48909
|
setAttachments((prev) => prev.map((a) => a.id === id ? { ...a, ...patch } : a));
|
|
48845
48910
|
}, []);
|
|
@@ -48928,7 +48993,7 @@ function useChatAttachments() {
|
|
|
48928
48993
|
},
|
|
48929
48994
|
[uploadUrlEndpoint, updateOne]
|
|
48930
48995
|
);
|
|
48931
|
-
const attachmentsRef =
|
|
48996
|
+
const attachmentsRef = useRef67([]);
|
|
48932
48997
|
attachmentsRef.current = attachments;
|
|
48933
48998
|
const addFiles = useCallback48(
|
|
48934
48999
|
(files) => {
|
|
@@ -49005,13 +49070,13 @@ function useChatAttachments() {
|
|
|
49005
49070
|
}
|
|
49006
49071
|
|
|
49007
49072
|
// src/components/chat/hooks/use-chat-attachment-image-gallery.tsx
|
|
49008
|
-
import { useCallback as useCallback49, useEffect as useEffect83, useRef as
|
|
49073
|
+
import { useCallback as useCallback49, useEffect as useEffect83, useRef as useRef68, useState as useState111 } from "react";
|
|
49009
49074
|
import { jsx as jsx359 } from "react/jsx-runtime";
|
|
49010
49075
|
var CLOSED = { isOpen: false, images: [], initialIndex: 0 };
|
|
49011
49076
|
function useChatAttachmentImageGallery() {
|
|
49012
49077
|
const runtime = useRequiredChatRuntime();
|
|
49013
49078
|
const viewUrlPrefix = runtime.endpoints.attachmentViewUrlPrefix;
|
|
49014
|
-
const panelRef =
|
|
49079
|
+
const panelRef = useRef68(null);
|
|
49015
49080
|
const [state, setState] = useState111(CLOSED);
|
|
49016
49081
|
const handleClose = useCallback49(() => setState(CLOSED), []);
|
|
49017
49082
|
useEffect83(() => {
|
|
@@ -49115,10 +49180,10 @@ function useChatIdentity() {
|
|
|
49115
49180
|
}
|
|
49116
49181
|
|
|
49117
49182
|
// src/components/chat/hooks/use-close-on-navigation.ts
|
|
49118
|
-
import { useEffect as useEffect85, useRef as
|
|
49183
|
+
import { useEffect as useEffect85, useRef as useRef69 } from "react";
|
|
49119
49184
|
function useCloseOnNavigation(close, pathname) {
|
|
49120
|
-
const prevPathnameRef =
|
|
49121
|
-
const initializedRef =
|
|
49185
|
+
const prevPathnameRef = useRef69(null);
|
|
49186
|
+
const initializedRef = useRef69(false);
|
|
49122
49187
|
useEffect85(() => {
|
|
49123
49188
|
if (!initializedRef.current) {
|
|
49124
49189
|
initializedRef.current = true;
|
|
@@ -49133,14 +49198,14 @@ function useCloseOnNavigation(close, pathname) {
|
|
|
49133
49198
|
}
|
|
49134
49199
|
|
|
49135
49200
|
// src/components/chat/hooks/use-chat.ts
|
|
49136
|
-
import { useState as useState114, useCallback as useCallback51, useEffect as useEffect86, useRef as
|
|
49201
|
+
import { useState as useState114, useCallback as useCallback51, useEffect as useEffect86, useRef as useRef71 } from "react";
|
|
49137
49202
|
|
|
49138
49203
|
// src/components/chat/hooks/use-sse.ts
|
|
49139
|
-
import { useState as useState113, useCallback as useCallback50, useRef as
|
|
49204
|
+
import { useState as useState113, useCallback as useCallback50, useRef as useRef70 } from "react";
|
|
49140
49205
|
function useSSE({ useMock = true, debugMode = false, streamFn } = {}) {
|
|
49141
49206
|
const [isStreaming, setIsStreaming] = useState113(false);
|
|
49142
49207
|
const [error, setError] = useState113(null);
|
|
49143
|
-
const abortControllerRef =
|
|
49208
|
+
const abortControllerRef = useRef70(null);
|
|
49144
49209
|
const fallbackStream = useCallback50(async function* () {
|
|
49145
49210
|
throw new Error(
|
|
49146
49211
|
"[useSSE] No streamFn provided and `useMock: true` is no longer wired into the lib. Supply a `streamFn` (see `createDocStreamFn` in use-embedded-chat) or migrate the mock to your host code."
|
|
@@ -49208,8 +49273,8 @@ function useChat({
|
|
|
49208
49273
|
} = {}) {
|
|
49209
49274
|
const [messages, setMessages] = useState114(() => initialMessages ?? []);
|
|
49210
49275
|
const [isTyping, setIsTyping] = useState114(false);
|
|
49211
|
-
const currentAssistantSegmentsRef =
|
|
49212
|
-
const onMessagesChangeRef =
|
|
49276
|
+
const currentAssistantSegmentsRef = useRef71([]);
|
|
49277
|
+
const onMessagesChangeRef = useRef71(onMessagesChange);
|
|
49213
49278
|
onMessagesChangeRef.current = onMessagesChange;
|
|
49214
49279
|
useEffect86(() => {
|
|
49215
49280
|
onMessagesChangeRef.current?.(messages);
|
|
@@ -49500,7 +49565,7 @@ function useChat({
|
|
|
49500
49565
|
}
|
|
49501
49566
|
|
|
49502
49567
|
// src/components/chat/hooks/use-sse-chat-adapter.ts
|
|
49503
|
-
import { useState as useState115, useEffect as useEffect87, useCallback as useCallback52, useMemo as useMemo42, useRef as
|
|
49568
|
+
import { useState as useState115, useEffect as useEffect87, useCallback as useCallback52, useMemo as useMemo42, useRef as useRef72 } from "react";
|
|
49504
49569
|
function createEmptyTurnMeta() {
|
|
49505
49570
|
return {
|
|
49506
49571
|
provider: null,
|
|
@@ -49821,20 +49886,20 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
|
|
|
49821
49886
|
const runtime = useRequiredChatRuntime();
|
|
49822
49887
|
const source = runtime.source || DEFAULT_CHAT_SOURCE;
|
|
49823
49888
|
const tableIdForDocumentType = options?.tableIdForDocumentType ?? defaultTableIdForDocumentType;
|
|
49824
|
-
const persistedRef =
|
|
49889
|
+
const persistedRef = useRef72(null);
|
|
49825
49890
|
if (persistedRef.current === null) {
|
|
49826
49891
|
pruneStaleChatStorage(source);
|
|
49827
49892
|
persistedRef.current = loadPersistedChat(source) || { messages: [], sources: [], sendCount: 0 };
|
|
49828
49893
|
}
|
|
49829
|
-
const sourcesMapRef =
|
|
49894
|
+
const sourcesMapRef = useRef72(
|
|
49830
49895
|
new Map(persistedRef.current.sources)
|
|
49831
49896
|
);
|
|
49832
|
-
const refsMapRef =
|
|
49897
|
+
const refsMapRef = useRef72(
|
|
49833
49898
|
new Map(persistedRef.current.refs ?? [])
|
|
49834
49899
|
);
|
|
49835
|
-
const metaMapRef =
|
|
49836
|
-
const messagesRef =
|
|
49837
|
-
const sendCountRef =
|
|
49900
|
+
const metaMapRef = useRef72(/* @__PURE__ */ new Map());
|
|
49901
|
+
const messagesRef = useRef72(persistedRef.current.messages);
|
|
49902
|
+
const sendCountRef = useRef72(persistedRef.current.sendCount);
|
|
49838
49903
|
const [streamingPhase, setStreamingPhase] = useState115("idle");
|
|
49839
49904
|
const [metaTick, setMetaTick] = useState115(0);
|
|
49840
49905
|
const bumpMetaTick = useCallback52(() => setMetaTick((t) => t + 1), []);
|
|
@@ -50108,7 +50173,7 @@ import {
|
|
|
50108
50173
|
useCallback as useCallback53,
|
|
50109
50174
|
useEffect as useEffect88,
|
|
50110
50175
|
useMemo as useMemo43,
|
|
50111
|
-
useRef as
|
|
50176
|
+
useRef as useRef73,
|
|
50112
50177
|
useState as useState116
|
|
50113
50178
|
} from "react";
|
|
50114
50179
|
|
|
@@ -50147,7 +50212,15 @@ function processHistoricalMessages(messages, options = {}) {
|
|
|
50147
50212
|
onReject,
|
|
50148
50213
|
chatTypeFilter,
|
|
50149
50214
|
approvalStatuses = {},
|
|
50150
|
-
|
|
50215
|
+
// An omitted option means "display every approval type" — the original
|
|
50216
|
+
// history semantics. Deliberately NOT defaulted to the realtime
|
|
50217
|
+
// processor's ['CLIENT']: consumers that pass a wider list to their
|
|
50218
|
+
// realtime processor but omit it on the history path would silently lose
|
|
50219
|
+
// pending non-CLIENT approval cards on every reload/reconnect refetch
|
|
50220
|
+
// (they also ignore `escalatedApprovals`). Realtime/history parity is
|
|
50221
|
+
// opt-in: pass the same explicit list to both.
|
|
50222
|
+
displayApprovalTypes,
|
|
50223
|
+
batchApprovalsEnabled
|
|
50151
50224
|
} = options;
|
|
50152
50225
|
const processedMessages = [];
|
|
50153
50226
|
const accumulator = createMessageSegmentAccumulator({ onApprove, onReject });
|
|
@@ -50212,7 +50285,13 @@ function processHistoricalMessages(messages, options = {}) {
|
|
|
50212
50285
|
}
|
|
50213
50286
|
lastAssistantId = msg.id;
|
|
50214
50287
|
messageDataArray.forEach((data) => {
|
|
50215
|
-
processMessageData(
|
|
50288
|
+
processMessageData(
|
|
50289
|
+
data,
|
|
50290
|
+
accumulator,
|
|
50291
|
+
approvalStatuses,
|
|
50292
|
+
{ displayApprovalTypes, batchApprovalsEnabled },
|
|
50293
|
+
escalatedApprovals
|
|
50294
|
+
);
|
|
50216
50295
|
});
|
|
50217
50296
|
const nextMsg = messages[index + 1];
|
|
50218
50297
|
const isLastMessage = index === messages.length - 1;
|
|
@@ -50436,7 +50515,7 @@ function extractErrorMessages(messages, options = {}) {
|
|
|
50436
50515
|
return errorMessages;
|
|
50437
50516
|
}
|
|
50438
50517
|
function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
50439
|
-
const { chatTypeFilter, assistantName = "Fae", assistantType = "fae", assistantAvatar, onApprove, onReject, approvalStatuses = {}, displayApprovalTypes } = options;
|
|
50518
|
+
const { chatTypeFilter, assistantName = "Fae", assistantType = "fae", assistantAvatar, onApprove, onReject, approvalStatuses = {}, displayApprovalTypes, batchApprovalsEnabled } = options;
|
|
50440
50519
|
const processedMessages = [];
|
|
50441
50520
|
const accumulator = createMessageSegmentAccumulator({ onApprove, onReject });
|
|
50442
50521
|
const escalatedApprovals = /* @__PURE__ */ new Map();
|
|
@@ -50500,7 +50579,13 @@ function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
|
50500
50579
|
}
|
|
50501
50580
|
lastAssistantId = msg.id;
|
|
50502
50581
|
messageDataArray.forEach((data) => {
|
|
50503
|
-
processMessageData(
|
|
50582
|
+
processMessageData(
|
|
50583
|
+
data,
|
|
50584
|
+
accumulator,
|
|
50585
|
+
approvalStatuses,
|
|
50586
|
+
{ displayApprovalTypes, batchApprovalsEnabled },
|
|
50587
|
+
escalatedApprovals
|
|
50588
|
+
);
|
|
50504
50589
|
});
|
|
50505
50590
|
const nextMsg = messages[index + 1];
|
|
50506
50591
|
const isLastMessage = index === messages.length - 1;
|
|
@@ -50529,6 +50614,65 @@ function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
|
50529
50614
|
};
|
|
50530
50615
|
}
|
|
50531
50616
|
|
|
50617
|
+
// src/components/chat/utils/extract-incomplete-message-state.ts
|
|
50618
|
+
function extractIncompleteMessageState(lastMessage) {
|
|
50619
|
+
if (!lastMessage || lastMessage.role !== "assistant" || typeof lastMessage.content === "string") {
|
|
50620
|
+
return void 0;
|
|
50621
|
+
}
|
|
50622
|
+
const segments = lastMessage.content;
|
|
50623
|
+
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
50624
|
+
const executingTools = /* @__PURE__ */ new Map();
|
|
50625
|
+
let hasIncompleteState = false;
|
|
50626
|
+
segments.forEach((segment) => {
|
|
50627
|
+
switch (segment.type) {
|
|
50628
|
+
case "tool_execution":
|
|
50629
|
+
if (segment.data.type === "EXECUTING_TOOL") {
|
|
50630
|
+
const toolKey = segment.data.toolExecutionRequestId || `${segment.data.integratedToolType}-${segment.data.toolFunction}`;
|
|
50631
|
+
executingTools.set(toolKey, {
|
|
50632
|
+
integratedToolType: segment.data.integratedToolType,
|
|
50633
|
+
toolFunction: segment.data.toolFunction,
|
|
50634
|
+
toolTitle: segment.data.toolTitle,
|
|
50635
|
+
parameters: segment.data.parameters
|
|
50636
|
+
});
|
|
50637
|
+
hasIncompleteState = true;
|
|
50638
|
+
}
|
|
50639
|
+
break;
|
|
50640
|
+
case "approval_request":
|
|
50641
|
+
if (segment.status === "pending" && segment.data.requestId) {
|
|
50642
|
+
pendingApprovals.set(segment.data.requestId, {
|
|
50643
|
+
command: segment.data.command,
|
|
50644
|
+
explanation: segment.data.explanation,
|
|
50645
|
+
approvalType: segment.data.approvalType || "CLIENT"
|
|
50646
|
+
});
|
|
50647
|
+
hasIncompleteState = true;
|
|
50648
|
+
}
|
|
50649
|
+
break;
|
|
50650
|
+
case "approval_batch": {
|
|
50651
|
+
const allDone = !!segment.data.executions && segment.data.toolCalls.every(
|
|
50652
|
+
(c) => segment.data.executions?.[c.toolExecutionRequestId]?.status === "done"
|
|
50653
|
+
);
|
|
50654
|
+
if (segment.status !== "rejected" && !allDone) {
|
|
50655
|
+
hasIncompleteState = true;
|
|
50656
|
+
}
|
|
50657
|
+
break;
|
|
50658
|
+
}
|
|
50659
|
+
case "context_compaction":
|
|
50660
|
+
if (segment.status === "started") {
|
|
50661
|
+
hasIncompleteState = true;
|
|
50662
|
+
}
|
|
50663
|
+
break;
|
|
50664
|
+
}
|
|
50665
|
+
});
|
|
50666
|
+
if (!hasIncompleteState) {
|
|
50667
|
+
return void 0;
|
|
50668
|
+
}
|
|
50669
|
+
return {
|
|
50670
|
+
existingSegments: segments,
|
|
50671
|
+
pendingApprovals: pendingApprovals.size > 0 ? pendingApprovals : void 0,
|
|
50672
|
+
executingTools: executingTools.size > 0 ? executingTools : void 0
|
|
50673
|
+
};
|
|
50674
|
+
}
|
|
50675
|
+
|
|
50532
50676
|
// src/components/chat/hooks/use-nats-chat-adapter.ts
|
|
50533
50677
|
function nextId(role) {
|
|
50534
50678
|
return `${role}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
@@ -50551,6 +50695,110 @@ function updateTrailingAssistant(prev, segments) {
|
|
|
50551
50695
|
{ ...last, segments }
|
|
50552
50696
|
];
|
|
50553
50697
|
}
|
|
50698
|
+
var CONTENT_DEDUP_WINDOW = 4;
|
|
50699
|
+
var SYSTEM_DEDUP_WINDOW = 10;
|
|
50700
|
+
function hasRecentMessage(prev, predicate, window2) {
|
|
50701
|
+
const start = Math.max(0, prev.length - window2);
|
|
50702
|
+
for (let i = prev.length - 1; i >= start; i--) {
|
|
50703
|
+
if (predicate(prev[i])) return true;
|
|
50704
|
+
}
|
|
50705
|
+
return false;
|
|
50706
|
+
}
|
|
50707
|
+
function appendToTrailingAssistant(prev, segments) {
|
|
50708
|
+
if (segments.length === 0) return prev;
|
|
50709
|
+
const last = prev[prev.length - 1];
|
|
50710
|
+
if (!last || last.role !== "assistant") {
|
|
50711
|
+
return [
|
|
50712
|
+
...prev,
|
|
50713
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments }
|
|
50714
|
+
];
|
|
50715
|
+
}
|
|
50716
|
+
const merged = [...last.segments ?? []];
|
|
50717
|
+
for (const seg of segments) {
|
|
50718
|
+
const tail = merged[merged.length - 1];
|
|
50719
|
+
if (seg.type === "text" && tail?.type === "text") {
|
|
50720
|
+
merged[merged.length - 1] = { type: "text", text: tail.text + seg.text };
|
|
50721
|
+
} else if (seg.type === "thinking" && tail?.type === "thinking") {
|
|
50722
|
+
merged[merged.length - 1] = { type: "thinking", text: tail.text + seg.text };
|
|
50723
|
+
} else if (seg.type === "approval_batch") {
|
|
50724
|
+
const idx = merged.findIndex(
|
|
50725
|
+
(m) => m.type === "approval_batch" && m.data.approvalRequestId === seg.data.approvalRequestId
|
|
50726
|
+
);
|
|
50727
|
+
if (idx !== -1) merged[idx] = seg;
|
|
50728
|
+
else merged.push(seg);
|
|
50729
|
+
} else if (seg.type === "approval_request") {
|
|
50730
|
+
const idx = merged.findIndex(
|
|
50731
|
+
(m) => m.type === "approval_request" && m.data.requestId === seg.data.requestId && m.data.command === seg.data.command
|
|
50732
|
+
);
|
|
50733
|
+
if (idx !== -1) merged[idx] = seg;
|
|
50734
|
+
else merged.push(seg);
|
|
50735
|
+
} else {
|
|
50736
|
+
merged.push(seg);
|
|
50737
|
+
}
|
|
50738
|
+
}
|
|
50739
|
+
return [...prev.slice(0, -1), { ...last, segments: merged }];
|
|
50740
|
+
}
|
|
50741
|
+
function upsertTrailingCompaction(prev, segments) {
|
|
50742
|
+
const compaction = [...segments].reverse().find((s) => s.type === "context_compaction");
|
|
50743
|
+
if (!compaction) return prev;
|
|
50744
|
+
const last = prev[prev.length - 1];
|
|
50745
|
+
if (!last || last.role !== "assistant") {
|
|
50746
|
+
return [
|
|
50747
|
+
...prev,
|
|
50748
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments: [compaction] }
|
|
50749
|
+
];
|
|
50750
|
+
}
|
|
50751
|
+
const existing = last.segments ?? [];
|
|
50752
|
+
const startedIdx = existing.map((s) => s.type === "context_compaction" && s.status === "started").lastIndexOf(true);
|
|
50753
|
+
const merged = startedIdx !== -1 ? existing.map((s, i) => i === startedIdx ? compaction : s) : [...existing, compaction];
|
|
50754
|
+
return [...prev.slice(0, -1), { ...last, segments: merged }];
|
|
50755
|
+
}
|
|
50756
|
+
function applyToolExecutionToMessages(prev, segment) {
|
|
50757
|
+
const toolData = segment.data;
|
|
50758
|
+
const execId = toolData.toolExecutionRequestId;
|
|
50759
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
50760
|
+
const message2 = prev[i];
|
|
50761
|
+
if (message2.role !== "assistant" || !message2.segments) continue;
|
|
50762
|
+
for (let j = message2.segments.length - 1; j >= 0; j--) {
|
|
50763
|
+
const seg = message2.segments[j];
|
|
50764
|
+
if (execId && seg.type === "approval_batch" && seg.data.toolCalls.some((c) => c.toolExecutionRequestId === execId)) {
|
|
50765
|
+
const prevExec = seg.data.executions?.[execId];
|
|
50766
|
+
if (toolData.type === "EXECUTING_TOOL" && prevExec?.status === "done") {
|
|
50767
|
+
return prev;
|
|
50768
|
+
}
|
|
50769
|
+
const nextExec = toolData.type === "EXECUTED_TOOL" ? { status: "done", result: toolData.result, success: toolData.success } : { status: "executing", result: prevExec?.result, success: prevExec?.success };
|
|
50770
|
+
const nextSegments = [...message2.segments];
|
|
50771
|
+
nextSegments[j] = {
|
|
50772
|
+
...seg,
|
|
50773
|
+
data: { ...seg.data, executions: { ...seg.data.executions ?? {}, [execId]: nextExec } }
|
|
50774
|
+
};
|
|
50775
|
+
const next = [...prev];
|
|
50776
|
+
next[i] = { ...message2, segments: nextSegments };
|
|
50777
|
+
return next;
|
|
50778
|
+
}
|
|
50779
|
+
if (seg.type === "tool_execution") {
|
|
50780
|
+
const matches = execId ? seg.data.toolExecutionRequestId === execId : seg.data.type === "EXECUTING_TOOL" && seg.data.integratedToolType === toolData.integratedToolType && seg.data.toolFunction === toolData.toolFunction;
|
|
50781
|
+
if (!matches) continue;
|
|
50782
|
+
if (toolData.type === "EXECUTING_TOOL" && seg.data.type === "EXECUTED_TOOL") {
|
|
50783
|
+
return prev;
|
|
50784
|
+
}
|
|
50785
|
+
const nextSegments = [...message2.segments];
|
|
50786
|
+
nextSegments[j] = {
|
|
50787
|
+
type: "tool_execution",
|
|
50788
|
+
data: {
|
|
50789
|
+
...toolData,
|
|
50790
|
+
toolTitle: toolData.toolTitle ?? seg.data.toolTitle,
|
|
50791
|
+
parameters: toolData.parameters || seg.data.parameters
|
|
50792
|
+
}
|
|
50793
|
+
};
|
|
50794
|
+
const next = [...prev];
|
|
50795
|
+
next[i] = { ...message2, segments: nextSegments };
|
|
50796
|
+
return next;
|
|
50797
|
+
}
|
|
50798
|
+
}
|
|
50799
|
+
}
|
|
50800
|
+
return appendToTrailingAssistant(prev, [segment]);
|
|
50801
|
+
}
|
|
50554
50802
|
function mapProcessedToUnified(processed) {
|
|
50555
50803
|
const out = [];
|
|
50556
50804
|
for (const m of processed) {
|
|
@@ -50590,6 +50838,7 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50590
50838
|
fetchChunks,
|
|
50591
50839
|
topics,
|
|
50592
50840
|
batchApprovalsEnabled,
|
|
50841
|
+
displayApprovalTypes,
|
|
50593
50842
|
fetchDialogs,
|
|
50594
50843
|
fetchDialogMessages,
|
|
50595
50844
|
createDialog: createDialogCallback,
|
|
@@ -50609,11 +50858,17 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50609
50858
|
const isManagedMode = fetchDialogs !== void 0;
|
|
50610
50859
|
const [internalDialogId, setInternalDialogId] = useState116(null);
|
|
50611
50860
|
const dialogId = isManagedMode ? internalDialogId : controlledDialogId !== void 0 ? controlledDialogId : null;
|
|
50861
|
+
const currentDialogIdRef = useRef73(dialogId);
|
|
50862
|
+
currentDialogIdRef.current = dialogId;
|
|
50612
50863
|
const [messages, setMessages] = useState116([]);
|
|
50613
50864
|
const [streamingPhase, setStreamingPhase] = useState116("idle");
|
|
50614
|
-
const streamingPhaseRef =
|
|
50865
|
+
const streamingPhaseRef = useRef73(streamingPhase);
|
|
50615
50866
|
streamingPhaseRef.current = streamingPhase;
|
|
50616
|
-
const suppressAgentBusyRef =
|
|
50867
|
+
const suppressAgentBusyRef = useRef73(0);
|
|
50868
|
+
const adoptTrailingAssistantRef = useRef73(false);
|
|
50869
|
+
const hasConnectedOnceRef = useRef73(false);
|
|
50870
|
+
const seenParticipantSeqsRef = useRef73(/* @__PURE__ */ new Set());
|
|
50871
|
+
const pendingEchoTextsRef = useRef73([]);
|
|
50617
50872
|
const [approvalStatuses, setApprovalStatuses] = useState116({});
|
|
50618
50873
|
const [dialogs, setDialogs] = useState116([]);
|
|
50619
50874
|
const [dialogsNextCursor, setDialogsNextCursor] = useState116(null);
|
|
@@ -50666,9 +50921,9 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50666
50921
|
},
|
|
50667
50922
|
[rejectRequestCallback]
|
|
50668
50923
|
);
|
|
50669
|
-
const handleApproveRef =
|
|
50924
|
+
const handleApproveRef = useRef73(handleApprove);
|
|
50670
50925
|
handleApproveRef.current = handleApprove;
|
|
50671
|
-
const handleRejectRef =
|
|
50926
|
+
const handleRejectRef = useRef73(handleReject);
|
|
50672
50927
|
handleRejectRef.current = handleReject;
|
|
50673
50928
|
const accumApprove = useCallback53((requestId) => {
|
|
50674
50929
|
if (!requestId) return;
|
|
@@ -50678,18 +50933,40 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50678
50933
|
if (!requestId) return;
|
|
50679
50934
|
return handleRejectRef.current(requestId);
|
|
50680
50935
|
}, []);
|
|
50681
|
-
const callbacksRef =
|
|
50682
|
-
onSegmentsUpdate: (segments) => {
|
|
50936
|
+
const callbacksRef = useRef73({
|
|
50937
|
+
onSegmentsUpdate: (segments, meta) => {
|
|
50938
|
+
if (meta?.append && meta.isCompacting) {
|
|
50939
|
+
setMessages((prev) => upsertTrailingCompaction(prev, segments));
|
|
50940
|
+
return;
|
|
50941
|
+
}
|
|
50942
|
+
if (meta?.append) {
|
|
50943
|
+
setMessages((prev) => appendToTrailingAssistant(prev, segments));
|
|
50944
|
+
return;
|
|
50945
|
+
}
|
|
50683
50946
|
setMessages((prev) => updateTrailingAssistant(prev, segments));
|
|
50684
50947
|
},
|
|
50685
|
-
onStreamStart: () =>
|
|
50948
|
+
onStreamStart: () => {
|
|
50949
|
+
setStreamingPhase("streaming");
|
|
50950
|
+
const adoptTail = adoptTrailingAssistantRef.current;
|
|
50951
|
+
adoptTrailingAssistantRef.current = false;
|
|
50952
|
+
setMessages((prev) => {
|
|
50953
|
+
const last = prev[prev.length - 1];
|
|
50954
|
+
if (!last || last.role !== "assistant" || adoptTail) return prev;
|
|
50955
|
+
const hasContent = (last.segments?.length ?? 0) > 0 || last.content !== "";
|
|
50956
|
+
if (!hasContent) return prev;
|
|
50957
|
+
return [
|
|
50958
|
+
...prev,
|
|
50959
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments: [] }
|
|
50960
|
+
];
|
|
50961
|
+
});
|
|
50962
|
+
},
|
|
50686
50963
|
onStreamEnd: () => setStreamingPhase("idle"),
|
|
50687
50964
|
// Agent is executing (approved) commands outside an open stream — keep
|
|
50688
50965
|
// the composer locked exactly like the in-stream phases. An open stream
|
|
50689
50966
|
// keeps ownership: only 'idle' upgrades to 'thinking'. Suppressed during
|
|
50690
50967
|
// initial catchup so a replayed dead tail can't lock a finished dialog.
|
|
50691
50968
|
onAgentBusy: () => {
|
|
50692
|
-
if (suppressAgentBusyRef.current) return;
|
|
50969
|
+
if (suppressAgentBusyRef.current > 0) return;
|
|
50693
50970
|
setStreamingPhase((p) => p === "idle" ? "thinking" : p);
|
|
50694
50971
|
},
|
|
50695
50972
|
// Terminal turn failures can arrive without a MESSAGE_END; unlock the
|
|
@@ -50704,33 +50981,177 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50704
50981
|
provider: meta.providerName || null,
|
|
50705
50982
|
modelLabel: meta.modelDisplayName || meta.modelName || null,
|
|
50706
50983
|
contextWindowMaxTokens: meta.contextWindow || null
|
|
50707
|
-
})
|
|
50984
|
+
}),
|
|
50985
|
+
// Post-MESSAGE_END tool chunks (approved commands executing after the
|
|
50986
|
+
// approval bubble, async batch results). Routed through the cross-message
|
|
50987
|
+
// updater — the accumulator was reset at MESSAGE_END, so the old
|
|
50988
|
+
// fallthrough replaced the whole trailing bubble with one tool segment.
|
|
50989
|
+
onToolExecuted: (segment) => {
|
|
50990
|
+
setMessages((prev) => applyToolExecutionToMessages(prev, segment));
|
|
50991
|
+
},
|
|
50992
|
+
// Cross-message approval status flip. Wiring this also makes the
|
|
50993
|
+
// processor skip its cumulative re-emit for resolved approvals — which,
|
|
50994
|
+
// post-MESSAGE_END, was an empty array that blanked the trailing bubble.
|
|
50995
|
+
onApprovalResolved: (requestId, status, _approvalType, resolvedByName) => {
|
|
50996
|
+
setMessages((prev) => {
|
|
50997
|
+
let changed = false;
|
|
50998
|
+
const next = prev.map((m) => {
|
|
50999
|
+
if (m.role !== "assistant" || !m.segments) return m;
|
|
51000
|
+
let msgChanged = false;
|
|
51001
|
+
const segs = m.segments.map((s) => {
|
|
51002
|
+
if (s.type === "approval_request" && s.data.requestId === requestId && s.status !== status) {
|
|
51003
|
+
msgChanged = true;
|
|
51004
|
+
return { ...s, status };
|
|
51005
|
+
}
|
|
51006
|
+
if (s.type === "approval_batch" && s.data.approvalRequestId === requestId) {
|
|
51007
|
+
const nextResolvedBy = resolvedByName ?? s.resolvedByName;
|
|
51008
|
+
if (s.status === status && nextResolvedBy === s.resolvedByName) return s;
|
|
51009
|
+
msgChanged = true;
|
|
51010
|
+
return { ...s, status, resolvedByName: nextResolvedBy };
|
|
51011
|
+
}
|
|
51012
|
+
return s;
|
|
51013
|
+
});
|
|
51014
|
+
if (!msgChanged) return m;
|
|
51015
|
+
changed = true;
|
|
51016
|
+
return { ...m, segments: segs };
|
|
51017
|
+
});
|
|
51018
|
+
return changed ? next : prev;
|
|
51019
|
+
});
|
|
51020
|
+
setApprovalStatuses(
|
|
51021
|
+
(prev) => prev[requestId] === status ? prev : { ...prev, [requestId]: status }
|
|
51022
|
+
);
|
|
51023
|
+
},
|
|
51024
|
+
// MESSAGE_REQUEST echo — a user message from THIS or another session.
|
|
51025
|
+
onUserMessage: (text, meta) => {
|
|
51026
|
+
if (!text) return;
|
|
51027
|
+
const seq = meta?.streamSeq;
|
|
51028
|
+
if (typeof seq === "number") {
|
|
51029
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51030
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51031
|
+
}
|
|
51032
|
+
if (meta?.ownerType !== "ADMIN") {
|
|
51033
|
+
const echoIdx = pendingEchoTextsRef.current.indexOf(text);
|
|
51034
|
+
if (echoIdx !== -1) {
|
|
51035
|
+
pendingEchoTextsRef.current.splice(echoIdx, 1);
|
|
51036
|
+
return;
|
|
51037
|
+
}
|
|
51038
|
+
}
|
|
51039
|
+
const authorType = meta?.ownerType === "ADMIN" ? "admin" : "user";
|
|
51040
|
+
setMessages((prev) => {
|
|
51041
|
+
if (typeof seq !== "number" && hasRecentMessage(
|
|
51042
|
+
prev,
|
|
51043
|
+
(m) => m.role === "user" && (m.authorType ?? "user") === authorType && m.content === text,
|
|
51044
|
+
CONTENT_DEDUP_WINDOW
|
|
51045
|
+
)) {
|
|
51046
|
+
return prev;
|
|
51047
|
+
}
|
|
51048
|
+
return [
|
|
51049
|
+
...prev,
|
|
51050
|
+
{
|
|
51051
|
+
id: nextId("user"),
|
|
51052
|
+
role: "user",
|
|
51053
|
+
content: text,
|
|
51054
|
+
...meta?.displayName ? { name: meta.displayName } : {},
|
|
51055
|
+
authorType,
|
|
51056
|
+
...meta?.contextItems && meta.contextItems.length > 0 ? {
|
|
51057
|
+
contextItems: meta.contextItems.map((ci) => ({
|
|
51058
|
+
type: ci.type,
|
|
51059
|
+
id: ci.id,
|
|
51060
|
+
label: ci.label ?? ci.id
|
|
51061
|
+
}))
|
|
51062
|
+
} : {}
|
|
51063
|
+
}
|
|
51064
|
+
];
|
|
51065
|
+
});
|
|
51066
|
+
},
|
|
51067
|
+
// Technician / admin direct message into the dialog.
|
|
51068
|
+
onDirectMessage: (text, meta) => {
|
|
51069
|
+
if (!text) return;
|
|
51070
|
+
const seq = meta?.streamSeq;
|
|
51071
|
+
if (typeof seq === "number") {
|
|
51072
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51073
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51074
|
+
}
|
|
51075
|
+
setMessages((prev) => {
|
|
51076
|
+
if (typeof seq !== "number" && hasRecentMessage(
|
|
51077
|
+
prev,
|
|
51078
|
+
(m) => m.role === "user" && m.authorType === "admin" && m.content === text,
|
|
51079
|
+
CONTENT_DEDUP_WINDOW
|
|
51080
|
+
)) {
|
|
51081
|
+
return prev;
|
|
51082
|
+
}
|
|
51083
|
+
return [
|
|
51084
|
+
...prev,
|
|
51085
|
+
{
|
|
51086
|
+
id: `direct-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
51087
|
+
role: "user",
|
|
51088
|
+
content: text,
|
|
51089
|
+
name: meta?.displayName ?? "Admin",
|
|
51090
|
+
authorType: "admin"
|
|
51091
|
+
}
|
|
51092
|
+
];
|
|
51093
|
+
});
|
|
51094
|
+
},
|
|
51095
|
+
// System notice — rendered as a name-only row (same shape the history
|
|
51096
|
+
// processor produces via `pushStandaloneMessages`).
|
|
51097
|
+
onSystemMessage: (text, meta) => {
|
|
51098
|
+
if (!text) return;
|
|
51099
|
+
const seq = meta?.streamSeq;
|
|
51100
|
+
if (typeof seq === "number") {
|
|
51101
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51102
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51103
|
+
}
|
|
51104
|
+
setMessages((prev) => {
|
|
51105
|
+
if (typeof seq !== "number" && hasRecentMessage(prev, (m) => m.authorType === "system" && m.name === text, SYSTEM_DEDUP_WINDOW)) {
|
|
51106
|
+
return prev;
|
|
51107
|
+
}
|
|
51108
|
+
return [
|
|
51109
|
+
...prev,
|
|
51110
|
+
{
|
|
51111
|
+
id: `system-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
51112
|
+
role: "user",
|
|
51113
|
+
content: "",
|
|
51114
|
+
name: text,
|
|
51115
|
+
authorType: "system"
|
|
51116
|
+
}
|
|
51117
|
+
];
|
|
51118
|
+
});
|
|
51119
|
+
}
|
|
50708
51120
|
});
|
|
50709
51121
|
const { processChunk, reset: resetAccumulator } = useRealtimeChunkProcessor({
|
|
50710
51122
|
callbacks: {
|
|
50711
|
-
onSegmentsUpdate: (segments) => callbacksRef.current.onSegmentsUpdate(segments),
|
|
51123
|
+
onSegmentsUpdate: (segments, meta) => callbacksRef.current.onSegmentsUpdate(segments, meta),
|
|
50712
51124
|
onStreamStart: () => callbacksRef.current.onStreamStart(),
|
|
50713
51125
|
onStreamEnd: () => callbacksRef.current.onStreamEnd(),
|
|
50714
51126
|
onAgentBusy: () => callbacksRef.current.onAgentBusy(),
|
|
50715
51127
|
onError: () => callbacksRef.current.onError(),
|
|
50716
51128
|
onTokenUsage: (data) => callbacksRef.current.onTokenUsage(data),
|
|
50717
51129
|
onMetadata: (meta) => callbacksRef.current.onMetadata(meta),
|
|
51130
|
+
onToolExecuted: (segment) => callbacksRef.current.onToolExecuted(segment),
|
|
51131
|
+
onApprovalResolved: (requestId, status, approvalType, resolvedByName) => callbacksRef.current.onApprovalResolved(requestId, status, approvalType, resolvedByName),
|
|
51132
|
+
onUserMessage: (text, meta) => callbacksRef.current.onUserMessage(text, meta),
|
|
51133
|
+
onDirectMessage: (text, meta) => callbacksRef.current.onDirectMessage(text, meta),
|
|
51134
|
+
onSystemMessage: (text, meta) => callbacksRef.current.onSystemMessage(text, meta),
|
|
50718
51135
|
onApprove: accumApprove,
|
|
50719
51136
|
onReject: accumReject
|
|
50720
51137
|
},
|
|
50721
|
-
batchApprovalsEnabled
|
|
51138
|
+
batchApprovalsEnabled,
|
|
51139
|
+
approvalStatuses,
|
|
51140
|
+
...displayApprovalTypes ? { displayApprovalTypes } : {}
|
|
50722
51141
|
});
|
|
50723
51142
|
const {
|
|
50724
51143
|
processChunk: catchupProcessChunk,
|
|
50725
51144
|
catchUpChunks,
|
|
50726
51145
|
startInitialBuffering,
|
|
50727
|
-
resetChunkTracking
|
|
51146
|
+
resetChunkTracking,
|
|
51147
|
+
resetAndCatchUp,
|
|
51148
|
+
isBufferingActive
|
|
50728
51149
|
} = useChunkCatchup({
|
|
50729
51150
|
dialogId: active ? dialogId : null,
|
|
50730
51151
|
onChunkReceived: (chunk) => processChunk(chunk),
|
|
50731
51152
|
fetchChunks
|
|
50732
51153
|
});
|
|
50733
|
-
const historyLoadSeqRef =
|
|
51154
|
+
const historyLoadSeqRef = useRef73(0);
|
|
50734
51155
|
const loadDialogHistory = useCallback53(
|
|
50735
51156
|
async (id, cursor) => {
|
|
50736
51157
|
if (!fetchDialogMessages) return;
|
|
@@ -50753,11 +51174,13 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50753
51174
|
onApprove: accumApprove,
|
|
50754
51175
|
onReject: accumReject,
|
|
50755
51176
|
approvalStatuses,
|
|
50756
|
-
batchApprovalsEnabled
|
|
51177
|
+
batchApprovalsEnabled,
|
|
51178
|
+
...displayApprovalTypes ? { displayApprovalTypes } : {}
|
|
50757
51179
|
}
|
|
50758
51180
|
);
|
|
50759
51181
|
const unified = mapProcessedToUnified(rawProcessed);
|
|
50760
51182
|
if (cursor === void 0) {
|
|
51183
|
+
adoptTrailingAssistantRef.current = isBufferingActive() && extractIncompleteMessageState(rawProcessed[rawProcessed.length - 1]) !== void 0;
|
|
50761
51184
|
setMessages(unified);
|
|
50762
51185
|
} else {
|
|
50763
51186
|
setMessages((prev) => [...unified, ...prev]);
|
|
@@ -50781,16 +51204,21 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50781
51204
|
chatTypeFilter,
|
|
50782
51205
|
approvalStatuses,
|
|
50783
51206
|
batchApprovalsEnabled,
|
|
51207
|
+
displayApprovalTypes,
|
|
50784
51208
|
accumApprove,
|
|
50785
|
-
accumReject
|
|
51209
|
+
accumReject,
|
|
51210
|
+
isBufferingActive
|
|
50786
51211
|
]
|
|
50787
51212
|
);
|
|
50788
|
-
const prevDialogIdRef =
|
|
51213
|
+
const prevDialogIdRef = useRef73(void 0);
|
|
50789
51214
|
useEffect88(() => {
|
|
50790
51215
|
if (prevDialogIdRef.current === dialogId) return;
|
|
50791
51216
|
prevDialogIdRef.current = dialogId;
|
|
50792
51217
|
historyLoadSeqRef.current += 1;
|
|
50793
51218
|
resetAccumulator();
|
|
51219
|
+
adoptTrailingAssistantRef.current = false;
|
|
51220
|
+
seenParticipantSeqsRef.current.clear();
|
|
51221
|
+
pendingEchoTextsRef.current = [];
|
|
50794
51222
|
setMessages([]);
|
|
50795
51223
|
setMessagesNextCursor(null);
|
|
50796
51224
|
setDialogTokenUsage(null);
|
|
@@ -50802,13 +51230,16 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50802
51230
|
}, [active, dialogId, loadDialogHistory, resetAccumulator]);
|
|
50803
51231
|
useEffect88(() => {
|
|
50804
51232
|
if (!active || !dialogId) return;
|
|
50805
|
-
suppressAgentBusyRef.current
|
|
51233
|
+
suppressAgentBusyRef.current += 1;
|
|
50806
51234
|
resetChunkTracking();
|
|
50807
51235
|
startInitialBuffering();
|
|
50808
51236
|
catchUpChunks().catch((err) => {
|
|
50809
51237
|
console.error("[useNatsChatAdapter] initial catchup failed:", err);
|
|
50810
51238
|
}).finally(() => {
|
|
50811
|
-
suppressAgentBusyRef.current =
|
|
51239
|
+
suppressAgentBusyRef.current = Math.max(0, suppressAgentBusyRef.current - 1);
|
|
51240
|
+
if (dialogId === currentDialogIdRef.current) {
|
|
51241
|
+
adoptTrailingAssistantRef.current = false;
|
|
51242
|
+
}
|
|
50812
51243
|
});
|
|
50813
51244
|
}, [active, dialogId, resetChunkTracking, startInitialBuffering, catchUpChunks]);
|
|
50814
51245
|
useNatsDialogSubscription({
|
|
@@ -50823,6 +51254,30 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50823
51254
|
onEvent: (payload, messageType) => {
|
|
50824
51255
|
catchupProcessChunk(payload, messageType);
|
|
50825
51256
|
setConnectionState("connected");
|
|
51257
|
+
},
|
|
51258
|
+
onConnect: () => {
|
|
51259
|
+
if (!hasConnectedOnceRef.current) {
|
|
51260
|
+
hasConnectedOnceRef.current = true;
|
|
51261
|
+
return;
|
|
51262
|
+
}
|
|
51263
|
+
suppressAgentBusyRef.current += 1;
|
|
51264
|
+
startInitialBuffering();
|
|
51265
|
+
void (async () => {
|
|
51266
|
+
try {
|
|
51267
|
+
if (dialogId && fetchDialogMessages) {
|
|
51268
|
+
await loadDialogHistory(dialogId);
|
|
51269
|
+
}
|
|
51270
|
+
if (dialogId !== currentDialogIdRef.current) return;
|
|
51271
|
+
await resetAndCatchUp();
|
|
51272
|
+
} catch (err) {
|
|
51273
|
+
console.error("[useNatsChatAdapter] reconnect catchup failed:", err);
|
|
51274
|
+
} finally {
|
|
51275
|
+
suppressAgentBusyRef.current = Math.max(0, suppressAgentBusyRef.current - 1);
|
|
51276
|
+
if (dialogId === currentDialogIdRef.current) {
|
|
51277
|
+
adoptTrailingAssistantRef.current = false;
|
|
51278
|
+
}
|
|
51279
|
+
}
|
|
51280
|
+
})();
|
|
50826
51281
|
}
|
|
50827
51282
|
});
|
|
50828
51283
|
useEffect88(() => {
|
|
@@ -50832,7 +51287,7 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50832
51287
|
}
|
|
50833
51288
|
setConnectionState("connecting");
|
|
50834
51289
|
}, [active, dialogId]);
|
|
50835
|
-
const initialDialogsLoadedRef =
|
|
51290
|
+
const initialDialogsLoadedRef = useRef73(false);
|
|
50836
51291
|
const loadDialogsPage = useCallback53(
|
|
50837
51292
|
async (cursor) => {
|
|
50838
51293
|
if (!fetchDialogs) return;
|
|
@@ -50874,6 +51329,8 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50874
51329
|
const sendMessage = useCallback53(
|
|
50875
51330
|
async (text, sendOptions) => {
|
|
50876
51331
|
const hidden = sendOptions?.hidden ?? false;
|
|
51332
|
+
pendingEchoTextsRef.current.push(text);
|
|
51333
|
+
if (pendingEchoTextsRef.current.length > 5) pendingEchoTextsRef.current.shift();
|
|
50877
51334
|
setMessages((prev) => [
|
|
50878
51335
|
...prev,
|
|
50879
51336
|
{
|
|
@@ -51105,7 +51562,7 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
51105
51562
|
}
|
|
51106
51563
|
|
|
51107
51564
|
// src/components/chat/hooks/use-unified-chat.ts
|
|
51108
|
-
import { useCallback as useCallback54, useMemo as useMemo44, useRef as
|
|
51565
|
+
import { useCallback as useCallback54, useMemo as useMemo44, useRef as useRef74 } from "react";
|
|
51109
51566
|
var EMPTY_SSE_OPTIONS = {};
|
|
51110
51567
|
function createDisabledNatsConfig() {
|
|
51111
51568
|
return {
|
|
@@ -51120,7 +51577,7 @@ function createDisabledNatsConfig() {
|
|
|
51120
51577
|
}
|
|
51121
51578
|
function useUnifiedChat(options) {
|
|
51122
51579
|
const { modes, activeMode, mingoStateOverride } = options;
|
|
51123
|
-
const disabledNatsRef =
|
|
51580
|
+
const disabledNatsRef = useRef74(null);
|
|
51124
51581
|
if (disabledNatsRef.current === null) {
|
|
51125
51582
|
disabledNatsRef.current = createDisabledNatsConfig();
|
|
51126
51583
|
}
|
|
@@ -51134,7 +51591,7 @@ function useUnifiedChat(options) {
|
|
|
51134
51591
|
{ active: natsActive }
|
|
51135
51592
|
);
|
|
51136
51593
|
const activeState = activeMode === "guide" ? sseState : mingoStateOverride ?? natsState;
|
|
51137
|
-
const activeStateRef =
|
|
51594
|
+
const activeStateRef = useRef74(activeState);
|
|
51138
51595
|
activeStateRef.current = activeState;
|
|
51139
51596
|
const stopMessage = useCallback54(() => activeStateRef.current.stopMessage(), []);
|
|
51140
51597
|
const clearMessages = useCallback54(
|
|
@@ -51254,65 +51711,6 @@ function useUnifiedChat(options) {
|
|
|
51254
51711
|
);
|
|
51255
51712
|
}
|
|
51256
51713
|
|
|
51257
|
-
// src/components/chat/utils/extract-incomplete-message-state.ts
|
|
51258
|
-
function extractIncompleteMessageState(lastMessage) {
|
|
51259
|
-
if (!lastMessage || lastMessage.role !== "assistant" || typeof lastMessage.content === "string") {
|
|
51260
|
-
return void 0;
|
|
51261
|
-
}
|
|
51262
|
-
const segments = lastMessage.content;
|
|
51263
|
-
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
51264
|
-
const executingTools = /* @__PURE__ */ new Map();
|
|
51265
|
-
let hasIncompleteState = false;
|
|
51266
|
-
segments.forEach((segment) => {
|
|
51267
|
-
switch (segment.type) {
|
|
51268
|
-
case "tool_execution":
|
|
51269
|
-
if (segment.data.type === "EXECUTING_TOOL") {
|
|
51270
|
-
const toolKey = segment.data.toolExecutionRequestId || `${segment.data.integratedToolType}-${segment.data.toolFunction}`;
|
|
51271
|
-
executingTools.set(toolKey, {
|
|
51272
|
-
integratedToolType: segment.data.integratedToolType,
|
|
51273
|
-
toolFunction: segment.data.toolFunction,
|
|
51274
|
-
toolTitle: segment.data.toolTitle,
|
|
51275
|
-
parameters: segment.data.parameters
|
|
51276
|
-
});
|
|
51277
|
-
hasIncompleteState = true;
|
|
51278
|
-
}
|
|
51279
|
-
break;
|
|
51280
|
-
case "approval_request":
|
|
51281
|
-
if (segment.status === "pending" && segment.data.requestId) {
|
|
51282
|
-
pendingApprovals.set(segment.data.requestId, {
|
|
51283
|
-
command: segment.data.command,
|
|
51284
|
-
explanation: segment.data.explanation,
|
|
51285
|
-
approvalType: segment.data.approvalType || "CLIENT"
|
|
51286
|
-
});
|
|
51287
|
-
hasIncompleteState = true;
|
|
51288
|
-
}
|
|
51289
|
-
break;
|
|
51290
|
-
case "approval_batch": {
|
|
51291
|
-
const allDone = !!segment.data.executions && segment.data.toolCalls.every(
|
|
51292
|
-
(c) => segment.data.executions?.[c.toolExecutionRequestId]?.status === "done"
|
|
51293
|
-
);
|
|
51294
|
-
if (segment.status !== "rejected" && !allDone) {
|
|
51295
|
-
hasIncompleteState = true;
|
|
51296
|
-
}
|
|
51297
|
-
break;
|
|
51298
|
-
}
|
|
51299
|
-
case "context_compaction":
|
|
51300
|
-
if (segment.status === "started") {
|
|
51301
|
-
hasIncompleteState = true;
|
|
51302
|
-
}
|
|
51303
|
-
break;
|
|
51304
|
-
}
|
|
51305
|
-
});
|
|
51306
|
-
if (!hasIncompleteState) {
|
|
51307
|
-
return void 0;
|
|
51308
|
-
}
|
|
51309
|
-
return {
|
|
51310
|
-
existingSegments: segments,
|
|
51311
|
-
pendingApprovals: pendingApprovals.size > 0 ? pendingApprovals : void 0,
|
|
51312
|
-
executingTools: executingTools.size > 0 ? executingTools : void 0
|
|
51313
|
-
};
|
|
51314
|
-
}
|
|
51315
|
-
|
|
51316
51714
|
// src/components/chat/utils/history-merge.ts
|
|
51317
51715
|
var SYNTHETIC_REALTIME_ID_PREFIXES = ["assistant-", "user-", "direct-", "system-", "error-"];
|
|
51318
51716
|
function isSyntheticRealtimeId(id) {
|
|
@@ -51503,7 +51901,7 @@ function buildStreamFrames(messages) {
|
|
|
51503
51901
|
|
|
51504
51902
|
// src/components/chat/embeddable-chat.tsx
|
|
51505
51903
|
init_cn();
|
|
51506
|
-
import { useCallback as useCallback56, useEffect as useEffect89, useMemo as useMemo46, useRef as
|
|
51904
|
+
import { useCallback as useCallback56, useEffect as useEffect89, useMemo as useMemo46, useRef as useRef76, useState as useState118 } from "react";
|
|
51507
51905
|
import * as DialogPrimitive4 from "@radix-ui/react-dialog";
|
|
51508
51906
|
import { usePreventScroll as usePreventScroll6 } from "@react-aria/overlays";
|
|
51509
51907
|
import { isIOS } from "@react-aria/utils";
|
|
@@ -51584,7 +51982,7 @@ init_button2();
|
|
|
51584
51982
|
import { FileText as FileText8, MessageSquare as MessageSquare3 } from "lucide-react";
|
|
51585
51983
|
|
|
51586
51984
|
// src/components/chat/hooks/use-chat-dialog-manager.ts
|
|
51587
|
-
import { useCallback as useCallback55, useMemo as useMemo45, useRef as
|
|
51985
|
+
import { useCallback as useCallback55, useMemo as useMemo45, useRef as useRef75, useState as useState117 } from "react";
|
|
51588
51986
|
function useChatDialogManager({
|
|
51589
51987
|
dialogs,
|
|
51590
51988
|
activeDialogId,
|
|
@@ -51624,7 +52022,7 @@ function useChatDialogManager({
|
|
|
51624
52022
|
const [archivedCursor, setArchivedCursor] = useState117(null);
|
|
51625
52023
|
const [archivedLoading, setArchivedLoading] = useState117(false);
|
|
51626
52024
|
const [archivedPending, setArchivedPending] = useState117(false);
|
|
51627
|
-
const archivedRequestIdRef =
|
|
52025
|
+
const archivedRequestIdRef = useRef75(0);
|
|
51628
52026
|
const loadArchivedPage = useCallback55(
|
|
51629
52027
|
async (cursor) => {
|
|
51630
52028
|
if (!fetchArchivedDialogs) return;
|
|
@@ -52121,7 +52519,7 @@ function EmbeddableChatInner({
|
|
|
52121
52519
|
return !window.matchMedia("(pointer: coarse)").matches;
|
|
52122
52520
|
});
|
|
52123
52521
|
usePreventScroll6({ isDisabled: !isOpen || shellLess });
|
|
52124
|
-
const navigatingAwayRef =
|
|
52522
|
+
const navigatingAwayRef = useRef76(false);
|
|
52125
52523
|
useEffect89(() => {
|
|
52126
52524
|
if (!isOpen) return;
|
|
52127
52525
|
if (shellLess) return;
|
|
@@ -52148,7 +52546,7 @@ function EmbeddableChatInner({
|
|
|
52148
52546
|
window.scrollTo(0, scrollY);
|
|
52149
52547
|
};
|
|
52150
52548
|
}, [isOpen, shellLess]);
|
|
52151
|
-
const chatInputRef =
|
|
52549
|
+
const chatInputRef = useRef76(null);
|
|
52152
52550
|
const [quickActionPreview, setQuickActionPreview] = useState118(null);
|
|
52153
52551
|
const slashCommandsProp = useMemo46(
|
|
52154
52552
|
() => ({
|
|
@@ -52252,7 +52650,7 @@ function EmbeddableChatInner({
|
|
|
52252
52650
|
hasMoreMessages,
|
|
52253
52651
|
loadMoreMessages
|
|
52254
52652
|
} = useUnifiedChat({ modes: effectiveModes, activeMode, mingoStateOverride: mingoState });
|
|
52255
|
-
const guidePromptSentRef =
|
|
52653
|
+
const guidePromptSentRef = useRef76(false);
|
|
52256
52654
|
useEffect89(() => {
|
|
52257
52655
|
if (!guidePendingPrompt) {
|
|
52258
52656
|
guidePromptSentRef.current = false;
|
|
@@ -52277,11 +52675,11 @@ function EmbeddableChatInner({
|
|
|
52277
52675
|
const [contextItems, setContextItems] = useState118([]);
|
|
52278
52676
|
const [contextPickerOpen, setContextPickerOpen] = useState118(false);
|
|
52279
52677
|
const [mentionQuery, setMentionQuery] = useState118(null);
|
|
52280
|
-
const mentionActiveRef =
|
|
52678
|
+
const mentionActiveRef = useRef76(false);
|
|
52281
52679
|
useEffect89(() => {
|
|
52282
52680
|
mentionActiveRef.current = mentionQuery !== null;
|
|
52283
52681
|
}, [mentionQuery]);
|
|
52284
|
-
const mentionKeysRef =
|
|
52682
|
+
const mentionKeysRef = useRef76(/* @__PURE__ */ new Set());
|
|
52285
52683
|
useEffect89(() => {
|
|
52286
52684
|
setContextItems([]);
|
|
52287
52685
|
setMentionQuery(null);
|
|
@@ -52378,7 +52776,7 @@ function EmbeddableChatInner({
|
|
|
52378
52776
|
() => effectiveAssistantIcon ? /* @__PURE__ */ jsx362(EntityIcon, { icon: effectiveAssistantIcon, size: 24 }) : /* @__PURE__ */ jsx362(MingoIcon, { className: "h-6 w-6", cornerColor: "var(--ods-flamingo-cyan-base)" }),
|
|
52379
52777
|
[effectiveAssistantIcon]
|
|
52380
52778
|
);
|
|
52381
|
-
const timestampCacheRef =
|
|
52779
|
+
const timestampCacheRef = useRef76(/* @__PURE__ */ new Map());
|
|
52382
52780
|
const guideUserName = activeMode === "guide" ? [identityUser?.firstName, identityUser?.lastName].filter(Boolean).join(" ").trim() || identityUser?.name?.trim() || void 0 : void 0;
|
|
52383
52781
|
const guideUserAvatar = activeMode === "guide" ? identityUser?.avatarUrl?.trim() || void 0 : void 0;
|
|
52384
52782
|
const messages = useMemo46(() => {
|
|
@@ -52576,7 +52974,7 @@ function EmbeddableChatInner({
|
|
|
52576
52974
|
}, [lastAssistantMsg, chatLoading]);
|
|
52577
52975
|
const [portalHost, setPortalHost] = useState118(null);
|
|
52578
52976
|
const [panelWidth, setPanelWidth] = useState118(0);
|
|
52579
|
-
const panelMeasureRef =
|
|
52977
|
+
const panelMeasureRef = useRef76(null);
|
|
52580
52978
|
useEffect89(() => {
|
|
52581
52979
|
const el = panelMeasureRef.current;
|
|
52582
52980
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
@@ -53697,11 +54095,14 @@ export {
|
|
|
53697
54095
|
processHistoricalMessages,
|
|
53698
54096
|
extractErrorMessages,
|
|
53699
54097
|
processHistoricalMessagesWithErrors,
|
|
54098
|
+
extractIncompleteMessageState,
|
|
54099
|
+
appendToTrailingAssistant,
|
|
54100
|
+
upsertTrailingCompaction,
|
|
54101
|
+
applyToolExecutionToMessages,
|
|
53700
54102
|
mapProcessedToUnified,
|
|
53701
54103
|
historicalToUnified,
|
|
53702
54104
|
useNatsChatAdapter,
|
|
53703
54105
|
useUnifiedChat,
|
|
53704
|
-
extractIncompleteMessageState,
|
|
53705
54106
|
SYNTHETIC_REALTIME_ID_PREFIXES,
|
|
53706
54107
|
flattenMessagePagesChronological,
|
|
53707
54108
|
maxPersistedStreamSeq,
|
|
@@ -54118,4 +54519,4 @@ export {
|
|
|
54118
54519
|
LogsList,
|
|
54119
54520
|
assets
|
|
54120
54521
|
};
|
|
54121
|
-
//# sourceMappingURL=chunk-
|
|
54522
|
+
//# sourceMappingURL=chunk-MAB4TQCO.js.map
|