@adminide-stack/yantra-mobile 12.0.28-alpha.74 → 12.0.28-alpha.76
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/lib/config/constants.js +3 -1
- package/lib/config/constants.js.map +1 -1
- package/lib/config/env-config.js +2 -1
- package/lib/config/env-config.js.map +1 -1
- package/lib/hooks/useCdecliAutoConnect.js +4 -2
- package/lib/hooks/useCdecliAutoConnect.js.map +1 -1
- package/lib/hooks/useCdecliChannel.js +18 -83
- package/lib/hooks/useCdecliChannel.js.map +1 -1
- package/lib/hooks/useChatApi.js +102 -50
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +66 -241
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/usePrerequisiteIds.js +87 -75
- package/lib/hooks/usePrerequisiteIds.js.map +1 -1
- package/lib/screens/Chat/index.js +6 -11
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +37 -84
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/NewChat/index.js +8 -44
- package/lib/screens/NewChat/index.js.map +1 -1
- package/lib/utils/cdecodeUri.js +69 -0
- package/lib/utils/cdecodeUri.js.map +1 -0
- package/lib/utils/syncMobileOrgRouteContext.js +61 -0
- package/lib/utils/syncMobileOrgRouteContext.js.map +1 -0
- package/package.json +4 -4
- package/lib/api/chatApi.js +0 -102
- package/lib/api/chatApi.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useState,useRef,useCallback,useMemo,useEffect}from'react';import {useChatMutations,useChatMessages}from'./useChatApi.js';import {useCdecliChannel}from'./useCdecliChannel.js';import {usePrerequisiteIds}from'./usePrerequisiteIds.js';
|
|
1
|
+
import {useState,useRef,useCallback,useMemo,useEffect}from'react';import {useChatMutations,useChatMessages}from'./useChatApi.js';import {useCdecliChannel}from'./useCdecliChannel.js';import {usePrerequisiteIds}from'./usePrerequisiteIds.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -17,29 +17,26 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
-
const REVEAL_CHUNK_SIZE = 6;
|
|
21
|
-
const REVEAL_INTERVAL_MS = 20;
|
|
22
20
|
function isCdecliAgentFailureOutput(text) {
|
|
23
21
|
const t = text.trim();
|
|
24
22
|
if (!t) return false;
|
|
25
23
|
return /⚠\s*Error:/.test(t) || /LLM stream error/i.test(t) || /Incorrect API key/i.test(t) || /invalid_api_key/i.test(t) || /authentication_error/i.test(t);
|
|
26
24
|
}
|
|
27
25
|
function useChatStream(sessionId, routing = {
|
|
28
|
-
|
|
26
|
+
channelConnected: false,
|
|
27
|
+
accountId: "default",
|
|
28
|
+
persistenceMode: "backend"
|
|
29
29
|
}) {
|
|
30
30
|
const [messages, setMessages] = useState([]);
|
|
31
31
|
const [response, setResponse] = useState("");
|
|
32
32
|
const [isLoading, setIsLoading] = useState(false);
|
|
33
33
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
34
34
|
const [error, setError] = useState(null);
|
|
35
|
-
const abortRef = useRef(null);
|
|
36
35
|
const isSendingRef = useRef(false);
|
|
37
|
-
const revealIntervalRef = useRef(null);
|
|
38
36
|
const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState(void 0);
|
|
39
37
|
const userMsgForSaveRef = useRef(null);
|
|
40
38
|
const saveSessionIdRef = useRef(null);
|
|
41
39
|
const cdecliRoundHandledRef = useRef(false);
|
|
42
|
-
const cdecliFallbackConversationRef = useRef(null);
|
|
43
40
|
const routingRef = useRef(routing);
|
|
44
41
|
routingRef.current = routing;
|
|
45
42
|
const {
|
|
@@ -54,175 +51,34 @@ function useChatStream(sessionId, routing = {
|
|
|
54
51
|
messagesLoaded: backendMessagesLoaded
|
|
55
52
|
} = useChatMessages(sessionId);
|
|
56
53
|
const lastHydratedSessionIdRef = useRef(null);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const preferNonStreaming = typeof (g == null ? void 0 : g.nativeCallSyncHook) === "function" || typeof (g == null ? void 0 : g.__fbBatchedBridge) !== "undefined";
|
|
68
|
-
const result = await streamChatResponse(chatMessages, void 0, abortRef.current.signal, {
|
|
69
|
-
preferNonStreaming
|
|
70
|
-
});
|
|
71
|
-
const fullContent = result.content;
|
|
72
|
-
if (preferNonStreaming && fullContent.length > 0) {
|
|
73
|
-
doingChunkedReveal = true;
|
|
74
|
-
if (revealIntervalRef.current) {
|
|
75
|
-
clearInterval(revealIntervalRef.current);
|
|
76
|
-
revealIntervalRef.current = null;
|
|
77
|
-
}
|
|
78
|
-
let revealedLen = 0;
|
|
79
|
-
revealIntervalRef.current = setInterval(() => {
|
|
80
|
-
var _a2, _b2;
|
|
81
|
-
revealedLen = Math.min(revealedLen + REVEAL_CHUNK_SIZE, fullContent.length);
|
|
82
|
-
setResponse(fullContent.slice(0, revealedLen));
|
|
83
|
-
if (revealedLen >= fullContent.length) {
|
|
84
|
-
if (revealIntervalRef.current) {
|
|
85
|
-
clearInterval(revealIntervalRef.current);
|
|
86
|
-
revealIntervalRef.current = null;
|
|
87
|
-
}
|
|
88
|
-
const assistantMessage2 = {
|
|
89
|
-
role: "assistant",
|
|
90
|
-
content: fullContent,
|
|
91
|
-
metadata: result.tokenUsage ? {
|
|
92
|
-
tokenUsage: {
|
|
93
|
-
inputTokens: result.tokenUsage.inputTokens,
|
|
94
|
-
outputTokens: result.tokenUsage.outputTokens,
|
|
95
|
-
totalTokens: result.tokenUsage.totalTokens
|
|
96
|
-
}
|
|
97
|
-
} : void 0
|
|
98
|
-
};
|
|
99
|
-
setMessages((prev) => [...prev, assistantMessage2]);
|
|
100
|
-
setResponse("");
|
|
101
|
-
if (effectiveSessionId) {
|
|
102
|
-
saveMessages(__spreadProps(__spreadValues({
|
|
103
|
-
sessionId: effectiveSessionId
|
|
104
|
-
}, accountUserId ? {
|
|
105
|
-
createdBy: accountUserId
|
|
106
|
-
} : {}), {
|
|
107
|
-
userMessage: {
|
|
108
|
-
content: userMessage.content,
|
|
109
|
-
attachments: (_a2 = userMessage.attachments) == null ? void 0 : _a2.map((a) => ({
|
|
110
|
-
id: a.id,
|
|
111
|
-
name: a.name,
|
|
112
|
-
type: a.type,
|
|
113
|
-
mimeType: a.mimeType,
|
|
114
|
-
size: a.size,
|
|
115
|
-
url: a.url
|
|
116
|
-
}))
|
|
117
|
-
},
|
|
118
|
-
assistantMessage: {
|
|
119
|
-
content: fullContent,
|
|
120
|
-
tokenCount: (_b2 = result.tokenUsage) == null ? void 0 : _b2.totalTokens,
|
|
121
|
-
model: void 0
|
|
122
|
-
}
|
|
123
|
-
})).catch((e) => console.error("[useChatStream] saveMessages (fallback):", e));
|
|
124
|
-
}
|
|
125
|
-
isSendingRef.current = false;
|
|
126
|
-
setIsLoading(false);
|
|
127
|
-
setIsStreaming(false);
|
|
128
|
-
abortRef.current = null;
|
|
129
|
-
userMsgForSaveRef.current = null;
|
|
130
|
-
saveSessionIdRef.current = null;
|
|
131
|
-
}
|
|
132
|
-
}, REVEAL_INTERVAL_MS);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const assistantMessage = {
|
|
54
|
+
const streamChannelId = sessionId || cdecliStreamOverrideId;
|
|
55
|
+
const finalizeCdecliRound = useCallback((assistantContent) => {
|
|
56
|
+
saveSessionIdRef.current = null;
|
|
57
|
+
userMsgForSaveRef.current = null;
|
|
58
|
+
setResponse("");
|
|
59
|
+
setIsLoading(false);
|
|
60
|
+
setIsStreaming(false);
|
|
61
|
+
isSendingRef.current = false;
|
|
62
|
+
if (assistantContent !== void 0) {
|
|
63
|
+
setMessages((prev) => [...prev, {
|
|
136
64
|
role: "assistant",
|
|
137
|
-
content:
|
|
138
|
-
|
|
139
|
-
tokenUsage: {
|
|
140
|
-
inputTokens: result.tokenUsage.inputTokens,
|
|
141
|
-
outputTokens: result.tokenUsage.outputTokens,
|
|
142
|
-
totalTokens: result.tokenUsage.totalTokens
|
|
143
|
-
}
|
|
144
|
-
} : void 0
|
|
145
|
-
};
|
|
146
|
-
setMessages((prev) => [...prev, assistantMessage]);
|
|
147
|
-
setResponse("");
|
|
148
|
-
if (effectiveSessionId) {
|
|
149
|
-
await saveMessages(__spreadProps(__spreadValues({
|
|
150
|
-
sessionId: effectiveSessionId
|
|
151
|
-
}, accountUserId ? {
|
|
152
|
-
createdBy: accountUserId
|
|
153
|
-
} : {}), {
|
|
154
|
-
userMessage: {
|
|
155
|
-
content: userMessage.content,
|
|
156
|
-
attachments: (_a = userMessage.attachments) == null ? void 0 : _a.map((a) => ({
|
|
157
|
-
id: a.id,
|
|
158
|
-
name: a.name,
|
|
159
|
-
type: a.type,
|
|
160
|
-
mimeType: a.mimeType,
|
|
161
|
-
size: a.size,
|
|
162
|
-
url: a.url
|
|
163
|
-
}))
|
|
164
|
-
},
|
|
165
|
-
assistantMessage: {
|
|
166
|
-
content: fullContent,
|
|
167
|
-
tokenCount: (_b = result.tokenUsage) == null ? void 0 : _b.totalTokens,
|
|
168
|
-
model: void 0
|
|
169
|
-
}
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
} catch (err) {
|
|
173
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
174
|
-
if (!msg.includes("abort")) setError(msg);
|
|
175
|
-
setResponse("");
|
|
176
|
-
} finally {
|
|
177
|
-
if (!doingChunkedReveal) {
|
|
178
|
-
isSendingRef.current = false;
|
|
179
|
-
setIsLoading(false);
|
|
180
|
-
setIsStreaming(false);
|
|
181
|
-
abortRef.current = null;
|
|
182
|
-
userMsgForSaveRef.current = null;
|
|
183
|
-
saveSessionIdRef.current = null;
|
|
184
|
-
}
|
|
65
|
+
content: assistantContent
|
|
66
|
+
}]);
|
|
185
67
|
}
|
|
186
|
-
}, [
|
|
187
|
-
const streamChannelId = sessionId || cdecliStreamOverrideId;
|
|
188
|
-
const isCdecliActive = routing.kind === "cdecli" && routing.channelConnected;
|
|
68
|
+
}, []);
|
|
189
69
|
const cdecliCallbacks = useMemo(() => ({
|
|
190
70
|
onChunk: (text) => {
|
|
191
|
-
if (routingRef.current.kind !== "cdecli") return;
|
|
192
71
|
setResponse((r) => r + text);
|
|
193
72
|
},
|
|
194
73
|
onComplete: (text) => {
|
|
195
74
|
var _a;
|
|
196
|
-
if (routingRef.current.kind !== "cdecli") return;
|
|
197
75
|
if (cdecliRoundHandledRef.current) {
|
|
198
76
|
return;
|
|
199
77
|
}
|
|
200
78
|
if (isCdecliAgentFailureOutput(text)) {
|
|
201
79
|
cdecliRoundHandledRef.current = true;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const um2 = userMsgForSaveRef.current;
|
|
205
|
-
const conv = cdecliFallbackConversationRef.current;
|
|
206
|
-
setResponse("");
|
|
207
|
-
setError(null);
|
|
208
|
-
userMsgForSaveRef.current = um2;
|
|
209
|
-
saveSessionIdRef.current = sid2;
|
|
210
|
-
setIsLoading(true);
|
|
211
|
-
setIsStreaming(true);
|
|
212
|
-
isSendingRef.current = true;
|
|
213
|
-
if ((conv == null ? void 0 : conv.length) && um2) {
|
|
214
|
-
void executeGroqStream(conv, sid2, um2);
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
setMessages((prev) => [...prev, {
|
|
218
|
-
role: "assistant",
|
|
219
|
-
content: text
|
|
220
|
-
}]);
|
|
221
|
-
setIsLoading(false);
|
|
222
|
-
setIsStreaming(false);
|
|
223
|
-
isSendingRef.current = false;
|
|
224
|
-
userMsgForSaveRef.current = null;
|
|
225
|
-
saveSessionIdRef.current = null;
|
|
80
|
+
setError("CDeCLI agent error. Check gateway status and server-side LLM configuration.");
|
|
81
|
+
finalizeCdecliRound(text);
|
|
226
82
|
return;
|
|
227
83
|
}
|
|
228
84
|
cdecliRoundHandledRef.current = true;
|
|
@@ -239,9 +95,9 @@ function useChatStream(sessionId, routing = {
|
|
|
239
95
|
setIsStreaming(false);
|
|
240
96
|
isSendingRef.current = false;
|
|
241
97
|
const rt = routingRef.current;
|
|
242
|
-
const persistClientSide = rt.
|
|
98
|
+
const persistClientSide = rt.persistenceMode !== "backend";
|
|
243
99
|
if (sid && um && persistClientSide) {
|
|
244
|
-
|
|
100
|
+
saveMessages(__spreadProps(__spreadValues({
|
|
245
101
|
sessionId: sid
|
|
246
102
|
}, accountUserId ? {
|
|
247
103
|
createdBy: accountUserId
|
|
@@ -262,47 +118,21 @@ function useChatStream(sessionId, routing = {
|
|
|
262
118
|
tokenCount: void 0,
|
|
263
119
|
model: "cdecli-serve"
|
|
264
120
|
}
|
|
265
|
-
})).catch((e) =>
|
|
121
|
+
})).catch((e) => {
|
|
122
|
+
console.error("[useChatStream] saveMessages (cdecli):", e);
|
|
123
|
+
});
|
|
266
124
|
}
|
|
267
125
|
},
|
|
268
126
|
onError: (err) => {
|
|
269
|
-
if (routingRef.current.kind !== "cdecli") return;
|
|
270
127
|
if (cdecliRoundHandledRef.current) return;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if ((conv == null ? void 0 : conv.length) && um) {
|
|
275
|
-
cdecliRoundHandledRef.current = true;
|
|
276
|
-
console.warn("[useChatStream] CDeCLI transport/stream error; falling back to direct chat API:", err);
|
|
277
|
-
setResponse("");
|
|
278
|
-
setError(null);
|
|
279
|
-
userMsgForSaveRef.current = um;
|
|
280
|
-
saveSessionIdRef.current = sid;
|
|
281
|
-
setIsLoading(true);
|
|
282
|
-
setIsStreaming(true);
|
|
283
|
-
isSendingRef.current = true;
|
|
284
|
-
void executeGroqStream(conv, sid, um);
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
cdecliRoundHandledRef.current = false;
|
|
288
|
-
setError(err);
|
|
289
|
-
setResponse("");
|
|
290
|
-
setIsLoading(false);
|
|
291
|
-
setIsStreaming(false);
|
|
292
|
-
isSendingRef.current = false;
|
|
293
|
-
userMsgForSaveRef.current = null;
|
|
294
|
-
saveSessionIdRef.current = null;
|
|
128
|
+
cdecliRoundHandledRef.current = true;
|
|
129
|
+
setError(err || "CDeCLI stream error.");
|
|
130
|
+
finalizeCdecliRound();
|
|
295
131
|
}
|
|
296
|
-
}), [saveMessages,
|
|
132
|
+
}), [saveMessages, accountUserId, finalizeCdecliRound]);
|
|
297
133
|
const {
|
|
298
134
|
sendMessage: sendCdecliMessage
|
|
299
|
-
} = useCdecliChannel(routing.
|
|
300
|
-
useEffect(() => () => {
|
|
301
|
-
if (revealIntervalRef.current) {
|
|
302
|
-
clearInterval(revealIntervalRef.current);
|
|
303
|
-
revealIntervalRef.current = null;
|
|
304
|
-
}
|
|
305
|
-
}, []);
|
|
135
|
+
} = useCdecliChannel(routing.channelConnected, routing.accountId, streamChannelId, cdecliCallbacks);
|
|
306
136
|
useEffect(() => {
|
|
307
137
|
if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {
|
|
308
138
|
setCdecliStreamOverrideId(void 0);
|
|
@@ -345,6 +175,7 @@ function useChatStream(sessionId, routing = {
|
|
|
345
175
|
const sendMessage = useCallback(async (content, attachments, sessionIdOverride) => {
|
|
346
176
|
if (!content.trim()) return;
|
|
347
177
|
const effectiveSessionId = sessionIdOverride !== void 0 ? sessionIdOverride : sessionId;
|
|
178
|
+
const rt = routingRef.current;
|
|
348
179
|
const userMessage = {
|
|
349
180
|
role: "user",
|
|
350
181
|
content: content.trim(),
|
|
@@ -359,51 +190,45 @@ function useChatStream(sessionId, routing = {
|
|
|
359
190
|
userMsgForSaveRef.current = userMessage;
|
|
360
191
|
saveSessionIdRef.current = effectiveSessionId != null ? effectiveSessionId : null;
|
|
361
192
|
cdecliRoundHandledRef.current = false;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
userMsgForSaveRef.current = null;
|
|
371
|
-
saveSessionIdRef.current = null;
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
if (!effectiveSessionId) {
|
|
375
|
-
setError("Missing chat session id.");
|
|
376
|
-
setMessages((p) => p.slice(0, -1));
|
|
377
|
-
isSendingRef.current = false;
|
|
378
|
-
setIsLoading(false);
|
|
379
|
-
setIsStreaming(false);
|
|
380
|
-
userMsgForSaveRef.current = null;
|
|
381
|
-
saveSessionIdRef.current = null;
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
if (sessionIdOverride) {
|
|
385
|
-
setCdecliStreamOverrideId(sessionIdOverride);
|
|
386
|
-
await new Promise((r) => setTimeout(r, 0));
|
|
387
|
-
}
|
|
388
|
-
cdecliFallbackConversationRef.current = [...messages, userMessage];
|
|
389
|
-
const ok = await sendCdecliMessage(content.trim(), effectiveSessionId);
|
|
390
|
-
if (!ok && !cdecliRoundHandledRef.current) {
|
|
391
|
-
const conv = cdecliFallbackConversationRef.current;
|
|
392
|
-
console.warn("[useChatStream] CDeCLI send returned false; falling back to direct chat API");
|
|
393
|
-
cdecliRoundHandledRef.current = true;
|
|
394
|
-
userMsgForSaveRef.current = userMessage;
|
|
395
|
-
saveSessionIdRef.current = effectiveSessionId != null ? effectiveSessionId : null;
|
|
396
|
-
void executeGroqStream(conv != null ? conv : [], effectiveSessionId != null ? effectiveSessionId : null, userMessage);
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
193
|
+
if (!rt.channelConnected) {
|
|
194
|
+
setError("CDeCLI is not connected yet. Check gateway status in the header.");
|
|
195
|
+
setMessages((p) => p.slice(0, -1));
|
|
196
|
+
isSendingRef.current = false;
|
|
197
|
+
setIsLoading(false);
|
|
198
|
+
setIsStreaming(false);
|
|
199
|
+
userMsgForSaveRef.current = null;
|
|
200
|
+
saveSessionIdRef.current = null;
|
|
399
201
|
return;
|
|
400
202
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
203
|
+
if (!effectiveSessionId) {
|
|
204
|
+
setError("Missing chat session id.");
|
|
205
|
+
setMessages((p) => p.slice(0, -1));
|
|
206
|
+
isSendingRef.current = false;
|
|
207
|
+
setIsLoading(false);
|
|
208
|
+
setIsStreaming(false);
|
|
209
|
+
userMsgForSaveRef.current = null;
|
|
210
|
+
saveSessionIdRef.current = null;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (sessionIdOverride) {
|
|
214
|
+
setCdecliStreamOverrideId(sessionIdOverride);
|
|
215
|
+
await new Promise((resolve) => {
|
|
216
|
+
setTimeout(resolve, 0);
|
|
217
|
+
});
|
|
406
218
|
}
|
|
219
|
+
const ok = await sendCdecliMessage(content.trim(), effectiveSessionId);
|
|
220
|
+
if (!ok && !cdecliRoundHandledRef.current) {
|
|
221
|
+
cdecliRoundHandledRef.current = true;
|
|
222
|
+
setError("Failed to send message via CDeCLI. Check gateway connection.");
|
|
223
|
+
setMessages((p) => p.slice(0, -1));
|
|
224
|
+
isSendingRef.current = false;
|
|
225
|
+
setIsLoading(false);
|
|
226
|
+
setIsStreaming(false);
|
|
227
|
+
userMsgForSaveRef.current = null;
|
|
228
|
+
saveSessionIdRef.current = null;
|
|
229
|
+
}
|
|
230
|
+
}, [sessionId, sendCdecliMessage]);
|
|
231
|
+
const cancel = useCallback(() => {
|
|
407
232
|
}, []);
|
|
408
233
|
const clearMessages = useCallback(() => {
|
|
409
234
|
setMessages([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\nimport { streamChatResponse } from '../api/chatApi';\n\nconst REVEAL_CHUNK_SIZE = 6;\nconst REVEAL_INTERVAL_MS = 20;\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** When `kind` is `cdecli`, messages go through messenger-gateway (same as web CDeCLI). */\nexport type UseChatStreamRouting =\n | { kind: 'groq' }\n | {\n kind: 'cdecli';\n channelConnected: boolean;\n accountId: string;\n /** From `gatewayConnect` / gateway registry — when `'backend'`, server persists; skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n };\n\nexport function useChatStream(sessionId: string | null, routing: UseChatStreamRouting = { kind: 'groq' }) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const isSendingRef = useRef(false);\n const revealIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n /** Snapshot of `[...priorMessages, userMessage]` for Groq fallback when CDeCLI send/stream fails. */\n const cdecliFallbackConversationRef = useRef<ChatMessage[] | null>(null);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n const { saveMessages } = useChatMutations();\n /**\n * `accountUserId` flows into `saveMessages` as `createdBy`, which the server\n * stores as `Post.editedBy`. The chat-history screen queries by\n * `messages(editedBy: accountUserId, …)`, so without this the user's\n * frontend-persisted (Groq) chats never show up in history.\n */\n const { accountUserId } = usePrerequisiteIds();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n /**\n * Tracks the sessionId we last finished hydrating from. Used to clear local state immediately\n * on session switch (before the new channel's network response arrives), so users never see\n * the previous channel's messages bleed into the newly opened channel.\n */\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const executeGroqStream = useCallback(\n async (conv: ChatMessage[], effectiveSessionId: string | null, userMessage: ChatMessage) => {\n abortRef.current = new AbortController();\n const chatMessages = conv.map((m) => ({ role: m.role, content: m.content }));\n let doingChunkedReveal = false;\n try {\n const g = global as Record<string, unknown>;\n const preferNonStreaming =\n typeof g?.nativeCallSyncHook === 'function' || typeof g?.__fbBatchedBridge !== 'undefined';\n const result = await streamChatResponse(chatMessages, undefined, abortRef.current.signal, {\n preferNonStreaming,\n });\n const fullContent = result.content;\n\n if (preferNonStreaming && fullContent.length > 0) {\n doingChunkedReveal = true;\n if (revealIntervalRef.current) {\n clearInterval(revealIntervalRef.current);\n revealIntervalRef.current = null;\n }\n let revealedLen = 0;\n revealIntervalRef.current = setInterval(() => {\n revealedLen = Math.min(revealedLen + REVEAL_CHUNK_SIZE, fullContent.length);\n setResponse(fullContent.slice(0, revealedLen));\n if (revealedLen >= fullContent.length) {\n if (revealIntervalRef.current) {\n clearInterval(revealIntervalRef.current);\n revealIntervalRef.current = null;\n }\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: fullContent,\n metadata: result.tokenUsage\n ? {\n tokenUsage: {\n inputTokens: result.tokenUsage.inputTokens,\n outputTokens: result.tokenUsage.outputTokens,\n totalTokens: result.tokenUsage.totalTokens,\n },\n }\n : undefined,\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setResponse('');\n if (effectiveSessionId) {\n saveMessages({\n sessionId: effectiveSessionId,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: userMessage.content,\n attachments: userMessage.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: fullContent,\n tokenCount: result.tokenUsage?.totalTokens,\n model: undefined,\n },\n }).catch((e) => console.error('[useChatStream] saveMessages (fallback):', e));\n }\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n abortRef.current = null;\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n }, REVEAL_INTERVAL_MS);\n return;\n }\n\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: fullContent,\n metadata: result.tokenUsage\n ? {\n tokenUsage: {\n inputTokens: result.tokenUsage.inputTokens,\n outputTokens: result.tokenUsage.outputTokens,\n totalTokens: result.tokenUsage.totalTokens,\n },\n }\n : undefined,\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n setResponse('');\n\n if (effectiveSessionId) {\n await saveMessages({\n sessionId: effectiveSessionId,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: userMessage.content,\n attachments: userMessage.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: fullContent,\n tokenCount: result.tokenUsage?.totalTokens,\n model: undefined,\n },\n });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes('abort')) setError(msg);\n setResponse('');\n } finally {\n if (!doingChunkedReveal) {\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n abortRef.current = null;\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n }\n },\n [saveMessages, accountUserId],\n );\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const isCdecliActive = routing.kind === 'cdecli' && routing.channelConnected;\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n if (routingRef.current.kind !== 'cdecli') return;\n setResponse((r) => r + text);\n },\n onComplete: (text: string) => {\n if (routingRef.current.kind !== 'cdecli') return;\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n console.warn('[useChatStream] CDeCLI agent error output; retrying via direct chat API');\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n const conv = cdecliFallbackConversationRef.current;\n setResponse('');\n setError(null);\n userMsgForSaveRef.current = um;\n saveSessionIdRef.current = sid;\n setIsLoading(true);\n setIsStreaming(true);\n isSendingRef.current = true;\n if (conv?.length && um) {\n void executeGroqStream(conv, sid, um);\n return;\n }\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.kind === 'cdecli' && rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n void saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => console.error('[useChatStream] saveMessages (cdecli):', e));\n }\n },\n onError: (err: string) => {\n if (routingRef.current.kind !== 'cdecli') return;\n if (cdecliRoundHandledRef.current) return;\n const conv = cdecliFallbackConversationRef.current;\n const um = userMsgForSaveRef.current;\n const sid = saveSessionIdRef.current;\n if (conv?.length && um) {\n cdecliRoundHandledRef.current = true;\n console.warn(\n '[useChatStream] CDeCLI transport/stream error; falling back to direct chat API:',\n err,\n );\n setResponse('');\n setError(null);\n userMsgForSaveRef.current = um;\n saveSessionIdRef.current = sid;\n setIsLoading(true);\n setIsStreaming(true);\n isSendingRef.current = true;\n void executeGroqStream(conv, sid, um);\n return;\n }\n cdecliRoundHandledRef.current = false;\n setError(err);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n },\n }),\n [saveMessages, executeGroqStream, accountUserId],\n );\n\n const { sendMessage: sendCdecliMessage } = useCdecliChannel(\n routing.kind === 'cdecli',\n isCdecliActive,\n routing.kind === 'cdecli' ? routing.accountId : 'default',\n streamChannelId,\n cdecliCallbacks,\n );\n\n useEffect(\n () => () => {\n if (revealIntervalRef.current) {\n clearInterval(revealIntervalRef.current);\n revealIntervalRef.current = null;\n }\n },\n [],\n );\n\n // Clear override once Apollo session id matches\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n // Drop the previous session's local state immediately. Without this, the prior\n // channel's messages stay rendered until the new channel's network response arrives.\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = sessionId;\n }\n\n // Apply backend results whenever they arrive for this session, including the empty case\n // (genuinely empty channel) once the query has actually returned. This is the path that\n // hydrates a tapped history row.\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n setMessages(formatted);\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (content: string, attachments?: MessageAttachment[], sessionIdOverride?: string | null) => {\n if (!content.trim()) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: content.trim(),\n attachments,\n };\n\n isSendingRef.current = true;\n setMessages((prev) => [...prev, userMessage]);\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n const rt = routingRef.current;\n if (rt.kind === 'cdecli') {\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((r) => setTimeout(r, 0));\n }\n\n cdecliFallbackConversationRef.current = [...messages, userMessage];\n\n const ok = await sendCdecliMessage(content.trim(), effectiveSessionId);\n if (!ok && !cdecliRoundHandledRef.current) {\n const conv = cdecliFallbackConversationRef.current;\n console.warn('[useChatStream] CDeCLI send returned false; falling back to direct chat API');\n cdecliRoundHandledRef.current = true;\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n void executeGroqStream(conv ?? [], effectiveSessionId ?? null, userMessage);\n return;\n }\n return;\n }\n\n await executeGroqStream([...messages, userMessage], effectiveSessionId ?? null, userMessage);\n },\n [messages, sessionId, sendCdecliMessage, executeGroqStream],\n );\n\n const cancel = useCallback(() => {\n if (abortRef.current) {\n abortRef.current.abort();\n }\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setResponse('');\n setError(null);\n }, []);\n\n /**\n * \"Loading\" specifically means: we have a sessionId but no data has arrived yet\n * (neither from cache nor from the network). Once `backendMessagesLoaded` flips\n * true — which now happens synchronously on a cache hit — this stays false even\n * if Apollo is still revalidating in the background, so revisiting a chat does\n * not flash a loader over already-rendered messages.\n *\n * Note the explicit `!messagesLoaded` check (not `messages.length === 0`): a\n * cached-but-empty channel has `messagesLoaded === true` and zero messages,\n * and we want the screen's empty state — not the hydrating loader.\n */\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":["_a","_b","assistantMessage","sid","um"],"mappings":";;;;;;;;;;;;;;;;;;;AAKA,MAAM,iBAAoB,GAAA,CAAA;AAC1B,MAAM,kBAAqB,GAAA,EAAA;AAG3B,SAAS,2BAA2B,IAAuB,EAAA;AACzD,EAAM,MAAA,CAAA,GAAI,KAAK,IAAK,EAAA;AACpB,EAAI,IAAA,CAAC,GAAU,OAAA,KAAA;AACf,EAAA,OAAO,aAAa,IAAK,CAAA,CAAC,KAAK,mBAAoB,CAAA,IAAA,CAAK,CAAC,CAAK,IAAA,oBAAA,CAAqB,IAAK,CAAA,CAAC,KAAK,kBAAmB,CAAA,IAAA,CAAK,CAAC,CAAK,IAAA,uBAAA,CAAwB,KAAK,CAAC,CAAA;AAC5J;AAkCgB,SAAA,aAAA,CAAc,WAA0B,OAAgC,GAAA;AAAA,EACtF,IAAM,EAAA;AACR,CAAG,EAAA;AACD,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAAwB,EAAE,CAAA;AAC1D,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,EAAE,CAAA;AAC3C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAM,MAAA,QAAA,GAAW,OAA+B,IAAI,CAAA;AACpD,EAAM,MAAA,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,EAAM,MAAA,iBAAA,GAAoB,OAA8C,IAAI,CAAA;AAG5E,EAAA,MAAM,CAAC,sBAAA,EAAwB,yBAAyB,CAAA,GAAI,SAA6B,MAAS,CAAA;AAClG,EAAM,MAAA,iBAAA,GAAoB,OAA2B,IAAI,CAAA;AACzD,EAAM,MAAA,gBAAA,GAAmB,OAAsB,IAAI,CAAA;AAEnD,EAAM,MAAA,qBAAA,GAAwB,OAAO,KAAK,CAAA;AAE1C,EAAM,MAAA,6BAAA,GAAgC,OAA6B,IAAI,CAAA;AACvE,EAAM,MAAA,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAU,GAAA,OAAA;AACrB,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,gBAAiB,EAAA;AAOrB,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,kBAAmB,EAAA;AACvB,EAAM,MAAA;AAAA,IACJ,QAAU,EAAA,eAAA;AAAA,IACV,OAAS,EAAA,sBAAA;AAAA,IACT,cAAgB,EAAA;AAAA,GAClB,GAAI,gBAAgB,SAAS,CAAA;AAM7B,EAAM,MAAA,wBAAA,GAA2B,OAAsB,IAAI,CAAA;AAC3D,EAAA,MAAM,iBAAoB,GAAA,WAAA,CAAY,OAAO,IAAA,EAAqB,oBAAmC,WAA6B,KAAA;AA5FpI,IAAA,IAAA,EAAA,EAAA,EAAA;AA6FI,IAAS,QAAA,CAAA,OAAA,GAAU,IAAI,eAAgB,EAAA;AACvC,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,GAAA,CAAI,CAAM,CAAA,MAAA;AAAA,MAClC,MAAM,CAAE,CAAA,IAAA;AAAA,MACR,SAAS,CAAE,CAAA;AAAA,KACX,CAAA,CAAA;AACF,IAAA,IAAI,kBAAqB,GAAA,KAAA;AACzB,IAAI,IAAA;AACF,MAAA,MAAM,CAAI,GAAA,MAAA;AACV,MAAA,MAAM,qBAAqB,QAAO,CAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,CAAA,CAAG,wBAAuB,UAAc,IAAA,QAAO,uBAAG,iBAAsB,CAAA,KAAA,WAAA;AAC1G,MAAA,MAAM,SAAS,MAAM,kBAAA,CAAmB,cAAc,KAAW,CAAA,EAAA,QAAA,CAAS,QAAQ,MAAQ,EAAA;AAAA,QACxF;AAAA,OACD,CAAA;AACD,MAAA,MAAM,cAAc,MAAO,CAAA,OAAA;AAC3B,MAAI,IAAA,kBAAA,IAAsB,WAAY,CAAA,MAAA,GAAS,CAAG,EAAA;AAChD,QAAqB,kBAAA,GAAA,IAAA;AACrB,QAAA,IAAI,kBAAkB,OAAS,EAAA;AAC7B,UAAA,aAAA,CAAc,kBAAkB,OAAO,CAAA;AACvC,UAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAAA;AAE9B,QAAA,IAAI,WAAc,GAAA,CAAA;AAClB,QAAkB,iBAAA,CAAA,OAAA,GAAU,YAAY,MAAM;AAjHtD,UAAA,IAAAA,GAAAC,EAAAA,GAAAA;AAkHU,UAAA,WAAA,GAAc,IAAK,CAAA,GAAA,CAAI,WAAc,GAAA,iBAAA,EAAmB,YAAY,MAAM,CAAA;AAC1E,UAAA,WAAA,CAAY,WAAY,CAAA,KAAA,CAAM,CAAG,EAAA,WAAW,CAAC,CAAA;AAC7C,UAAI,IAAA,WAAA,IAAe,YAAY,MAAQ,EAAA;AACrC,YAAA,IAAI,kBAAkB,OAAS,EAAA;AAC7B,cAAA,aAAA,CAAc,kBAAkB,OAAO,CAAA;AACvC,cAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAAA;AAE9B,YAAA,MAAMC,iBAAgC,GAAA;AAAA,cACpC,IAAM,EAAA,WAAA;AAAA,cACN,OAAS,EAAA,WAAA;AAAA,cACT,QAAA,EAAU,OAAO,UAAa,GAAA;AAAA,gBAC5B,UAAY,EAAA;AAAA,kBACV,WAAA,EAAa,OAAO,UAAW,CAAA,WAAA;AAAA,kBAC/B,YAAA,EAAc,OAAO,UAAW,CAAA,YAAA;AAAA,kBAChC,WAAA,EAAa,OAAO,UAAW,CAAA;AAAA;AACjC,eACE,GAAA,KAAA;AAAA,aACN;AACA,YAAA,WAAA,CAAY,CAAQ,IAAA,KAAA,CAAC,GAAG,IAAA,EAAMA,iBAAgB,CAAC,CAAA;AAC/C,YAAA,WAAA,CAAY,EAAE,CAAA;AACd,YAAA,IAAI,kBAAoB,EAAA;AACtB,cAAa,YAAA,CAAA,aAAA,CAAA,cAAA,CAAA;AAAA,gBACX,SAAW,EAAA;AAAA,eAAA,EACP,aAAgB,GAAA;AAAA,gBAClB,SAAW,EAAA;AAAA,eACb,GAAI,EAJO,CAAA,EAAA;AAAA,gBAKX,WAAa,EAAA;AAAA,kBACX,SAAS,WAAY,CAAA,OAAA;AAAA,kBACrB,cAAaF,GAAA,GAAA,WAAA,CAAY,gBAAZ,IAAAA,GAAAA,KAAAA,CAAAA,GAAAA,GAAAA,CAAyB,IAAI,CAAM,CAAA,MAAA;AAAA,oBAC9C,IAAI,CAAE,CAAA,EAAA;AAAA,oBACN,MAAM,CAAE,CAAA,IAAA;AAAA,oBACR,MAAM,CAAE,CAAA,IAAA;AAAA,oBACR,UAAU,CAAE,CAAA,QAAA;AAAA,oBACZ,MAAM,CAAE,CAAA,IAAA;AAAA,oBACR,KAAK,CAAE,CAAA;AAAA,mBACT,CAAA;AAAA,iBACF;AAAA,gBACA,gBAAkB,EAAA;AAAA,kBAChB,OAAS,EAAA,WAAA;AAAA,kBACT,UAAYC,EAAAA,CAAAA,GAAAA,GAAA,MAAO,CAAA,UAAA,KAAP,gBAAAA,GAAmB,CAAA,WAAA;AAAA,kBAC/B,KAAO,EAAA,KAAA;AAAA;AACT,eACF,CAAC,EAAE,KAAM,CAAA,CAAA,CAAA,KAAK,QAAQ,KAAM,CAAA,0CAAA,EAA4C,CAAC,CAAC,CAAA;AAAA;AAE5E,YAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,YAAA,YAAA,CAAa,KAAK,CAAA;AAClB,YAAA,cAAA,CAAe,KAAK,CAAA;AACpB,YAAA,QAAA,CAAS,OAAU,GAAA,IAAA;AACnB,YAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,YAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAAA;AAC7B,WACC,kBAAkB,CAAA;AACrB,QAAA;AAAA;AAEF,MAAA,MAAM,gBAAgC,GAAA;AAAA,QACpC,IAAM,EAAA,WAAA;AAAA,QACN,OAAS,EAAA,WAAA;AAAA,QACT,QAAA,EAAU,OAAO,UAAa,GAAA;AAAA,UAC5B,UAAY,EAAA;AAAA,YACV,WAAA,EAAa,OAAO,UAAW,CAAA,WAAA;AAAA,YAC/B,YAAA,EAAc,OAAO,UAAW,CAAA,YAAA;AAAA,YAChC,WAAA,EAAa,OAAO,UAAW,CAAA;AAAA;AACjC,SACE,GAAA,KAAA;AAAA,OACN;AACA,MAAA,WAAA,CAAY,CAAQ,IAAA,KAAA,CAAC,GAAG,IAAA,EAAM,gBAAgB,CAAC,CAAA;AAC/C,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,IAAI,kBAAoB,EAAA;AACtB,QAAA,MAAM,YAAa,CAAA,aAAA,CAAA,cAAA,CAAA;AAAA,UACjB,SAAW,EAAA;AAAA,SAAA,EACP,aAAgB,GAAA;AAAA,UAClB,SAAW,EAAA;AAAA,SACb,GAAI,EAJa,CAAA,EAAA;AAAA,UAKjB,WAAa,EAAA;AAAA,YACX,SAAS,WAAY,CAAA,OAAA;AAAA,YACrB,WAAa,EAAA,CAAA,EAAA,GAAA,WAAA,CAAY,WAAZ,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAyB,IAAI,CAAM,CAAA,MAAA;AAAA,cAC9C,IAAI,CAAE,CAAA,EAAA;AAAA,cACN,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,UAAU,CAAE,CAAA,QAAA;AAAA,cACZ,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,KAAK,CAAE,CAAA;AAAA,aACT,CAAA;AAAA,WACF;AAAA,UACA,gBAAkB,EAAA;AAAA,YAChB,OAAS,EAAA,WAAA;AAAA,YACT,UAAA,EAAA,CAAY,EAAO,GAAA,MAAA,CAAA,UAAA,KAAP,IAAmB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,WAAA;AAAA,YAC/B,KAAO,EAAA,KAAA;AAAA;AACT,SACD,CAAA,CAAA;AAAA;AACH,aACO,GAAK,EAAA;AACZ,MAAA,MAAM,MAAM,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,IAAI,CAAC,GAAI,CAAA,QAAA,CAAS,OAAO,CAAA,WAAY,GAAG,CAAA;AACxC,MAAA,WAAA,CAAY,EAAE,CAAA;AAAA,KACd,SAAA;AACA,MAAA,IAAI,CAAC,kBAAoB,EAAA;AACvB,QAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,cAAA,CAAe,KAAK,CAAA;AACpB,QAAA,QAAA,CAAS,OAAU,GAAA,IAAA;AACnB,QAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAAA;AAC7B;AACF,GACC,EAAA,CAAC,YAAc,EAAA,aAAa,CAAC,CAAA;AAChC,EAAA,MAAM,kBAAkB,SAAa,IAAA,sBAAA;AACrC,EAAA,MAAM,cAAiB,GAAA,OAAA,CAAQ,IAAS,KAAA,QAAA,IAAY,OAAQ,CAAA,gBAAA;AAC5D,EAAM,MAAA,eAAA,GAAkB,QAAQ,OAAO;AAAA,IACrC,OAAA,EAAS,CAAC,IAAiB,KAAA;AACzB,MAAI,IAAA,UAAA,CAAW,OAAQ,CAAA,IAAA,KAAS,QAAU,EAAA;AAC1C,MAAY,WAAA,CAAA,CAAA,CAAA,KAAK,IAAI,IAAI,CAAA;AAAA,KAC3B;AAAA,IACA,UAAA,EAAY,CAAC,IAAiB,KAAA;AAnOlC,MAAA,IAAA,EAAA;AAoOM,MAAI,IAAA,UAAA,CAAW,OAAQ,CAAA,IAAA,KAAS,QAAU,EAAA;AAC1C,MAAA,IAAI,sBAAsB,OAAS,EAAA;AACjC,QAAA;AAAA;AAEF,MAAI,IAAA,0BAAA,CAA2B,IAAI,CAAG,EAAA;AACpC,QAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,QAAA,OAAA,CAAQ,KAAK,yEAAyE,CAAA;AACtF,QAAA,MAAME,OAAM,gBAAiB,CAAA,OAAA;AAC7B,QAAA,MAAMC,MAAK,iBAAkB,CAAA,OAAA;AAC7B,QAAA,MAAM,OAAO,6BAA8B,CAAA,OAAA;AAC3C,QAAA,WAAA,CAAY,EAAE,CAAA;AACd,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,iBAAA,CAAkB,OAAUA,GAAAA,GAAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAUD,GAAAA,IAAAA;AAC3B,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,cAAA,CAAe,IAAI,CAAA;AACnB,QAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,QAAI,IAAA,CAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAM,WAAUC,GAAI,EAAA;AACtB,UAAK,KAAA,iBAAA,CAAkB,IAAMD,EAAAA,IAAAA,EAAKC,GAAE,CAAA;AACpC,UAAA;AAAA;AAEF,QAAY,WAAA,CAAA,CAAA,IAAA,KAAQ,CAAC,GAAG,IAAM,EAAA;AAAA,UAC5B,IAAM,EAAA,WAAA;AAAA,UACN,OAAS,EAAA;AAAA,SACV,CAAC,CAAA;AACF,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,cAAA,CAAe,KAAK,CAAA;AACpB,QAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,QAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAC3B,QAAA;AAAA;AAEF,MAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,MAAA,MAAM,MAAM,gBAAiB,CAAA,OAAA;AAC7B,MAAA,MAAM,KAAK,iBAAkB,CAAA,OAAA;AAC7B,MAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAC3B,MAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,MAAY,WAAA,CAAA,CAAA,IAAA,KAAQ,CAAC,GAAG,IAAM,EAAA;AAAA,QAC5B,IAAM,EAAA,WAAA;AAAA,QACN,OAAS,EAAA;AAAA,OACV,CAAC,CAAA;AACF,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,cAAA,CAAe,KAAK,CAAA;AACpB,MAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,MAAA,MAAM,KAAK,UAAW,CAAA,OAAA;AACtB,MAAA,MAAM,iBAAoB,GAAA,EAAA,CAAG,IAAS,KAAA,QAAA,IAAY,GAAG,eAAoB,KAAA,SAAA;AACzE,MAAI,IAAA,GAAA,IAAO,MAAM,iBAAmB,EAAA;AAClC,QAAA,KAAK,YAAa,CAAA,aAAA,CAAA,cAAA,CAAA;AAAA,UAChB,SAAW,EAAA;AAAA,SAAA,EACP,aAAgB,GAAA;AAAA,UAClB,SAAW,EAAA;AAAA,SACb,GAAI,EAJY,CAAA,EAAA;AAAA,UAKhB,WAAa,EAAA;AAAA,YACX,SAAS,EAAG,CAAA,OAAA;AAAA,YACZ,WAAa,EAAA,CAAA,EAAA,GAAA,EAAA,CAAG,WAAH,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAgB,IAAI,CAAM,CAAA,MAAA;AAAA,cACrC,IAAI,CAAE,CAAA,EAAA;AAAA,cACN,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,UAAU,CAAE,CAAA,QAAA;AAAA,cACZ,MAAM,CAAE,CAAA,IAAA;AAAA,cACR,KAAK,CAAE,CAAA;AAAA,aACT,CAAA;AAAA,WACF;AAAA,UACA,gBAAkB,EAAA;AAAA,YAChB,OAAS,EAAA,IAAA;AAAA,YACT,UAAY,EAAA,MAAA;AAAA,YACZ,KAAO,EAAA;AAAA;AACT,SACF,CAAC,EAAE,KAAM,CAAA,CAAA,CAAA,KAAK,QAAQ,KAAM,CAAA,wCAAA,EAA0C,CAAC,CAAC,CAAA;AAAA;AAC1E,KACF;AAAA,IACA,OAAA,EAAS,CAAC,GAAgB,KAAA;AACxB,MAAI,IAAA,UAAA,CAAW,OAAQ,CAAA,IAAA,KAAS,QAAU,EAAA;AAC1C,MAAA,IAAI,sBAAsB,OAAS,EAAA;AACnC,MAAA,MAAM,OAAO,6BAA8B,CAAA,OAAA;AAC3C,MAAA,MAAM,KAAK,iBAAkB,CAAA,OAAA;AAC7B,MAAA,MAAM,MAAM,gBAAiB,CAAA,OAAA;AAC7B,MAAI,IAAA,CAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAM,WAAU,EAAI,EAAA;AACtB,QAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,QAAQ,OAAA,CAAA,IAAA,CAAK,mFAAmF,GAAG,CAAA;AACnG,QAAA,WAAA,CAAY,EAAE,CAAA;AACd,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,iBAAA,CAAkB,OAAU,GAAA,EAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAU,GAAA,GAAA;AAC3B,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,cAAA,CAAe,IAAI,CAAA;AACnB,QAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,QAAK,KAAA,iBAAA,CAAkB,IAAM,EAAA,GAAA,EAAK,EAAE,CAAA;AACpC,QAAA;AAAA;AAEF,MAAA,qBAAA,CAAsB,OAAU,GAAA,KAAA;AAChC,MAAA,QAAA,CAAS,GAAG,CAAA;AACZ,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,cAAA,CAAe,KAAK,CAAA;AACpB,MAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,MAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,MAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAAA;AAC7B,GACE,CAAA,EAAA,CAAC,YAAc,EAAA,iBAAA,EAAmB,aAAa,CAAC,CAAA;AACpD,EAAM,MAAA;AAAA,IACJ,WAAa,EAAA;AAAA,GACX,GAAA,gBAAA,CAAiB,OAAQ,CAAA,IAAA,KAAS,QAAU,EAAA,cAAA,EAAgB,OAAQ,CAAA,IAAA,KAAS,QAAW,GAAA,OAAA,CAAQ,SAAY,GAAA,SAAA,EAAW,iBAAiB,eAAe,CAAA;AAC3J,EAAA,SAAA,CAAU,MAAM,MAAM;AACpB,IAAA,IAAI,kBAAkB,OAAS,EAAA;AAC7B,MAAA,aAAA,CAAc,kBAAkB,OAAO,CAAA;AACvC,MAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAAA;AAC9B,GACF,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,SAAA,IAAa,sBAA0B,IAAA,SAAA,KAAc,sBAAwB,EAAA;AAC/E,MAAA,yBAAA,CAA0B,MAAS,CAAA;AAAA;AACrC,GACC,EAAA,CAAC,SAAW,EAAA,sBAAsB,CAAC,CAAA;AACtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,aAAa,OAAS,EAAA;AAC1B,IAAA,IAAI,CAAC,SAAW,EAAA;AACd,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,wBAAA,CAAyB,OAAU,GAAA,IAAA;AACnC,MAAA;AAAA;AAEF,IAAM,MAAA,cAAA,GAAiB,yBAAyB,OAAY,KAAA,SAAA;AAC5D,IAAA,IAAI,cAAgB,EAAA;AAGlB,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,WAAA,CAAY,EAAE,CAAA;AACd,MAAA,wBAAA,CAAyB,OAAU,GAAA,SAAA;AAAA;AAMrC,IAAA,IAAI,qBAAuB,EAAA;AACzB,MAAA,MAAM,SAA4B,GAAA,CAAA,eAAA,IAAA,IAAA,GAAA,eAAA,GAAmB,EAAC,EAAG,IAAI,CAAI,GAAA,KAAA;AA9WvE,QAAA,IAAA,EAAA;AA8W2E,QAAA,OAAA;AAAA,UACnE,MAAM,GAAI,CAAA,IAAA;AAAA,UACV,OAAA,EAAA,CAAS,EAAI,GAAA,GAAA,CAAA,OAAA,KAAJ,IAAe,GAAA,EAAA,GAAA,EAAA;AAAA,UACxB,QAAA,EAAU,IAAI,UAAa,GAAA;AAAA,YACzB,UAAY,EAAA;AAAA,cACV,WAAa,EAAA,CAAA;AAAA,cACb,cAAc,GAAI,CAAA,UAAA;AAAA,cAClB,aAAa,GAAI,CAAA;AAAA,aACnB;AAAA,YACA,OAAO,GAAI,CAAA;AAAA,WACT,GAAA;AAAA,SACN;AAAA,OAAE,CAAA;AACF,MAAA,WAAA,CAAY,SAAS,CAAA;AACrB,MAAA,WAAA,CAAY,EAAE,CAAA;AAAA;AAChB,GACC,EAAA,CAAC,SAAW,EAAA,eAAA,EAAiB,qBAAqB,CAAC,CAAA;AACtD,EAAA,MAAM,WAAc,GAAA,WAAA,CAAY,OAAO,OAAA,EAAiB,aAAmC,iBAAsC,KAAA;AAC/H,IAAI,IAAA,CAAC,OAAQ,CAAA,IAAA,EAAQ,EAAA;AACrB,IAAM,MAAA,kBAAA,GAAqB,iBAAsB,KAAA,MAAA,GAAY,iBAAoB,GAAA,SAAA;AACjF,IAAA,MAAM,WAA2B,GAAA;AAAA,MAC/B,IAAM,EAAA,MAAA;AAAA,MACN,OAAA,EAAS,QAAQ,IAAK,EAAA;AAAA,MACtB;AAAA,KACF;AACA,IAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,IAAA,WAAA,CAAY,CAAQ,IAAA,KAAA,CAAC,GAAG,IAAA,EAAM,WAAW,CAAC,CAAA;AAC1C,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,cAAA,CAAe,IAAI,CAAA;AACnB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,iBAAA,CAAkB,OAAU,GAAA,WAAA;AAC5B,IAAA,gBAAA,CAAiB,UAAU,kBAAsB,IAAA,IAAA,GAAA,kBAAA,GAAA,IAAA;AACjD,IAAA,qBAAA,CAAsB,OAAU,GAAA,KAAA;AAChC,IAAA,MAAM,KAAK,UAAW,CAAA,OAAA;AACtB,IAAI,IAAA,EAAA,CAAG,SAAS,QAAU,EAAA;AACxB,MAAI,IAAA,CAAC,GAAG,gBAAkB,EAAA;AACxB,QAAA,QAAA,CAAS,kEAAkE,CAAA;AAC3E,QAAA,WAAA,CAAY,CAAK,CAAA,KAAA,CAAA,CAAE,KAAM,CAAA,CAAA,EAAG,EAAE,CAAC,CAAA;AAC/B,QAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,cAAA,CAAe,KAAK,CAAA;AACpB,QAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAC3B,QAAA;AAAA;AAEF,MAAA,IAAI,CAAC,kBAAoB,EAAA;AACvB,QAAA,QAAA,CAAS,0BAA0B,CAAA;AACnC,QAAA,WAAA,CAAY,CAAK,CAAA,KAAA,CAAA,CAAE,KAAM,CAAA,CAAA,EAAG,EAAE,CAAC,CAAA;AAC/B,QAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,cAAA,CAAe,KAAK,CAAA;AACpB,QAAA,iBAAA,CAAkB,OAAU,GAAA,IAAA;AAC5B,QAAA,gBAAA,CAAiB,OAAU,GAAA,IAAA;AAC3B,QAAA;AAAA;AAEF,MAAA,IAAI,iBAAmB,EAAA;AACrB,QAAA,yBAAA,CAA0B,iBAAiB,CAAA;AAC3C,QAAA,MAAM,IAAI,OAAc,CAAA,CAAA,CAAA,KAAK,UAAW,CAAA,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA;AAE/C,MAAA,6BAAA,CAA8B,OAAU,GAAA,CAAC,GAAG,QAAA,EAAU,WAAW,CAAA;AACjE,MAAA,MAAM,KAAK,MAAM,iBAAA,CAAkB,OAAQ,CAAA,IAAA,IAAQ,kBAAkB,CAAA;AACrE,MAAA,IAAI,CAAC,EAAA,IAAM,CAAC,qBAAA,CAAsB,OAAS,EAAA;AACzC,QAAA,MAAM,OAAO,6BAA8B,CAAA,OAAA;AAC3C,QAAA,OAAA,CAAQ,KAAK,6EAA6E,CAAA;AAC1F,QAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,QAAA,iBAAA,CAAkB,OAAU,GAAA,WAAA;AAC5B,QAAA,gBAAA,CAAiB,UAAU,kBAAsB,IAAA,IAAA,GAAA,kBAAA,GAAA,IAAA;AACjD,QAAA,KAAK,kBAAkB,IAAQ,IAAA,IAAA,GAAA,IAAA,GAAA,EAAI,EAAA,kBAAA,IAAA,IAAA,GAAA,kBAAA,GAAsB,MAAM,WAAW,CAAA;AAC1E,QAAA;AAAA;AAEF,MAAA;AAAA;AAEF,IAAM,MAAA,iBAAA,CAAkB,CAAC,GAAG,QAAA,EAAU,WAAW,CAAG,EAAA,kBAAA,IAAA,IAAA,GAAA,kBAAA,GAAsB,MAAM,WAAW,CAAA;AAAA,KAC1F,CAAC,QAAA,EAAU,SAAW,EAAA,iBAAA,EAAmB,iBAAiB,CAAC,CAAA;AAC9D,EAAM,MAAA,MAAA,GAAS,YAAY,MAAM;AAC/B,IAAA,IAAI,SAAS,OAAS,EAAA;AACpB,MAAA,QAAA,CAAS,QAAQ,KAAM,EAAA;AAAA;AACzB,GACF,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,aAAA,GAAgB,YAAY,MAAM;AACtC,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,GACf,EAAG,EAAE,CAAA;AAaL,EAAA,MAAM,eAAkB,GAAA,CAAC,CAAC,SAAA,IAAa,0BAA0B,CAAC,qBAAA;AAClE,EAAO,OAAA;AAAA,IACL,QAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAa,EAAA,QAAA,CAAS,MAAS,GAAA,CAAA,IAAK,CAAC,CAAC,QAAA;AAAA,IACtC,WAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF"}
|
|
1
|
+
{"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** Mobile chat routes exclusively through CDeCLI (messenger-gateway). */\nexport interface UseChatStreamRouting {\n channelConnected: boolean;\n accountId: string;\n /** When `'backend'`, the gateway persists posts — skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n}\n\nexport function useChatStream(\n sessionId: string | null,\n routing: UseChatStreamRouting = {\n channelConnected: false,\n accountId: 'default',\n persistenceMode: 'backend',\n },\n) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const isSendingRef = useRef(false);\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n const { saveMessages } = useChatMutations();\n const { accountUserId } = usePrerequisiteIds();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const finalizeCdecliRound = useCallback((assistantContent?: string) => {\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n if (assistantContent !== undefined) {\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: assistantContent }]);\n }\n }, []);\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n setResponse((r) => r + text);\n },\n onComplete: (text: string) => {\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n setError('CDeCLI agent error. Check gateway status and server-side LLM configuration.');\n finalizeCdecliRound(text);\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => {\n console.error('[useChatStream] saveMessages (cdecli):', e);\n });\n }\n },\n onError: (err: string) => {\n if (cdecliRoundHandledRef.current) return;\n cdecliRoundHandledRef.current = true;\n setError(err || 'CDeCLI stream error.');\n finalizeCdecliRound();\n },\n }),\n [saveMessages, accountUserId, finalizeCdecliRound],\n );\n\n const { sendMessage: sendCdecliMessage } = useCdecliChannel(\n routing.channelConnected,\n routing.accountId,\n streamChannelId,\n cdecliCallbacks,\n );\n\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = sessionId;\n }\n\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n setMessages(formatted);\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (content: string, attachments?: MessageAttachment[], sessionIdOverride?: string | null) => {\n if (!content.trim()) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n const rt = routingRef.current;\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: content.trim(),\n attachments,\n };\n\n isSendingRef.current = true;\n setMessages((prev) => [...prev, userMessage]);\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 0);\n });\n }\n\n const ok = await sendCdecliMessage(content.trim(), effectiveSessionId);\n if (!ok && !cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n setError('Failed to send message via CDeCLI. Check gateway connection.');\n setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n },\n [sessionId, sendCdecliMessage],\n );\n\n const cancel = useCallback(() => {\n /* CDeCLI streams are not abortable client-side; no-op for API parity. */\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setResponse('');\n setError(null);\n }, []);\n\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":[],"mappings":"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"}
|