@adminide-stack/yantra-mobile 12.0.80-alpha.1 → 12.0.80-alpha.2

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.
@@ -1,4 +1,4 @@
1
- import {useRef,useCallback,useEffect}from'react';import {AppState}from'react-native';import {useApolloClient}from'@apollo/client/index.js';import {isConnectorReply}from'common';import {quickReplyViaBrain}from'../services/brainQuickReply.js';import {stripModelCostHeader,MESSENGER_ACTIVE_STREAM_QUERY}from'./messengerStream.js';import {CHAT_RUN_TIMEOUT_TEXT,EMPTY_CHAT_RESPONSE_TEXT,resolveAssistantReply,CDECLI_MAX_RUN_MS}from'../features/chat/emptyChatResponse.js';import {splitPreResponse,isFastLaneRunId}from'../features/chat/preResponse.js';import {useGatewaySendMessageMutation,useMessengerStreamDeltaSubscription,useGatewayInboundMessageByChannelSubscription}from'common/graphql';var __defProp = Object.defineProperty;
1
+ import {useRef,useCallback,useEffect}from'react';import {AppState}from'react-native';import {useApolloClient}from'@apollo/client/index.js';import {isConnectorReply}from'common';import {useGatewaySendMessageMutation,useMessengerStreamDeltaSubscription,useGatewayInboundMessageByChannelSubscription}from'common/graphql';import {quickReplyViaBrain}from'../services/brainQuickReply.js';import {stripModelCostHeader,MESSENGER_ACTIVE_STREAM_QUERY}from'./messengerStream.js';import {resolveAssistantReply,CHAT_RUN_TIMEOUT_TEXT,EMPTY_CHAT_RESPONSE_TEXT,CDECLI_MAX_RUN_MS}from'../features/chat/emptyChatResponse.js';import {splitPreResponse,joinPreResponse,isFastLaneRunId}from'../features/chat/preResponse.js';import {clientTimezone}from'../utils/clientTimezone.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -37,6 +37,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
37
37
  const apolloClient = useApolloClient();
38
38
  const seededChannelRef = useRef(null);
39
39
  const quickReplyShownRef = useRef(false);
40
+ const preResponseRef = useRef(null);
40
41
  const completedRunIdRef = useRef(null);
41
42
  const deliveredInboundRef = useRef([]);
42
43
  const ingestAccumulatedText = useCallback((accumulated, asFastLane = false) => {
@@ -48,12 +49,14 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
48
49
  } = splitPreResponse(stripped);
49
50
  if (preResponse) {
50
51
  quickReplyShownRef.current = true;
52
+ preResponseRef.current = preResponse;
51
53
  (_b = (_a = cbRef.current).onQuickReply) == null ? void 0 : _b.call(_a, preResponse);
52
54
  }
53
55
  if (asFastLane) {
54
56
  const fast = (preResponse || fullText).trim();
55
57
  if (fast) {
56
58
  quickReplyShownRef.current = true;
59
+ preResponseRef.current = fast;
57
60
  (_d = (_c = cbRef.current).onQuickReply) == null ? void 0 : _d.call(_c, fast);
58
61
  }
59
62
  return;
@@ -83,7 +86,9 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
83
86
  const pending = pendingRef.current;
84
87
  if (!pending || stoppingRef.current) return;
85
88
  stoppingRef.current = true;
86
- const chatId = pending.chatId;
89
+ const {
90
+ chatId
91
+ } = pending;
87
92
  pendingRef.current = null;
88
93
  hasReceivedDeltasRef.current = false;
89
94
  streamCompletedRef.current = true;
@@ -104,7 +109,9 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
104
109
  }
105
110
  }).catch(() => {
106
111
  });
107
- cbRef.current.onComplete(reason === "max-run" ? CHAT_RUN_TIMEOUT_TEXT : EMPTY_CHAT_RESPONSE_TEXT);
112
+ const pre = preResponseRef.current;
113
+ preResponseRef.current = null;
114
+ cbRef.current.onComplete(joinPreResponse(pre, reason === "max-run" ? CHAT_RUN_TIMEOUT_TEXT : EMPTY_CHAT_RESPONSE_TEXT));
108
115
  stoppingRef.current = false;
109
116
  }, [accountId, clearRunTimers, sendMutation]);
