@google/gemini-cli 0.65.0-nightly.20261013.g51617c1bc → 0.65.0-preview.0

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.
Files changed (66) hide show
  1. package/bundle/{chunk-BXWN65YH.js → chunk-2WVLIJA5.js} +1 -1
  2. package/bundle/{chunk-5322VSKQ.js → chunk-43EXRO7A.js} +1 -1
  3. package/bundle/{chunk-3EFBILEW.js → chunk-4DCA4L53.js} +2 -2
  4. package/bundle/{chunk-NAGGT65S.js → chunk-4JGVVJGK.js} +1 -1
  5. package/bundle/{chunk-VJXI22NX.js → chunk-BFIV7GTA.js} +2 -2
  6. package/bundle/{chunk-NJIZWOAO.js → chunk-F6AJM4WN.js} +3 -3
  7. package/bundle/{chunk-EPXYFN6C.js → chunk-GSQEBEGC.js} +3 -3
  8. package/bundle/{chunk-SSAL6PAH.js → chunk-H2CZXS7F.js} +1 -1
  9. package/bundle/{chunk-76GSGGHI.js → chunk-HLOOE7YN.js} +1 -1
  10. package/bundle/{chunk-ZZJRXUDM.js → chunk-K4G5D5ZZ.js} +1 -1
  11. package/bundle/{chunk-B22AOTUS.js → chunk-K7AA35SP.js} +26 -22
  12. package/bundle/{chunk-HVVLEMLR.js → chunk-K7NOVQ6G.js} +24 -20
  13. package/bundle/{chunk-C3XVWXTB.js → chunk-LLE5Z636.js} +7 -7
  14. package/bundle/{chunk-KR7RUPIE.js → chunk-NL7ZHGCH.js} +1 -1
  15. package/bundle/{chunk-6M4QEFFF.js → chunk-QJK54DSE.js} +8 -9
  16. package/bundle/{chunk-EA2F2LNY.js → chunk-RPHDSDL6.js} +1 -1
  17. package/bundle/{chunk-LBJNFX6K.js → chunk-S7BCRBI4.js} +1 -1
  18. package/bundle/{chunk-LB7T3Q3K.js → chunk-SN7QZKXC.js} +58 -71
  19. package/bundle/{chunk-GI5HEZHG.js → chunk-TP236FKO.js} +14976 -7914
  20. package/bundle/{chunk-LJV6OKHI.js → chunk-V2R74WAG.js} +5 -7
  21. package/bundle/{chunk-VLEIPZMF.js → chunk-V72FRESD.js} +2 -2
  22. package/bundle/{chunk-N2N4FSJX.js → chunk-VF5WQSOE.js} +1 -1
  23. package/bundle/{chunk-5OZJ7SSG.js → chunk-WGL5FJOS.js} +3 -3
  24. package/bundle/{chunk-JCR3XD5H.js → chunk-WTRK3NVX.js} +7 -7
  25. package/bundle/{cleanup-C3GRMYTQ.js → cleanup-HPADDONA.js} +2 -2
  26. package/bundle/{cleanup-HHEU7BTA.js → cleanup-JOMSXKMP.js} +2 -2
  27. package/bundle/{cleanup-VCQCBVRV.js → cleanup-LYRJHMMO.js} +2 -2
  28. package/bundle/{core-EX2SPRDZ.js → core-IVQAI4S6.js} +1 -1
  29. package/bundle/{dist-GG436DD3.js → core-NCJTYARO.js} +1 -1
  30. package/bundle/{devtoolsService-OI7AEJQC.js → devtoolsService-HIZA3JGR.js} +2 -2
  31. package/bundle/{devtoolsService-E3YLHACW.js → devtoolsService-JFJBTZ4B.js} +3 -4
  32. package/bundle/{devtoolsService-CSRUFNFL.js → devtoolsService-WP2OPVPB.js} +2 -2
  33. package/bundle/{dist-MRDCUCIF.js → dist-GQKLLBDW.js} +1 -1
  34. package/bundle/{gemini-TWP2M62H.js → gemini-546WMAHG.js} +198 -214
  35. package/bundle/{gemini-W7O4SF3Y.js → gemini-5TUKZVGS.js} +14 -14
  36. package/bundle/{gemini-GG2HNQFT.js → gemini-7CHJYSHM.js} +13 -13
  37. package/bundle/gemini.js +7 -7
  38. package/bundle/{interactiveCli-3Y2RHZKF.js → interactiveCli-5XIAIY74.js} +1069 -554
  39. package/bundle/{interactiveCli-GBXKC6IY.js → interactiveCli-E3PUPYMZ.js} +1069 -554
  40. package/bundle/{interactiveCli-E5RBGMKR.js → interactiveCli-L4PK7YY3.js} +1348 -852
  41. package/bundle/{liteRtServerManager-BV7LQRJK.js → liteRtServerManager-22ISMNN2.js} +4 -4
  42. package/bundle/{liteRtServerManager-EW5TUX2V.js → liteRtServerManager-JCTYJBV5.js} +4 -4
  43. package/bundle/{liteRtServerManager-G3ETQGQD.js → liteRtServerManager-JERG6KYC.js} +4 -4
  44. package/bundle/{oauth2-provider-NVW65VJA.js → oauth2-provider-477UJQX6.js} +1 -1
  45. package/bundle/{oauth2-provider-6Z2ZXOX6.js → oauth2-provider-MKWWBW4K.js} +79 -41
  46. package/bundle/{oauth2-provider-4CXU66CN.js → oauth2-provider-XRUER2XR.js} +1 -1
  47. package/bundle/{start-AZFYLAF2.js → start-AGMBPY3O.js} +6 -6
  48. package/bundle/{start-BHB4KDHO.js → start-MVIPJNQ5.js} +6 -6
  49. package/bundle/{start-CHWZQ4ZN.js → start-RZWSVT55.js} +6 -6
  50. package/package.json +1 -1
  51. package/bundle/chunk-5YND2HLC.js +0 -1571
  52. package/bundle/chunk-IJ7X4I2Z.js +0 -425
  53. package/bundle/chunk-K6N5Z54J.js +0 -154
  54. package/bundle/chunk-LZISQJNJ.js +0 -512
  55. package/bundle/chunk-OB6IRF7N.js +0 -118
  56. package/bundle/chunk-TLYQMFOC.js +0 -17535
  57. package/bundle/chunk-UVUPZGTC.js +0 -402042
  58. package/bundle/chunk-XHQIF7OW.js +0 -103253
  59. package/bundle/cleanup-XUHY5LXE.js +0 -32
  60. package/bundle/devtoolsService-NB2AMKES.js +0 -4359
  61. package/bundle/dist-O7VOOHX4.js +0 -2268
  62. package/bundle/gemini-UZP4MEXP.js +0 -17951
  63. package/bundle/interactiveCli-R3ZT6N5Z.js +0 -35014
  64. package/bundle/liteRtServerManager-YM2L7SJG.js +0 -65
  65. package/bundle/oauth2-provider-VEKJJAQ2.js +0 -273
  66. package/bundle/start-NJW6EU4P.js +0 -18
@@ -171,10 +171,10 @@ import {
171
171
  widestLineFromStyledChars,
172
172
  wordBreakStyledChars,
173
173
  wrapStyledChars
174
- } from "./chunk-C3XVWXTB.js";
174
+ } from "./chunk-LLE5Z636.js";
175
175
  import {
176
176
  require_source
177
- } from "./chunk-NAGGT65S.js";
177
+ } from "./chunk-4JGVVJGK.js";
178
178
  import {
179
179
  appEvents
180
180
  } from "./chunk-5PS3AYFU.js";
@@ -227,24 +227,24 @@ import {
227
227
  stripAnsi,
228
228
  stripUnsafeCharacters,
229
229
  toCodePoints
230
- } from "./chunk-5322VSKQ.js";
230
+ } from "./chunk-43EXRO7A.js";
231
231
  import {
232
232
  handleAutoUpdate,
233
233
  isDevelopment,
234
234
  relaunchApp,
235
235
  setUpdateHandler
236
- } from "./chunk-IJ7X4I2Z.js";
236
+ } from "./chunk-V72FRESD.js";
237
237
  import {
238
238
  isTodoList,
239
239
  mapCoreStatusToDisplayStatus,
240
240
  require_react
241
- } from "./chunk-76GSGGHI.js";
241
+ } from "./chunk-HLOOE7YN.js";
242
242
  import {
243
243
  registerCleanup,
244
244
  removeCleanup,
245
245
  runExitCleanup,
246
246
  setupTtyCheck
247
- } from "./chunk-N2N4FSJX.js";
247
+ } from "./chunk-VF5WQSOE.js";
248
248
  import {
249
249
  ACTIVATE_SKILL_TOOL_NAME,
250
250
  AGENT_TOOL_NAME,
@@ -431,7 +431,7 @@ import {
431
431
  validatePlanContent,
432
432
  validatePlanPath,
433
433
  writeToStdout
434
- } from "./chunk-HVVLEMLR.js";
434
+ } from "./chunk-TP236FKO.js";
435
435
  import "./chunk-664ZODQF.js";
436
436
  import "./chunk-IUUIT4SU.js";
437
437
  import "./chunk-L6PII3GR.js";
@@ -18714,6 +18714,9 @@ function useDebouncedValue(value, delay2 = 200) {
18714
18714
  }, [value, delay2]);
18715
18715
  return debounced;
18716
18716
  }