110
117
  const armTimeout = useCallback(() => {
@@ -155,6 +162,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
155
162
  hasReceivedDeltasRef.current = false;
156
163
  accumulatedLenRef.current = 0;
157
164
  lastRunIdRef.current = null;
165
+ preResponseRef.current = null;
158
166
  }
159
167
  const prevRunId = lastRunIdRef.current;
160
168
  if (delta.runId && delta.runId !== prevRunId) {
@@ -242,13 +250,18 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
242
250
  hasReceivedDeltasRef.current = false;
243
251
  accumulatedLenRef.current = 0;
244
252
  }
245
- if (preResponse) (_g = (_f = cbRef.current).onQuickReply) == null ? void 0 : _g.call(_f, preResponse);
253
+ if (preResponse) {
254
+ preResponseRef.current = preResponse;
255
+ (_g = (_f = cbRef.current).onQuickReply) == null ? void 0 : _g.call(_f, preResponse);
256
+ }
246
257
  if (msg.text && !finalText.trim() && preResponse) return;
247
258
  if (!finalText.trim() && !pendingRef.current && !hasReceivedDeltasRef.current) return;
248
259
  if (finalText.trim() && !hasReceivedDeltasRef.current) {
249
260
  cbRef.current.onChunk(finalText);
250
261
  }
251
- cbRef.current.onComplete(resolveAssistantReply(finalText));
262
+ const pre = preResponseRef.current;
263
+ preResponseRef.current = null;
264
+ cbRef.current.onComplete(joinPreResponse(pre, resolveAssistantReply(finalText)));
252
265
  if (externalId) deliveredInboundRef.current = [...deliveredInboundRef.current.slice(-49), externalId];
253
266
  pendingRef.current = null;
254
267
  hasReceivedDeltasRef.current = false;
@@ -279,6 +292,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
279
292
  accumulatedLenRef.current = 0;
280
293
  lastRunIdRef.current = null;
281
294
  quickReplyShownRef.current = false;
295
+ preResponseRef.current = null;
282
296
  const turn = ++turnSeqRef.current;
283
297
  if (media.length === 0 && !isConnectorReply(text)) {
284
298
  void quickReplyViaBrain(text).then((answer) => {
@@ -291,6 +305,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
291
305
  });
292
306
  }
293
307
  try {
308
+ const timezone = clientTimezone();
294
309
  const result = await sendMutation({
295
310
  variables: {
296
311
  input: __spreadValues(__spreadValues({
@@ -300,11 +315,13 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
300
315
  text
301
316
  }, media.length > 0 ? {
302
317
  media
303
- } : {}), model || skill ? {
304
- metadata: __spreadValues(__spreadValues({}, model && {
318
+ } : {}), model || skill || timezone ? {
319
+ metadata: __spreadValues(__spreadValues(__spreadValues({}, model && {
305
320
  model
306
321
  }), skill && {
307
322
  skill
323
+ }), timezone && {
324
+ timezone
308
325
  })
309
326
  } : {})
310
327
  }
@@ -330,7 +347,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
330
347
  clearRunTimers();
331
348
  return false;
332
349
  }
333
- }, [isConnected, accountId, channelId, sendMutation, model, skill, armTimeout, armMaxRun, clearRunTimers]);
350
+ }, [isConnected, accountId, sendMutation, model, skill, armTimeout, armMaxRun, clearRunTimers]);
334
351
  useEffect(() => () => {
335
352
  pendingRef.current = null;
336
353
  hasReceivedDeltasRef.current = false;
@@ -391,6 +408,7 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
391
408
  error: "CDeCLI is not connected."
392
409
  };
393
410
  try {
411
+ const timezone = clientTimezone();
394
412
  const result = await sendMutation({
395
413
  variables: {
396
414
  input: __spreadProps(__spreadValues({
@@ -401,12 +419,14 @@ function useCdecliChannel(isConnected, accountId, channelId, callbacks, model, s
401
419
  }, media.length > 0 ? {
402
420
  media
403
421
  } : {}), {
404
- metadata: __spreadValues(__spreadValues({
422
+ metadata: __spreadValues(__spreadValues(__spreadValues({
405
423
  queueAware: true
406
424
  }, model && {
407
425
  model
408
426
  }), skill && {
409
427
  skill
428
+ }), timezone && {
429
+ timezone
410
430
  })
411
431
  })
412
432
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useCdecliChannel.js","sources":["../../src/hooks/useCdecliChannel.ts"],"sourcesContent":["/**\n * useCdecliChannel — wires the cdecli-serve messenger-gateway channel into the mobile chat UI.\n *\n * Kept in sync with `packages-modules/account/browser/src/hooks/useCdecliChannel.ts`.\n * When the CDeCLI channel is connected:\n * - `sendMessage(text, chatId, media)` calls `gatewaySendMessage`\n * - `MessengerStreamDelta` subscription delivers streaming chunks via `onChunk`\n * - `GatewayInboundMessageByChannel` delivers the final reply via `onComplete`\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { useApolloClient } from '@apollo/client';\nimport { isConnectorReply } from 'common';\nimport { quickReplyViaBrain } from '../services/brainQuickReply';\nimport { MESSENGER_ACTIVE_STREAM_QUERY, stripModelCostHeader } from './messengerStream';\nimport {\n CHAT_RUN_TIMEOUT_TEXT,\n CDECLI_MAX_RUN_MS,\n EMPTY_CHAT_RESPONSE_TEXT,\n resolveAssistantReply,\n} from '../features/chat/emptyChatResponse';\nimport { isFastLaneRunId, splitPreResponse } from '../features/chat/preResponse';\nimport {\n useGatewaySendMessageMutation,\n useGatewayInboundMessageByChannelSubscription,\n useMessengerStreamDeltaSubscription,\n} from 'common/graphql';\n\n// `error?: undefined` on the success arm keeps `result.error` reachable on the\n// union: with strictNullChecks off (repo-wide), TS will not narrow the\n// discriminated union after an `if (result.ok) continue`.\nexport type SteerResult = { ok: true; error?: undefined } | { ok: false; error: string };\n\n/**\n * What became of a message sent while a turn was running:\n * - `queued`: the gateway queued it for the agent, which answers it when the\n * running turn ends. `id` cancels it (`cancelQueued`).\n * - `answered`: the gateway answered it on the spot (a status question) with a\n * notice that arrives through `onNotice`.\n * - `started`: the running turn had already ended, so the agent took it right\n * away; its answer arrives as a follow-up.\n */\nexport type QueuedSendResult =\n | { status: 'queued'; id: string; error?: undefined }\n | { status: 'answered' | 'started'; id?: undefined; error?: undefined }\n | { status: 'failed'; id?: undefined; error: string };\n\n/** The gateway's send-result ids for a message it queued or answered itself. */\nconst QUEUED_EXTERNAL_ID_PREFIX = 'handoff-queued-';\nconst STATUS_EXTERNAL_ID_PREFIX = 'handoff-status-';\n/** Messages from the gateway itself (a status answer, a long-wait report). */\nconst GATEWAY_NOTICE_ID_PREFIX = 'handoff-';\n\nexport interface CdecliChannelCallbacks {\n onChunk: (text: string) => void;\n /**\n * A fast provisional answer from `yantra-brain` or `CDECLI_FAST_LANE=pre`.\n * Shown as a Quick answer strip — never the main bubble. Pass the full\n * text so far (not a delta). Do not pass `''` to hide it when the agent\n * starts; web keeps the strip beside the agent reply.\n */\n onQuickReply?: (text: string) => void;\n /**\n * The agent started a new run (typically after the fast lane). Clear the\n * main bubble so the agent's tokens do not append onto the provisional\n * article.\n */\n onStreamRestart?: () => void;\n onComplete: (text: string) => void;\n onError: (error: string) => void;\n /**\n * A message from the gateway about queued work (a status answer, a\n * long-wait report) that arrived while a reply is still streaming. It is\n * shown beside that reply and does NOT end it.\n */\n onNotice?: (text: string) => void;\n}\n\nexport function isNoActiveSessionError(message: string): boolean {\n return /no active session/i.test(message);\n}\n\n/**\n * Idle window, not a total budget. The timer is re-armed on every streamed\n * delta (a turn that is actively streaming is not stuck), and paused while the\n * app is backgrounded (iOS suspends the WebSocket + throttles JS timers, so a\n * wall-clock timer would otherwise fire a false \"did not respond\" the instant\n * the app returns to the foreground). It fires only after this much CONTINUOUS\n * silence with the app in the foreground.\n */\nconst CDECLI_RESPONSE_TIMEOUT_MS = 300_000;\n\nexport function useCdecliChannel(\n isConnected: boolean,\n accountId: string,\n channelId: string | undefined,\n callbacks: CdecliChannelCallbacks,\n model?: string,\n skill?: string,\n) {\n const [sendMutation] = useGatewaySendMessageMutation();\n const cbRef = useRef(callbacks);\n cbRef.current = callbacks;\n\n const pendingRef = useRef<{ text: string; sentAt: number; chatId: string } | null>(null);\n const hasReceivedDeltasRef = useRef(false);\n const reconnectedStreamRef = useRef(false);\n const streamCompletedRef = useRef(false);\n const accumulatedLenRef = useRef(0);\n const lastRunIdRef = useRef<string | null>(null);\n const apolloClient = useApolloClient();\n const seededChannelRef = useRef<string | null>(null);\n const quickReplyShownRef = useRef(false);\n /**\n * The run the last finished turn streamed on. After a turn ends the agent\n * can still speak with no send behind it - the gateway runs a request it\n * queued while the agent was busy and follows up with the answer. That\n * arrives as a NEW run (or a new final message) and must open a round of\n * its own; a late delta from THIS run must not.\n */\n const completedRunIdRef = useRef<string | null>(null);\n /** Final messages already delivered, so a redelivery never paints twice. */\n const deliveredInboundRef = useRef<string[]>([]);\n\n /**\n * Forward newly-accumulated stream text. Shared by live deltas and the\n * mount-time resume seed so neither gaps nor double-delivery happen when\n * the user leaves Chat for history and comes back mid-turn.\n */\n const ingestAccumulatedText = useCallback((accumulated: string, asFastLane = false) => {\n const stripped = stripModelCostHeader(accumulated);\n const { preResponse, text: fullText } = splitPreResponse(stripped);\n if (preResponse) {\n quickReplyShownRef.current = true;\n cbRef.current.onQuickReply?.(preResponse);\n }\n if (asFastLane) {\n const fast = (preResponse || fullText).trim();\n if (fast) {\n quickReplyShownRef.current = true;\n cbRef.current.onQuickReply?.(fast);\n }\n return;\n }\n const newChunk = fullText.substring(accumulatedLenRef.current);\n accumulatedLenRef.current = fullText.length;\n if (newChunk) cbRef.current.onChunk(newChunk);\n }, []);\n // Identity of the current turn for the brain race. A counter, not a\n // timestamp: two sends can share a millisecond, and a timestamp would then\n // let a brain answer for a superseded turn paint over the live one.\n const turnSeqRef = useRef(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const maxRunTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const runStartedAtRef = useRef<number | null>(null);\n const stoppingRef = useRef(false);\n\n const streamSkip = !channelId;\n const streamChannelId = channelId || accountId;\n\n const clearRunTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (maxRunTimerRef.current) {\n clearTimeout(maxRunTimerRef.current);\n maxRunTimerRef.current = null;\n }\n }, []);\n\n const stopTurn = useCallback(\n (reason: 'idle' | 'max-run') => {\n const pending = pendingRef.current;\n if (!pending || stoppingRef.current) return;\n stoppingRef.current = true;\n const chatId = pending.chatId;\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n runStartedAtRef.current = null;\n clearRunTimers();\n void sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n }).catch(() => {\n /* local stop still lands a standard reply */\n });\n cbRef.current.onComplete(reason === 'max-run' ? CHAT_RUN_TIMEOUT_TEXT : EMPTY_CHAT_RESPONSE_TEXT);\n stoppingRef.current = false;\n },\n [accountId, clearRunTimers, sendMutation],\n );\n\n /** (Re)start the idle timer for the in-flight turn. No-op if none pending. */\n const armTimeout = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n if (!pendingRef.current) {\n timeoutRef.current = null;\n return;\n }\n timeoutRef.current = setTimeout(() => stopTurn('idle'), CDECLI_RESPONSE_TIMEOUT_MS);\n }, [stopTurn]);\n\n /** Hard 2-minute cap from send start — still-streaming turns are cancelled too. */\n const armMaxRun = useCallback(() => {\n if (maxRunTimerRef.current) clearTimeout(maxRunTimerRef.current);\n const started = runStartedAtRef.current;\n if (!pendingRef.current || started == null) {\n maxRunTimerRef.current = null;\n return;\n }\n const remaining = CDECLI_MAX_RUN_MS - (Date.now() - started);\n maxRunTimerRef.current = setTimeout(() => stopTurn('max-run'), Math.max(0, remaining));\n }, [stopTurn]);\n\n // Pause JS timers in the background; on resume re-arm from wall-clock start\n // so a 2-minute run that finished while away is stopped immediately.\n useEffect(() => {\n const sub = AppState.addEventListener('change', (next) => {\n if (next === 'active') {\n if (pendingRef.current && !streamCompletedRef.current) {\n armTimeout();\n armMaxRun();\n }\n } else {\n clearRunTimers();\n }\n });\n return () => sub.remove();\n }, [armMaxRun, armTimeout, clearRunTimers]);\n\n useMessengerStreamDeltaSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const delta = data?.data?.messengerStreamDelta;\n if (!delta) return;\n\n if (delta.isFinal) return;\n\n // A new run after the turn finished, with no send behind it, is the\n // agent following up. Open a round for it rather than drop it until\n // the user happens to send again.\n if (\n streamCompletedRef.current &&\n delta.runId &&\n delta.runId !== completedRunIdRef.current &&\n !isFastLaneRunId(delta.runId)\n ) {\n streamCompletedRef.current = false;\n hasReceivedDeltasRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n }\n\n const prevRunId = lastRunIdRef.current;\n if (delta.runId && delta.runId !== prevRunId) {\n accumulatedLenRef.current = 0;\n // Fast-lane run (`fast-…`) then agent (`serve-…`): start a fresh\n // bubble instead of appending the agent onto the provisional article.\n if (prevRunId && !isFastLaneRunId(delta.runId)) {\n cbRef.current.onStreamRestart?.();\n }\n }\n if (delta.runId) lastRunIdRef.current = delta.runId;\n\n if (streamCompletedRef.current) return;\n\n // Pick up a turn that kept running after the user left Chat for history.\n if (!pendingRef.current) {\n if (!reconnectedStreamRef.current) {\n reconnectedStreamRef.current = true;\n accumulatedLenRef.current = 0;\n }\n }\n\n hasReceivedDeltasRef.current = true;\n armTimeout();\n ingestAccumulatedText(delta.text ?? '', isFastLaneRunId(delta.runId));\n },\n onError: (err) => {\n console.error('[useCdecliChannel] stream delta subscription error:', err);\n },\n });\n\n // Seed the in-flight reply when Chat remounts (history → chat) mid-stream.\n useEffect(() => {\n if (streamSkip || !streamChannelId) return undefined;\n if (seededChannelRef.current === streamChannelId) return undefined;\n seededChannelRef.current = streamChannelId;\n accumulatedLenRef.current = 0;\n streamCompletedRef.current = false;\n reconnectedStreamRef.current = false;\n lastRunIdRef.current = null;\n\n let cancelled = false;\n apolloClient\n .query({\n query: MESSENGER_ACTIVE_STREAM_QUERY,\n variables: { channelId: streamChannelId },\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n })\n .then(({ data }) => {\n if (cancelled) return;\n const snapshot = data?.messengerActiveStream as\n | { runId?: string; text?: string; isFinal?: boolean }\n | null\n | undefined;\n if (!snapshot?.text || snapshot.isFinal) return;\n if (streamCompletedRef.current) return;\n if (accumulatedLenRef.current > 0) return;\n reconnectedStreamRef.current = true;\n hasReceivedDeltasRef.current = true;\n if (snapshot.runId) lastRunIdRef.current = snapshot.runId;\n ingestAccumulatedText(snapshot.text);\n })\n .catch(() => {\n /* pre-#701 backend or transient failure — live deltas self-heal */\n });\n return () => {\n cancelled = true;\n };\n }, [streamChannelId, streamSkip, apolloClient, ingestAccumulatedText]);\n\n useGatewayInboundMessageByChannelSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const msg = data?.data?.gatewayInboundMessageByChannel;\n if (!msg) return;\n const externalId = msg.externalId ?? '';\n if (externalId && deliveredInboundRef.current.includes(externalId)) return;\n const sanitizedText = stripModelCostHeader(msg.text ?? '');\n const { preResponse, text: finalText } = splitPreResponse(sanitizedText);\n // The gateway speaking about queued work (a status answer, a\n // long-wait report) while a reply is still on its way belongs beside\n // that reply. Taken as the round's final message it would cut the\n // reply off, and the rest of its stream would be dropped.\n if (\n externalId.startsWith(GATEWAY_NOTICE_ID_PREFIX) &&\n finalText.trim() &&\n !streamCompletedRef.current &&\n (pendingRef.current || hasReceivedDeltasRef.current)\n ) {\n deliveredInboundRef.current = [...deliveredInboundRef.current.slice(-49), externalId];\n cbRef.current.onNotice?.(finalText.trim());\n return;\n }\n if (streamCompletedRef.current) {\n // A final message after the turn finished that did not stream -\n // e.g. the gateway's word on a message it queued, or a queued\n // request's answer - is a follow-up of its own. Only a message\n // this hook has not delivered yet can be one.\n if (!externalId || !finalText.trim()) return;\n streamCompletedRef.current = false;\n hasReceivedDeltasRef.current = false;\n accumulatedLenRef.current = 0;\n }\n if (preResponse) cbRef.current.onQuickReply?.(preResponse);\n // Fast-lane-only inbound: keep waiting for the agent complete.\n if (msg.text && !finalText.trim() && preResponse) return;\n if (!finalText.trim() && !pendingRef.current && !hasReceivedDeltasRef.current) return;\n\n if (finalText.trim() && !hasReceivedDeltasRef.current) {\n cbRef.current.onChunk(finalText);\n }\n\n cbRef.current.onComplete(resolveAssistantReply(finalText));\n if (externalId) deliveredInboundRef.current = [...deliveredInboundRef.current.slice(-49), externalId];\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n },\n onError: (err) => {\n console.error('[useCdecliChannel] subscription error:', err);\n cbRef.current.onError(err.message || 'CDeCLI subscription error');\n },\n });\n\n const sendMessage = useCallback(\n async (\n text: string,\n chatId = 'messenger',\n media: Array<{ type: string; url: string; data?: string; mimeType?: string; filename?: string }> = [],\n ): Promise<boolean> => {\n if (!isConnected) return false;\n\n pendingRef.current = { text, sentAt: Date.now(), chatId };\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n quickReplyShownRef.current = false;\n\n // Ask the brain the same question in parallel with the send. On a cold\n // first turn the agent can take minutes before its first delta; the\n // brain answers in seconds. Its reply is painted only if nothing real\n // has arrived yet, and is replaced in place the moment it does. Fire\n // and forget: a brain failure changes nothing about the turn.\n // Never run it for media turns — the brain only sees `text`, so\n // \"what is this\" + a photo becomes a generic \"what are you referring to\".\n // Nor for a connect card's `[CONNECTOR_CONNECTED:…]` / `[CONNECTOR_DECLINED:…]`\n // reply: it answers the agent's parked request and asks nothing, so a brain\n // \"answer\" would paint a bogus bubble over the agent's real follow-up.\n const turn = ++turnSeqRef.current;\n if (media.length === 0 && !isConnectorReply(text)) {\n void quickReplyViaBrain(text).then((answer) => {\n if (!answer) return;\n // Stale if the turn moved on, or the agent already spoke.\n if (turnSeqRef.current !== turn || !pendingRef.current) return;\n if (hasReceivedDeltasRef.current || streamCompletedRef.current) return;\n quickReplyShownRef.current = true;\n cbRef.current.onQuickReply?.(answer);\n });\n }\n\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(media.length > 0 ? { media: media as never } : {}),\n ...(model || skill\n ? { metadata: { ...(model && { model }), ...(skill && { skill }) } }\n : {}),\n },\n },\n });\n\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI send failed';\n cbRef.current.onError(errMsg);\n pendingRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n return false;\n }\n\n runStartedAtRef.current = Date.now();\n armTimeout();\n armMaxRun();\n\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n cbRef.current.onError(msg);\n pendingRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n return false;\n }\n },\n [isConnected, accountId, channelId, sendMutation, model, skill, armTimeout, armMaxRun, clearRunTimers],\n );\n\n useEffect(\n () => () => {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n },\n [clearRunTimers],\n );\n\n /**\n * Inject a follow-up into the turn that is currently streaming.\n * Same `gatewaySendMessage` mutation with `metadata.steer = true` (browser\n * `useCdecliChannel.steer`). Do NOT reset streaming refs: the existing\n * delta subscription must keep running.\n *\n * \"Cannot steer: no active session\" is an expected race before cdecli has\n * started the turn. Callers should queue and retry; do not `console.error`\n * (that pops the RN LogBox and looks like a crash).\n */\n const steer = useCallback(\n async (text: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n metadata: { steer: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI steer failed';\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] steer failed:', errMsg);\n }\n return { ok: false, error: errMsg };\n }\n return { ok: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn('[useCdecliChannel] steer mutation error:', msg);\n return { ok: false, error: msg };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Send a message while a turn is running. The gateway queues it for the\n * agent, which answers it when the running turn ends - the way Claude Code\n * and Cursor queue a message typed mid-turn. `queueAware` tells the gateway\n * this client shows the queue itself, so no \"Got it\" reply comes back.\n *\n * Unlike `sendMessage` this touches none of the in-flight round's refs: the\n * running reply keeps streaming, and the queued message's answer arrives\n * later as a follow-up round of its own.\n */\n const sendQueued = useCallback(\n async (\n text: string,\n chatId = 'messenger',\n media: Array<{ type: string; url: string; data?: string; mimeType?: string; filename?: string }> = [],\n ): Promise<QueuedSendResult> => {\n if (!isConnected) return { status: 'failed', error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(media.length > 0 ? { media: media as never } : {}),\n metadata: { queueAware: true, ...(model && { model }), ...(skill && { skill }) },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) return { status: 'failed', error: payload?.error || 'CDeCLI send failed' };\n const externalId = payload.externalId ?? '';\n if (externalId.startsWith(QUEUED_EXTERNAL_ID_PREFIX)) {\n return { status: 'queued', id: externalId.slice(QUEUED_EXTERNAL_ID_PREFIX.length) };\n }\n if (externalId.startsWith(STATUS_EXTERNAL_ID_PREFIX)) return { status: 'answered' };\n return { status: 'started' };\n } catch (err) {\n return { status: 'failed', error: err instanceof Error ? err.message : String(err) };\n }\n },\n [isConnected, accountId, sendMutation, model, skill],\n );\n\n /** Take one queued message back before the agent gets to it. */\n const cancelQueued = useCallback(\n async (id: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: { channelType: 'cdecli-serve', accountId, chatId, text: '', metadata: { dequeue: id } },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n return payload?.success\n ? { ok: true }\n : { ok: false, error: payload?.error || 'Could not cancel that message.' };\n } catch (err) {\n return { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Abort the in-flight turn. `metadata.cancel = true` maps to\n * `POST /v1/chat/cancel` on cdecli-serve (browser parity).\n */\n const cancel = useCallback(\n async (chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n pendingRef.current = null;\n runStartedAtRef.current = null;\n // The stopped run is over for this client: a delta it still emits\n // must not reopen as a follow-up. The next run (a queued message the\n // agent now takes) does, since its runId differs.\n if (hasReceivedDeltasRef.current || lastRunIdRef.current) {\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n hasReceivedDeltasRef.current = false;\n }\n clearRunTimers();\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI cancel failed';\n // Trash-clear / greet flows cancel with nothing running — expected.\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] cancel failed:', errMsg);\n }\n return false;\n }\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[useCdecliChannel] cancel mutation error:', msg);\n return false;\n }\n },\n [isConnected, accountId, sendMutation, clearRunTimers],\n );\n\n return { sendMessage, sendQueued, cancelQueued, steer, cancel };\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"useCdecliChannel.js","sources":["../../src/hooks/useCdecliChannel.ts"],"sourcesContent":["/**\n * useCdecliChannel — wires the cdecli-serve messenger-gateway channel into the mobile chat UI.\n *\n * Kept in sync with `packages-modules/account/browser/src/hooks/useCdecliChannel.ts`.\n * When the CDeCLI channel is connected:\n * - `sendMessage(text, chatId, media)` calls `gatewaySendMessage`\n * - `MessengerStreamDelta` subscription delivers streaming chunks via `onChunk`\n * - `GatewayInboundMessageByChannel` delivers the final reply via `onComplete`\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { useApolloClient } from '@apollo/client';\nimport { isConnectorReply } from 'common';\nimport {\n useGatewaySendMessageMutation,\n useGatewayInboundMessageByChannelSubscription,\n useMessengerStreamDeltaSubscription,\n} from 'common/graphql';\nimport { quickReplyViaBrain } from '../services/brainQuickReply';\nimport { MESSENGER_ACTIVE_STREAM_QUERY, stripModelCostHeader } from './messengerStream';\nimport {\n CHAT_RUN_TIMEOUT_TEXT,\n CDECLI_MAX_RUN_MS,\n EMPTY_CHAT_RESPONSE_TEXT,\n resolveAssistantReply,\n} from '../features/chat/emptyChatResponse';\nimport { isFastLaneRunId, joinPreResponse, splitPreResponse } from '../features/chat/preResponse';\nimport { clientTimezone } from '../utils/clientTimezone';\n\n// `error?: undefined` on the success arm keeps `result.error` reachable on the\n// union: with strictNullChecks off (repo-wide), TS will not narrow the\n// discriminated union after an `if (result.ok) continue`.\nexport type SteerResult = { ok: true; error?: undefined } | { ok: false; error: string };\n\n/**\n * What became of a message sent while a turn was running:\n * - `queued`: the gateway queued it for the agent, which answers it when the\n * running turn ends. `id` cancels it (`cancelQueued`).\n * - `answered`: the gateway answered it on the spot (a status question) with a\n * notice that arrives through `onNotice`.\n * - `started`: the running turn had already ended, so the agent took it right\n * away; its answer arrives as a follow-up.\n */\nexport type QueuedSendResult =\n | { status: 'queued'; id: string; error?: undefined }\n | { status: 'answered' | 'started'; id?: undefined; error?: undefined }\n | { status: 'failed'; id?: undefined; error: string };\n\n/** The gateway's send-result ids for a message it queued or answered itself. */\nconst QUEUED_EXTERNAL_ID_PREFIX = 'handoff-queued-';\nconst STATUS_EXTERNAL_ID_PREFIX = 'handoff-status-';\n/** Messages from the gateway itself (a status answer, a long-wait report). */\nconst GATEWAY_NOTICE_ID_PREFIX = 'handoff-';\n\nexport interface CdecliChannelCallbacks {\n onChunk: (text: string) => void;\n /**\n * A fast provisional answer from `yantra-brain` or `CDECLI_FAST_LANE=pre`.\n * Shown as a Quick answer strip — never the main bubble. Pass the full\n * text so far (not a delta). Do not pass `''` to hide it when the agent\n * starts; web keeps the strip beside the agent reply.\n */\n onQuickReply?: (text: string) => void;\n /**\n * The agent started a new run (typically after the fast lane). Clear the\n * main bubble so the agent's tokens do not append onto the provisional\n * article.\n */\n onStreamRestart?: () => void;\n /**\n * The turn's final reply. When the gateway's fast lane answered first, its\n * quick answer comes back prepended in the persisted `[PRE_RESPONSE]` framing,\n * so the finished bubble matches the same reply reloaded from history.\n */\n onComplete: (text: string) => void;\n onError: (error: string) => void;\n /**\n * A message from the gateway about queued work (a status answer, a\n * long-wait report) that arrived while a reply is still streaming. It is\n * shown beside that reply and does NOT end it.\n */\n onNotice?: (text: string) => void;\n}\n\nexport function isNoActiveSessionError(message: string): boolean {\n return /no active session/i.test(message);\n}\n\n/**\n * Idle window, not a total budget. The timer is re-armed on every streamed\n * delta (a turn that is actively streaming is not stuck), and paused while the\n * app is backgrounded (iOS suspends the WebSocket + throttles JS timers, so a\n * wall-clock timer would otherwise fire a false \"did not respond\" the instant\n * the app returns to the foreground). It fires only after this much CONTINUOUS\n * silence with the app in the foreground.\n */\nconst CDECLI_RESPONSE_TIMEOUT_MS = 300_000;\n\nexport function useCdecliChannel(\n isConnected: boolean,\n accountId: string,\n channelId: string | undefined,\n callbacks: CdecliChannelCallbacks,\n model?: string,\n skill?: string,\n) {\n const [sendMutation] = useGatewaySendMessageMutation();\n const cbRef = useRef(callbacks);\n cbRef.current = callbacks;\n\n const pendingRef = useRef<{ text: string; sentAt: number; chatId: string } | null>(null);\n const hasReceivedDeltasRef = useRef(false);\n const reconnectedStreamRef = useRef(false);\n const streamCompletedRef = useRef(false);\n const accumulatedLenRef = useRef(0);\n const lastRunIdRef = useRef<string | null>(null);\n const apolloClient = useApolloClient();\n const seededChannelRef = useRef<string | null>(null);\n const quickReplyShownRef = useRef(false);\n /**\n * The gateway's quick answer for the running turn. Unlike the brain assist it\n * is persisted with the reply, so it is handed back on completion and the\n * strip outlives the stream. Cleared at the start and the end of every turn.\n */\n const preResponseRef = useRef<string | null>(null);\n /**\n * The run the last finished turn streamed on. After a turn ends the agent\n * can still speak with no send behind it - the gateway runs a request it\n * queued while the agent was busy and follows up with the answer. That\n * arrives as a NEW run (or a new final message) and must open a round of\n * its own; a late delta from THIS run must not.\n */\n const completedRunIdRef = useRef<string | null>(null);\n /** Final messages already delivered, so a redelivery never paints twice. */\n const deliveredInboundRef = useRef<string[]>([]);\n\n /**\n * Forward newly-accumulated stream text. Shared by live deltas and the\n * mount-time resume seed so neither gaps nor double-delivery happen when\n * the user leaves Chat for history and comes back mid-turn.\n */\n const ingestAccumulatedText = useCallback((accumulated: string, asFastLane = false) => {\n const stripped = stripModelCostHeader(accumulated);\n const { preResponse, text: fullText } = splitPreResponse(stripped);\n if (preResponse) {\n quickReplyShownRef.current = true;\n preResponseRef.current = preResponse;\n cbRef.current.onQuickReply?.(preResponse);\n }\n if (asFastLane) {\n const fast = (preResponse || fullText).trim();\n if (fast) {\n quickReplyShownRef.current = true;\n preResponseRef.current = fast;\n cbRef.current.onQuickReply?.(fast);\n }\n return;\n }\n const newChunk = fullText.substring(accumulatedLenRef.current);\n accumulatedLenRef.current = fullText.length;\n if (newChunk) cbRef.current.onChunk(newChunk);\n }, []);\n // Identity of the current turn for the brain race. A counter, not a\n // timestamp: two sends can share a millisecond, and a timestamp would then\n // let a brain answer for a superseded turn paint over the live one.\n const turnSeqRef = useRef(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const maxRunTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const runStartedAtRef = useRef<number | null>(null);\n const stoppingRef = useRef(false);\n\n const streamSkip = !channelId;\n const streamChannelId = channelId || accountId;\n\n const clearRunTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (maxRunTimerRef.current) {\n clearTimeout(maxRunTimerRef.current);\n maxRunTimerRef.current = null;\n }\n }, []);\n\n const stopTurn = useCallback(\n (reason: 'idle' | 'max-run') => {\n const pending = pendingRef.current;\n if (!pending || stoppingRef.current) return;\n stoppingRef.current = true;\n const { chatId } = pending;\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n runStartedAtRef.current = null;\n clearRunTimers();\n void sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n }).catch(() => {\n /* local stop still lands a standard reply */\n });\n const pre = preResponseRef.current;\n preResponseRef.current = null;\n cbRef.current.onComplete(\n joinPreResponse(pre, reason === 'max-run' ? CHAT_RUN_TIMEOUT_TEXT : EMPTY_CHAT_RESPONSE_TEXT),\n );\n stoppingRef.current = false;\n },\n [accountId, clearRunTimers, sendMutation],\n );\n\n /** (Re)start the idle timer for the in-flight turn. No-op if none pending. */\n const armTimeout = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n if (!pendingRef.current) {\n timeoutRef.current = null;\n return;\n }\n timeoutRef.current = setTimeout(() => stopTurn('idle'), CDECLI_RESPONSE_TIMEOUT_MS);\n }, [stopTurn]);\n\n /** Hard 2-minute cap from send start — still-streaming turns are cancelled too. */\n const armMaxRun = useCallback(() => {\n if (maxRunTimerRef.current) clearTimeout(maxRunTimerRef.current);\n const started = runStartedAtRef.current;\n if (!pendingRef.current || started == null) {\n maxRunTimerRef.current = null;\n return;\n }\n const remaining = CDECLI_MAX_RUN_MS - (Date.now() - started);\n maxRunTimerRef.current = setTimeout(() => stopTurn('max-run'), Math.max(0, remaining));\n }, [stopTurn]);\n\n // Pause JS timers in the background; on resume re-arm from wall-clock start\n // so a 2-minute run that finished while away is stopped immediately.\n useEffect(() => {\n const sub = AppState.addEventListener('change', (next) => {\n if (next === 'active') {\n if (pendingRef.current && !streamCompletedRef.current) {\n armTimeout();\n armMaxRun();\n }\n } else {\n clearRunTimers();\n }\n });\n return () => sub.remove();\n }, [armMaxRun, armTimeout, clearRunTimers]);\n\n useMessengerStreamDeltaSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const delta = data?.data?.messengerStreamDelta;\n if (!delta) return;\n\n if (delta.isFinal) return;\n\n // A new run after the turn finished, with no send behind it, is the\n // agent following up. Open a round for it rather than drop it until\n // the user happens to send again.\n if (\n streamCompletedRef.current &&\n delta.runId &&\n delta.runId !== completedRunIdRef.current &&\n !isFastLaneRunId(delta.runId)\n ) {\n streamCompletedRef.current = false;\n hasReceivedDeltasRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n preResponseRef.current = null;\n }\n\n const prevRunId = lastRunIdRef.current;\n if (delta.runId && delta.runId !== prevRunId) {\n accumulatedLenRef.current = 0;\n // Fast-lane run (`fast-…`) then agent (`serve-…`): start a fresh\n // bubble instead of appending the agent onto the provisional article.\n if (prevRunId && !isFastLaneRunId(delta.runId)) {\n cbRef.current.onStreamRestart?.();\n }\n }\n if (delta.runId) lastRunIdRef.current = delta.runId;\n\n if (streamCompletedRef.current) return;\n\n // Pick up a turn that kept running after the user left Chat for history.\n if (!pendingRef.current) {\n if (!reconnectedStreamRef.current) {\n reconnectedStreamRef.current = true;\n accumulatedLenRef.current = 0;\n }\n }\n\n hasReceivedDeltasRef.current = true;\n armTimeout();\n ingestAccumulatedText(delta.text ?? '', isFastLaneRunId(delta.runId));\n },\n onError: (err) => {\n console.error('[useCdecliChannel] stream delta subscription error:', err);\n },\n });\n\n // Seed the in-flight reply when Chat remounts (history → chat) mid-stream.\n useEffect(() => {\n if (streamSkip || !streamChannelId) return undefined;\n if (seededChannelRef.current === streamChannelId) return undefined;\n seededChannelRef.current = streamChannelId;\n accumulatedLenRef.current = 0;\n streamCompletedRef.current = false;\n reconnectedStreamRef.current = false;\n lastRunIdRef.current = null;\n\n let cancelled = false;\n apolloClient\n .query({\n query: MESSENGER_ACTIVE_STREAM_QUERY,\n variables: { channelId: streamChannelId },\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n })\n .then(({ data }) => {\n if (cancelled) return;\n const snapshot = data?.messengerActiveStream as\n | { runId?: string; text?: string; isFinal?: boolean }\n | null\n | undefined;\n if (!snapshot?.text || snapshot.isFinal) return;\n if (streamCompletedRef.current) return;\n if (accumulatedLenRef.current > 0) return;\n reconnectedStreamRef.current = true;\n hasReceivedDeltasRef.current = true;\n if (snapshot.runId) lastRunIdRef.current = snapshot.runId;\n ingestAccumulatedText(snapshot.text);\n })\n .catch(() => {\n /* pre-#701 backend or transient failure — live deltas self-heal */\n });\n return () => {\n cancelled = true;\n };\n }, [streamChannelId, streamSkip, apolloClient, ingestAccumulatedText]);\n\n useGatewayInboundMessageByChannelSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const msg = data?.data?.gatewayInboundMessageByChannel;\n if (!msg) return;\n const externalId = msg.externalId ?? '';\n if (externalId && deliveredInboundRef.current.includes(externalId)) return;\n const sanitizedText = stripModelCostHeader(msg.text ?? '');\n const { preResponse, text: finalText } = splitPreResponse(sanitizedText);\n // The gateway speaking about queued work (a status answer, a\n // long-wait report) while a reply is still on its way belongs beside\n // that reply. Taken as the round's final message it would cut the\n // reply off, and the rest of its stream would be dropped.\n if (\n externalId.startsWith(GATEWAY_NOTICE_ID_PREFIX) &&\n finalText.trim() &&\n !streamCompletedRef.current &&\n (pendingRef.current || hasReceivedDeltasRef.current)\n ) {\n deliveredInboundRef.current = [...deliveredInboundRef.current.slice(-49), externalId];\n cbRef.current.onNotice?.(finalText.trim());\n return;\n }\n if (streamCompletedRef.current) {\n // A final message after the turn finished that did not stream -\n // e.g. the gateway's word on a message it queued, or a queued\n // request's answer - is a follow-up of its own. Only a message\n // this hook has not delivered yet can be one.\n if (!externalId || !finalText.trim()) return;\n streamCompletedRef.current = false;\n hasReceivedDeltasRef.current = false;\n accumulatedLenRef.current = 0;\n }\n if (preResponse) {\n preResponseRef.current = preResponse;\n cbRef.current.onQuickReply?.(preResponse);\n }\n // Fast-lane-only inbound: keep waiting for the agent complete.\n if (msg.text && !finalText.trim() && preResponse) return;\n if (!finalText.trim() && !pendingRef.current && !hasReceivedDeltasRef.current) return;\n\n if (finalText.trim() && !hasReceivedDeltasRef.current) {\n cbRef.current.onChunk(finalText);\n }\n\n const pre = preResponseRef.current;\n preResponseRef.current = null;\n cbRef.current.onComplete(joinPreResponse(pre, resolveAssistantReply(finalText)));\n if (externalId) deliveredInboundRef.current = [...deliveredInboundRef.current.slice(-49), externalId];\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n },\n onError: (err) => {\n console.error('[useCdecliChannel] subscription error:', err);\n cbRef.current.onError(err.message || 'CDeCLI subscription error');\n },\n });\n\n const sendMessage = useCallback(\n async (\n text: string,\n chatId = 'messenger',\n media: Array<{ type: string; url: string; data?: string; mimeType?: string; filename?: string }> = [],\n ): Promise<boolean> => {\n if (!isConnected) return false;\n\n pendingRef.current = { text, sentAt: Date.now(), chatId };\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n quickReplyShownRef.current = false;\n preResponseRef.current = null;\n\n // Ask the brain the same question in parallel with the send. On a cold\n // first turn the agent can take minutes before its first delta; the\n // brain answers in seconds. Its reply is painted only if nothing real\n // has arrived yet, and is replaced in place the moment it does. Fire\n // and forget: a brain failure changes nothing about the turn.\n // Never run it for media turns — the brain only sees `text`, so\n // \"what is this\" + a photo becomes a generic \"what are you referring to\".\n // Nor for a connect card's `[CONNECTOR_CONNECTED:…]` / `[CONNECTOR_DECLINED:…]`\n // reply: it answers the agent's parked request and asks nothing, so a brain\n // \"answer\" would paint a bogus bubble over the agent's real follow-up.\n const turn = ++turnSeqRef.current;\n if (media.length === 0 && !isConnectorReply(text)) {\n void quickReplyViaBrain(text).then((answer) => {\n if (!answer) return;\n // Stale if the turn moved on, or the agent already spoke.\n if (turnSeqRef.current !== turn || !pendingRef.current) return;\n if (hasReceivedDeltasRef.current || streamCompletedRef.current) return;\n quickReplyShownRef.current = true;\n cbRef.current.onQuickReply?.(answer);\n });\n }\n\n try {\n const timezone = clientTimezone();\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(media.length > 0 ? { media: media as never } : {}),\n ...(model || skill || timezone\n ? {\n metadata: {\n ...(model && { model }),\n ...(skill && { skill }),\n ...(timezone && { timezone }),\n },\n }\n : {}),\n },\n },\n });\n\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI send failed';\n cbRef.current.onError(errMsg);\n pendingRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n return false;\n }\n\n runStartedAtRef.current = Date.now();\n armTimeout();\n armMaxRun();\n\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n cbRef.current.onError(msg);\n pendingRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n return false;\n }\n },\n [isConnected, accountId, sendMutation, model, skill, armTimeout, armMaxRun, clearRunTimers],\n );\n\n useEffect(\n () => () => {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n lastRunIdRef.current = null;\n runStartedAtRef.current = null;\n clearRunTimers();\n },\n [clearRunTimers],\n );\n\n /**\n * Inject a follow-up into the turn that is currently streaming.\n * Same `gatewaySendMessage` mutation with `metadata.steer = true` (browser\n * `useCdecliChannel.steer`). Do NOT reset streaming refs: the existing\n * delta subscription must keep running.\n *\n * \"Cannot steer: no active session\" is an expected race before cdecli has\n * started the turn. Callers should queue and retry; do not `console.error`\n * (that pops the RN LogBox and looks like a crash).\n */\n const steer = useCallback(\n async (text: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n metadata: { steer: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI steer failed';\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] steer failed:', errMsg);\n }\n return { ok: false, error: errMsg };\n }\n return { ok: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn('[useCdecliChannel] steer mutation error:', msg);\n return { ok: false, error: msg };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Send a message while a turn is running. The gateway queues it for the\n * agent, which answers it when the running turn ends - the way Claude Code\n * and Cursor queue a message typed mid-turn. `queueAware` tells the gateway\n * this client shows the queue itself, so no \"Got it\" reply comes back.\n *\n * Unlike `sendMessage` this touches none of the in-flight round's refs: the\n * running reply keeps streaming, and the queued message's answer arrives\n * later as a follow-up round of its own.\n */\n const sendQueued = useCallback(\n async (\n text: string,\n chatId = 'messenger',\n media: Array<{ type: string; url: string; data?: string; mimeType?: string; filename?: string }> = [],\n ): Promise<QueuedSendResult> => {\n if (!isConnected) return { status: 'failed', error: 'CDeCLI is not connected.' };\n try {\n const timezone = clientTimezone();\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(media.length > 0 ? { media: media as never } : {}),\n metadata: {\n queueAware: true,\n ...(model && { model }),\n ...(skill && { skill }),\n ...(timezone && { timezone }),\n },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) return { status: 'failed', error: payload?.error || 'CDeCLI send failed' };\n const externalId = payload.externalId ?? '';\n if (externalId.startsWith(QUEUED_EXTERNAL_ID_PREFIX)) {\n return { status: 'queued', id: externalId.slice(QUEUED_EXTERNAL_ID_PREFIX.length) };\n }\n if (externalId.startsWith(STATUS_EXTERNAL_ID_PREFIX)) return { status: 'answered' };\n return { status: 'started' };\n } catch (err) {\n return { status: 'failed', error: err instanceof Error ? err.message : String(err) };\n }\n },\n [isConnected, accountId, sendMutation, model, skill],\n );\n\n /** Take one queued message back before the agent gets to it. */\n const cancelQueued = useCallback(\n async (id: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: { channelType: 'cdecli-serve', accountId, chatId, text: '', metadata: { dequeue: id } },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n return payload?.success\n ? { ok: true }\n : { ok: false, error: payload?.error || 'Could not cancel that message.' };\n } catch (err) {\n return { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Abort the in-flight turn. `metadata.cancel = true` maps to\n * `POST /v1/chat/cancel` on cdecli-serve (browser parity).\n */\n const cancel = useCallback(\n async (chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n pendingRef.current = null;\n runStartedAtRef.current = null;\n // The stopped run is over for this client: a delta it still emits\n // must not reopen as a follow-up. The next run (a queued message the\n // agent now takes) does, since its runId differs.\n if (hasReceivedDeltasRef.current || lastRunIdRef.current) {\n streamCompletedRef.current = true;\n completedRunIdRef.current = lastRunIdRef.current;\n hasReceivedDeltasRef.current = false;\n }\n clearRunTimers();\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI cancel failed';\n // Trash-clear / greet flows cancel with nothing running — expected.\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] cancel failed:', errMsg);\n }\n return false;\n }\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[useCdecliChannel] cancel mutation error:', msg);\n return false;\n }\n },\n [isConnected, accountId, sendMutation, clearRunTimers],\n );\n\n return { sendMessage, sendQueued, cancelQueued, steer, cancel };\n}\n"],"names":["_a"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {useApolloClient}from'@apollo/client/index.js';import {SortEnum,RoomType,PostTypeEnum,isConnectorReply,stripConnectorConnect,AiAgentMessageRole}from'common';import {useGetChannelsByUserWithLastMessageQuery,useMessagesQuery,MessagesDocument,useAddChannelMutation,useSendMessagesMutation,OnChatMessageAddedDocument,GetChannelsByUserWithLastMessageDocument}from'common/graphql';import {useMemo,useCallback,useEffect}from'react';import {v4}from'uuid';import {isAttachedCaption,historyAttachmentTitle,attachmentsFromUserContent}from'../features/attachments/historyAttachmentLabel.js';import {stripAskUser}from'../features/chat/askUser.js';import {parseToolActivity}from'../features/chat/toolActivity.js';var __defProp = Object.defineProperty;
1
+ import {useApolloClient}from'@apollo/client/index.js';import {SortEnum,RoomType,PostTypeEnum,isConnectorReply,stripConnectorConnect,AiAgentMessageRole}from'common';import {useGetChannelsByUserWithLastMessageQuery,useMessagesQuery,MessagesDocument,useAddChannelMutation,useSendMessagesMutation,OnChatMessageAddedDocument,GetChannelsByUserWithLastMessageDocument}from'common/graphql';import {useMemo,useCallback,useEffect}from'react';import {v4}from'uuid';import {isAttachedCaption,historyAttachmentTitle,attachmentsFromUserContent}from'../features/attachments/historyAttachmentLabel.js';import {stripAskUser}from'../features/chat/askUser.js';import {parseToolActivity}from'../features/chat/toolActivity.js';import {splitPreResponse}from'../features/chat/preResponse.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -297,9 +297,16 @@ function looksLikeAssistantReply(text, role) {
297
297
  if (!role && t.length > 180) return true;
298
298
  return false;
299
299
  }
300
+ function stripInlineMarkdown(text) {
301
+ return text.replace(/^#{1,6}\s+/, "").replace(/(\*\*|__)(.+?)\1/g, "$2").replace(/`([^`]+)`/g, "$1");
302
+ }
300
303
  function cleanHistoryPreview(raw) {
301
304
  if (isConnectorReply(raw)) return "";
302
- const withoutAsk = stripConnectorConnect(stripAskUser(raw));
305
+ const {
306
+ preResponse,
307
+ text: answer
308
+ } = splitPreResponse(raw);
309
+ const withoutAsk = stripConnectorConnect(stripAskUser(answer));
303
310
  const {
304
311
  text: withoutTools
305
312
  } = parseToolActivity(withoutAsk, false);
@@ -307,7 +314,7 @@ function cleanHistoryPreview(raw) {
307
314
  t = t.replace(/^(thinking[.…]*\s*)+/i, "").trim();
308
315
  t = t.replace(/^let me check on that requested skill[^\n.!?]*[.!?-]?\s*/i, "").trim();
309
316
  t = t.replace(/^(?:[⚙🔧⚙️⚠][^\n]*\n)+\s*/gu, "").trim();
310
- return t;
317
+ return stripInlineMarkdown(t || cleanMessageText(preResponse != null ? preResponse : ""));
311
318
  }
312
319
  function buildSessionFromChannel(channel) {
313
320
  var _a, _b, _c, _d, _e, _f;