18717
+ function escapeRegExp(value) {
18718
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18719
+ }
18717
18720
  function useReverseSearchCompletion(buffer, history, reverseSearchActive) {
18718
18721
  const {
18719
18722
  suggestions,
@@ -18743,11 +18746,12 @@ function useReverseSearchCompletion(buffer, history, reverseSearchActive) {
18743
18746
  const searchHistory = (0, import_react63.useCallback)(
18744
18747
  (query, items) => {
18745
18748
  const out = [];
18749
+ const regex = new RegExp(escapeRegExp(query), "iu");
18746
18750
  for (let i = 0; i < items.length; i++) {
18747
18751
  const cmd = items[i];
18748
- const idx = cmd.toLowerCase().indexOf(query);
18749
- if (idx !== -1) {
18750
- out.push({ label: cmd, value: cmd, matchedIndex: idx });
18752
+ const match = regex.exec(cmd);
18753
+ if (match) {
18754
+ out.push({ label: cmd, value: cmd, matchedIndex: match.index });
18751
18755
  }
18752
18756
  }
18753
18757
  return out;
@@ -18762,10 +18766,10 @@ function useReverseSearchCompletion(buffer, history, reverseSearchActive) {
18762
18766
  value: cmd,
18763
18767
  matchedIndex: -1
18764
18768
  }));
18765
- const query = debouncedQuery.toLowerCase();
18766
- const canUseCache = prevQueryRef.current && query.startsWith(prevQueryRef.current) && prevMatchesRef.current.length > 0;
18769
+ const lowerQuery = debouncedQuery.toLowerCase();
18770
+ const canUseCache = prevQueryRef.current && lowerQuery.startsWith(prevQueryRef.current) && prevMatchesRef.current.length > 0;
18767
18771
  const source = canUseCache ? prevMatchesRef.current.map((m) => m.value) : history;
18768
- return searchHistory(query, source);
18772
+ return searchHistory(debouncedQuery, source);
18769
18773
  }, [debouncedQuery, history, reverseSearchActive, searchHistory]);
18770
18774
  (0, import_react63.useEffect)(() => {
18771
18775
  if (!reverseSearchActive) {
@@ -26690,7 +26694,7 @@ var useLogger = (config) => {
26690
26694
  };
26691
26695
 
26692
26696
  // packages/cli/src/ui/hooks/useGeminiStream.ts
26693
- var import_react97 = __toESM(require_react(), 1);
26697
+ var import_react99 = __toESM(require_react(), 1);
26694
26698
 
26695
26699
  // packages/cli/src/ui/utils/markdownUtilities.ts
26696
26700
  var isIndexInsideCodeBlock = (content, indexToTest) => {
@@ -27056,6 +27060,638 @@ function adaptToolCalls(coreCalls, prevTracked) {
27056
27060
  // packages/cli/src/ui/hooks/useGeminiStream.ts
27057
27061
  import { promises as fs6 } from "node:fs";
27058
27062
  import path13 from "node:path";
27063
+
27064
+ // packages/cli/src/ui/hooks/useAgentStream.ts
27065
+ var import_react98 = __toESM(require_react(), 1);
27066
+
27067
+ // packages/cli/src/ui/hooks/useTurnActivityMonitor.ts
27068
+ var import_react97 = __toESM(require_react(), 1);
27069
+ var useTurnActivityMonitor = (streamingState, activePtyId, pendingToolCalls = []) => {
27070
+ const [operationStartTime, setOperationStartTime] = (0, import_react97.useState)(0);
27071
+ const prevPtyIdRef = (0, import_react97.useRef)(void 0);
27072
+ const prevStreamingStateRef = (0, import_react97.useRef)(void 0);
27073
+ (0, import_react97.useEffect)(() => {
27074
+ const isNowResponding = streamingState === "responding" /* Responding */;
27075
+ const wasResponding = prevStreamingStateRef.current === "responding" /* Responding */;
27076
+ const ptyChanged = activePtyId !== prevPtyIdRef.current;
27077
+ if (isNowResponding && (!wasResponding || ptyChanged)) {
27078
+ setOperationStartTime(Date.now());
27079
+ } else if (!isNowResponding && wasResponding) {
27080
+ setOperationStartTime(0);
27081
+ }
27082
+ prevPtyIdRef.current = activePtyId;
27083
+ prevStreamingStateRef.current = streamingState;
27084
+ }, [streamingState, activePtyId]);
27085
+ const isRedirectionActive = (0, import_react97.useMemo)(
27086
+ () => (
27087
+ // Check active tool calls for run_shell_command
27088
+ pendingToolCalls.some((tc) => {
27089
+ if (tc.request.name !== "run_shell_command") return false;
27090
+ const command = tc.request.args?.command || "";
27091
+ return hasRedirection(command);
27092
+ })
27093
+ ),
27094
+ [pendingToolCalls]
27095
+ );
27096
+ return {
27097
+ operationStartTime,
27098
+ isRedirectionActive
27099
+ };
27100
+ };
27101
+
27102
+ // packages/cli/src/ui/hooks/useAgentStream.ts
27103
+ var CANCELLED_TOOL_ERROR_MESSAGE = "[Operation Cancelled] Reason: User cancelled operation";
27104
+ function createCancelledToolCall(request, tool, invocation) {
27105
+ const fallbackToolName = request.name.trim() || "generic_tool";
27106
+ return {
27107
+ status: "cancelled" /* Cancelled */,
27108
+ request,
27109
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
27110
+ tool: tool ?? {
27111
+ name: fallbackToolName,
27112
+ displayName: fallbackToolName
27113
+ },
27114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
27115
+ invocation: invocation ?? {
27116
+ getDescription: () => fallbackToolName
27117
+ },
27118
+ response: {
27119
+ callId: request.callId,
27120
+ responseParts: [
27121
+ {
27122
+ functionResponse: {
27123
+ id: request.callId,
27124
+ name: request.name,
27125
+ response: {
27126
+ error: CANCELLED_TOOL_ERROR_MESSAGE
27127
+ }
27128
+ }
27129
+ }
27130
+ ],
27131
+ resultDisplay: void 0,
27132
+ error: new Error(CANCELLED_TOOL_ERROR_MESSAGE),
27133
+ errorType: "unhandled_exception" /* UNHANDLED_EXCEPTION */
27134
+ }
27135
+ };
27136
+ }
27137
+ var useAgentStream = ({
27138
+ agent,
27139
+ config,
27140
+ addItem,
27141
+ onCancelSubmit,
27142
+ isShellFocused,
27143
+ logger
27144
+ }) => {
27145
+ const [initError] = (0, import_react98.useState)(null);
27146
+ const [retryStatus] = (0, import_react98.useState)(null);
27147
+ const [streamingState, setStreamingState] = (0, import_react98.useState)(
27148
+ "idle" /* Idle */
27149
+ );
27150
+ const [thought, setThought] = (0, import_react98.useState)(null);
27151
+ const [lastOutputTime, setLastOutputTime] = (0, import_react98.useState)(Date.now());
27152
+ const currentStreamIdRef = (0, import_react98.useRef)(null);
27153
+ const userMessageTimestampRef = (0, import_react98.useRef)(0);
27154
+ const geminiMessageBufferRef = (0, import_react98.useRef)("");
27155
+ const [pendingHistoryItem, pendingHistoryItemRef, setPendingHistoryItem] = useStateAndRef(null);
27156
+ const [trackedTools, trackedToolsRef, setTrackedTools] = useStateAndRef([]);
27157
+ const toolRequestArgsRef = (0, import_react98.useRef)(
27158
+ /* @__PURE__ */ new Map()
27159
+ );
27160
+ const cancellationStateRef = (0, import_react98.useRef)(
27161
+ "idle" /* Idle */
27162
+ );
27163
+ const cancelPromiseRef = (0, import_react98.useRef)(Promise.resolve());
27164
+ const [pushedToolCallIds, pushedToolCallIdsRef, setPushedToolCallIds] = useStateAndRef(/* @__PURE__ */ new Set());
27165
+ const [_isFirstToolInGroup, isFirstToolInGroupRef, setIsFirstToolInGroup] = useStateAndRef(true);
27166
+ const [_hasEmittedBoxInTurn, hasEmittedBoxInTurnRef, setHasEmittedBoxInTurn] = useStateAndRef(false);
27167
+ const { startNewPrompt } = useSessionStats();
27168
+ const activePtyId = void 0;
27169
+ const backgroundTaskCount = 0;
27170
+ const isBackgroundTaskVisible = false;
27171
+ const toggleBackgroundTasks = (0, import_react98.useCallback)(() => {
27172
+ }, []);
27173
+ const backgroundCurrentExecution = void 0;
27174
+ const backgroundTasks = (0, import_react98.useMemo)(() => /* @__PURE__ */ new Map(), []);
27175
+ const dismissBackgroundTask = (0, import_react98.useCallback)(async (_pid) => {
27176
+ }, []);
27177
+ const pendingToolCalls = (0, import_react98.useMemo)(
27178
+ () => trackedTools.map((t) => ({
27179
+ request: {
27180
+ name: t.originalRequestName || t.name,
27181
+ args: { command: t.description },
27182
+ callId: t.callId,
27183
+ isClientInitiated: t.isClientInitiated ?? false,
27184
+ prompt_id: ""
27185
+ },
27186
+ status: t.status
27187
+ })),
27188
+ [trackedTools]
27189
+ );
27190
+ const [loopDetectionConfirmationRequest] = (0, import_react98.useState)(null);
27191
+ const flushPendingText = (0, import_react98.useCallback)(() => {
27192
+ if (pendingHistoryItemRef.current) {
27193
+ addItem(pendingHistoryItemRef.current, userMessageTimestampRef.current);
27194
+ setPendingHistoryItem(null);
27195
+ geminiMessageBufferRef.current = "";
27196
+ }
27197
+ }, [addItem, pendingHistoryItemRef, setPendingHistoryItem]);
27198
+ const cancelOngoingRequest = (0, import_react98.useCallback)(
27199
+ async (clearBuffer = true) => {
27200
+ if (!agent) {
27201
+ return;
27202
+ }
27203
+ if (cancellationStateRef.current === "cancelling" /* Cancelling */) {
27204
+ if (clearBuffer) {
27205
+ onCancelSubmit(false, true);
27206
+ }
27207
+ try {
27208
+ await cancelPromiseRef.current;
27209
+ } catch (error) {
27210
+ debugLogger.warn(`Error awaiting cancelTask: ${error}`);
27211
+ }
27212
+ return;
27213
+ }
27214
+ cancellationStateRef.current = "cancelling" /* Cancelling */;
27215
+ const cancelTask = (async () => {
27216
+ try {
27217
+ let timeoutId2;
27218
+ try {
27219
+ await Promise.race([
27220
+ agent.abort(),
27221
+ new Promise((resolve3) => {
27222
+ timeoutId2 = setTimeout(resolve3, 1e3);
27223
+ })
27224
+ ]);
27225
+ } finally {
27226
+ if (timeoutId2 !== void 0) {
27227
+ clearTimeout(timeoutId2);
27228
+ }
27229
+ }
27230
+ const unpushedTools = trackedToolsRef.current.filter(
27231
+ (tc) => !pushedToolCallIdsRef.current.has(tc.callId)
27232
+ );
27233
+ if (unpushedTools.length > 0) {
27234
+ setTrackedTools(
27235
+ (prev) => prev.map((tc) => {
27236
+ if (!pushedToolCallIdsRef.current.has(tc.callId) && tc.status !== "success" /* Success */ && tc.status !== "error" /* Error */ && tc.status !== "cancelled" /* Cancelled */) {
27237
+ return {
27238
+ ...tc,
27239
+ status: "cancelled" /* Cancelled */
27240
+ };
27241
+ }
27242
+ return tc;
27243
+ })
27244
+ );
27245
+ }
27246
+ try {
27247
+ const client = config?.getGeminiClient?.();
27248
+ const chat = client?.getChat?.();
27249
+ if (chat) {
27250
+ const seenCallIds = /* @__PURE__ */ new Set();
27251
+ const synthesizedCalls = [];
27252
+ for (const tc of unpushedTools) {
27253
+ if (tc.isClientInitiated) {
27254
+ continue;
27255
+ }
27256
+ seenCallIds.add(tc.callId);
27257
+ const name = tc.originalRequestName || tc.name;
27258
+ const args = toolRequestArgsRef.current.get(tc.callId) ?? {};
27259
+ synthesizedCalls.push(
27260
+ createCancelledToolCall({
27261
+ callId: tc.callId,
27262
+ name,
27263
+ args,
27264
+ isClientInitiated: false,
27265
+ prompt_id: ""
27266
+ })
27267
+ );
27268
+ }
27269
+ const clientHistory = client?.getHistory?.() ?? [];
27270
+ const lastTurn = clientHistory.at(-1);
27271
+ if (lastTurn?.role === "model" && Array.isArray(lastTurn.parts)) {
27272
+ let index = 0;
27273
+ for (const part of lastTurn.parts) {
27274
+ const fc = part.functionCall;
27275
+ if (fc?.name) {
27276
+ const callId = fc.id ?? `${fc.name}-${Date.now()}-${index++}`;
27277
+ if (!seenCallIds.has(callId)) {
27278
+ seenCallIds.add(callId);
27279
+ synthesizedCalls.push(
27280
+ createCancelledToolCall({
27281
+ callId,
27282
+ name: fc.name,
27283
+ args: fc.args ?? {},
27284
+ isClientInitiated: false,
27285
+ prompt_id: ""
27286
+ })
27287
+ );
27288
+ }
27289
+ }
27290
+ }
27291
+ }
27292
+ if (synthesizedCalls.length > 0) {
27293
+ const currentModel = client?.getCurrentSequenceModel?.() ?? config?.getModel?.() ?? "";
27294
+ chat.recordCompletedToolCalls(currentModel, synthesizedCalls);
27295
+ }
27296
+ }
27297
+ } catch (error) {
27298
+ debugLogger.warn(
27299
+ `Error recording cancelled tool calls in agent stream: ${error}`
27300
+ );
27301
+ }
27302
+ setStreamingState("idle" /* Idle */);
27303
+ onCancelSubmit(false, clearBuffer);
27304
+ } finally {
27305
+ cancellationStateRef.current = "idle" /* Idle */;
27306
+ }
27307
+ })();
27308
+ cancelPromiseRef.current = cancelTask;
27309
+ try {
27310
+ await cancelTask;
27311
+ } catch (error) {
27312
+ debugLogger.warn(`Error awaiting cancelTask: ${error}`);
27313
+ }
27314
+ },
27315
+ [
27316
+ agent,
27317
+ config,
27318
+ onCancelSubmit,
27319
+ pushedToolCallIdsRef,
27320
+ setStreamingState,
27321
+ setTrackedTools,
27322
+ trackedToolsRef
27323
+ ]
27324
+ );
27325
+ const handleApprovalModeChange = (0, import_react98.useCallback)(
27326
+ async (newApprovalMode) => {
27327
+ debugLogger.debug(`Approval mode changed to ${newApprovalMode} (stub)`);
27328
+ },
27329
+ []
27330
+ );
27331
+ const handleEvent = (0, import_react98.useCallback)(
27332
+ (event) => {
27333
+ setLastOutputTime(Date.now());
27334
+ switch (event.type) {
27335
+ case "agent_start":
27336
+ setStreamingState("responding" /* Responding */);
27337
+ break;
27338
+ case "agent_end":
27339
+ setStreamingState("idle" /* Idle */);
27340
+ flushPendingText();
27341
+ break;
27342
+ case "message":
27343
+ if (event.role === "agent") {
27344
+ for (const part of event.content) {
27345
+ if (part.type === "text") {
27346
+ geminiMessageBufferRef.current += part.text;
27347
+ const splitPoint = findLastSafeSplitPoint(
27348
+ geminiMessageBufferRef.current
27349
+ );
27350
+ if (splitPoint === geminiMessageBufferRef.current.length) {
27351
+ setPendingHistoryItem({
27352
+ type: "gemini",
27353
+ text: geminiMessageBufferRef.current
27354
+ });
27355
+ } else {
27356
+ const before = geminiMessageBufferRef.current.substring(
27357
+ 0,
27358
+ splitPoint
27359
+ );
27360
+ const after = geminiMessageBufferRef.current.substring(splitPoint);
27361
+ addItem(
27362
+ { type: "gemini", text: before },
27363
+ userMessageTimestampRef.current
27364
+ );
27365
+ geminiMessageBufferRef.current = after;
27366
+ setPendingHistoryItem({
27367
+ type: "gemini_content",
27368
+ text: after
27369
+ });
27370
+ }
27371
+ } else if (part.type === "thought") {
27372
+ setThought(parseThought(part.thought));
27373
+ }
27374
+ }
27375
+ }
27376
+ break;
27377
+ case "tool_request": {
27378
+ flushPendingText();
27379
+ toolRequestArgsRef.current.set(event.requestId, event.args);
27380
+ const legacyState = event._meta?.legacyState;
27381
+ const displayName = legacyState?.displayName ?? event.name;
27382
+ const isOutputMarkdown = legacyState?.isOutputMarkdown ?? false;
27383
+ const desc = legacyState?.description ?? "";
27384
+ const fallbackKind = "other" /* Other */;
27385
+ const newCall = {
27386
+ callId: event.requestId,
27387
+ name: displayName,
27388
+ originalRequestName: event.name,
27389
+ description: desc,
27390
+ display: event.display,
27391
+ status: "scheduled" /* Scheduled */,
27392
+ isClientInitiated: false,
27393
+ renderOutputAsMarkdown: isOutputMarkdown,
27394
+ kind: legacyState?.kind ?? fallbackKind,
27395
+ confirmationDetails: void 0,
27396
+ resultDisplay: void 0
27397
+ };
27398
+ setTrackedTools((prev) => [...prev, newCall]);
27399
+ break;
27400
+ }
27401
+ case "tool_update": {
27402
+ setTrackedTools(
27403
+ (prev) => prev.map((tc) => {
27404
+ if (tc.callId !== event.requestId) return tc;
27405
+ const legacyState = event._meta?.legacyState;
27406
+ const evtStatus = legacyState?.status;
27407
+ let status = tc.status;
27408
+ if (evtStatus === "executing")
27409
+ status = "executing" /* Executing */;
27410
+ else if (evtStatus === "error") status = "error" /* Error */;
27411
+ else if (evtStatus === "success")
27412
+ status = "success" /* Success */;
27413
+ const display = event.display?.result;
27414
+ const liveOutput = displayContentToString(display) ?? tc.resultDisplay;
27415
+ const progressMessage = legacyState?.progressMessage ?? tc.progressMessage;
27416
+ const progress = legacyState?.progress ?? tc.progress;
27417
+ const progressTotal = legacyState?.progressTotal ?? tc.progressTotal;
27418
+ const ptyId = legacyState?.pid ?? tc.ptyId;
27419
+ const description = legacyState?.description ?? tc.description;
27420
+ return {
27421
+ ...tc,
27422
+ status,
27423
+ display: event.display ? { ...tc.display, ...event.display } : tc.display,
27424
+ resultDisplay: liveOutput,
27425
+ progressMessage,
27426
+ progress,
27427
+ progressTotal,
27428
+ ptyId,
27429
+ description
27430
+ };
27431
+ })
27432
+ );
27433
+ break;
27434
+ }
27435
+ case "tool_response": {
27436
+ setTrackedTools(
27437
+ (prev) => prev.map((tc) => {
27438
+ if (tc.callId !== event.requestId) return tc;
27439
+ const legacyState = event._meta?.legacyState;
27440
+ const outputFile = legacyState?.outputFile;
27441
+ const display = event.display?.result;
27442
+ const resultDisplay = displayContentToString(display) ?? tc.resultDisplay;
27443
+ return {
27444
+ ...tc,
27445
+ status: event.isError ? "error" /* Error */ : "success" /* Success */,
27446
+ display: event.display ? { ...tc.display, ...event.display } : tc.display,
27447
+ resultDisplay,
27448
+ outputFile
27449
+ };
27450
+ })
27451
+ );
27452
+ break;
27453
+ }
27454
+ case "error": {
27455
+ const message = event._meta?.["code"] === "AGENT_EXECUTION_BLOCKED" ? `Agent execution blocked: ${event.message}` : event.message;
27456
+ addItem(
27457
+ { type: "error" /* ERROR */, text: message },
27458
+ userMessageTimestampRef.current
27459
+ );
27460
+ break;
27461
+ }
27462
+ case "initialize":
27463
+ case "session_update":
27464
+ case "elicitation_request":
27465
+ case "elicitation_response":
27466
+ case "usage":
27467
+ case "custom":
27468
+ break;
27469
+ default:
27470
+ debugLogger.error("Unknown agent event type:", event);
27471
+ event;
27472
+ break;
27473
+ }
27474
+ },
27475
+ [
27476
+ addItem,
27477
+ flushPendingText,
27478
+ setPendingHistoryItem,
27479
+ setTrackedTools,
27480
+ setStreamingState,
27481
+ setThought,
27482
+ setLastOutputTime
27483
+ ]
27484
+ );
27485
+ (0, import_react98.useEffect)(() => {
27486
+ const unsubscribe = agent?.subscribe(handleEvent);
27487
+ return () => unsubscribe?.();
27488
+ }, [agent, handleEvent]);
27489
+ useKeypress(
27490
+ (key) => {
27491
+ if (key.name === "escape" && !isShellFocused) {
27492
+ void cancelOngoingRequest(false);
27493
+ return true;
27494
+ }
27495
+ return false;
27496
+ },
27497
+ {
27498
+ isActive: streamingState === "responding" /* Responding */ || streamingState === "waiting_for_confirmation" /* WaitingForConfirmation */
27499
+ }
27500
+ );
27501
+ const submitQuery = (0, import_react98.useCallback)(
27502
+ async (query, options, _prompt_id) => {
27503
+ if (!agent) return;
27504
+ const timestamp = Date.now();
27505
+ setLastOutputTime(timestamp);
27506
+ userMessageTimestampRef.current = timestamp;
27507
+ geminiMessageBufferRef.current = "";
27508
+ if (!options?.isContinuation) {
27509
+ toolRequestArgsRef.current.clear();
27510
+ if (typeof query === "string") {
27511
+ addItem({ type: "user" /* USER */, text: query }, timestamp);
27512
+ void logger?.logMessage("user" /* USER */, query);
27513
+ }
27514
+ startNewPrompt();
27515
+ }
27516
+ const parts = geminiPartsToContentParts(
27517
+ typeof query === "string" ? [{ text: query }] : query
27518
+ );
27519
+ try {
27520
+ const { streamId } = await agent.send({
27521
+ message: { content: parts }
27522
+ });
27523
+ currentStreamIdRef.current = streamId;
27524
+ } catch (err) {
27525
+ addItem(
27526
+ { type: "error" /* ERROR */, text: getErrorMessage(err) },
27527
+ timestamp
27528
+ );
27529
+ }
27530
+ },
27531
+ [agent, addItem, logger, startNewPrompt]
27532
+ );
27533
+ (0, import_react98.useEffect)(() => {
27534
+ if (trackedTools.length > 0) {
27535
+ const isNewBatch = !trackedTools.some(
27536
+ (tc) => pushedToolCallIdsRef.current.has(tc.callId)
27537
+ );
27538
+ if (isNewBatch) {
27539
+ setPushedToolCallIds(/* @__PURE__ */ new Set());
27540
+ setIsFirstToolInGroup(true);
27541
+ }
27542
+ } else if (streamingState === "idle" /* Idle */) {
27543
+ setPushedToolCallIds(/* @__PURE__ */ new Set());
27544
+ setIsFirstToolInGroup(true);
27545
+ }
27546
+ }, [
27547
+ trackedTools,
27548
+ pushedToolCallIdsRef,
27549
+ setPushedToolCallIds,
27550
+ setIsFirstToolInGroup,
27551
+ streamingState
27552
+ ]);
27553
+ (0, import_react98.useEffect)(() => {
27554
+ if (trackedTools.length === 0) return;
27555
+ const allTerminal = trackedTools.every(
27556
+ (tc) => tc.status === "success" || tc.status === "error" || tc.status === "cancelled"
27557
+ );
27558
+ const toolsToPush = trackedTools.filter(
27559
+ (tc) => !pushedToolCallIdsRef.current.has(tc.callId)
27560
+ );
27561
+ if (allTerminal && toolsToPush.length > 0) {
27562
+ const newPushed = new Set(pushedToolCallIdsRef.current);
27563
+ for (const tc of toolsToPush) {
27564
+ newPushed.add(tc.callId);
27565
+ }
27566
+ const appearance = getToolGroupBorderAppearance(
27567
+ { type: "tool_group", tools: trackedTools },
27568
+ activePtyId,
27569
+ !!isShellFocused,
27570
+ [],
27571
+ backgroundTasks
27572
+ );
27573
+ const hasBoxInBatch = toolsToPush.some(
27574
+ (tc) => tc.display?.format !== "notice"
27575
+ );
27576
+ const shouldStartNewBlock = isFirstToolInGroupRef.current || !hasEmittedBoxInTurnRef.current && hasBoxInBatch;
27577
+ const historyItem = {
27578
+ type: "tool_display_group",
27579
+ tools: toolsToPush.map((tc) => ({
27580
+ name: tc.name,
27581
+ description: tc.description,
27582
+ ...tc.display,
27583
+ status: tc.status,
27584
+ originalRequestName: tc.originalRequestName
27585
+ })),
27586
+ borderTop: shouldStartNewBlock,
27587
+ borderBottom: true,
27588
+ ...appearance
27589
+ };
27590
+ addItem(historyItem);
27591
+ setPushedToolCallIds(newPushed);
27592
+ if (hasBoxInBatch) {
27593
+ setHasEmittedBoxInTurn(true);
27594
+ }
27595
+ setIsFirstToolInGroup(false);
27596
+ }
27597
+ }, [
27598
+ trackedTools,
27599
+ pushedToolCallIdsRef,
27600
+ isFirstToolInGroupRef,
27601
+ hasEmittedBoxInTurnRef,
27602
+ setPushedToolCallIds,
27603
+ setIsFirstToolInGroup,
27604
+ setHasEmittedBoxInTurn,
27605
+ addItem,
27606
+ activePtyId,
27607
+ isShellFocused,
27608
+ backgroundTasks
27609
+ ]);
27610
+ const pendingToolGroupItems = (0, import_react98.useMemo)(() => {
27611
+ const remainingTools = trackedTools.filter(
27612
+ (tc) => !pushedToolCallIdsRef.current.has(tc.callId)
27613
+ );
27614
+ const items = [];
27615
+ const appearance = getToolGroupBorderAppearance(
27616
+ { type: "tool_group", tools: trackedTools },
27617
+ activePtyId,
27618
+ !!isShellFocused,
27619
+ [],
27620
+ backgroundTasks
27621
+ );
27622
+ if (remainingTools.length > 0) {
27623
+ const hasBoxInPending = remainingTools.some(
27624
+ (tc) => tc.display?.format !== "notice"
27625
+ );
27626
+ const shouldStartNewBlock = pushedToolCallIds.size === 0 || !hasEmittedBoxInTurnRef.current && hasBoxInPending;
27627
+ items.push({
27628
+ type: "tool_display_group",
27629
+ tools: remainingTools.map((tc) => ({
27630
+ name: tc.name,
27631
+ description: tc.description,
27632
+ ...tc.display,
27633
+ status: tc.status,
27634
+ originalRequestName: tc.originalRequestName
27635
+ })),
27636
+ borderTop: shouldStartNewBlock,
27637
+ borderBottom: false,
27638
+ ...appearance
27639
+ });
27640
+ }
27641
+ const allTerminal = trackedTools.length > 0 && trackedTools.every(
27642
+ (tc) => tc.status === "success" || tc.status === "error" || tc.status === "cancelled"
27643
+ );
27644
+ const allPushed = trackedTools.length > 0 && trackedTools.every((tc) => pushedToolCallIds.has(tc.callId));
27645
+ const anyVisibleInHistory = pushedToolCallIds.size > 0;
27646
+ const anyVisibleInPending = remainingTools.length > 0;
27647
+ if (trackedTools.length > 0 && !(allTerminal && allPushed) && (anyVisibleInHistory || anyVisibleInPending)) {
27648
+ items.push({
27649
+ type: "tool_display_group",
27650
+ tools: [],
27651
+ borderTop: false,
27652
+ borderBottom: true,
27653
+ ...appearance
27654
+ });
27655
+ }
27656
+ return items;
27657
+ }, [
27658
+ trackedTools,
27659
+ pushedToolCallIds,
27660
+ pushedToolCallIdsRef,
27661
+ hasEmittedBoxInTurnRef,
27662
+ activePtyId,
27663
+ isShellFocused,
27664
+ backgroundTasks
27665
+ ]);
27666
+ const pendingHistoryItems = (0, import_react98.useMemo)(
27667
+ () => [pendingHistoryItem, ...pendingToolGroupItems].filter(
27668
+ (i) => i !== void 0 && i !== null
27669
+ ),
27670
+ [pendingHistoryItem, pendingToolGroupItems]
27671
+ );
27672
+ return {
27673
+ streamingState,
27674
+ submitQuery,
27675
+ initError,
27676
+ pendingHistoryItems,
27677
+ thought,
27678
+ cancelOngoingRequest,
27679
+ pendingToolCalls,
27680
+ handleApprovalModeChange,
27681
+ activePtyId,
27682
+ loopDetectionConfirmationRequest,
27683
+ lastOutputTime,
27684
+ backgroundTaskCount,
27685
+ isBackgroundTaskVisible,
27686
+ toggleBackgroundTasks,
27687
+ backgroundCurrentExecution,
27688
+ backgroundTasks,
27689
+ retryStatus,
27690
+ dismissBackgroundTask
27691
+ };
27692
+ };
27693
+
27694
+ // packages/cli/src/ui/hooks/useGeminiStream.ts
27059
27695
  var isTopicTool2 = (name) => name === UPDATE_TOPIC_TOOL_NAME || name === UPDATE_TOPIC_DISPLAY_NAME;
27060
27696
  var SUPPRESSED_TOOL_ERRORS_NOTE = 'Some internal tool attempts failed before this final error. Press F12 for diagnostics, or run /settings and change "Error Verbosity" to full for details.';
27061
27697
  var LOW_VERBOSITY_FAILURE_NOTE = 'This request failed. Press F12 for diagnostics, or run /settings and change "Error Verbosity" to full for full details.';
@@ -27103,35 +27739,41 @@ function calculateStreamingState(isResponding, toolCalls) {
27103
27739
  return "idle" /* Idle */;
27104
27740
  }
27105
27741
  var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebugMessage, handleSlashCommand, shellModeActive, getPreferredEditor, onAuthError, _performMemoryRefresh, modelSwitchedFromQuotaError, setModelSwitchedFromQuotaError, onCancelSubmit, setShellInputFocused, terminalWidth, terminalHeight, isShellFocused, consumeUserHint) => {
27106
- const [initError, setInitError] = (0, import_react97.useState)(null);
27107
- const [retryStatus, setRetryStatus] = (0, import_react97.useState)(
27742
+ const [initError, setInitError] = (0, import_react99.useState)(null);
27743
+ const [retryStatus, setRetryStatus] = (0, import_react99.useState)(
27108
27744
  null
27109
27745
  );
27110
27746
  const isLowErrorVerbosity = settings.merged.ui?.errorVerbosity !== "full";
27111
- const suppressedToolErrorCountRef = (0, import_react97.useRef)(0);
27112
- const suppressedToolErrorNoteShownRef = (0, import_react97.useRef)(false);
27113
- const lowVerbosityFailureNoteShownRef = (0, import_react97.useRef)(false);
27114
- const abortControllerRef = (0, import_react97.useRef)(null);
27115
- const turnCancelledRef = (0, import_react97.useRef)(false);
27116
- const activeQueryIdRef = (0, import_react97.useRef)(null);
27117
- const previousApprovalModeRef = (0, import_react97.useRef)(
27747
+ const suppressedToolErrorCountRef = (0, import_react99.useRef)(0);
27748
+ const suppressedToolErrorNoteShownRef = (0, import_react99.useRef)(false);
27749
+ const lowVerbosityFailureNoteShownRef = (0, import_react99.useRef)(false);
27750
+ const abortControllerRef = (0, import_react99.useRef)(null);
27751
+ const turnCancelledRef = (0, import_react99.useRef)(false);
27752
+ const pendingToolCallRequestsRef = (0, import_react99.useRef)([]);
27753
+ const activeSchedulePromiseRef = (0, import_react99.useRef)(null);
27754
+ const cancellationStateRef = (0, import_react99.useRef)(
27755
+ "idle" /* Idle */
27756
+ );
27757
+ const cancelPromiseRef = (0, import_react99.useRef)(Promise.resolve());
27758
+ const activeQueryIdRef = (0, import_react99.useRef)(null);
27759
+ const previousApprovalModeRef = (0, import_react99.useRef)(
27118
27760
  config.getApprovalMode()
27119
27761
  );
27120
27762
  const [isResponding, isRespondingRef, setIsResponding] = useStateAndRef(false);
27121
27763
  const [thought, thoughtRef, setThought] = useStateAndRef(null);
27122
27764
  const [pendingHistoryItem, pendingHistoryItemRef, setPendingHistoryItem] = useStateAndRef(null);
27123
- const [lastGeminiActivityTime, setLastGeminiActivityTime] = (0, import_react97.useState)(0);
27765
+ const [lastGeminiActivityTime, setLastGeminiActivityTime] = (0, import_react99.useState)(0);
27124
27766
  const [pushedToolCallIds, pushedToolCallIdsRef, setPushedToolCallIds] = useStateAndRef(/* @__PURE__ */ new Set());
27125
27767
  const [_isFirstToolInGroup, isFirstToolInGroupRef, setIsFirstToolInGroup] = useStateAndRef(true);
27126
27768
  const { startNewPrompt, getPromptCount } = useSessionStats();
27127
27769
  const logger = useLogger(config);
27128
- const gitService = (0, import_react97.useMemo)(() => {
27770
+ const gitService = (0, import_react99.useMemo)(() => {
27129
27771
  if (!config.getProjectRoot()) {
27130
27772
  return;
27131
27773
  }
27132
27774
  return new GitService(config.getProjectRoot(), config.storage);
27133
27775
  }, [config]);
27134
- (0, import_react97.useEffect)(() => {
27776
+ (0, import_react99.useEffect)(() => {
27135
27777
  const handleRetryAttempt = (payload) => {
27136
27778
  if (turnCancelledRef.current || !isRespondingRef.current) {
27137
27779
  return;
@@ -27152,6 +27794,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27152
27794
  lastToolOutputTime
27153
27795
  ] = useToolScheduler(
27154
27796
  async (completedToolCallsFromScheduler) => {
27797
+ pendingToolCallRequestsRef.current = [];
27155
27798
  if (completedToolCallsFromScheduler.length > 0) {
27156
27799
  const toolsToPush = completedToolCallsFromScheduler.filter(
27157
27800
  (tc) => !pushedToolCallIdsRef.current.has(tc.request.callId)
@@ -27186,15 +27829,25 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27186
27829
  }
27187
27830
  setToolCallsForDisplay([]);
27188
27831
  try {
27189
- const currentModel = config.getGeminiClient().getCurrentSequenceModel() ?? config.getModel();
27190
- config.getGeminiClient().getChat().recordCompletedToolCalls(
27191
- currentModel,
27192
- completedToolCallsFromScheduler
27193
- );
27194
- await recordToolCallInteractions(
27195
- config,
27196
- completedToolCallsFromScheduler
27832
+ const client = geminiClient ?? config.getGeminiClient();
27833
+ const currentModel = client?.getCurrentSequenceModel?.() ?? config.getModel();
27834
+ const normalizedCompletedCalls = completedToolCallsFromScheduler.map(
27835
+ (tc) => {
27836
+ if (tc.status === "cancelled" /* Cancelled */ && (!tc.response?.responseParts || tc.response.responseParts.length === 0)) {
27837
+ return {
27838
+ ...tc,
27839
+ response: createCancelledToolCall(
27840
+ tc.request,
27841
+ tc.tool,
27842
+ tc.invocation
27843
+ ).response
27844
+ };
27845
+ }
27846
+ return tc;
27847
+ }
27197
27848
  );
27849
+ client?.getChat?.()?.recordCompletedToolCalls(currentModel, normalizedCompletedCalls);
27850
+ await recordToolCallInteractions(config, normalizedCompletedCalls);
27198
27851
  } catch (error) {
27199
27852
  debugLogger.warn(
27200
27853
  `Error recording completed tool call information: ${error}`
@@ -27206,13 +27859,13 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27206
27859
  config,
27207
27860
  getPreferredEditor
27208
27861
  );
27209
- const activeBackgroundExecutionId = (0, import_react97.useMemo)(() => {
27862
+ const activeBackgroundExecutionId = (0, import_react99.useMemo)(() => {
27210
27863
  const executingBackgroundableTool = toolCalls.find(
27211
27864
  isBackgroundableExecutingToolCall
27212
27865
  );
27213
27866
  return executingBackgroundableTool?.pid;
27214
27867
  }, [toolCalls]);
27215
- const onExec = (0, import_react97.useCallback)(
27868
+ const onExec = (0, import_react99.useCallback)(
27216
27869
  async (done) => {
27217
27870
  setIsResponding(true);
27218
27871
  await done;
@@ -27243,11 +27896,11 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27243
27896
  terminalHeight,
27244
27897
  activeBackgroundExecutionId
27245
27898
  );
27246
- const streamingState = (0, import_react97.useMemo)(
27899
+ const streamingState = (0, import_react99.useMemo)(
27247
27900
  () => calculateStreamingState(isResponding, toolCalls),
27248
27901
  [isResponding, toolCalls]
27249
27902
  );
27250
- (0, import_react97.useEffect)(() => {
27903
+ (0, import_react99.useEffect)(() => {
27251
27904
  if (toolCalls.length > 0) {
27252
27905
  const isNewBatch = !toolCalls.some(
27253
27906
  (tc) => pushedToolCallIdsRef.current.has(tc.request.callId)
@@ -27267,7 +27920,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27267
27920
  setIsFirstToolInGroup,
27268
27921
  streamingState
27269
27922
  ]);
27270
- (0, import_react97.useEffect)(() => {
27923
+ (0, import_react99.useEffect)(() => {
27271
27924
  const toolsToPush = [];
27272
27925
  for (let i = 0; i < toolCalls.length; i++) {
27273
27926
  const tc = toolCalls[i];
@@ -27367,7 +28020,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27367
28020
  backgroundTasks,
27368
28021
  settings.merged.ui?.compactToolOutput
27369
28022
  ]);
27370
- const pendingToolGroupItems = (0, import_react97.useMemo)(() => {
28023
+ const pendingToolGroupItems = (0, import_react99.useMemo)(() => {
27371
28024
  const remainingTools = toolCalls.filter(
27372
28025
  (tc) => !pushedToolCallIds.has(tc.request.callId)
27373
28026
  );
@@ -27437,26 +28090,26 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27437
28090
  backgroundTasks,
27438
28091
  settings.merged.ui?.compactToolOutput
27439
28092
  ]);
27440
- const lastQueryRef = (0, import_react97.useRef)(null);
27441
- const lastPromptIdRef = (0, import_react97.useRef)(null);
27442
- const loopDetectedRef = (0, import_react97.useRef)(false);
27443
- const autoNudgeAttemptCountRef = (0, import_react97.useRef)(0);
28093
+ const lastQueryRef = (0, import_react99.useRef)(null);
28094
+ const lastPromptIdRef = (0, import_react99.useRef)(null);
28095
+ const loopDetectedRef = (0, import_react99.useRef)(false);
28096
+ const autoNudgeAttemptCountRef = (0, import_react99.useRef)(0);
27444
28097
  const MAX_AUTO_NUDGE_ATTEMPTS = 2;
27445
- const submitQueryRef = (0, import_react97.useRef)(null);
28098
+ const submitQueryRef = (0, import_react99.useRef)(null);
27446
28099
  const [
27447
28100
  loopDetectionConfirmationRequest,
27448
28101
  setLoopDetectionConfirmationRequest
27449
- ] = (0, import_react97.useState)(null);
28102
+ ] = (0, import_react99.useState)(null);
27450
28103
  const activePtyId = activeShellPtyId ?? activeBackgroundExecutionId ?? void 0;
27451
- const prevActiveShellPtyIdRef = (0, import_react97.useRef)(null);
27452
- (0, import_react97.useEffect)(() => {
28104
+ const prevActiveShellPtyIdRef = (0, import_react99.useRef)(null);
28105
+ (0, import_react99.useEffect)(() => {
27453
28106
  if (turnCancelledRef.current && prevActiveShellPtyIdRef.current !== null && activeShellPtyId === null) {
27454
28107
  addItem({ type: "info" /* INFO */, text: "Request cancelled." });
27455
28108
  setIsResponding(false);
27456
28109
  }
27457
28110
  prevActiveShellPtyIdRef.current = activeShellPtyId;
27458
28111
  }, [activeShellPtyId, addItem, setIsResponding]);
27459
- (0, import_react97.useEffect)(() => {
28112
+ (0, import_react99.useEffect)(() => {
27460
28113
  if (config.getApprovalMode() === "yolo" /* YOLO */ && streamingState === "idle" /* Idle */) {
27461
28114
  const lastUserMessageIndex = history.findLastIndex(
27462
28115
  (item) => item.type === "user" /* USER */
@@ -27470,12 +28123,12 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27470
28123
  }
27471
28124
  }
27472
28125
  }, [streamingState, config, history]);
27473
- (0, import_react97.useEffect)(() => {
28126
+ (0, import_react99.useEffect)(() => {
27474
28127
  if (!isResponding) {
27475
28128
  setRetryStatus(null);
27476
28129
  }
27477
28130
  }, [isResponding]);
27478
- const maybeAddSuppressedToolErrorNote = (0, import_react97.useCallback)(
28131
+ const maybeAddSuppressedToolErrorNote = (0, import_react99.useCallback)(
27479
28132
  (userMessageTimestamp) => {
27480
28133
  if (!isLowErrorVerbosity) {
27481
28134
  return;
@@ -27497,7 +28150,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27497
28150
  },
27498
28151
  [addItem, isLowErrorVerbosity]
27499
28152
  );
27500
- const maybeAddLowVerbosityFailureNote = (0, import_react97.useCallback)(
28153
+ const maybeAddLowVerbosityFailureNote = (0, import_react99.useCallback)(
27501
28154
  (userMessageTimestamp) => {
27502
28155
  if (!isLowErrorVerbosity || config.getDebugMode()) {
27503
28156
  return;
@@ -27516,16 +28169,25 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27516
28169
  },
27517
28170
  [addItem, config, isLowErrorVerbosity]
27518
28171
  );
27519
- const cancelOngoingRequest = (0, import_react97.useCallback)(
27520
- (clearBuffer = true) => {
28172
+ const cancelOngoingRequest = (0, import_react99.useCallback)(
28173
+ async (clearBuffer = true) => {
27521
28174
  if (turnCancelledRef.current) {
27522
28175
  if (clearBuffer) {
27523
28176
  onCancelSubmit(false, true);
27524
28177
  }
28178
+ if (cancellationStateRef.current === "cancelling" /* Cancelling */) {
28179
+ try {
28180
+ await cancelPromiseRef.current;
28181
+ } catch (error) {
28182
+ debugLogger.warn(
28183
+ `Error awaiting schedulePromise on cancel: ${error}`
28184
+ );
28185
+ }
28186
+ }
27525
28187
  return;
27526
28188
  }
27527
- const hasActiveTools = toolCalls.some(
27528
- (tc) => tc.status === "executing" /* Executing */ || tc.status === "scheduled" /* Scheduled */ || tc.status === "validating" /* Validating */
28189
+ const hasActiveTools = pendingToolCallRequestsRef.current.length > 0 || toolCalls.some(
28190
+ (tc) => tc.status === "executing" /* Executing */ || tc.status === "scheduled" /* Scheduled */ || tc.status === "validating" /* Validating */ || tc.status === "awaiting_approval" /* AwaitingApproval */
27529
28191
  );
27530
28192
  if (streamingState === "idle" /* Idle */ && !isRespondingRef.current && !hasActiveTools) {
27531
28193
  if (clearBuffer) {
@@ -27543,6 +28205,74 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27543
28205
  }
27544
28206
  abortControllerRef.current.abort();
27545
28207
  cancelAllToolCalls(abortControllerRef.current.signal);
28208
+ try {
28209
+ const client = geminiClient ?? config.getGeminiClient?.();
28210
+ const chat = client?.getChat?.();
28211
+ if (chat) {
28212
+ const seenCallIds = /* @__PURE__ */ new Set();
28213
+ const synthesizedCalls = [];
28214
+ for (const tc of toolCalls) {
28215
+ if (tc.request.isClientInitiated) {
28216
+ continue;
28217
+ }
28218
+ const isAlreadySubmitted = (tc.status === "success" /* Success */ || tc.status === "error" /* Error */ || tc.status === "cancelled" /* Cancelled */) && tc.responseSubmittedToGemini;
28219
+ if (isAlreadySubmitted) {
28220
+ seenCallIds.add(tc.request.callId);
28221
+ continue;
28222
+ }
28223
+ seenCallIds.add(tc.request.callId);
28224
+ if ((tc.status === "success" /* Success */ || tc.status === "error" /* Error */ || tc.status === "cancelled" /* Cancelled */) && (tc.response?.responseParts?.length ?? 0) > 0) {
28225
+ synthesizedCalls.push(tc);
28226
+ } else {
28227
+ synthesizedCalls.push(
28228
+ createCancelledToolCall(
28229
+ tc.request,
28230
+ tc.tool,
28231
+ "invocation" in tc ? tc.invocation : void 0
28232
+ )
28233
+ );
28234
+ }
28235
+ }
28236
+ for (const req of pendingToolCallRequestsRef.current) {
28237
+ if (req.isClientInitiated || seenCallIds.has(req.callId)) {
28238
+ continue;
28239
+ }
28240
+ seenCallIds.add(req.callId);
28241
+ synthesizedCalls.push(createCancelledToolCall(req));
28242
+ }
28243
+ const clientHistory = client?.getHistory?.() ?? [];
28244
+ const lastTurn = clientHistory.at(-1);
28245
+ if (lastTurn?.role === "model" && Array.isArray(lastTurn.parts)) {
28246
+ let index = 0;
28247
+ for (const part of lastTurn.parts) {
28248
+ const fc = part.functionCall;
28249
+ if (fc?.name) {
28250
+ const callId = fc.id ?? `${fc.name}-${Date.now()}-${index++}`;
28251
+ if (!seenCallIds.has(callId)) {
28252
+ seenCallIds.add(callId);
28253
+ synthesizedCalls.push(
28254
+ createCancelledToolCall({
28255
+ callId,
28256
+ name: fc.name,
28257
+ args: fc.args ?? {},
28258
+ isClientInitiated: false,
28259
+ prompt_id: lastPromptIdRef.current ?? ""
28260
+ })
28261
+ );
28262
+ }
28263
+ }
28264
+ }
28265
+ }
28266
+ if (synthesizedCalls.length > 0) {
28267
+ const currentModel = client?.getCurrentSequenceModel?.() ?? config.getModel?.() ?? "";
28268
+ chat.recordCompletedToolCalls(currentModel, synthesizedCalls);
28269
+ }
28270
+ }
28271
+ } catch (error) {
28272
+ debugLogger.warn(
28273
+ `Error recording cancelled tool calls on abort: ${error}`
28274
+ );
28275
+ }
27546
28276
  if (pendingHistoryItemRef.current) {
27547
28277
  if (pendingHistoryItemRef.current.type === "tool_group" && pendingHistoryItemRef.current.tools.some(
27548
28278
  (t) => t.name === SHELL_COMMAND_NAME
@@ -27579,6 +28309,35 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27579
28309
  }
27580
28310
  onCancelSubmit(false, clearBuffer);
27581
28311
  setShellInputFocused(false);
28312
+ const schedulePromise = activeSchedulePromiseRef.current;
28313
+ if (schedulePromise) {
28314
+ cancellationStateRef.current = "cancelling" /* Cancelling */;
28315
+ const cancelTask = (async () => {
28316
+ let timeoutId2;
28317
+ try {
28318
+ await Promise.race([
28319
+ Promise.resolve(schedulePromise).catch(() => {
28320
+ }),
28321
+ new Promise((resolve3) => {
28322
+ timeoutId2 = setTimeout(resolve3, 1e3);
28323
+ })
28324
+ ]);
28325
+ } finally {
28326
+ if (timeoutId2 !== void 0) {
28327
+ clearTimeout(timeoutId2);
28328
+ }
28329
+ cancellationStateRef.current = "idle" /* Idle */;
28330
+ }
28331
+ })();
28332
+ cancelPromiseRef.current = cancelTask;
28333
+ try {
28334
+ await cancelTask;
28335
+ } catch (error) {
28336
+ debugLogger.warn(
28337
+ `Error awaiting schedulePromise on cancel: ${error}`
28338
+ );
28339
+ }
28340
+ }
27582
28341
  },
27583
28342
  [
27584
28343
  streamingState,
@@ -27591,13 +28350,15 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27591
28350
  cancelAllToolCalls,
27592
28351
  toolCalls,
27593
28352
  activeShellPtyId,
27594
- setIsResponding
28353
+ setIsResponding,
28354
+ geminiClient,
28355
+ config
27595
28356
  ]
27596
28357
  );
27597
28358
  useKeypress(
27598
28359
  (key) => {
27599
28360
  if (key.name === "escape" && !isShellFocused) {
27600
- cancelOngoingRequest(false);
28361
+ void cancelOngoingRequest(false);
27601
28362
  return true;
27602
28363
  }
27603
28364
  return false;
@@ -27606,7 +28367,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27606
28367
  isActive: streamingState === "responding" /* Responding */ || streamingState === "waiting_for_confirmation" /* WaitingForConfirmation */
27607
28368
  }
27608
28369
  );
27609
- const prepareQueryForGemini = (0, import_react97.useCallback)(
28370
+ const prepareQueryForGemini = (0, import_react99.useCallback)(
27610
28371
  async (query, userMessageTimestamp, abortSignal, prompt_id) => {
27611
28372
  if (turnCancelledRef.current) {
27612
28373
  return { queryToSend: null, shouldProceed: false };
@@ -27712,7 +28473,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27712
28473
  settings
27713
28474
  ]
27714
28475
  );
27715
- const handleContentEvent = (0, import_react97.useCallback)(
28476
+ const handleContentEvent = (0, import_react99.useCallback)(
27716
28477
  (eventValue, currentGeminiMessageBuffer, userMessageTimestamp) => {
27717
28478
  setRetryStatus(null);
27718
28479
  if (turnCancelledRef.current) {
@@ -27753,7 +28514,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27753
28514
  },
27754
28515
  [addItem, pendingHistoryItemRef, setPendingHistoryItem]
27755
28516
  );
27756
- const handleThoughtEvent = (0, import_react97.useCallback)(
28517
+ const handleThoughtEvent = (0, import_react99.useCallback)(
27757
28518
  (eventValue, _userMessageTimestamp) => {
27758
28519
  setThought(eventValue);
27759
28520
  if (getInlineThinkingMode(settings) === "full") {
@@ -27765,7 +28526,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27765
28526
  },
27766
28527
  [addItem, settings, setThought]
27767
28528
  );
27768
- const handleUserCancelledEvent = (0, import_react97.useCallback)(
28529
+ const handleUserCancelledEvent = (0, import_react99.useCallback)(
27769
28530
  (userMessageTimestamp) => {
27770
28531
  if (turnCancelledRef.current) {
27771
28532
  return;
@@ -27800,7 +28561,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27800
28561
  setIsResponding
27801
28562
  ]
27802
28563
  );
27803
- const handleErrorEvent = (0, import_react97.useCallback)(
28564
+ const handleErrorEvent = (0, import_react99.useCallback)(
27804
28565
  (eventValue, userMessageTimestamp) => {
27805
28566
  if (pendingHistoryItemRef.current) {
27806
28567
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
@@ -27833,7 +28594,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27833
28594
  maybeAddLowVerbosityFailureNote
27834
28595
  ]
27835
28596
  );
27836
- const handleInvalidStreamEvent = (0, import_react97.useCallback)(
28597
+ const handleInvalidStreamEvent = (0, import_react99.useCallback)(
27837
28598
  (eventValue, userMessageTimestamp) => {
27838
28599
  if (pendingHistoryItemRef.current) {
27839
28600
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
@@ -27879,7 +28640,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27879
28640
  geminiClient
27880
28641
  ]
27881
28642
  );
27882
- const handleCitationEvent = (0, import_react97.useCallback)(
28643
+ const handleCitationEvent = (0, import_react99.useCallback)(
27883
28644
  (text, userMessageTimestamp) => {
27884
28645
  if (!showCitations(settings)) {
27885
28646
  return;
@@ -27892,7 +28653,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27892
28653
  },
27893
28654
  [addItem, pendingHistoryItemRef, setPendingHistoryItem, settings]
27894
28655
  );
27895
- const handleFinishedEvent = (0, import_react97.useCallback)(
28656
+ const handleFinishedEvent = (0, import_react99.useCallback)(
27896
28657
  (event, userMessageTimestamp) => {
27897
28658
  const finishReason = event.value.reason;
27898
28659
  if (!finishReason) {
@@ -27928,7 +28689,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27928
28689
  },
27929
28690
  [addItem]
27930
28691
  );
27931
- const handleChatCompressionEvent = (0, import_react97.useCallback)(
28692
+ const handleChatCompressionEvent = (0, import_react99.useCallback)(
27932
28693
  (eventValue, userMessageTimestamp) => {
27933
28694
  if (pendingHistoryItemRef.current) {
27934
28695
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
@@ -27954,14 +28715,14 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27954
28715
  },
27955
28716
  [addItem, pendingHistoryItemRef, setPendingHistoryItem, config]
27956
28717
  );
27957
- const handleMaxSessionTurnsEvent = (0, import_react97.useCallback)(
28718
+ const handleMaxSessionTurnsEvent = (0, import_react99.useCallback)(
27958
28719
  () => addItem({
27959
28720
  type: "info",
27960
28721
  text: `The session has reached the maximum number of turns: ${config.getMaxSessionTurns()}. Please update this limit in your setting.json file.`
27961
28722
  }),
27962
28723
  [addItem, config]
27963
28724
  );
27964
- const handleContextWindowWillOverflowEvent = (0, import_react97.useCallback)(
28725
+ const handleContextWindowWillOverflowEvent = (0, import_react99.useCallback)(
27965
28726
  (estimatedRequestTokenCount, remainingTokenCount) => {
27966
28727
  onCancelSubmit(true);
27967
28728
  const limit = tokenLimit(config.getModel());
@@ -27977,7 +28738,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27977
28738
  },
27978
28739
  [addItem, onCancelSubmit, config]
27979
28740
  );
27980
- const handleChatModelEvent = (0, import_react97.useCallback)(
28741
+ const handleChatModelEvent = (0, import_react99.useCallback)(
27981
28742
  (eventValue, userMessageTimestamp) => {
27982
28743
  if (!settings.merged.ui.showModelInfoInChat) {
27983
28744
  return;
@@ -27996,7 +28757,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
27996
28757
  },
27997
28758
  [addItem, pendingHistoryItemRef, setPendingHistoryItem, settings]
27998
28759
  );
27999
- const handleAgentExecutionStoppedEvent = (0, import_react97.useCallback)(
28760
+ const handleAgentExecutionStoppedEvent = (0, import_react99.useCallback)(
28000
28761
  (reason, userMessageTimestamp, systemMessage, contextCleared) => {
28001
28762
  if (pendingHistoryItemRef.current) {
28002
28763
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
@@ -28029,7 +28790,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28029
28790
  maybeAddLowVerbosityFailureNote
28030
28791
  ]
28031
28792
  );
28032
- const handleAgentExecutionBlockedEvent = (0, import_react97.useCallback)(
28793
+ const handleAgentExecutionBlockedEvent = (0, import_react99.useCallback)(
28033
28794
  (reason, userMessageTimestamp, systemMessage, contextCleared) => {
28034
28795
  if (pendingHistoryItemRef.current) {
28035
28796
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
@@ -28060,7 +28821,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28060
28821
  maybeAddLowVerbosityFailureNote
28061
28822
  ]
28062
28823
  );
28063
- const processGeminiStreamEvents = (0, import_react97.useCallback)(
28824
+ const processGeminiStreamEvents = (0, import_react99.useCallback)(
28064
28825
  async (stream, userMessageTimestamp, signal, isContinuation, prompt_id) => {
28065
28826
  let geminiMessageBuffer = "";
28066
28827
  const toolCallRequests = [];
@@ -28083,6 +28844,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28083
28844
  break;
28084
28845
  case "tool_call_request" /* ToolCallRequest */:
28085
28846
  toolCallRequests.push(event.value);
28847
+ pendingToolCallRequestsRef.current.push(event.value);
28086
28848
  break;
28087
28849
  case "user_cancelled" /* UserCancelled */:
28088
28850
  handleUserCancelledEvent(userMessageTimestamp);
@@ -28149,7 +28911,18 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28149
28911
  addItem(pendingHistoryItemRef.current, userMessageTimestamp);
28150
28912
  setPendingHistoryItem(null);
28151
28913
  }
28152
- await scheduleToolCalls(toolCallRequests, signal);
28914
+ const schedulePromise = Promise.resolve(
28915
+ scheduleToolCalls(toolCallRequests, signal)
28916
+ );
28917
+ activeSchedulePromiseRef.current = schedulePromise;
28918
+ try {
28919
+ await schedulePromise;
28920
+ } finally {
28921
+ if (activeSchedulePromiseRef.current === schedulePromise) {
28922
+ activeSchedulePromiseRef.current = null;
28923
+ }
28924
+ pendingToolCallRequestsRef.current = [];
28925
+ }
28153
28926
  } else {
28154
28927
  const hasVisibleText = geminiMessageBuffer.trim().length > 0;
28155
28928
  if (isContinuation && !hasVisibleText && autoNudgeAttemptCountRef.current < MAX_AUTO_NUDGE_ATTEMPTS) {
@@ -28186,7 +28959,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28186
28959
  setThought
28187
28960
  ]
28188
28961
  );
28189
- const submitQuery = (0, import_react97.useCallback)(
28962
+ const submitQuery = (0, import_react99.useCallback)(
28190
28963
  async (query, options, prompt_id) => runInDevTraceSpan(
28191
28964
  {
28192
28965
  operation: options?.isContinuation ? "system_prompt" /* SystemPrompt */ : "user_prompt" /* UserPrompt */,
@@ -28200,6 +28973,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28200
28973
  activeQueryIdRef.current = queryId;
28201
28974
  const userMessageTimestamp = Date.now();
28202
28975
  if (!options?.isContinuation) {
28976
+ pendingToolCallRequestsRef.current = [];
28203
28977
  autoNudgeAttemptCountRef.current = 0;
28204
28978
  setModelSwitchedFromQuotaError(false);
28205
28979
  config.setQuotaErrorOccurred(false);
@@ -28351,7 +29125,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28351
29125
  ]
28352
29126
  );
28353
29127
  submitQueryRef.current = submitQuery;
28354
- const handleApprovalModeChange = (0, import_react97.useCallback)(
29128
+ const handleApprovalModeChange = (0, import_react99.useCallback)(
28355
29129
  async (newApprovalMode) => {
28356
29130
  if (previousApprovalModeRef.current === "plan" /* PLAN */ && newApprovalMode !== "plan" /* PLAN */ && streamingState === "idle" /* Idle */) {
28357
29131
  if (geminiClient) {
@@ -28414,7 +29188,7 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28414
29188
  },
28415
29189
  [config, toolCalls, geminiClient, streamingState, addItem, onDebugMessage]
28416
29190
  );
28417
- const handleCompletedTools = (0, import_react97.useCallback)(
29191
+ const handleCompletedTools = (0, import_react99.useCallback)(
28418
29192
  async (completedToolCallsFromScheduler) => {
28419
29193
  const completedAndReadyToSubmitTools = completedToolCallsFromScheduler.filter(
28420
29194
  (tc) => {
@@ -28587,13 +29361,13 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28587
29361
  toolCalls
28588
29362
  ]
28589
29363
  );
28590
- const pendingHistoryItems = (0, import_react97.useMemo)(
29364
+ const pendingHistoryItems = (0, import_react99.useMemo)(
28591
29365
  () => [pendingHistoryItem, ...pendingToolGroupItems].filter(
28592
29366
  (i) => i !== void 0 && i !== null
28593
29367
  ),
28594
29368
  [pendingHistoryItem, pendingToolGroupItems]
28595
29369
  );
28596
- (0, import_react97.useEffect)(() => {
29370
+ (0, import_react99.useEffect)(() => {
28597
29371
  const saveRestorableToolCalls = async () => {
28598
29372
  if (!config.getCheckpointingEnabled()) {
28599
29373
  return;
@@ -28662,475 +29436,6 @@ var useGeminiStream = (geminiClient, history, addItem, config, settings, onDebug
28662
29436
  };
28663
29437
  };
28664
29438
 
28665
- // packages/cli/src/ui/hooks/useAgentStream.ts
28666
- var import_react99 = __toESM(require_react(), 1);
28667
-
28668
- // packages/cli/src/ui/hooks/useTurnActivityMonitor.ts
28669
- var import_react98 = __toESM(require_react(), 1);
28670
- var useTurnActivityMonitor = (streamingState, activePtyId, pendingToolCalls = []) => {
28671
- const [operationStartTime, setOperationStartTime] = (0, import_react98.useState)(0);
28672
- const prevPtyIdRef = (0, import_react98.useRef)(void 0);
28673
- const prevStreamingStateRef = (0, import_react98.useRef)(void 0);
28674
- (0, import_react98.useEffect)(() => {
28675
- const isNowResponding = streamingState === "responding" /* Responding */;
28676
- const wasResponding = prevStreamingStateRef.current === "responding" /* Responding */;
28677
- const ptyChanged = activePtyId !== prevPtyIdRef.current;
28678
- if (isNowResponding && (!wasResponding || ptyChanged)) {
28679
- setOperationStartTime(Date.now());
28680
- } else if (!isNowResponding && wasResponding) {
28681
- setOperationStartTime(0);
28682
- }
28683
- prevPtyIdRef.current = activePtyId;
28684
- prevStreamingStateRef.current = streamingState;
28685
- }, [streamingState, activePtyId]);
28686
- const isRedirectionActive = (0, import_react98.useMemo)(
28687
- () => (
28688
- // Check active tool calls for run_shell_command
28689
- pendingToolCalls.some((tc) => {
28690
- if (tc.request.name !== "run_shell_command") return false;
28691
- const command = tc.request.args?.command || "";
28692
- return hasRedirection(command);
28693
- })
28694
- ),
28695
- [pendingToolCalls]
28696
- );
28697
- return {
28698
- operationStartTime,
28699
- isRedirectionActive
28700
- };
28701
- };
28702
-
28703
- // packages/cli/src/ui/hooks/useAgentStream.ts
28704
- var useAgentStream = ({
28705
- agent,
28706
- addItem,
28707
- onCancelSubmit,
28708
- isShellFocused,
28709
- logger
28710
- }) => {
28711
- const [initError] = (0, import_react99.useState)(null);
28712
- const [retryStatus] = (0, import_react99.useState)(null);
28713
- const [streamingState, setStreamingState] = (0, import_react99.useState)(
28714
- "idle" /* Idle */
28715
- );
28716
- const [thought, setThought] = (0, import_react99.useState)(null);
28717
- const [lastOutputTime, setLastOutputTime] = (0, import_react99.useState)(Date.now());
28718
- const currentStreamIdRef = (0, import_react99.useRef)(null);
28719
- const userMessageTimestampRef = (0, import_react99.useRef)(0);
28720
- const geminiMessageBufferRef = (0, import_react99.useRef)("");
28721
- const [pendingHistoryItem, pendingHistoryItemRef, setPendingHistoryItem] = useStateAndRef(null);
28722
- const [trackedTools, , setTrackedTools] = useStateAndRef([]);
28723
- const [pushedToolCallIds, pushedToolCallIdsRef, setPushedToolCallIds] = useStateAndRef(/* @__PURE__ */ new Set());
28724
- const [_isFirstToolInGroup, isFirstToolInGroupRef, setIsFirstToolInGroup] = useStateAndRef(true);
28725
- const [_hasEmittedBoxInTurn, hasEmittedBoxInTurnRef, setHasEmittedBoxInTurn] = useStateAndRef(false);
28726
- const { startNewPrompt } = useSessionStats();
28727
- const activePtyId = void 0;
28728
- const backgroundTaskCount = 0;
28729
- const isBackgroundTaskVisible = false;
28730
- const toggleBackgroundTasks = (0, import_react99.useCallback)(() => {
28731
- }, []);
28732
- const backgroundCurrentExecution = void 0;
28733
- const backgroundTasks = (0, import_react99.useMemo)(() => /* @__PURE__ */ new Map(), []);
28734
- const dismissBackgroundTask = (0, import_react99.useCallback)(async (_pid) => {
28735
- }, []);
28736
- const pendingToolCalls = (0, import_react99.useMemo)(
28737
- () => trackedTools.map((t) => ({
28738
- request: {
28739
- name: t.originalRequestName || t.name,
28740
- args: { command: t.description },
28741
- callId: t.callId,
28742
- isClientInitiated: t.isClientInitiated ?? false,
28743
- prompt_id: ""
28744
- },
28745
- status: t.status
28746
- })),
28747
- [trackedTools]
28748
- );
28749
- const [loopDetectionConfirmationRequest] = (0, import_react99.useState)(null);
28750
- const flushPendingText = (0, import_react99.useCallback)(() => {
28751
- if (pendingHistoryItemRef.current) {
28752
- addItem(pendingHistoryItemRef.current, userMessageTimestampRef.current);
28753
- setPendingHistoryItem(null);
28754
- geminiMessageBufferRef.current = "";
28755
- }
28756
- }, [addItem, pendingHistoryItemRef, setPendingHistoryItem]);
28757
- const cancelOngoingRequest = (0, import_react99.useCallback)(
28758
- async (clearBuffer = true) => {
28759
- if (agent) {
28760
- await agent.abort();
28761
- setStreamingState("idle" /* Idle */);
28762
- onCancelSubmit(false, clearBuffer);
28763
- }
28764
- },
28765
- [agent, onCancelSubmit]
28766
- );
28767
- const handleApprovalModeChange = (0, import_react99.useCallback)(
28768
- async (newApprovalMode) => {
28769
- debugLogger.debug(`Approval mode changed to ${newApprovalMode} (stub)`);
28770
- },
28771
- []
28772
- );
28773
- const handleEvent = (0, import_react99.useCallback)(
28774
- (event) => {
28775
- setLastOutputTime(Date.now());
28776
- switch (event.type) {
28777
- case "agent_start":
28778
- setStreamingState("responding" /* Responding */);
28779
- break;
28780
- case "agent_end":
28781
- setStreamingState("idle" /* Idle */);
28782
- flushPendingText();
28783
- break;
28784
- case "message":
28785
- if (event.role === "agent") {
28786
- for (const part of event.content) {
28787
- if (part.type === "text") {
28788
- geminiMessageBufferRef.current += part.text;
28789
- const splitPoint = findLastSafeSplitPoint(
28790
- geminiMessageBufferRef.current
28791
- );
28792
- if (splitPoint === geminiMessageBufferRef.current.length) {
28793
- setPendingHistoryItem({
28794
- type: "gemini",
28795
- text: geminiMessageBufferRef.current
28796
- });
28797
- } else {
28798
- const before = geminiMessageBufferRef.current.substring(
28799
- 0,
28800
- splitPoint
28801
- );
28802
- const after = geminiMessageBufferRef.current.substring(splitPoint);
28803
- addItem(
28804
- { type: "gemini", text: before },
28805
- userMessageTimestampRef.current
28806
- );
28807
- geminiMessageBufferRef.current = after;
28808
- setPendingHistoryItem({
28809
- type: "gemini_content",
28810
- text: after
28811
- });
28812
- }
28813
- } else if (part.type === "thought") {
28814
- setThought(parseThought(part.thought));
28815
- }
28816
- }
28817
- }
28818
- break;
28819
- case "tool_request": {
28820
- flushPendingText();
28821
- const legacyState = event._meta?.legacyState;
28822
- const displayName = legacyState?.displayName ?? event.name;
28823
- const isOutputMarkdown = legacyState?.isOutputMarkdown ?? false;
28824
- const desc = legacyState?.description ?? "";
28825
- const fallbackKind = "other" /* Other */;
28826
- const newCall = {
28827
- callId: event.requestId,
28828
- name: displayName,
28829
- originalRequestName: event.name,
28830
- description: desc,
28831
- display: event.display,
28832
- status: "scheduled" /* Scheduled */,
28833
- isClientInitiated: false,
28834
- renderOutputAsMarkdown: isOutputMarkdown,
28835
- kind: legacyState?.kind ?? fallbackKind,
28836
- confirmationDetails: void 0,
28837
- resultDisplay: void 0
28838
- };
28839
- setTrackedTools((prev) => [...prev, newCall]);
28840
- break;
28841
- }
28842
- case "tool_update": {
28843
- setTrackedTools(
28844
- (prev) => prev.map((tc) => {
28845
- if (tc.callId !== event.requestId) return tc;
28846
- const legacyState = event._meta?.legacyState;
28847
- const evtStatus = legacyState?.status;
28848
- let status = tc.status;
28849
- if (evtStatus === "executing")
28850
- status = "executing" /* Executing */;
28851
- else if (evtStatus === "error") status = "error" /* Error */;
28852
- else if (evtStatus === "success")
28853
- status = "success" /* Success */;
28854
- const display = event.display?.result;
28855
- const liveOutput = displayContentToString(display) ?? tc.resultDisplay;
28856
- const progressMessage = legacyState?.progressMessage ?? tc.progressMessage;
28857
- const progress = legacyState?.progress ?? tc.progress;
28858
- const progressTotal = legacyState?.progressTotal ?? tc.progressTotal;
28859
- const ptyId = legacyState?.pid ?? tc.ptyId;
28860
- const description = legacyState?.description ?? tc.description;
28861
- return {
28862
- ...tc,
28863
- status,
28864
- display: event.display ? { ...tc.display, ...event.display } : tc.display,
28865
- resultDisplay: liveOutput,
28866
- progressMessage,
28867
- progress,
28868
- progressTotal,
28869
- ptyId,
28870
- description
28871
- };
28872
- })
28873
- );
28874
- break;
28875
- }
28876
- case "tool_response": {
28877
- setTrackedTools(
28878
- (prev) => prev.map((tc) => {
28879
- if (tc.callId !== event.requestId) return tc;
28880
- const legacyState = event._meta?.legacyState;
28881
- const outputFile = legacyState?.outputFile;
28882
- const display = event.display?.result;
28883
- const resultDisplay = displayContentToString(display) ?? tc.resultDisplay;
28884
- return {
28885
- ...tc,
28886
- status: event.isError ? "error" /* Error */ : "success" /* Success */,
28887
- display: event.display ? { ...tc.display, ...event.display } : tc.display,
28888
- resultDisplay,
28889
- outputFile
28890
- };
28891
- })
28892
- );
28893
- break;
28894
- }
28895
- case "error": {
28896
- const message = event._meta?.["code"] === "AGENT_EXECUTION_BLOCKED" ? `Agent execution blocked: ${event.message}` : event.message;
28897
- addItem(
28898
- { type: "error" /* ERROR */, text: message },
28899
- userMessageTimestampRef.current
28900
- );
28901
- break;
28902
- }
28903
- case "initialize":
28904
- case "session_update":
28905
- case "elicitation_request":
28906
- case "elicitation_response":
28907
- case "usage":
28908
- case "custom":
28909
- break;
28910
- default:
28911
- debugLogger.error("Unknown agent event type:", event);
28912
- event;
28913
- break;
28914
- }
28915
- },
28916
- [
28917
- addItem,
28918
- flushPendingText,
28919
- setPendingHistoryItem,
28920
- setTrackedTools,
28921
- setStreamingState,
28922
- setThought,
28923
- setLastOutputTime
28924
- ]
28925
- );
28926
- (0, import_react99.useEffect)(() => {
28927
- const unsubscribe = agent?.subscribe(handleEvent);
28928
- return () => unsubscribe?.();
28929
- }, [agent, handleEvent]);
28930
- useKeypress(
28931
- (key) => {
28932
- if (key.name === "escape" && !isShellFocused) {
28933
- void cancelOngoingRequest(false);
28934
- return true;
28935
- }
28936
- return false;
28937
- },
28938
- {
28939
- isActive: streamingState === "responding" /* Responding */ || streamingState === "waiting_for_confirmation" /* WaitingForConfirmation */
28940
- }
28941
- );
28942
- const submitQuery = (0, import_react99.useCallback)(
28943
- async (query, options, _prompt_id) => {
28944
- if (!agent) return;
28945
- const timestamp = Date.now();
28946
- setLastOutputTime(timestamp);
28947
- userMessageTimestampRef.current = timestamp;
28948
- geminiMessageBufferRef.current = "";
28949
- if (!options?.isContinuation) {
28950
- if (typeof query === "string") {
28951
- addItem({ type: "user" /* USER */, text: query }, timestamp);
28952
- void logger?.logMessage("user" /* USER */, query);
28953
- }
28954
- startNewPrompt();
28955
- }
28956
- const parts = geminiPartsToContentParts(
28957
- typeof query === "string" ? [{ text: query }] : query
28958
- );
28959
- try {
28960
- const { streamId } = await agent.send({
28961
- message: { content: parts }
28962
- });
28963
- currentStreamIdRef.current = streamId;
28964
- } catch (err) {
28965
- addItem(
28966
- { type: "error" /* ERROR */, text: getErrorMessage(err) },
28967
- timestamp
28968
- );
28969
- }
28970
- },
28971
- [agent, addItem, logger, startNewPrompt]
28972
- );
28973
- (0, import_react99.useEffect)(() => {
28974
- if (trackedTools.length > 0) {
28975
- const isNewBatch = !trackedTools.some(
28976
- (tc) => pushedToolCallIdsRef.current.has(tc.callId)
28977
- );
28978
- if (isNewBatch) {
28979
- setPushedToolCallIds(/* @__PURE__ */ new Set());
28980
- setIsFirstToolInGroup(true);
28981
- }
28982
- } else if (streamingState === "idle" /* Idle */) {
28983
- setPushedToolCallIds(/* @__PURE__ */ new Set());
28984
- setIsFirstToolInGroup(true);
28985
- }
28986
- }, [
28987
- trackedTools,
28988
- pushedToolCallIdsRef,
28989
- setPushedToolCallIds,
28990
- setIsFirstToolInGroup,
28991
- streamingState
28992
- ]);
28993
- (0, import_react99.useEffect)(() => {
28994
- if (trackedTools.length === 0) return;
28995
- const allTerminal = trackedTools.every(
28996
- (tc) => tc.status === "success" || tc.status === "error" || tc.status === "cancelled"
28997
- );
28998
- const toolsToPush = trackedTools.filter(
28999
- (tc) => !pushedToolCallIdsRef.current.has(tc.callId)
29000
- );
29001
- if (allTerminal && toolsToPush.length > 0) {
29002
- const newPushed = new Set(pushedToolCallIdsRef.current);
29003
- for (const tc of toolsToPush) {
29004
- newPushed.add(tc.callId);
29005
- }
29006
- const appearance = getToolGroupBorderAppearance(
29007
- { type: "tool_group", tools: trackedTools },
29008
- activePtyId,
29009
- !!isShellFocused,
29010
- [],
29011
- backgroundTasks
29012
- );
29013
- const hasBoxInBatch = toolsToPush.some(
29014
- (tc) => tc.display?.format !== "notice"
29015
- );
29016
- const shouldStartNewBlock = isFirstToolInGroupRef.current || !hasEmittedBoxInTurnRef.current && hasBoxInBatch;
29017
- const historyItem = {
29018
- type: "tool_display_group",
29019
- tools: toolsToPush.map((tc) => ({
29020
- name: tc.name,
29021
- description: tc.description,
29022
- ...tc.display,
29023
- status: tc.status,
29024
- originalRequestName: tc.originalRequestName
29025
- })),
29026
- borderTop: shouldStartNewBlock,
29027
- borderBottom: true,
29028
- ...appearance
29029
- };
29030
- addItem(historyItem);
29031
- setPushedToolCallIds(newPushed);
29032
- if (hasBoxInBatch) {
29033
- setHasEmittedBoxInTurn(true);
29034
- }
29035
- setIsFirstToolInGroup(false);
29036
- }
29037
- }, [
29038
- trackedTools,
29039
- pushedToolCallIdsRef,
29040
- isFirstToolInGroupRef,
29041
- hasEmittedBoxInTurnRef,
29042
- setPushedToolCallIds,
29043
- setIsFirstToolInGroup,
29044
- setHasEmittedBoxInTurn,
29045
- addItem,
29046
- activePtyId,
29047
- isShellFocused,
29048
- backgroundTasks
29049
- ]);
29050
- const pendingToolGroupItems = (0, import_react99.useMemo)(() => {
29051
- const remainingTools = trackedTools.filter(
29052
- (tc) => !pushedToolCallIdsRef.current.has(tc.callId)
29053
- );
29054
- const items = [];
29055
- const appearance = getToolGroupBorderAppearance(
29056
- { type: "tool_group", tools: trackedTools },
29057
- activePtyId,
29058
- !!isShellFocused,
29059
- [],
29060
- backgroundTasks
29061
- );
29062
- if (remainingTools.length > 0) {
29063
- const hasBoxInPending = remainingTools.some(
29064
- (tc) => tc.display?.format !== "notice"
29065
- );
29066
- const shouldStartNewBlock = pushedToolCallIds.size === 0 || !hasEmittedBoxInTurnRef.current && hasBoxInPending;
29067
- items.push({
29068
- type: "tool_display_group",
29069
- tools: remainingTools.map((tc) => ({
29070
- name: tc.name,
29071
- description: tc.description,
29072
- ...tc.display,
29073
- status: tc.status,
29074
- originalRequestName: tc.originalRequestName
29075
- })),
29076
- borderTop: shouldStartNewBlock,
29077
- borderBottom: false,
29078
- ...appearance
29079
- });
29080
- }
29081
- const allTerminal = trackedTools.length > 0 && trackedTools.every(
29082
- (tc) => tc.status === "success" || tc.status === "error" || tc.status === "cancelled"
29083
- );
29084
- const allPushed = trackedTools.length > 0 && trackedTools.every((tc) => pushedToolCallIds.has(tc.callId));
29085
- const anyVisibleInHistory = pushedToolCallIds.size > 0;
29086
- const anyVisibleInPending = remainingTools.length > 0;
29087
- if (trackedTools.length > 0 && !(allTerminal && allPushed) && (anyVisibleInHistory || anyVisibleInPending)) {
29088
- items.push({
29089
- type: "tool_display_group",
29090
- tools: [],
29091
- borderTop: false,
29092
- borderBottom: true,
29093
- ...appearance
29094
- });
29095
- }
29096
- return items;
29097
- }, [
29098
- trackedTools,
29099
- pushedToolCallIds,
29100
- pushedToolCallIdsRef,
29101
- hasEmittedBoxInTurnRef,
29102
- activePtyId,
29103
- isShellFocused,
29104
- backgroundTasks
29105
- ]);
29106
- const pendingHistoryItems = (0, import_react99.useMemo)(
29107
- () => [pendingHistoryItem, ...pendingToolGroupItems].filter(
29108
- (i) => i !== void 0 && i !== null
29109
- ),
29110
- [pendingHistoryItem, pendingToolGroupItems]
29111
- );
29112
- return {
29113
- streamingState,
29114
- submitQuery,
29115
- initError,
29116
- pendingHistoryItems,
29117
- thought,
29118
- cancelOngoingRequest,
29119
- pendingToolCalls,
29120
- handleApprovalModeChange,
29121
- activePtyId,
29122
- loopDetectionConfirmationRequest,
29123
- lastOutputTime,
29124
- backgroundTaskCount,
29125
- isBackgroundTaskVisible,
29126
- toggleBackgroundTasks,
29127
- backgroundCurrentExecution,
29128
- backgroundTasks,
29129
- retryStatus,
29130
- dismissBackgroundTask
29131
- };
29132
- };
29133
-
29134
29439
  // packages/cli/src/ui/hooks/vim.ts
29135
29440
  var import_react100 = __toESM(require_react(), 1);
29136
29441
  var DIGIT_MULTIPLIER = 10;
@@ -32644,6 +32949,49 @@ function useVisibilityToggle() {
32644
32949
  var import_jsx_runtime137 = __toESM(require_jsx_runtime(), 1);
32645
32950
  var SHELL_WIDTH_FRACTION = 0.89;
32646
32951
  var SHELL_HEIGHT_PADDING = 10;
32952
+ var ENTER_SYNCHRONIZED_OUTPUT = "\x1B[?2026h";
32953
+ var EXIT_SYNCHRONIZED_OUTPUT = "\x1B[?2026l";
32954
+ var RESIZE_DEBOUNCE_MS = 100;
32955
+ var RESIZE_CORK_SAFETY_TIMEOUT_MS = 1e3;
32956
+ function discardCorkedStdoutBuffer(stream) {
32957
+ try {
32958
+ const state = stream._writableState;
32959
+ if (state && (state.corked ?? 0) > 0 && Array.isArray(state.buffered)) {
32960
+ const startIndex = state.bufferedIndex ?? 0;
32961
+ const entries = state.buffered.slice(startIndex);
32962
+ let discardedLength = 0;
32963
+ for (const entry of entries) {
32964
+ if (entry?.chunk) {
32965
+ if (typeof entry.chunk === "string") {
32966
+ discardedLength += Buffer.byteLength(
32967
+ entry.chunk,
32968
+ entry.encoding ?? "utf8"
32969
+ );
32970
+ } else if ("length" in entry.chunk && typeof entry.chunk.length === "number") {
32971
+ discardedLength += entry.chunk.length;
32972
+ }
32973
+ }
32974
+ }
32975
+ state.buffered.length = startIndex;
32976
+ state.length = Math.max(0, (state.length ?? 0) - discardedLength);
32977
+ if ("allBuffers" in state) state.allBuffers = true;
32978
+ if ("allNoop" in state) state.allNoop = true;
32979
+ for (const entry of entries) {
32980
+ if (entry && typeof entry.callback === "function") {
32981
+ entry.callback(null);
32982
+ }
32983
+ }
32984
+ }
32985
+ } catch (error) {
32986
+ debugLogger.warn("Failed to discard corked stdout buffer safely:", error);
32987
+ }
32988
+ }
32989
+ function refreshStdoutSize(stream) {
32990
+ const resizableStream = stream;
32991
+ if (typeof resizableStream._refreshSize === "function") {
32992
+ resizableStream._refreshSize();
32993
+ }
32994
+ }
32647
32995
  var AppContainer = (props) => {
32648
32996
  const isHelpDismissKey = useIsHelpDismissKey();
32649
32997
  const keyMatchers = useKeyMatchers();
@@ -32957,12 +33305,89 @@ var AppContainer = (props) => {
32957
33305
  addConfirmUpdateExtensionRequest,
32958
33306
  addItem: historyManager.addItem
32959
33307
  });
33308
+ const isStdoutCorkedRef = (0, import_react119.useRef)(false);
33309
+ const isRefreshingStaticRef = (0, import_react119.useRef)(false);
33310
+ const resizeCorkSafetyTimerRef = (0, import_react119.useRef)(null);
33311
+ const resizeDebounceTimerRef = (0, import_react119.useRef)(null);
33312
+ const lastStdoutColumnsRef = (0, import_react119.useRef)(
33313
+ stdout.columns ?? process12.stdout.columns ?? terminalWidth
33314
+ );
33315
+ const lastRefreshedColumnsRef = (0, import_react119.useRef)(terminalWidth);
33316
+ const terminalWidthRef = (0, import_react119.useRef)(terminalWidth);
33317
+ terminalWidthRef.current = terminalWidth;
33318
+ const clearResizeCorkSafetyTimer = (0, import_react119.useCallback)(() => {
33319
+ if (resizeCorkSafetyTimerRef.current) {
33320
+ clearTimeout(resizeCorkSafetyTimerRef.current);
33321
+ resizeCorkSafetyTimerRef.current = null;
33322
+ }
33323
+ }, []);
33324
+ const clearResizeDebounceTimer = (0, import_react119.useCallback)(() => {
33325
+ if (resizeDebounceTimerRef.current) {
33326
+ clearTimeout(resizeDebounceTimerRef.current);
33327
+ resizeDebounceTimerRef.current = null;
33328
+ }
33329
+ }, []);
33330
+ const corkStdout = (0, import_react119.useCallback)(() => {
33331
+ if (!isStdoutCorkedRef.current && typeof stdout.cork === "function") {
33332
+ stdout.cork();
33333
+ isStdoutCorkedRef.current = true;
33334
+ }
33335
+ }, [stdout]);
33336
+ const uncorkStdout = (0, import_react119.useCallback)(() => {
33337
+ clearResizeCorkSafetyTimer();
33338
+ if (isStdoutCorkedRef.current && typeof stdout.uncork === "function") {
33339
+ isStdoutCorkedRef.current = false;
33340
+ stdout.uncork();
33341
+ }
33342
+ }, [stdout, clearResizeCorkSafetyTimer]);
32960
33343
  const refreshStatic = (0, import_react119.useCallback)(() => {
32961
33344
  if (!isAlternateBuffer && !config.getUseTerminalBuffer()) {
33345
+ clearResizeDebounceTimer();
33346
+ refreshStdoutSize(stdout);
33347
+ if (typeof stdout.prependListener === "function" && stdout.columns !== void 0 && stdout.columns !== terminalWidthRef.current) {
33348
+ corkStdout();
33349
+ clearResizeCorkSafetyTimer();
33350
+ resizeCorkSafetyTimerRef.current = setTimeout(() => {
33351
+ discardCorkedStdoutBuffer(stdout);
33352
+ uncorkStdout();
33353
+ }, RESIZE_CORK_SAFETY_TIMEOUT_MS);
33354
+ return;
33355
+ }
33356
+ clearResizeCorkSafetyTimer();
33357
+ lastRefreshedColumnsRef.current = terminalWidthRef.current;
33358
+ if (typeof stdout.cork === "function") {
33359
+ corkStdout();
33360
+ discardCorkedStdoutBuffer(stdout);
33361
+ isRefreshingStaticRef.current = true;
33362
+ stdout.write(ENTER_SYNCHRONIZED_OUTPUT);
33363
+ }
32962
33364
  stdout.write(base_exports.clearTerminal);
32963
33365
  setHistoryRemountKey((prev) => prev + 1);
32964
33366
  }
32965
- }, [setHistoryRemountKey, isAlternateBuffer, stdout, config]);
33367
+ }, [
33368
+ setHistoryRemountKey,
33369
+ isAlternateBuffer,
33370
+ stdout,
33371
+ config,
33372
+ clearResizeDebounceTimer,
33373
+ clearResizeCorkSafetyTimer,
33374
+ corkStdout,
33375
+ uncorkStdout
33376
+ ]);
33377
+ (0, import_react119.useLayoutEffect)(() => {
33378
+ if (isRefreshingStaticRef.current) {
33379
+ isRefreshingStaticRef.current = false;
33380
+ refreshStdoutSize(stdout);
33381
+ if (stdout.columns !== void 0 && stdout.columns !== lastRefreshedColumnsRef.current) {
33382
+ discardCorkedStdoutBuffer(stdout);
33383
+ stdout.write(EXIT_SYNCHRONIZED_OUTPUT);
33384
+ uncorkStdout();
33385
+ return;
33386
+ }
33387
+ stdout.write(EXIT_SYNCHRONIZED_OUTPUT);
33388
+ uncorkStdout();
33389
+ }
33390
+ }, [historyRemountKey, stdout, uncorkStdout]);
32966
33391
  const shouldUseAlternateScreen = shouldEnterAlternateScreen(
32967
33392
  isAlternateBuffer,
32968
33393
  config.getScreenReader()
@@ -33207,6 +33632,28 @@ Logging in with Google... Restarting Gemini CLI to continue.
33207
33632
  toggleCleanUiDetailsVisible,
33208
33633
  revealCleanUiDetailsTemporarily
33209
33634
  } = useVisibilityToggle();
33635
+ const cancelPromiseRef = (0, import_react119.useRef)(null);
33636
+ const awaitCancelPromise = (0, import_react119.useCallback)(async () => {
33637
+ if (!cancelPromiseRef.current) {
33638
+ return;
33639
+ }
33640
+ let timeoutId2;
33641
+ try {
33642
+ await Promise.race([
33643
+ cancelPromiseRef.current,
33644
+ new Promise((resolve3) => {
33645
+ timeoutId2 = setTimeout(resolve3, 1e3);
33646
+ })
33647
+ ]);
33648
+ } catch (error) {
33649
+ debugLogger.warn(`Error awaiting cancellation: ${error}`);
33650
+ } finally {
33651
+ if (timeoutId2 !== void 0) {
33652
+ clearTimeout(timeoutId2);
33653
+ }
33654
+ cancelPromiseRef.current = null;
33655
+ }
33656
+ }, []);
33210
33657
  const slashCommandActions = (0, import_react119.useMemo)(
33211
33658
  () => ({
33212
33659
  openAuthDialog: () => setAuthState("updating" /* Updating */),
@@ -33223,6 +33670,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
33223
33670
  closeThemeDialog();
33224
33671
  setQuittingMessages(messages);
33225
33672
  setTimeout(async () => {
33673
+ await awaitCancelPromise();
33226
33674
  await runExitCleanup();
33227
33675
  process12.exit(0);
33228
33676
  }, 100);
@@ -33258,6 +33706,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
33258
33706
  openVoiceModelDialog,
33259
33707
  openAgentConfigDialog,
33260
33708
  setQuittingMessages,
33709
+ awaitCancelPromise,
33261
33710
  setDebugMessage,
33262
33711
  setShowPrivacyNotice,
33263
33712
  setCorgiMode,
@@ -33404,6 +33853,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
33404
33853
  // eslint-disable-next-line react-hooks/rules-of-hooks
33405
33854
  useAgentStream({
33406
33855
  agent: streamAgent,
33856
+ config,
33407
33857
  addItem: historyManager.addItem,
33408
33858
  onCancelSubmit,
33409
33859
  isShellFocused: embeddedShellFocused,
@@ -33758,15 +34208,18 @@ ${queuedText}` : queuedText;
33758
34208
  const [showFullTodos, setShowFullTodos] = (0, import_react119.useState)(false);
33759
34209
  const [renderMarkdown, setRenderMarkdown] = (0, import_react119.useState)(true);
33760
34210
  const handleExitRepeat = (0, import_react119.useCallback)(
33761
- (count) => {
34211
+ async (count) => {
33762
34212
  if (count > 2) {
33763
34213
  recordExitFail(config);
33764
34214
  }
33765
34215
  if (count > 1) {
33766
- void handleSlashCommand("/quit", void 0, void 0, false);
34216
+ if (cancelPromiseRef.current) {
34217
+ await awaitCancelPromise();
34218
+ }
34219
+ await handleSlashCommand("/quit", void 0, void 0, false);
33767
34220
  }
33768
34221
  },
33769
- [config, handleSlashCommand]
34222
+ [config, handleSlashCommand, awaitCancelPromise]
33770
34223
  );
33771
34224
  const { pressCount: ctrlCPressCount, handlePress: handleCtrlCPress } = useRepeatedKeyPress({
33772
34225
  windowMs: WARNING_PROMPT_DURATION_MS,
@@ -33794,6 +34247,7 @@ ${queuedText}` : queuedText;
33794
34247
  needsRestart: ideNeedsRestart,
33795
34248
  restartReason: ideTrustRestartReason
33796
34249
  } = useIdeTrustListener();
34250
+ const prevWidthRef = (0, import_react119.useRef)(terminalWidth);
33797
34251
  useIncludeDirsTrust(config, isTrustedFolder, historyManager, setCustomDialog);
33798
34252
  const tabFocusTimeoutRef = (0, import_react119.useRef)(null);
33799
34253
  (0, import_react119.useEffect)(() => {
@@ -33843,6 +34297,64 @@ ${queuedText}` : queuedText;
33843
34297
  setShowIdeRestartPrompt(true);
33844
34298
  }
33845
34299
  }, [ideNeedsRestart]);
34300
+ (0, import_react119.useEffect)(() => {
34301
+ if (isAlternateBuffer || config.getUseTerminalBuffer() || typeof stdout.prependListener !== "function") {
34302
+ return;
34303
+ }
34304
+ const handleResizeStart = () => {
34305
+ const currentColumns = stdout.columns ?? process12.stdout.columns;
34306
+ if (currentColumns !== void 0 && currentColumns !== lastStdoutColumnsRef.current) {
34307
+ lastStdoutColumnsRef.current = currentColumns;
34308
+ corkStdout();
34309
+ clearResizeCorkSafetyTimer();
34310
+ resizeCorkSafetyTimerRef.current = setTimeout(() => {
34311
+ discardCorkedStdoutBuffer(stdout);
34312
+ uncorkStdout();
34313
+ }, RESIZE_CORK_SAFETY_TIMEOUT_MS);
34314
+ }
34315
+ };
34316
+ stdout.prependListener("resize", handleResizeStart);
34317
+ return () => {
34318
+ stdout.off("resize", handleResizeStart);
34319
+ clearResizeDebounceTimer();
34320
+ if (isRefreshingStaticRef.current) {
34321
+ isRefreshingStaticRef.current = false;
34322
+ stdout.write(EXIT_SYNCHRONIZED_OUTPUT);
34323
+ }
34324
+ uncorkStdout();
34325
+ };
34326
+ }, [
34327
+ stdout,
34328
+ isAlternateBuffer,
34329
+ config,
34330
+ corkStdout,
34331
+ uncorkStdout,
34332
+ clearResizeDebounceTimer,
34333
+ clearResizeCorkSafetyTimer
34334
+ ]);
34335
+ (0, import_react119.useEffect)(() => {
34336
+ if (prevWidthRef.current === terminalWidth) {
34337
+ return;
34338
+ }
34339
+ prevWidthRef.current = terminalWidth;
34340
+ if (isAlternateBuffer || config.getUseTerminalBuffer()) {
34341
+ clearResizeDebounceTimer();
34342
+ return;
34343
+ }
34344
+ clearResizeDebounceTimer();
34345
+ resizeDebounceTimerRef.current = setTimeout(() => {
34346
+ refreshStatic();
34347
+ }, RESIZE_DEBOUNCE_MS);
34348
+ return () => {
34349
+ clearResizeDebounceTimer();
34350
+ };
34351
+ }, [
34352
+ terminalWidth,
34353
+ refreshStatic,
34354
+ clearResizeDebounceTimer,
34355
+ isAlternateBuffer,
34356
+ config
34357
+ ]);
33846
34358
  (0, import_react119.useEffect)(() => {
33847
34359
  const unsubscribe = ideContextStore.subscribe(setIdeContextState);
33848
34360
  setIdeContextState(ideContextStore.get());
@@ -33897,7 +34409,10 @@ ${queuedText}` : queuedText;
33897
34409
  return true;
33898
34410
  }
33899
34411
  if (keyMatchers["basic.quit" /* QUIT */](key)) {
33900
- void cancelOngoingRequest?.();
34412
+ const cancelPromise = cancelOngoingRequest?.();
34413
+ if (cancelPromise) {
34414
+ cancelPromiseRef.current = cancelPromise;
34415
+ }
33901
34416
  handleCtrlCPress();
33902
34417
  return true;
33903
34418
  } else if (keyMatchers["basic.exit" /* EXIT */](key)) {
@@ -33964,7 +34479,7 @@ ${queuedText}` : queuedText;
33964
34479
  if (keyMatchers["app.showErrorDetails" /* SHOW_ERROR_DETAILS */](key)) {
33965
34480
  if (settings.merged.general.devtools) {
33966
34481
  void (async () => {
33967
- const { toggleDevToolsPanel } = await import("./devtoolsService-OI7AEJQC.js");
34482
+ const { toggleDevToolsPanel } = await import("./devtoolsService-JFJBTZ4B.js");
33968
34483
  await toggleDevToolsPanel(
33969
34484
  config,
33970
34485
  showErrorDetails,