@within-7/minto 0.3.6 → 0.3.9

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 (153) hide show
  1. package/{cli.js → cli.cjs} +25 -23
  2. package/dist/commands/language.js +137 -0
  3. package/dist/commands/language.js.map +7 -0
  4. package/dist/commands/new.js +56 -0
  5. package/dist/commands/new.js.map +7 -0
  6. package/dist/commands/resume.js +251 -16
  7. package/dist/commands/resume.js.map +2 -2
  8. package/dist/commands/sessions.js +224 -0
  9. package/dist/commands/sessions.js.map +7 -0
  10. package/dist/commands/setup.js +3 -2
  11. package/dist/commands/setup.js.map +2 -2
  12. package/dist/commands/stats.js +235 -0
  13. package/dist/commands/stats.js.map +7 -0
  14. package/dist/commands/status.js +11 -5
  15. package/dist/commands/status.js.map +2 -2
  16. package/dist/commands/undo.js +26 -16
  17. package/dist/commands/undo.js.map +2 -2
  18. package/dist/commands.js +6 -0
  19. package/dist/commands.js.map +2 -2
  20. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  21. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  22. package/dist/components/Config.js +9 -8
  23. package/dist/components/Config.js.map +2 -2
  24. package/dist/components/HeaderBar.js +2 -1
  25. package/dist/components/HeaderBar.js.map +2 -2
  26. package/dist/components/Help.js +2 -1
  27. package/dist/components/Help.js.map +2 -2
  28. package/dist/components/HotkeyHelpPanel.js +46 -44
  29. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  30. package/dist/components/Logo.js +5 -2
  31. package/dist/components/Logo.js.map +2 -2
  32. package/dist/components/MCPServerApprovalDialog.js +6 -5
  33. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  34. package/dist/components/MCPServerMultiselectDialog.js +5 -4
  35. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  36. package/dist/components/MessageSelector.js +4 -3
  37. package/dist/components/MessageSelector.js.map +2 -2
  38. package/dist/components/ModelConfig.js +13 -12
  39. package/dist/components/ModelConfig.js.map +2 -2
  40. package/dist/components/ModelListManager.js +4 -3
  41. package/dist/components/ModelListManager.js.map +2 -2
  42. package/dist/components/PromptInput.js +72 -39
  43. package/dist/components/PromptInput.js.map +2 -2
  44. package/dist/components/SensitiveFileWarning.js +12 -8
  45. package/dist/components/SensitiveFileWarning.js.map +2 -2
  46. package/dist/components/TabbedListView/ScrollableList.js +91 -0
  47. package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
  48. package/dist/components/TabbedListView/SearchInput.js +23 -0
  49. package/dist/components/TabbedListView/SearchInput.js.map +7 -0
  50. package/dist/components/TabbedListView/TabBar.js +20 -0
  51. package/dist/components/TabbedListView/TabBar.js.map +7 -0
  52. package/dist/components/TabbedListView/TabbedListView.js +171 -0
  53. package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
  54. package/dist/components/TabbedListView/index.js +11 -0
  55. package/dist/components/TabbedListView/index.js.map +7 -0
  56. package/dist/components/TabbedListView/types.js +1 -0
  57. package/dist/components/TabbedListView/types.js.map +7 -0
  58. package/dist/components/TodoChangeBlock.js +6 -5
  59. package/dist/components/TodoChangeBlock.js.map +3 -3
  60. package/dist/components/TodoPanel.js +6 -3
  61. package/dist/components/TodoPanel.js.map +3 -3
  62. package/dist/components/TrustDialog.js +6 -5
  63. package/dist/components/TrustDialog.js.map +2 -2
  64. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
  65. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
  66. package/dist/constants/macros.js +1 -1
  67. package/dist/constants/macros.js.map +1 -1
  68. package/dist/constants/product.js +2 -2
  69. package/dist/constants/product.js.map +1 -1
  70. package/dist/constants/prompts.js +17 -0
  71. package/dist/constants/prompts.js.map +2 -2
  72. package/dist/constants/toolInputExamples.js +5 -1
  73. package/dist/constants/toolInputExamples.js.map +2 -2
  74. package/dist/core/tokenStatsManager.js +5 -0
  75. package/dist/core/tokenStatsManager.js.map +2 -2
  76. package/dist/entrypoints/bootstrap.js +54 -0
  77. package/dist/entrypoints/bootstrap.js.map +7 -0
  78. package/dist/entrypoints/cli.js +132 -23
  79. package/dist/entrypoints/cli.js.map +3 -3
  80. package/dist/history.js +75 -15
  81. package/dist/history.js.map +2 -2
  82. package/dist/i18n/index.js +2 -2
  83. package/dist/i18n/index.js.map +2 -2
  84. package/dist/i18n/locales/en.js +283 -1
  85. package/dist/i18n/locales/en.js.map +2 -2
  86. package/dist/i18n/locales/zh-CN.js +283 -1
  87. package/dist/i18n/locales/zh-CN.js.map +2 -2
  88. package/dist/i18n/types.js.map +1 -1
  89. package/dist/index.js +1 -1
  90. package/dist/index.js.map +2 -2
  91. package/dist/messages.js +11 -0
  92. package/dist/messages.js.map +2 -2
  93. package/dist/permissions.js.map +2 -2
  94. package/dist/query.js +9 -0
  95. package/dist/query.js.map +2 -2
  96. package/dist/screens/REPL.js +45 -7
  97. package/dist/screens/REPL.js.map +2 -2
  98. package/dist/services/customCommands.js +14 -8
  99. package/dist/services/customCommands.js.map +2 -2
  100. package/dist/tools/TaskTool/TaskTool.js +176 -1
  101. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  102. package/dist/tools/TodoWriteTool/prompt.js +21 -0
  103. package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
  104. package/dist/tools/URLFetcherTool/prompt.js +14 -9
  105. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  106. package/dist/tools/WebSearchTool/prompt.js +12 -6
  107. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  108. package/dist/types/PermissionMode.js +30 -1
  109. package/dist/types/PermissionMode.js.map +2 -2
  110. package/dist/types/plugin.js.map +2 -2
  111. package/dist/utils/agentHookExecutor.js +106 -0
  112. package/dist/utils/agentHookExecutor.js.map +7 -0
  113. package/dist/utils/agentLoader.js +212 -26
  114. package/dist/utils/agentLoader.js.map +2 -2
  115. package/dist/utils/agentMemory.js +134 -0
  116. package/dist/utils/agentMemory.js.map +7 -0
  117. package/dist/utils/config.js +51 -1
  118. package/dist/utils/config.js.map +2 -2
  119. package/dist/utils/configPaths.js +199 -0
  120. package/dist/utils/configPaths.js.map +7 -0
  121. package/dist/utils/historyManager.js +234 -0
  122. package/dist/utils/historyManager.js.map +7 -0
  123. package/dist/utils/messages.js +13 -8
  124. package/dist/utils/messages.js.map +2 -2
  125. package/dist/utils/migration/index.js +37 -0
  126. package/dist/utils/migration/index.js.map +7 -0
  127. package/dist/utils/migration/migrateHistory.js +273 -0
  128. package/dist/utils/migration/migrateHistory.js.map +7 -0
  129. package/dist/utils/migration/migrateTodos.js +323 -0
  130. package/dist/utils/migration/migrateTodos.js.map +7 -0
  131. package/dist/utils/pasteCache.js +309 -0
  132. package/dist/utils/pasteCache.js.map +7 -0
  133. package/dist/utils/pluginLoader.js +6 -3
  134. package/dist/utils/pluginLoader.js.map +2 -2
  135. package/dist/utils/sessionIndex.js +192 -0
  136. package/dist/utils/sessionIndex.js.map +7 -0
  137. package/dist/utils/sessionTracker.js +170 -0
  138. package/dist/utils/sessionTracker.js.map +7 -0
  139. package/dist/utils/skillLoader.js +91 -5
  140. package/dist/utils/skillLoader.js.map +2 -2
  141. package/dist/utils/stats.js +417 -0
  142. package/dist/utils/stats.js.map +7 -0
  143. package/dist/utils/stringSubstitution.js +107 -0
  144. package/dist/utils/stringSubstitution.js.map +7 -0
  145. package/dist/utils/teamConfig.js +3 -1
  146. package/dist/utils/teamConfig.js.map +2 -2
  147. package/dist/utils/todoStorage.js +51 -19
  148. package/dist/utils/todoStorage.js.map +2 -2
  149. package/dist/utils/tooling/safeRender.js.map +2 -2
  150. package/dist/version.js +2 -2
  151. package/dist/version.js.map +1 -1
  152. package/package.json +71 -28
  153. package/scripts/{postinstall.js → postinstall.cjs} +1 -1
@@ -1,4 +1,4 @@
1
- import { Box, Newline, Static, Text } from "ink";
1
+ import { Box, Newline, Static, Text, useApp } from "ink";
2
2
  import ProjectOnboarding, {
3
3
  markProjectOnboardingComplete
4
4
  } from "../components/ProjectOnboarding.js";
@@ -33,7 +33,8 @@ import { getTodos, initTodoSession } from "../utils/todoStorage.js";
33
33
  import {
34
34
  setMessagesGetter,
35
35
  setMessagesSetter,
36
- setModelConfigChangeHandler
36
+ setModelConfigChangeHandler,
37
+ setLanguageChangeHandler
37
38
  } from "../messages.js";
38
39
  import {
39
40
  query
@@ -86,7 +87,15 @@ import { useMessageGroups } from "../hooks/useMessageGroups.js";
86
87
  import { useAgentTranscripts } from "../hooks/useAgentTranscripts.js";
87
88
  import { GroupRenderer } from "../components/messages/GroupRenderer.js";
88
89
  import { SEMANTIC_COLORS } from "../constants/colors.js";
89
- const RESUME_VISIBLE_MESSAGE_COUNT = 10;
90
+ import {
91
+ initSessionTracker,
92
+ recordFirstPrompt,
93
+ incrementMessageCount,
94
+ incrementToolCallCount,
95
+ flushSessionStats,
96
+ endSession
97
+ } from "../utils/sessionTracker.js";
98
+ const RESUME_VISIBLE_MESSAGE_COUNT = Infinity;
90
99
  function REPL({
91
100
  commands,
92
101
  safeMode,
@@ -113,6 +122,7 @@ function REPL({
113
122
  getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0)
114
123
  );
115
124
  const [isResizeClearing, setIsResizeClearing] = useState(false);
125
+ const { exit: unmountREPL } = useApp();
116
126
  useFullscreenExitCallback(async () => {
117
127
  setIsResizeClearing(true);
118
128
  await new Promise((resolve) => setTimeout(resolve, 50));
@@ -366,6 +376,10 @@ function REPL({
366
376
  });
367
377
  markProjectOnboardingComplete();
368
378
  const lastMessage = newMessages[newMessages.length - 1];
379
+ if (lastMessage.type === "user" && typeof lastMessage.message.content === "string") {
380
+ recordFirstPrompt(lastMessage.message.content);
381
+ incrementMessageCount(1);
382
+ }
369
383
  if (lastMessage.type === "user" && typeof lastMessage.message.content === "string") {
370
384
  }
371
385
  if (lastMessage.type === "assistant") {
@@ -410,6 +424,15 @@ function REPL({
410
424
  messageBatchBufferRef.current?.add(message);
411
425
  if (message.type === "assistant") {
412
426
  lastAssistantMessage = message;
427
+ incrementMessageCount(1);
428
+ if (Array.isArray(message.message.content)) {
429
+ const toolUseCount = message.message.content.filter(
430
+ (block) => typeof block === "object" && block.type === "tool_use"
431
+ ).length;
432
+ if (toolUseCount > 0) {
433
+ incrementToolCallCount(toolUseCount);
434
+ }
435
+ }
413
436
  }
414
437
  }
415
438
  if (isKodingRequest && lastAssistantMessage && lastAssistantMessage.type === "assistant") {
@@ -435,6 +458,7 @@ function REPL({
435
458
  } finally {
436
459
  setIsLoading(false);
437
460
  setAbortController(null);
461
+ flushSessionStats();
438
462
  if (queuedPromptsRef.current.length > 0) {
439
463
  setTimeout(() => {
440
464
  if (processNextQueuedPromptRef.current) {
@@ -462,6 +486,15 @@ function REPL({
462
486
  setForkNumber((prev) => prev + 1);
463
487
  });
464
488
  }, []);
489
+ useEffect(() => {
490
+ setLanguageChangeHandler(async () => {
491
+ setIsResizeClearing(true);
492
+ await new Promise((resolve) => setTimeout(resolve, 50));
493
+ await clearTerminal();
494
+ setForkNumber((prev) => prev + 1);
495
+ setIsResizeClearing(false);
496
+ });
497
+ }, []);
465
498
  useEffect(() => {
466
499
  messagesRef.current = messages;
467
500
  }, [messages]);
@@ -481,10 +514,13 @@ function REPL({
481
514
  plugins
482
515
  );
483
516
  hookManagerRef.current = hookManager;
517
+ initSessionTracker(getOriginalCwd());
484
518
  hookManager.executeSessionStart().catch((err) => {
485
519
  debugLogger.error("SessionStart hooks failed", { error: err });
486
520
  });
487
521
  return () => {
522
+ flushSessionStats();
523
+ endSession("other");
488
524
  hookManager.executeSessionEnd("other").catch((err) => {
489
525
  debugLogger.error("SessionEnd hooks failed", { error: err });
490
526
  });
@@ -560,7 +596,7 @@ function REPL({
560
596
  const result = [
561
597
  {
562
598
  type: "static",
563
- jsx: /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%", key: `logo${forkNumber}` }, /* @__PURE__ */ React.createElement(
599
+ jsx: /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%", key: "logo" }, /* @__PURE__ */ React.createElement(
564
600
  Logo,
565
601
  {
566
602
  mcpClients,
@@ -878,7 +914,7 @@ function REPL({
878
914
  isVisible: lastTurnDurationMs !== null
879
915
  }
880
916
  ),
881
- toolJSX ? toolJSX.jsx : null,
917
+ toolJSX?.shouldHidePromptInput ? toolJSX.jsx : null,
882
918
  !toolJSX && binaryFeedbackContext && !isMessageSelectorVisible && /* @__PURE__ */ React.createElement(
883
919
  BinaryFeedback,
884
920
  {
@@ -982,9 +1018,11 @@ function REPL({
982
1018
  setQueuedPrompts((prev) => prev.slice(0, -1));
983
1019
  return lastPrompt;
984
1020
  },
985
- onInterrupt
1021
+ onInterrupt,
1022
+ isOverlayActive: !!(toolJSX && !toolJSX.shouldHidePromptInput),
1023
+ unmount: unmountREPL
986
1024
  }
987
- ))
1025
+ ), toolJSX && !toolJSX.shouldHidePromptInput && toolJSX.jsx)
988
1026
  ), isMessageSelectorVisible && /* @__PURE__ */ React.createElement(React.Fragment, { key: `message-selector-wrapper-${forkNumber}` }, /* @__PURE__ */ React.createElement(
989
1027
  MessageSelector,
990
1028
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/screens/REPL.tsx"],
4
- "sourcesContent": ["import {\n ToolUseBlockParam,\n ToolResultBlockParam,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Box, Newline, Static, Text } from 'ink'\nimport ProjectOnboarding, {\n markProjectOnboardingComplete,\n} from '@components/ProjectOnboarding'\nimport type { SafetyMode } from '@utils/config'\nimport { CostThresholdDialog } from '@components/CostThresholdDialog'\nimport * as React from 'react'\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react'\nimport { Command } from '@commands'\nimport { Logo } from '@components/Logo'\nimport { Message } from '@components/Message'\nimport { MessageResponse } from '@components/MessageResponse'\nimport { BashStreamingProgress } from '@components/BashStreamingProgress'\nimport { MessageSelector } from '@components/MessageSelector'\nimport { MessageBatchBuffer } from '@utils/MessageBatchBuffer'\nimport {\n PermissionRequest,\n type ToolUseConfirm,\n} from '@components/permissions/PermissionRequest'\nimport PromptInput from '@components/PromptInput'\nimport { getSystemPrompt } from '@constants/prompts'\nimport { getContext } from '@context'\nimport { getTotalCost, useCostSummary } from '@costTracker'\nimport { useLogStartupTime } from '@hooks/useLogStartupTime'\nimport { addToHistory } from '@history'\nimport { useApiKeyVerification } from '@hooks/useApiKeyVerification'\n// useCancelRequest removed - ESC interrupt logic consolidated into onInterrupt callback\nimport useCanUseTool from '@hooks/useCanUseTool'\nimport { useLogMessages, serializeMessageForLog } from '@hooks/useLogMessages'\nimport { overwriteLog } from '@utils/log'\nimport { PermissionProvider } from '@context/PermissionContext'\nimport { useFullscreenExitCallback } from '@hooks/useTerminalSize'\nimport { ModeIndicator } from '@components/ModeIndicator'\nimport { TodoPanel } from '@components/TodoPanel'\nimport { TurnCompletionIndicator } from '@components/TurnCompletionIndicator'\nimport { getTodos, initTodoSession } from '@utils/todoStorage'\nimport {\n setMessagesGetter,\n setMessagesSetter,\n setModelConfigChangeHandler,\n} from '@messages'\nimport {\n type AssistantMessage,\n type BinaryFeedbackResult,\n type Message as MessageType,\n type ProgressMessage,\n type StreamingProgressContent,\n query,\n} from '@query'\nimport type { WrappedClient } from '@services/mcpClient'\nimport type { Tool } from '@tool'\n// Auto-updater removed; only show a new version banner passed from CLI\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n getVerboseLabel,\n} from '@utils/config'\nimport { MACRO } from '@constants/macros'\nimport { getNextAvailableLogForkNumber } from '@utils/log'\nimport {\n getErroredToolUseMessages,\n getInProgressToolUseIDs,\n getLastAssistantMessageId,\n getToolUseID,\n getUnresolvedToolUseIDs,\n INTERRUPT_MESSAGE,\n isNotEmptyMessage,\n type NormalizedMessage,\n normalizeMessages,\n normalizeMessagesForAPI,\n processUserInput,\n reorderMessages,\n extractTag,\n createAssistantMessage,\n createAssistantAPIErrorMessage,\n} from '@utils/messages'\nimport { logError } from '@utils/log'\nimport { getModelManager, ModelManager } from '@utils/model'\nimport { clearTerminal, updateTerminalTitle } from '@utils/terminal'\nimport { BinaryFeedback } from '@components/binary-feedback/BinaryFeedback'\nimport { getMaxThinkingTokens } from '@utils/thinking'\nimport { getOriginalCwd } from '@utils/state'\nimport { handleHashCommand } from '@commands/terminalSetup'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport {\n initializeHookManager,\n getHookManager,\n type HookManager,\n} from '@utils/hookManager'\nimport { loadAllPlugins } from '@utils/pluginLoader'\nimport { randomUUID } from 'crypto'\nimport { getMessagesPath } from '@utils/log'\nimport {\n BackgroundShellManager,\n type BackgroundShell,\n} from '@utils/BackgroundShellManager'\nimport { BackgroundTasksPanel } from '@components/BackgroundTasksPanel'\nimport { AskUserQuestionDialog } from '@components/AskUserQuestionDialog/AskUserQuestionDialog'\nimport {\n getToolUseIdByAgentId,\n getAgentIdByToolUseId,\n restoreToolUseAgentMappings,\n} from '@utils/agentTranscripts'\nimport type { AskUserQuestionContext } from '@minto-types/askUserQuestion'\nimport useAskUser from '@hooks/useAskUser'\n// V1+ hierarchical message display imports\nimport { useMessageGroups } from '@hooks/useMessageGroups'\nimport { useAgentTranscripts } from '@hooks/useAgentTranscripts'\nimport { GroupRenderer } from '@components/messages/GroupRenderer'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\n// Maximum number of recent messages to display when resuming a conversation\nconst RESUME_VISIBLE_MESSAGE_COUNT = 10\n\ntype Props = {\n commands: Command[]\n /** @deprecated Use safetyMode instead */\n safeMode?: boolean\n /** Safety mode: 'yolo' | 'smart' | 'strict' */\n safetyMode?: SafetyMode\n debug?: boolean\n initialForkNumber?: number | undefined\n initialPrompt: string | undefined\n // A unique name for the message log file, used to identify the fork\n messageLogName: string\n shouldShowPromptInput: boolean\n tools: Tool[]\n /**\n * Verbose mode: shows full parameters and complete outputs when enabled\n */\n verbose?: boolean | undefined\n // Initial messages to populate the REPL with\n initialMessages?: MessageType[]\n // MCP clients\n mcpClients?: WrappedClient[]\n // Flag to indicate if current model is default\n isDefaultModel?: boolean\n // Update banner info passed from CLI before first render\n initialUpdateVersion?: string | null\n initialUpdateCommands?: string[] | null\n // Whether to use limited input mode (raw mode not supported)\n fallbackMode?: boolean\n // Whether this is a resumed conversation (shows collapsed history indicator)\n isResumedConversation?: boolean\n}\n\nexport type BinaryFeedbackContext = {\n m1: AssistantMessage\n m2: AssistantMessage\n resolve: (result: BinaryFeedbackResult) => void\n}\n\nexport function REPL({\n commands,\n safeMode,\n safetyMode = 'yolo',\n debug = false,\n initialForkNumber = 0,\n initialPrompt,\n messageLogName,\n shouldShowPromptInput,\n tools,\n verbose: verboseFromCLI,\n initialMessages,\n mcpClients = [],\n isDefaultModel = true,\n initialUpdateVersion,\n initialUpdateCommands,\n fallbackMode = false,\n isResumedConversation = false,\n}: Props): React.ReactNode {\n // Verbose mode state - can be toggled at runtime with Ctrl+O\n // Default to normal mode (false), only use verbose if explicitly set via CLI\n const [verbose, setVerbose] = useState<boolean>(\n verboseFromCLI === true ? true : false,\n )\n\n // Used to force the logo to re-render and conversation log to use a new file\n const [forkNumber, setForkNumber] = useState(\n getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0),\n )\n\n // State to temporarily hide transient UI during resize to prevent ghost artifacts\n const [isResizeClearing, setIsResizeClearing] = useState(false)\n\n // Re-render UI when significant resize occurs to clear ghost artifacts\n // Strategy: Hide transient UI -> clear terminal -> restore UI\n useFullscreenExitCallback(async () => {\n // Step 1: Hide all transient UI by setting clearing state\n setIsResizeClearing(true)\n\n // Step 2: Wait a frame for React to render the empty state\n await new Promise(resolve => setTimeout(resolve, 50))\n\n // Step 3: Clear the terminal to remove any ghost artifacts\n await clearTerminal()\n\n // Step 4: Increment forkNumber and restore UI\n setForkNumber(prev => prev + 1)\n setIsResizeClearing(false)\n })\n\n const [\n forkConvoWithMessagesOnTheNextRender,\n setForkConvoWithMessagesOnTheNextRender,\n ] = useState<MessageType[] | null>(null)\n\n // \uD83D\uDD27 Simplified AbortController management - inspired by reference system\n const [abortController, setAbortController] =\n useState<AbortController | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n // No auto-updater state\n const [toolJSX, setToolJSX] = useState<{\n jsx: React.ReactNode | null\n shouldHidePromptInput: boolean\n } | null>(null)\n const [toolUseConfirm, setToolUseConfirm] = useState<ToolUseConfirm | null>(\n null,\n )\n const [messages, setMessages] = useState<MessageType[]>(initialMessages ?? [])\n // Ref to track latest messages for synchronous access in onInterrupt\n // This ensures we can save messages even when React state updates are pending\n const messagesRef = useRef<MessageType[]>(initialMessages ?? [])\n // Phase 4.1: Message history stack for Esc Esc rollback\n const [messageHistory, setMessageHistory] = useState<MessageType[][]>([])\n const [inputValue, setInputValue] = useState('')\n const [inputMode, setInputMode] = useState<'bash' | 'prompt' | 'koding'>(\n 'prompt',\n )\n const [submitCount, setSubmitCount] = useState(0)\n const [isMessageSelectorVisible, setIsMessageSelectorVisible] =\n useState(false)\n const [showCostDialog, setShowCostDialog] = useState(false)\n const [haveShownCostDialog, setHaveShownCostDialog] = useState(\n getGlobalConfig().hasAcknowledgedCostThreshold,\n )\n\n const [binaryFeedbackContext, setBinaryFeedbackContext] =\n useState<BinaryFeedbackContext | null>(null)\n const [askUserQuestionContext, setAskUserQuestionContext] =\n useState<AskUserQuestionContext | null>(null)\n // New version banner: passed in from CLI to guarantee top placement\n const updateAvailableVersion = initialUpdateVersion ?? null\n const updateCommands = initialUpdateCommands ?? null\n // No separate Static for banner; it renders inside Logo\n\n // TodoPanel state\n const [isTodoPanelVisible, setIsTodoPanelVisible] = useState(true)\n\n // Verbose toggle feedback message - survives PromptInput remount\n const [verboseToggleMessage, setVerboseToggleMessage] = useState<\n string | null\n >(null)\n\n // Turn duration tracking for \"Cogitated\" display\n const turnStartTimeRef = useRef<number | null>(null)\n const [lastTurnDurationMs, setLastTurnDurationMs] = useState<number | null>(\n null,\n )\n\n // Waiting list: queued messages to process after current task completes\n const [queuedPrompts, setQueuedPrompts] = useState<string[]>([])\n // Ref to track latest queued prompts (avoid stale closure issues)\n const queuedPromptsRef = useRef<string[]>([])\n useEffect(() => {\n queuedPromptsRef.current = queuedPrompts\n }, [queuedPrompts])\n\n // Track turn duration for \"Cogitated\" display\n useEffect(() => {\n if (isLoading) {\n // Turn started - record start time, clear previous duration\n turnStartTimeRef.current = Date.now()\n setLastTurnDurationMs(null)\n } else if (turnStartTimeRef.current !== null) {\n // Turn ended - calculate and store duration\n const duration = Date.now() - turnStartTimeRef.current\n setLastTurnDurationMs(duration)\n turnStartTimeRef.current = null\n }\n }, [isLoading])\n\n // Background tasks state\n const [backgroundShells, setBackgroundShells] = useState<BackgroundShell[]>(\n [],\n )\n const [showBackgroundPanel, setShowBackgroundPanel] = useState(false)\n\n // Phase 2.1: Removed recentlyCompletedIDs state - immediate static rendering for better performance\n const prevUnresolvedRef = useRef<Set<string>>(new Set())\n\n // Message batch buffer to eliminate flicker from rapid successive updates\n const messageBatchBufferRef = useRef<MessageBatchBuffer | null>(null)\n\n // Initialize batch buffer on first render\n if (messageBatchBufferRef.current === null) {\n messageBatchBufferRef.current = new MessageBatchBuffer(\n batchedMessages => {\n setMessages(prev => [...prev, ...batchedMessages])\n },\n {\n flushInterval: 100, // Batch messages for 100ms\n maxBatchSize: 50, // Force flush if 50+ messages buffered\n debug: false, // Set to true for debugging\n },\n )\n }\n\n // Cleanup buffer on unmount\n useEffect(() => {\n return () => {\n messageBatchBufferRef.current?.dispose()\n }\n }, [])\n\n const getBinaryFeedbackResponse = useCallback(\n (\n m1: AssistantMessage,\n m2: AssistantMessage,\n ): Promise<BinaryFeedbackResult> => {\n return new Promise<BinaryFeedbackResult>(resolvePromise => {\n setBinaryFeedbackContext({\n m1,\n m2,\n resolve: resolvePromise,\n })\n })\n },\n [],\n )\n\n const readFileTimestamps = useRef<{\n [filename: string]: number\n }>({})\n\n // Hook manager for plugin hooks\n const hookManagerRef = useRef<HookManager | null>(null)\n\n const { status: apiKeyStatus, reverify } = useApiKeyVerification()\n // Unified interrupt handler - called by PromptInput when ESC is pressed with empty input\n // Consolidates all cleanup logic in one place (no separate useCancelRequest hook needed)\n function onInterrupt() {\n if (!isLoading) {\n return\n }\n\n // \uD83D\uDD27 Force save messages before interrupt to prevent conversation loss\n // This is critical because React's useEffect-based saving might not run\n // in time when state changes rapidly during interrupt\n const currentMessages = messagesRef.current\n if (currentMessages.length > 0) {\n const serializedMessages = currentMessages.map(serializeMessageForLog)\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, 0),\n serializedMessages,\n )\n }\n\n // Clean up UI state\n setToolJSX(null)\n setToolUseConfirm(null)\n setBinaryFeedbackContext(null)\n setIsLoading(false)\n // Abort the request\n if (toolUseConfirm) {\n toolUseConfirm.onAbort()\n } else if (abortController && !abortController.signal.aborted) {\n abortController.abort()\n }\n }\n\n // Legacy onCancel for other callers (e.g., PermissionRequest)\n function onCancel() {\n onInterrupt()\n }\n\n useEffect(() => {\n if (forkConvoWithMessagesOnTheNextRender) {\n setForkNumber(_ => _ + 1)\n setForkConvoWithMessagesOnTheNextRender(null)\n setMessages(forkConvoWithMessagesOnTheNextRender)\n }\n }, [forkConvoWithMessagesOnTheNextRender])\n\n useEffect(() => {\n const totalCost = getTotalCost()\n if (totalCost >= 5 /* $5 */ && !showCostDialog && !haveShownCostDialog) {\n setShowCostDialog(true)\n }\n }, [messages, showCostDialog, haveShownCostDialog])\n\n // Update banner is provided by CLI at startup; no async check here.\n\n const canUseTool = useCanUseTool(setToolUseConfirm)\n const askUser = useAskUser(setAskUserQuestionContext)\n\n async function onInit() {\n reverify()\n\n if (!initialPrompt) {\n return\n }\n\n setIsLoading(true)\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n try {\n // \uD83D\uDD27 Force fresh config read to ensure model switching works\n const model = new ModelManager(getGlobalConfig()).getModelName('main')\n const newMessages = await processUserInput(\n initialPrompt,\n 'prompt',\n setToolJSX,\n {\n abortController: newAbortController,\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n maxThinkingTokens: 0,\n },\n messageId: getLastAssistantMessageId(messages),\n setForkConvoWithMessagesOnTheNextRender,\n readFileTimestamps: readFileTimestamps.current,\n },\n null,\n )\n\n if (newMessages.length) {\n for (const message of newMessages) {\n if (message.type === 'user') {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n }\n setMessages(_ => [..._, ...newMessages])\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n if (lastMessage.type === 'assistant') {\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, ...newMessages]),\n ])\n\n for await (const message of query(\n [...messages, ...newMessages],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n safetyMode,\n maxThinkingTokens,\n },\n messageId: getLastAssistantMessageId([...messages, ...newMessages]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: newAbortController,\n setToolJSX,\n askUser,\n },\n getBinaryFeedbackResponse,\n )) {\n // Use batch buffer to reduce render frequency\n messageBatchBufferRef.current?.add(message)\n }\n\n // Flush any remaining buffered messages immediately after query completes\n messageBatchBufferRef.current?.flush()\n } else {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n\n setHaveShownCostDialog(\n getGlobalConfig().hasAcknowledgedCostThreshold || false,\n )\n } catch (error) {\n // \uD83D\uDD27 Fix: Handle errors gracefully and show error to user\n logError(error)\n setMessages(oldMessages => [\n ...oldMessages,\n createAssistantAPIErrorMessage(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n ),\n ])\n } finally {\n // \uD83D\uDD27 Fix: Always clean up state, even on error\n setIsLoading(false)\n setAbortController(null)\n }\n }\n\n // Phase 4.1: Rollback to previous message state\n function rollbackConversation(): boolean {\n if (messageHistory.length === 0) {\n return false // No history to rollback to\n }\n\n // Pop the last snapshot and restore it\n const previousMessages = messageHistory[messageHistory.length - 1]!\n setMessages(previousMessages)\n setMessageHistory(history => history.slice(0, -1))\n\n return true // Successfully rolled back\n }\n\n // Process the next queued prompt (called after current task completes)\n // This is defined as a ref to avoid stale closure issues\n const processNextQueuedPromptRef = useRef<(() => Promise<void>) | null>(null)\n\n async function onQuery(\n newMessages: MessageType[],\n passedAbortController?: AbortController,\n ) {\n // Use passed AbortController or create new one\n const controllerToUse = passedAbortController || new AbortController()\n if (!passedAbortController) {\n setAbortController(controllerToUse)\n }\n // \uD83D\uDD27 Fix: Always set isLoading to true at the start\n setIsLoading(true)\n\n // Reset verbose mode to normal when user starts new task\n // User can manually enable verbose with Ctrl+O during task execution\n setVerbose(false)\n\n // Check if this is a Koding request based on last message's options\n const isKodingRequest =\n newMessages.length > 0 &&\n newMessages[0].type === 'user' &&\n 'options' in newMessages[0] &&\n newMessages[0].options?.isKodingRequest === true\n\n // Phase 4.1: Save message history snapshot before adding new messages\n setMessages(oldMessages => {\n // Save current state to history stack (limit to last 10 snapshots)\n setMessageHistory(history => [...history, oldMessages].slice(-10))\n return [...oldMessages, ...newMessages]\n })\n\n // Mark onboarding as complete when any user message is sent to the assistant\n markProjectOnboardingComplete()\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n\n // Update terminal title based on user message\n if (\n lastMessage.type === 'user' &&\n typeof lastMessage.message.content === 'string'\n ) {\n // updateTerminalTitle(lastMessage.message.content)\n }\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n try {\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, lastMessage]),\n ])\n\n let lastAssistantMessage: MessageType | null = null\n\n // query the API\n for await (const message of query(\n [...messages, lastMessage],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n safetyMode,\n maxThinkingTokens,\n // If this came from Koding mode, pass that along\n isKodingRequest: isKodingRequest || undefined,\n },\n messageId: getLastAssistantMessageId([...messages, lastMessage]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: controllerToUse,\n setToolJSX,\n askUser,\n },\n getBinaryFeedbackResponse,\n )) {\n // Use batch buffer to reduce render frequency\n messageBatchBufferRef.current?.add(message)\n\n // Keep track of the last assistant message for Koding mode\n if (message.type === 'assistant') {\n lastAssistantMessage = message\n }\n }\n\n // If this was a Koding request and we got an assistant message back,\n // save it to MINTO.md (and CLAUDE.md if exists)\n if (\n isKodingRequest &&\n lastAssistantMessage &&\n lastAssistantMessage.type === 'assistant'\n ) {\n try {\n const content =\n typeof lastAssistantMessage.message.content === 'string'\n ? lastAssistantMessage.message.content\n : lastAssistantMessage.message.content\n .filter(block => block.type === 'text')\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n\n // Add the content to MINTO.md (and CLAUDE.md if exists)\n if (content && content.trim().length > 0) {\n handleHashCommand(content)\n }\n } catch (error) {\n console.error('Error saving response to project docs:', error)\n }\n }\n\n // Flush any remaining buffered messages immediately after query completes\n messageBatchBufferRef.current?.flush()\n } catch (error) {\n // \uD83D\uDD27 Fix: Handle errors gracefully and show error to user\n logError(error)\n\n // Flush buffer before showing error to ensure all messages are visible\n messageBatchBufferRef.current?.flush()\n setMessages(oldMessages => [\n ...oldMessages,\n createAssistantAPIErrorMessage(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n ),\n ])\n } finally {\n // \uD83D\uDD27 Fix: Always clean up state, even on error\n setIsLoading(false)\n setAbortController(null)\n\n // Process next queued prompt if any (waiting list feature)\n if (queuedPromptsRef.current.length > 0) {\n // Use setTimeout to allow state to settle before processing next\n setTimeout(() => {\n if (processNextQueuedPromptRef.current) {\n processNextQueuedPromptRef.current()\n }\n }, 100)\n }\n }\n }\n\n // Register cost summary tracker\n useCostSummary()\n\n // Register messages getter and setter\n useEffect(() => {\n const getMessages = () => messages\n setMessagesGetter(getMessages)\n setMessagesSetter(setMessages)\n }, [messages])\n\n // Initialize todo session with unique identifier\n // Using messageLogName + forkNumber as session ID to ensure:\n // 1. Each conversation has its own todo list\n // 2. Resumed conversations restore their todos\n useEffect(() => {\n const todoSessionId = `${messageLogName}-${forkNumber}`\n initTodoSession(todoSessionId)\n\n // Restore transcript mappings for history restore\n // This enables proper display of Task tool results from previous sessions\n if (initialMessages && initialMessages.length > 0) {\n restoreToolUseAgentMappings()\n }\n }, [messageLogName, forkNumber, initialMessages])\n\n // Register model config change handler for UI refresh\n useEffect(() => {\n setModelConfigChangeHandler(() => {\n setForkNumber(prev => prev + 1)\n })\n }, [])\n\n // Keep messagesRef in sync with messages state for synchronous access\n useEffect(() => {\n messagesRef.current = messages\n }, [messages])\n\n // Record transcripts locally, for debugging and conversation recovery\n useLogMessages(messages, messageLogName, forkNumber)\n\n // Log startup time\n useLogStartupTime()\n\n // Initial load\n useEffect(() => {\n onInit()\n // TODO: fix this\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Initialize hook manager\n useEffect(() => {\n try {\n const plugins = loadAllPlugins()\n const sessionId = randomUUID()\n const transcriptPath = getMessagesPath(messageLogName, forkNumber, 0)\n\n const hookManager = initializeHookManager(\n sessionId,\n transcriptPath,\n plugins,\n )\n hookManagerRef.current = hookManager\n\n // Execute SessionStart hooks\n hookManager.executeSessionStart().catch(err => {\n debugLogger.error('SessionStart hooks failed', { error: err })\n })\n\n // Cleanup: Execute SessionEnd hooks\n return () => {\n hookManager.executeSessionEnd('other').catch(err => {\n debugLogger.error('SessionEnd hooks failed', { error: err })\n })\n }\n } catch (err) {\n debugLogger.error('Failed to initialize hook manager', { error: err })\n }\n }, [messageLogName, forkNumber])\n\n // Update background shells using event-driven approach (no polling)\n useEffect(() => {\n const manager = BackgroundShellManager.getInstance()\n // Initialize with current list\n setBackgroundShells(manager.list())\n\n // Subscribe to list changes\n const handleListChange = (shells: BackgroundShell[]) => {\n setBackgroundShells(shells)\n }\n manager.on('listChange', handleListChange)\n\n return () => {\n manager.off('listChange', handleListChange)\n }\n }, [])\n\n // Optimize: Cache normalized messages and only recompute when messages actually change\n // This useMemo will only rerun when the messages array reference changes\n const normalizedMessages = useMemo(\n () => normalizeMessages(messages).filter(isNotEmptyMessage),\n [messages],\n )\n\n const unresolvedToolUseIDs = useMemo(\n () => getUnresolvedToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n // Phase 2.1: Removed 300ms delay useEffect - immediate static rendering\n // Update prevUnresolvedRef when unresolvedToolUseIDs changes\n useEffect(() => {\n prevUnresolvedRef.current = new Set(unresolvedToolUseIDs)\n }, [unresolvedToolUseIDs])\n\n const inProgressToolUseIDs = useMemo(\n () => getInProgressToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const erroredToolUseIDs = useMemo(\n () =>\n new Set(\n getErroredToolUseMessages(normalizedMessages).map(\n _ => (_.message.content[0]! as ToolUseBlockParam).id,\n ),\n ),\n [normalizedMessages],\n )\n\n // V1+ Message Groups - identifies parallel task groups for unified rendering\n const {\n groups: messageGroups,\n getGroupForMessage,\n getGroupForToolUse,\n shouldGroupBeStatic,\n displayConfig,\n } = useMessageGroups(\n normalizedMessages,\n unresolvedToolUseIDs,\n inProgressToolUseIDs,\n verbose,\n )\n\n // V1+ Agent Transcripts - real-time transcript access for task display\n // getTranscript enables lazy loading from disk for historical messages\n const { transcripts: agentTranscripts, getTranscript } = useAgentTranscripts()\n\n // V1+ Tool outputs map for group rendering\n const toolOutputs = useMemo(() => {\n const outputs = new Map<string, ToolResultBlockParam>()\n for (const msg of normalizedMessages) {\n if (msg.type === 'user' && msg.message.role === 'user') {\n for (const block of msg.message.content) {\n if (typeof block === 'object' && block.type === 'tool_result') {\n outputs.set(block.tool_use_id, block as ToolResultBlockParam)\n }\n }\n }\n }\n return outputs\n }, [normalizedMessages])\n\n // Type for message JSX items - pre-rendered JSX with static/transient type\n type MessageJSXItem = {\n type: 'static' | 'transient'\n jsx: React.ReactElement\n }\n\n // Static item type for Ink's Static component (requires id for deduplication)\n type StaticItem = { id: string; jsx: React.ReactElement }\n\n const messagesJSX = useMemo(() => {\n const reorderedMessages = reorderMessages(normalizedMessages)\n\n // Calculate how many messages to hide when resuming a conversation\n const hiddenMessageCount =\n isResumedConversation &&\n reorderedMessages.length > RESUME_VISIBLE_MESSAGE_COUNT\n ? reorderedMessages.length - RESUME_VISIBLE_MESSAGE_COUNT\n : 0\n\n // Only show recent messages when resuming, but keep all messages in memory for context\n const visibleMessages =\n hiddenMessageCount > 0\n ? reorderedMessages.slice(-RESUME_VISIBLE_MESSAGE_COUNT)\n : reorderedMessages\n\n // Build the result array\n const result: MessageJSXItem[] = [\n {\n type: 'static',\n jsx: (\n <Box flexDirection=\"column\" width=\"100%\" key={`logo${forkNumber}`}>\n <Logo\n mcpClients={mcpClients}\n isDefaultModel={isDefaultModel}\n updateBannerVersion={updateAvailableVersion}\n updateBannerCommands={updateCommands}\n />\n <ProjectOnboarding workspaceDir={getOriginalCwd()} />\n </Box>\n ),\n },\n ]\n\n // Show collapsed history indicator when resuming with hidden messages\n if (hiddenMessageCount > 0) {\n result.push({\n type: 'static' as const,\n jsx: (\n <Box key=\"collapsed-history\" paddingLeft={2} marginBottom={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n \u00B7\u00B7\u00B7 {hiddenMessageCount} earlier messages hidden \u00B7\u00B7\u00B7\n </Text>\n </Box>\n ),\n })\n }\n\n // V1+ Track rendered groups to avoid duplicate rendering\n const renderedGroupIds = new Set<string>()\n // V1+ Track tool_use_ids that are part of groups (to skip their tool_result messages)\n const groupToolUseIds = new Set<string>()\n // V1+ Track TaskOutput tool_use_ids that reference grouped tasks (to skip their tool_result messages)\n const taskOutputToolUseIdsToSkip = new Set<string>()\n\n // Render all messages - with V1+ group detection for parallel-tasks and task groups\n for (const _ of visibleMessages) {\n const toolUseID = getToolUseID(_)\n\n // V1+ Check if this message belongs to a group (parallel-tasks or task)\n // For progress messages, use toolUseID to find the group (since progress messages have different UUIDs)\n // For assistant messages, use the message UUID directly\n let group = getGroupForMessage(_.uuid)\n if (!group && _.type === 'progress') {\n // This is a progress message for a task - look up by toolUseID\n group = getGroupForToolUse(_.toolUseID)\n }\n\n // V1+ Handle grouped messages (parallel-tasks and single task groups)\n if (group && (group.type === 'parallel-tasks' || group.type === 'task')) {\n // Skip if this group was already rendered\n if (renderedGroupIds.has(group.id)) {\n continue\n }\n renderedGroupIds.add(group.id)\n\n // Track all tool_use_ids in this group to skip their tool_result messages later\n if (group.metadata.siblingToolUseIds) {\n for (const id of group.metadata.siblingToolUseIds as string[]) {\n groupToolUseIds.add(id)\n }\n }\n if (group.metadata.toolUseId) {\n groupToolUseIds.add(group.metadata.toolUseId as string)\n }\n\n // Render the entire group using GroupRenderer\n const isGroupStatic = shouldGroupBeStatic(group)\n const groupType = isGroupStatic ? 'static' : 'transient'\n\n const shouldAnimate =\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !isGroupStatic\n\n result.push({\n type: groupType,\n jsx: (\n <Box key={`group-${group.id}`} width=\"100%\">\n <GroupRenderer\n group={group}\n context={{\n depth: 0,\n isLastChild: true,\n displayConfig,\n shouldAnimate,\n getTranscript,\n }}\n messages={normalizedMessages}\n transcripts={agentTranscripts}\n outputs={toolOutputs}\n />\n </Box>\n ),\n })\n continue\n }\n\n // V1+ Skip tool_result messages for tools that are part of a group\n // (their output is rendered within the group view)\n // Also skip tool_result messages for TaskOutput calls that reference grouped tasks\n if (_.type === 'user' && _.message.role === 'user') {\n const content = _.message.content\n if (Array.isArray(content)) {\n const toolResult = content.find(\n (block): block is ToolResultBlockParam =>\n typeof block === 'object' && block.type === 'tool_result',\n )\n if (\n toolResult &&\n (groupToolUseIds.has(toolResult.tool_use_id) ||\n taskOutputToolUseIdsToSkip.has(toolResult.tool_use_id))\n ) {\n continue\n }\n }\n }\n\n // V1+ Skip TaskOutput tool calls that reference agents belonging to a group\n // (their output is already rendered within the group view)\n if (_.type === 'assistant') {\n const content = _.message.content\n if (Array.isArray(content)) {\n const taskOutputCall = content.find(\n (block): block is ToolUseBlockParam =>\n typeof block === 'object' &&\n block.type === 'tool_use' &&\n block.name === 'TaskOutput',\n )\n if (taskOutputCall) {\n const taskId = (taskOutputCall.input as { task_id?: string })\n ?.task_id\n if (taskId) {\n // Check if this task_id (agentId) corresponds to a tool_use_id in a group\n const correspondingToolUseId = getToolUseIdByAgentId(taskId)\n if (\n correspondingToolUseId &&\n groupToolUseIds.has(correspondingToolUseId)\n ) {\n // Track this TaskOutput's tool_use_id so we can also skip its tool_result\n taskOutputToolUseIdsToSkip.add(taskOutputCall.id)\n continue\n }\n }\n }\n }\n }\n\n // Skip streaming progress messages when tool is already completed\n // The final tool_result message will show the complete output, avoiding duplicate display\n if (\n _.type === 'progress' &&\n 'type' in _.content &&\n _.content.type === 'streaming' &&\n !unresolvedToolUseIDs.has(_.toolUseID)\n ) {\n continue\n }\n\n // Normal message rendering\n const message =\n _.type === 'progress' ? (\n // Check if this is a streaming progress content (e.g., from BashTool)\n 'type' in _.content && _.content.type === 'streaming' ? (\n <BashStreamingProgress\n stdout={(_.content as StreamingProgressContent).stdout}\n stderr={(_.content as StreamingProgressContent).stderr}\n isStreaming={(_.content as StreamingProgressContent).isStreaming}\n />\n ) : (_.content as AssistantMessage).message.content[0]?.type ===\n 'text' &&\n // TaskTool interrupts use Progress messages without extra \u23BF\n // since <Message /> component already adds the margin\n (_.content as AssistantMessage).message.content[0].text ===\n INTERRUPT_MESSAGE ? (\n <Message\n message={_.content as AssistantMessage}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n ) : (\n <MessageResponse\n children={\n <Message\n message={_.content as AssistantMessage}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={\n new Set([\n (\n (_.content as AssistantMessage).message\n .content[0]! as ToolUseBlockParam\n ).id,\n ])\n }\n shouldAnimate={false}\n shouldShowDot={false}\n />\n }\n />\n )\n ) : (\n <Message\n message={_}\n messages={normalizedMessages}\n addMargin={true}\n tools={tools}\n verbose={verbose}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n shouldAnimate={\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n (!toolUseID || inProgressToolUseIDs.has(toolUseID))\n }\n shouldShowDot={true}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )\n\n const type = shouldRenderStatically(\n _,\n normalizedMessages,\n unresolvedToolUseIDs,\n )\n ? 'static'\n : 'transient'\n\n if (debug) {\n result.push({\n type,\n jsx: (\n <Box\n borderStyle=\"single\"\n borderColor={type === 'static' ? 'green' : 'red'}\n key={_.uuid}\n width=\"100%\"\n >\n {message}\n </Box>\n ),\n })\n } else {\n result.push({\n type,\n jsx: (\n <Box key={_.uuid} width=\"100%\">\n {message}\n </Box>\n ),\n })\n }\n }\n\n return result\n }, [\n forkNumber,\n normalizedMessages,\n tools,\n verbose,\n debug,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n toolJSX,\n toolUseConfirm,\n isMessageSelectorVisible,\n unresolvedToolUseIDs,\n mcpClients,\n isDefaultModel,\n isResumedConversation,\n // V1+ dependencies\n messageGroups,\n getGroupForMessage,\n getGroupForToolUse,\n shouldGroupBeStatic,\n displayConfig,\n agentTranscripts,\n toolOutputs,\n ])\n\n // only show the dialog once not loading\n const showingCostDialog = !isLoading && showCostDialog\n\n // Separate static and dynamic messages for proper Ink Static component usage\n // Static messages: completed messages that won't change - protected from Ink's clearTerminal\n // Dynamic messages: in-progress messages that need to re-render\n const { staticItems, dynamicItems } = useMemo(() => {\n const staticItems: StaticItem[] = []\n const dynamicItems: MessageJSXItem[] = []\n\n for (const item of messagesJSX) {\n if (item.type === 'static') {\n // Extract key from jsx element for Static component deduplication\n const key = item.jsx.key?.toString() || `static-${staticItems.length}`\n staticItems.push({ id: key, jsx: item.jsx })\n } else if (item.type === 'transient') {\n dynamicItems.push(item)\n }\n }\n\n return { staticItems, dynamicItems }\n }, [messagesJSX])\n\n // =========================================================================\n // Stable callback functions for PromptInput props\n // Using useCallback prevents memo invalidation on parent re-renders\n // =========================================================================\n\n // Toggle message selector visibility\n const handleShowMessageSelector = useCallback(() => {\n setIsMessageSelectorVisible(prev => !prev)\n }, [])\n\n // Toggle todo panel visibility\n const handleToggleTodoPanel = useCallback(() => {\n setIsTodoPanelVisible(prev => !prev)\n }, [])\n\n // Toggle background panel visibility\n const handleToggleBackgroundPanel = useCallback(() => {\n setShowBackgroundPanel(prev => !prev)\n }, [])\n\n // Handle model change (force re-render)\n const handleModelChange = useCallback(() => {\n setForkNumber(prev => prev + 1)\n }, [])\n\n // Verbose toggle handler - clear screen and force re-render\n // Must increment forkNumber to force Static component to re-render conversation history\n // Sets verboseToggleMessage to show feedback after PromptInput remounts\n //\n // Flow: Hide UI -> wait for empty render -> clear terminal -> update state -> restore UI\n // This prevents ghost artifacts from appearing during the transition\n const handleToggleVerbose = useCallback(async (newVerbose: boolean) => {\n // Set the feedback message BEFORE remount so it survives\n const message = `${getVerboseLabel(newVerbose)} (Ctrl+O)`\n setVerboseToggleMessage(message)\n // Clear after 2 seconds\n setTimeout(() => setVerboseToggleMessage(null), 2000)\n\n // Step 1: Hide all transient UI\n setIsResizeClearing(true)\n\n // Step 2: Wait for React to render the empty state\n await new Promise(resolve => setTimeout(resolve, 50))\n\n // Step 3: Clear the terminal to remove any ghost artifacts\n await clearTerminal()\n\n // Step 4: Update state and restore UI\n setVerbose(newVerbose)\n setForkNumber(prev => prev + 1)\n setIsResizeClearing(false)\n }, [])\n\n // Queue-aware onQuery handler - queues prompts when busy\n const handleQueueAwareQuery = useCallback(\n async (newMessages: MessageType[], abortController?: AbortController) => {\n // If not loading, process immediately\n if (!isLoading) {\n return onQuery(newMessages, abortController)\n }\n\n // Otherwise, extract the user prompt and queue it\n const userMessage = newMessages.find(m => m.type === 'user')\n if (userMessage && userMessage.type === 'user') {\n const promptText =\n typeof userMessage.message.content === 'string'\n ? userMessage.message.content\n : ''\n if (promptText) {\n setQueuedPrompts(prev => [...prev, promptText])\n }\n }\n },\n [isLoading],\n )\n\n // Process next queued prompt - called after current task completes\n useEffect(() => {\n processNextQueuedPromptRef.current = async () => {\n if (queuedPrompts.length === 0) return\n\n // Pop the first queued prompt\n const nextPrompt = queuedPrompts[0]\n setQueuedPrompts(prev => prev.slice(1))\n\n if (!nextPrompt) return\n\n // Process it like a normal user submission\n const userMessage: MessageType = {\n type: 'user',\n uuid: randomUUID(),\n message: {\n role: 'user',\n content: nextPrompt,\n },\n }\n\n // Start the query\n setIsLoading(true)\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n await onQuery([userMessage], newAbortController)\n }\n }, [queuedPrompts])\n\n return (\n <PermissionProvider\n isBypassPermissionsModeAvailable={!safeMode}\n children={\n <React.Fragment>\n {/* Update banner now renders inside Logo for stable placement */}\n {/* Wrap in fragment with key to ensure re-render on fullscreen exit */}\n <React.Fragment key={`mode-indicator-${forkNumber}`}>\n <ModeIndicator />\n </React.Fragment>\n {/*\n Static/Dynamic separation for proper Ink rendering:\n\n 1. Static messages use Ink's <Static> component:\n - Content written to terminal is PRESERVED (not cleared by Ink)\n - Items are deduped by `id` - same id = same output\n - Perfect for: completed messages, finished tool results\n\n 2. Dynamic messages render normally (below Static):\n - Can be re-rendered without affecting static content above\n - Used for: in-progress tools, current interaction\n\n This architecture solves the clearTerminal issue:\n - When outputHeight >= terminal rows, Ink calls clearTerminal + re-render\n - But Static content is already written to terminal, not affected by this\n - Only dynamic content below gets cleared and re-rendered\n */}\n {/* STATIC SECTION: Completed messages protected from Ink's clearTerminal */}\n {/* Note: Static component uses forkNumber in fragment key to force rebuild on verbose toggle */}\n <React.Fragment key={`static-wrapper-${forkNumber}`}>\n <Static<StaticItem>\n items={staticItems}\n children={item => (\n <React.Fragment key={item.id}>{item.jsx}</React.Fragment>\n )}\n />\n </React.Fragment>\n\n {/* DYNAMIC SECTION: In-progress content that can re-render */}\n <React.Fragment key={`dynamic-messages-${forkNumber}`}>\n {/* Render transient items */}\n {dynamicItems.map(item => item.jsx)}\n </React.Fragment>\n {/*\n IMPORTANT: Key prop tied to forkNumber ensures all transient UI components\n are properly re-rendered when exiting fullscreen mode. This prevents ghost\n artifacts from appearing when the terminal shrinks significantly.\n See useFullscreenExitCallback above which increments forkNumber on fullscreen exit.\n */}\n <Box\n key={`transient-ui-${forkNumber}`}\n borderColor=\"red\"\n borderStyle={debug ? 'single' : undefined}\n flexDirection=\"column\"\n width=\"100%\"\n >\n {/* Unified Spinner + TodoPanel - shows when loading OR when there are incomplete todos */}\n {/* Hidden during resize clearing to prevent ghost artifacts */}\n {!isResizeClearing &&\n !toolJSX &&\n !toolUseConfirm &&\n !binaryFeedbackContext && (\n <TodoPanel\n todos={getTodos()}\n isVisible={isTodoPanelVisible}\n isLoading={isLoading}\n showTodoList={isTodoPanelVisible}\n />\n )}\n {/* Turn completion indicator - shows \"Cogitated for Xm Ys\" after AI turn completes */}\n {!isResizeClearing &&\n !isLoading &&\n !toolJSX &&\n !toolUseConfirm &&\n !binaryFeedbackContext && (\n <TurnCompletionIndicator\n durationMs={lastTurnDurationMs}\n isVisible={lastTurnDurationMs !== null}\n />\n )}\n {toolJSX ? toolJSX.jsx : null}\n {!toolJSX && binaryFeedbackContext && !isMessageSelectorVisible && (\n <BinaryFeedback\n m1={binaryFeedbackContext.m1}\n m2={binaryFeedbackContext.m2}\n resolve={result => {\n binaryFeedbackContext.resolve(result)\n setTimeout(() => setBinaryFeedbackContext(null), 0)\n }}\n verbose={verbose}\n normalizedMessages={normalizedMessages}\n tools={tools}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )}\n {!toolJSX &&\n toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext && (\n <PermissionRequest\n toolUseConfirm={toolUseConfirm}\n onDone={() => setToolUseConfirm(null)}\n verbose={verbose}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n askUserQuestionContext && (\n <AskUserQuestionDialog\n context={askUserQuestionContext}\n onDone={() => setAskUserQuestionContext(null)}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext &&\n showingCostDialog && (\n <CostThresholdDialog\n onDone={() => {\n setShowCostDialog(false)\n setHaveShownCostDialog(true)\n const projectConfig = getGlobalConfig()\n saveGlobalConfig({\n ...projectConfig,\n hasAcknowledgedCostThreshold: true,\n })\n }}\n />\n )}\n\n {!toolUseConfirm &&\n !toolJSX?.shouldHidePromptInput &&\n shouldShowPromptInput &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext &&\n !showingCostDialog && (\n <>\n {/* BackgroundTasksPanel */}\n <BackgroundTasksPanel\n shells={backgroundShells}\n isVisible={showBackgroundPanel}\n onSelect={shell => {\n // View shell details (could show detailed output)\n setShowBackgroundPanel(false)\n }}\n onKill={shell => {\n BackgroundShellManager.getInstance().kill(shell.id)\n }}\n onClose={() => setShowBackgroundPanel(false)}\n />\n <PromptInput\n commands={commands}\n forkNumber={forkNumber}\n messageLogName={messageLogName}\n tools={tools}\n isDisabled={apiKeyStatus === 'invalid'}\n isLoading={isLoading}\n onQuery={onQuery}\n debug={debug}\n verbose={verbose}\n verboseToggleMessage={verboseToggleMessage}\n messages={messages}\n setToolJSX={setToolJSX}\n input={inputValue}\n onInputChange={setInputValue}\n mode={inputMode}\n onModeChange={setInputMode}\n submitCount={submitCount}\n onSubmitCountChange={setSubmitCount}\n setIsLoading={setIsLoading}\n setAbortController={setAbortController}\n onShowMessageSelector={handleShowMessageSelector}\n setForkConvoWithMessagesOnTheNextRender={\n setForkConvoWithMessagesOnTheNextRender\n }\n readFileTimestamps={readFileTimestamps.current}\n abortController={abortController}\n onModelChange={handleModelChange}\n onRollbackConversation={rollbackConversation}\n onToggleTodoPanel={handleToggleTodoPanel}\n onToggleVerbose={handleToggleVerbose}\n onToggleBackgroundPanel={handleToggleBackgroundPanel}\n backgroundShellCount={\n backgroundShells.filter(s => s.status === 'running')\n .length\n }\n isBackgroundPanelOpen={showBackgroundPanel}\n fallbackMode={fallbackMode}\n queuedPrompts={queuedPrompts}\n onQueuePrompt={prompt =>\n setQueuedPrompts(prev => [...prev, prompt])\n }\n onPopQueuedPrompt={() => {\n if (queuedPrompts.length === 0) return undefined\n const lastPrompt = queuedPrompts[queuedPrompts.length - 1]\n setQueuedPrompts(prev => prev.slice(0, -1))\n return lastPrompt\n }}\n onInterrupt={onInterrupt}\n />\n </>\n )}\n </Box>\n {isMessageSelectorVisible && (\n <React.Fragment key={`message-selector-wrapper-${forkNumber}`}>\n <MessageSelector\n erroredToolUseIDs={erroredToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n messages={normalizeMessagesForAPI(messages)}\n onSelect={async message => {\n setIsMessageSelectorVisible(false)\n\n // If the user selected the current prompt, do nothing\n if (!messages.includes(message)) {\n return\n }\n\n // Cancel tool use calls/requests\n onCancel()\n\n // Hack: make sure the \"Interrupted by user\" message is\n // rendered in response to the cancellation. Otherwise,\n // the screen will be cleared but there will remain a\n // vestigial \"Interrupted by user\" message at the top.\n setImmediate(async () => {\n // Clear messages, and re-render\n await clearTerminal()\n setMessages([])\n setForkConvoWithMessagesOnTheNextRender(\n messages.slice(0, messages.indexOf(message)),\n )\n\n // Populate/reset the prompt input\n if (typeof message.message.content === 'string') {\n setInputValue(message.message.content)\n }\n })\n }}\n onEscape={() => setIsMessageSelectorVisible(false)}\n tools={tools}\n />\n </React.Fragment>\n )}\n {/** Fix occasional rendering artifact */}\n <Newline />\n </React.Fragment>\n }\n />\n )\n}\n\nfunction shouldRenderStatically(\n message: NormalizedMessage,\n messages: NormalizedMessage[],\n unresolvedToolUseIDs: Set<string>,\n): boolean {\n switch (message.type) {\n case 'user':\n case 'assistant': {\n const toolUseID = getToolUseID(message)\n if (!toolUseID) {\n return true\n }\n if (unresolvedToolUseIDs.has(toolUseID)) {\n return false\n }\n // Phase 2.1: Removed delay - immediately mark as static when resolved\n\n const correspondingProgressMessage = messages.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n ) as ProgressMessage | null\n if (!correspondingProgressMessage) {\n return true\n }\n\n return !intersects(\n unresolvedToolUseIDs,\n correspondingProgressMessage.siblingToolUseIDs,\n )\n }\n case 'progress':\n // Phase 2.1: Immediately mark as static when resolved - no delay\n return !intersects(unresolvedToolUseIDs, message.siblingToolUseIDs)\n }\n}\n\nfunction intersects<A>(a: Set<A>, b: Set<A>): boolean {\n return a.size > 0 && b.size > 0 && [...a].some(_ => b.has(_))\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n ToolUseBlockParam,\n ToolResultBlockParam,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Box, Newline, Static, Text, useApp } from 'ink'\nimport ProjectOnboarding, {\n markProjectOnboardingComplete,\n} from '@components/ProjectOnboarding'\nimport type { SafetyMode } from '@utils/config'\nimport { CostThresholdDialog } from '@components/CostThresholdDialog'\nimport * as React from 'react'\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react'\nimport { Command } from '@commands'\nimport { Logo } from '@components/Logo'\nimport { Message } from '@components/Message'\nimport { MessageResponse } from '@components/MessageResponse'\nimport { BashStreamingProgress } from '@components/BashStreamingProgress'\nimport { MessageSelector } from '@components/MessageSelector'\nimport { MessageBatchBuffer } from '@utils/MessageBatchBuffer'\nimport {\n PermissionRequest,\n type ToolUseConfirm,\n} from '@components/permissions/PermissionRequest'\nimport PromptInput from '@components/PromptInput'\nimport { getSystemPrompt } from '@constants/prompts'\nimport { getContext } from '@context'\nimport { getTotalCost, useCostSummary } from '@costTracker'\nimport { useLogStartupTime } from '@hooks/useLogStartupTime'\nimport { addToHistory } from '@history'\nimport { useApiKeyVerification } from '@hooks/useApiKeyVerification'\n// useCancelRequest removed - ESC interrupt logic consolidated into onInterrupt callback\nimport useCanUseTool from '@hooks/useCanUseTool'\nimport { useLogMessages, serializeMessageForLog } from '@hooks/useLogMessages'\nimport { overwriteLog } from '@utils/log'\nimport { PermissionProvider } from '@context/PermissionContext'\nimport { useFullscreenExitCallback } from '@hooks/useTerminalSize'\nimport { ModeIndicator } from '@components/ModeIndicator'\nimport { TodoPanel } from '@components/TodoPanel'\nimport { TurnCompletionIndicator } from '@components/TurnCompletionIndicator'\nimport { getTodos, initTodoSession } from '@utils/todoStorage'\nimport {\n setMessagesGetter,\n setMessagesSetter,\n setModelConfigChangeHandler,\n setLanguageChangeHandler,\n} from '@messages'\nimport {\n type AssistantMessage,\n type BinaryFeedbackResult,\n type Message as MessageType,\n type ProgressMessage,\n type StreamingProgressContent,\n query,\n} from '@query'\nimport type { WrappedClient } from '@services/mcpClient'\nimport type { Tool } from '@tool'\n// Auto-updater removed; only show a new version banner passed from CLI\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n getVerboseLabel,\n} from '@utils/config'\nimport { MACRO } from '@constants/macros'\nimport { getNextAvailableLogForkNumber } from '@utils/log'\nimport {\n getErroredToolUseMessages,\n getInProgressToolUseIDs,\n getLastAssistantMessageId,\n getToolUseID,\n getUnresolvedToolUseIDs,\n INTERRUPT_MESSAGE,\n isNotEmptyMessage,\n type NormalizedMessage,\n normalizeMessages,\n normalizeMessagesForAPI,\n processUserInput,\n reorderMessages,\n extractTag,\n createAssistantMessage,\n createAssistantAPIErrorMessage,\n} from '@utils/messages'\nimport { logError } from '@utils/log'\nimport { getModelManager, ModelManager } from '@utils/model'\nimport { clearTerminal, updateTerminalTitle } from '@utils/terminal'\nimport { BinaryFeedback } from '@components/binary-feedback/BinaryFeedback'\nimport { getMaxThinkingTokens } from '@utils/thinking'\nimport { getOriginalCwd } from '@utils/state'\nimport { handleHashCommand } from '@commands/terminalSetup'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport {\n initializeHookManager,\n getHookManager,\n type HookManager,\n} from '@utils/hookManager'\nimport { loadAllPlugins } from '@utils/pluginLoader'\nimport { randomUUID } from 'crypto'\nimport { getMessagesPath } from '@utils/log'\nimport {\n BackgroundShellManager,\n type BackgroundShell,\n} from '@utils/BackgroundShellManager'\nimport { BackgroundTasksPanel } from '@components/BackgroundTasksPanel'\nimport { AskUserQuestionDialog } from '@components/AskUserQuestionDialog/AskUserQuestionDialog'\nimport {\n getToolUseIdByAgentId,\n getAgentIdByToolUseId,\n restoreToolUseAgentMappings,\n} from '@utils/agentTranscripts'\nimport type { AskUserQuestionContext } from '@minto-types/askUserQuestion'\nimport useAskUser from '@hooks/useAskUser'\n// V1+ hierarchical message display imports\nimport { useMessageGroups } from '@hooks/useMessageGroups'\nimport { useAgentTranscripts } from '@hooks/useAgentTranscripts'\nimport { GroupRenderer } from '@components/messages/GroupRenderer'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport {\n initSessionTracker,\n recordFirstPrompt,\n incrementMessageCount,\n incrementToolCallCount,\n flushSessionStats,\n endSession,\n getSessionId,\n} from '@utils/sessionTracker'\n\n// Maximum number of recent messages to display when resuming a conversation\n// Set to Infinity to show all messages (user can scroll to see earlier ones)\nconst RESUME_VISIBLE_MESSAGE_COUNT = Infinity\n\ntype Props = {\n commands: Command[]\n /** @deprecated Use safetyMode instead */\n safeMode?: boolean\n /** Safety mode: 'yolo' | 'smart' | 'strict' */\n safetyMode?: SafetyMode\n debug?: boolean\n initialForkNumber?: number | undefined\n initialPrompt: string | undefined\n // A unique name for the message log file, used to identify the fork\n messageLogName: string\n shouldShowPromptInput: boolean\n tools: Tool[]\n /**\n * Verbose mode: shows full parameters and complete outputs when enabled\n */\n verbose?: boolean | undefined\n // Initial messages to populate the REPL with\n initialMessages?: MessageType[]\n // MCP clients\n mcpClients?: WrappedClient[]\n // Flag to indicate if current model is default\n isDefaultModel?: boolean\n // Update banner info passed from CLI before first render\n initialUpdateVersion?: string | null\n initialUpdateCommands?: string[] | null\n // Whether to use limited input mode (raw mode not supported)\n fallbackMode?: boolean\n // Whether this is a resumed conversation (shows collapsed history indicator)\n isResumedConversation?: boolean\n}\n\nexport type BinaryFeedbackContext = {\n m1: AssistantMessage\n m2: AssistantMessage\n resolve: (result: BinaryFeedbackResult) => void\n}\n\nexport function REPL({\n commands,\n safeMode,\n safetyMode = 'yolo',\n debug = false,\n initialForkNumber = 0,\n initialPrompt,\n messageLogName,\n shouldShowPromptInput,\n tools,\n verbose: verboseFromCLI,\n initialMessages,\n mcpClients = [],\n isDefaultModel = true,\n initialUpdateVersion,\n initialUpdateCommands,\n fallbackMode = false,\n isResumedConversation = false,\n}: Props): React.ReactNode {\n // Verbose mode state - can be toggled at runtime with Ctrl+O\n // Default to normal mode (false), only use verbose if explicitly set via CLI\n const [verbose, setVerbose] = useState<boolean>(\n verboseFromCLI === true ? true : false,\n )\n\n // Used to force the logo to re-render and conversation log to use a new file\n const [forkNumber, setForkNumber] = useState(\n getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0),\n )\n\n // State to temporarily hide transient UI during resize to prevent ghost artifacts\n const [isResizeClearing, setIsResizeClearing] = useState(false)\n\n // Get exit function from Ink for unmounting (used by /resume command)\n const { exit: unmountREPL } = useApp()\n\n // Re-render UI when significant resize occurs to clear ghost artifacts\n // Strategy: Hide transient UI -> clear terminal -> restore UI\n useFullscreenExitCallback(async () => {\n // Step 1: Hide all transient UI by setting clearing state\n setIsResizeClearing(true)\n\n // Step 2: Wait a frame for React to render the empty state\n await new Promise(resolve => setTimeout(resolve, 50))\n\n // Step 3: Clear the terminal to remove any ghost artifacts\n await clearTerminal()\n\n // Step 4: Increment forkNumber and restore UI\n setForkNumber(prev => prev + 1)\n setIsResizeClearing(false)\n })\n\n const [\n forkConvoWithMessagesOnTheNextRender,\n setForkConvoWithMessagesOnTheNextRender,\n ] = useState<MessageType[] | null>(null)\n\n // \uD83D\uDD27 Simplified AbortController management - inspired by reference system\n const [abortController, setAbortController] =\n useState<AbortController | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n // No auto-updater state\n const [toolJSX, setToolJSX] = useState<{\n jsx: React.ReactNode | null\n shouldHidePromptInput: boolean\n } | null>(null)\n const [toolUseConfirm, setToolUseConfirm] = useState<ToolUseConfirm | null>(\n null,\n )\n const [messages, setMessages] = useState<MessageType[]>(initialMessages ?? [])\n // Ref to track latest messages for synchronous access in onInterrupt\n // This ensures we can save messages even when React state updates are pending\n const messagesRef = useRef<MessageType[]>(initialMessages ?? [])\n // Phase 4.1: Message history stack for Esc Esc rollback\n const [messageHistory, setMessageHistory] = useState<MessageType[][]>([])\n const [inputValue, setInputValue] = useState('')\n const [inputMode, setInputMode] = useState<'bash' | 'prompt' | 'koding'>(\n 'prompt',\n )\n const [submitCount, setSubmitCount] = useState(0)\n const [isMessageSelectorVisible, setIsMessageSelectorVisible] =\n useState(false)\n const [showCostDialog, setShowCostDialog] = useState(false)\n const [haveShownCostDialog, setHaveShownCostDialog] = useState(\n getGlobalConfig().hasAcknowledgedCostThreshold,\n )\n\n const [binaryFeedbackContext, setBinaryFeedbackContext] =\n useState<BinaryFeedbackContext | null>(null)\n const [askUserQuestionContext, setAskUserQuestionContext] =\n useState<AskUserQuestionContext | null>(null)\n // New version banner: passed in from CLI to guarantee top placement\n const updateAvailableVersion = initialUpdateVersion ?? null\n const updateCommands = initialUpdateCommands ?? null\n // No separate Static for banner; it renders inside Logo\n\n // TodoPanel state\n const [isTodoPanelVisible, setIsTodoPanelVisible] = useState(true)\n\n // Verbose toggle feedback message - survives PromptInput remount\n const [verboseToggleMessage, setVerboseToggleMessage] = useState<\n string | null\n >(null)\n\n // Turn duration tracking for \"Cogitated\" display\n const turnStartTimeRef = useRef<number | null>(null)\n const [lastTurnDurationMs, setLastTurnDurationMs] = useState<number | null>(\n null,\n )\n\n // Waiting list: queued messages to process after current task completes\n const [queuedPrompts, setQueuedPrompts] = useState<string[]>([])\n // Ref to track latest queued prompts (avoid stale closure issues)\n const queuedPromptsRef = useRef<string[]>([])\n useEffect(() => {\n queuedPromptsRef.current = queuedPrompts\n }, [queuedPrompts])\n\n // Track turn duration for \"Cogitated\" display\n useEffect(() => {\n if (isLoading) {\n // Turn started - record start time, clear previous duration\n turnStartTimeRef.current = Date.now()\n setLastTurnDurationMs(null)\n } else if (turnStartTimeRef.current !== null) {\n // Turn ended - calculate and store duration\n const duration = Date.now() - turnStartTimeRef.current\n setLastTurnDurationMs(duration)\n turnStartTimeRef.current = null\n }\n }, [isLoading])\n\n // Background tasks state\n const [backgroundShells, setBackgroundShells] = useState<BackgroundShell[]>(\n [],\n )\n const [showBackgroundPanel, setShowBackgroundPanel] = useState(false)\n\n // Phase 2.1: Removed recentlyCompletedIDs state - immediate static rendering for better performance\n const prevUnresolvedRef = useRef<Set<string>>(new Set())\n\n // Message batch buffer to eliminate flicker from rapid successive updates\n const messageBatchBufferRef = useRef<MessageBatchBuffer | null>(null)\n\n // Initialize batch buffer on first render\n if (messageBatchBufferRef.current === null) {\n messageBatchBufferRef.current = new MessageBatchBuffer(\n batchedMessages => {\n setMessages(prev => [...prev, ...batchedMessages])\n },\n {\n flushInterval: 100, // Batch messages for 100ms\n maxBatchSize: 50, // Force flush if 50+ messages buffered\n debug: false, // Set to true for debugging\n },\n )\n }\n\n // Cleanup buffer on unmount\n useEffect(() => {\n return () => {\n messageBatchBufferRef.current?.dispose()\n }\n }, [])\n\n const getBinaryFeedbackResponse = useCallback(\n (\n m1: AssistantMessage,\n m2: AssistantMessage,\n ): Promise<BinaryFeedbackResult> => {\n return new Promise<BinaryFeedbackResult>(resolvePromise => {\n setBinaryFeedbackContext({\n m1,\n m2,\n resolve: resolvePromise,\n })\n })\n },\n [],\n )\n\n const readFileTimestamps = useRef<{\n [filename: string]: number\n }>({})\n\n // Hook manager for plugin hooks\n const hookManagerRef = useRef<HookManager | null>(null)\n\n const { status: apiKeyStatus, reverify } = useApiKeyVerification()\n // Unified interrupt handler - called by PromptInput when ESC is pressed with empty input\n // Consolidates all cleanup logic in one place (no separate useCancelRequest hook needed)\n function onInterrupt() {\n if (!isLoading) {\n return\n }\n\n // \uD83D\uDD27 Force save messages before interrupt to prevent conversation loss\n // This is critical because React's useEffect-based saving might not run\n // in time when state changes rapidly during interrupt\n const currentMessages = messagesRef.current\n if (currentMessages.length > 0) {\n const serializedMessages = currentMessages.map(serializeMessageForLog)\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, 0),\n serializedMessages,\n )\n }\n\n // Clean up UI state\n setToolJSX(null)\n setToolUseConfirm(null)\n setBinaryFeedbackContext(null)\n setIsLoading(false)\n // Abort the request\n if (toolUseConfirm) {\n toolUseConfirm.onAbort()\n } else if (abortController && !abortController.signal.aborted) {\n abortController.abort()\n }\n }\n\n // Legacy onCancel for other callers (e.g., PermissionRequest)\n function onCancel() {\n onInterrupt()\n }\n\n useEffect(() => {\n if (forkConvoWithMessagesOnTheNextRender) {\n setForkNumber(_ => _ + 1)\n setForkConvoWithMessagesOnTheNextRender(null)\n setMessages(forkConvoWithMessagesOnTheNextRender)\n }\n }, [forkConvoWithMessagesOnTheNextRender])\n\n useEffect(() => {\n const totalCost = getTotalCost()\n if (totalCost >= 5 /* $5 */ && !showCostDialog && !haveShownCostDialog) {\n setShowCostDialog(true)\n }\n }, [messages, showCostDialog, haveShownCostDialog])\n\n // Update banner is provided by CLI at startup; no async check here.\n\n const canUseTool = useCanUseTool(setToolUseConfirm)\n const askUser = useAskUser(setAskUserQuestionContext)\n\n async function onInit() {\n reverify()\n\n if (!initialPrompt) {\n return\n }\n\n setIsLoading(true)\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n try {\n // \uD83D\uDD27 Force fresh config read to ensure model switching works\n const model = new ModelManager(getGlobalConfig()).getModelName('main')\n const newMessages = await processUserInput(\n initialPrompt,\n 'prompt',\n setToolJSX,\n {\n abortController: newAbortController,\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n maxThinkingTokens: 0,\n },\n messageId: getLastAssistantMessageId(messages),\n setForkConvoWithMessagesOnTheNextRender,\n readFileTimestamps: readFileTimestamps.current,\n },\n null,\n )\n\n if (newMessages.length) {\n for (const message of newMessages) {\n if (message.type === 'user') {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n }\n setMessages(_ => [..._, ...newMessages])\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n if (lastMessage.type === 'assistant') {\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, ...newMessages]),\n ])\n\n for await (const message of query(\n [...messages, ...newMessages],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n safetyMode,\n maxThinkingTokens,\n },\n messageId: getLastAssistantMessageId([...messages, ...newMessages]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: newAbortController,\n setToolJSX,\n askUser,\n },\n getBinaryFeedbackResponse,\n )) {\n // Use batch buffer to reduce render frequency\n messageBatchBufferRef.current?.add(message)\n }\n\n // Flush any remaining buffered messages immediately after query completes\n messageBatchBufferRef.current?.flush()\n } else {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n\n setHaveShownCostDialog(\n getGlobalConfig().hasAcknowledgedCostThreshold || false,\n )\n } catch (error) {\n // \uD83D\uDD27 Fix: Handle errors gracefully and show error to user\n logError(error)\n setMessages(oldMessages => [\n ...oldMessages,\n createAssistantAPIErrorMessage(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n ),\n ])\n } finally {\n // \uD83D\uDD27 Fix: Always clean up state, even on error\n setIsLoading(false)\n setAbortController(null)\n }\n }\n\n // Phase 4.1: Rollback to previous message state\n function rollbackConversation(): boolean {\n if (messageHistory.length === 0) {\n return false // No history to rollback to\n }\n\n // Pop the last snapshot and restore it\n const previousMessages = messageHistory[messageHistory.length - 1]!\n setMessages(previousMessages)\n setMessageHistory(history => history.slice(0, -1))\n\n return true // Successfully rolled back\n }\n\n // Process the next queued prompt (called after current task completes)\n // This is defined as a ref to avoid stale closure issues\n const processNextQueuedPromptRef = useRef<(() => Promise<void>) | null>(null)\n\n async function onQuery(\n newMessages: MessageType[],\n passedAbortController?: AbortController,\n ) {\n // Use passed AbortController or create new one\n const controllerToUse = passedAbortController || new AbortController()\n if (!passedAbortController) {\n setAbortController(controllerToUse)\n }\n // \uD83D\uDD27 Fix: Always set isLoading to true at the start\n setIsLoading(true)\n\n // Reset verbose mode to normal when user starts new task\n // User can manually enable verbose with Ctrl+O during task execution\n setVerbose(false)\n\n // Check if this is a Koding request based on last message's options\n const isKodingRequest =\n newMessages.length > 0 &&\n newMessages[0].type === 'user' &&\n 'options' in newMessages[0] &&\n newMessages[0].options?.isKodingRequest === true\n\n // Phase 4.1: Save message history snapshot before adding new messages\n setMessages(oldMessages => {\n // Save current state to history stack (limit to last 10 snapshots)\n setMessageHistory(history => [...history, oldMessages].slice(-10))\n return [...oldMessages, ...newMessages]\n })\n\n // Mark onboarding as complete when any user message is sent to the assistant\n markProjectOnboardingComplete()\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n\n // Track session: record first prompt and increment message count\n if (\n lastMessage.type === 'user' &&\n typeof lastMessage.message.content === 'string'\n ) {\n // Record first prompt for session tracking (no-op if already recorded)\n recordFirstPrompt(lastMessage.message.content)\n // Increment message count for this user message\n incrementMessageCount(1)\n }\n\n // Update terminal title based on user message\n if (\n lastMessage.type === 'user' &&\n typeof lastMessage.message.content === 'string'\n ) {\n // updateTerminalTitle(lastMessage.message.content)\n }\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n try {\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, lastMessage]),\n ])\n\n let lastAssistantMessage: MessageType | null = null\n\n // query the API\n for await (const message of query(\n [...messages, lastMessage],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n safetyMode,\n maxThinkingTokens,\n // If this came from Koding mode, pass that along\n isKodingRequest: isKodingRequest || undefined,\n },\n messageId: getLastAssistantMessageId([...messages, lastMessage]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: controllerToUse,\n setToolJSX,\n askUser,\n },\n getBinaryFeedbackResponse,\n )) {\n // Use batch buffer to reduce render frequency\n messageBatchBufferRef.current?.add(message)\n\n // Keep track of the last assistant message for Koding mode\n if (message.type === 'assistant') {\n lastAssistantMessage = message\n // Track assistant message count\n incrementMessageCount(1)\n\n // Track tool calls in assistant messages\n if (Array.isArray(message.message.content)) {\n const toolUseCount = message.message.content.filter(\n block => typeof block === 'object' && block.type === 'tool_use',\n ).length\n if (toolUseCount > 0) {\n incrementToolCallCount(toolUseCount)\n }\n }\n }\n }\n\n // If this was a Koding request and we got an assistant message back,\n // save it to MINTO.md (and CLAUDE.md if exists)\n if (\n isKodingRequest &&\n lastAssistantMessage &&\n lastAssistantMessage.type === 'assistant'\n ) {\n try {\n const content =\n typeof lastAssistantMessage.message.content === 'string'\n ? lastAssistantMessage.message.content\n : lastAssistantMessage.message.content\n .filter(block => block.type === 'text')\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n\n // Add the content to MINTO.md (and CLAUDE.md if exists)\n if (content && content.trim().length > 0) {\n handleHashCommand(content)\n }\n } catch (error) {\n console.error('Error saving response to project docs:', error)\n }\n }\n\n // Flush any remaining buffered messages immediately after query completes\n messageBatchBufferRef.current?.flush()\n } catch (error) {\n // \uD83D\uDD27 Fix: Handle errors gracefully and show error to user\n logError(error)\n\n // Flush buffer before showing error to ensure all messages are visible\n messageBatchBufferRef.current?.flush()\n setMessages(oldMessages => [\n ...oldMessages,\n createAssistantAPIErrorMessage(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n ),\n ])\n } finally {\n // \uD83D\uDD27 Fix: Always clean up state, even on error\n setIsLoading(false)\n setAbortController(null)\n\n // Flush session stats after each turn completes\n flushSessionStats()\n\n // Process next queued prompt if any (waiting list feature)\n if (queuedPromptsRef.current.length > 0) {\n // Use setTimeout to allow state to settle before processing next\n setTimeout(() => {\n if (processNextQueuedPromptRef.current) {\n processNextQueuedPromptRef.current()\n }\n }, 100)\n }\n }\n }\n\n // Register cost summary tracker\n useCostSummary()\n\n // Register messages getter and setter\n useEffect(() => {\n const getMessages = () => messages\n setMessagesGetter(getMessages)\n setMessagesSetter(setMessages)\n }, [messages])\n\n // Initialize todo session with unique identifier\n // Using messageLogName + forkNumber as session ID to ensure:\n // 1. Each conversation has its own todo list\n // 2. Resumed conversations restore their todos\n useEffect(() => {\n const todoSessionId = `${messageLogName}-${forkNumber}`\n initTodoSession(todoSessionId)\n\n // Restore transcript mappings for history restore\n // This enables proper display of Task tool results from previous sessions\n if (initialMessages && initialMessages.length > 0) {\n restoreToolUseAgentMappings()\n }\n }, [messageLogName, forkNumber, initialMessages])\n\n // Register model config change handler for UI refresh\n useEffect(() => {\n setModelConfigChangeHandler(() => {\n setForkNumber(prev => prev + 1)\n })\n }, [])\n\n // Register language change handler for UI refresh\n // Uses the same flow as verbose toggle: hide UI -> wait -> clear terminal -> re-render\n useEffect(() => {\n setLanguageChangeHandler(async () => {\n // Step 1: Hide all transient UI to prevent ghost artifacts\n setIsResizeClearing(true)\n\n // Step 2: Wait for React to render the empty state\n await new Promise(resolve => setTimeout(resolve, 50))\n\n // Step 3: Clear the terminal\n await clearTerminal()\n\n // Step 4: Trigger re-render and restore UI\n setForkNumber(prev => prev + 1)\n setIsResizeClearing(false)\n })\n }, [])\n\n // Keep messagesRef in sync with messages state for synchronous access\n useEffect(() => {\n messagesRef.current = messages\n }, [messages])\n\n // Record transcripts locally, for debugging and conversation recovery\n useLogMessages(messages, messageLogName, forkNumber)\n\n // Log startup time\n useLogStartupTime()\n\n // Initial load\n useEffect(() => {\n onInit()\n // TODO: fix this\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Initialize hook manager and session tracker\n useEffect(() => {\n try {\n const plugins = loadAllPlugins()\n const sessionId = randomUUID()\n const transcriptPath = getMessagesPath(messageLogName, forkNumber, 0)\n\n const hookManager = initializeHookManager(\n sessionId,\n transcriptPath,\n plugins,\n )\n hookManagerRef.current = hookManager\n\n // Initialize session tracker with the same sessionId\n initSessionTracker(getOriginalCwd())\n\n // Execute SessionStart hooks\n hookManager.executeSessionStart().catch(err => {\n debugLogger.error('SessionStart hooks failed', { error: err })\n })\n\n // Cleanup: Execute SessionEnd hooks and end session tracking\n return () => {\n // Flush session stats before ending\n flushSessionStats()\n endSession('other')\n\n hookManager.executeSessionEnd('other').catch(err => {\n debugLogger.error('SessionEnd hooks failed', { error: err })\n })\n }\n } catch (err) {\n debugLogger.error('Failed to initialize hook manager', { error: err })\n }\n }, [messageLogName, forkNumber])\n\n // Update background shells using event-driven approach (no polling)\n useEffect(() => {\n const manager = BackgroundShellManager.getInstance()\n // Initialize with current list\n setBackgroundShells(manager.list())\n\n // Subscribe to list changes\n const handleListChange = (shells: BackgroundShell[]) => {\n setBackgroundShells(shells)\n }\n manager.on('listChange', handleListChange)\n\n return () => {\n manager.off('listChange', handleListChange)\n }\n }, [])\n\n // Optimize: Cache normalized messages and only recompute when messages actually change\n // This useMemo will only rerun when the messages array reference changes\n const normalizedMessages = useMemo(\n () => normalizeMessages(messages).filter(isNotEmptyMessage),\n [messages],\n )\n\n const unresolvedToolUseIDs = useMemo(\n () => getUnresolvedToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n // Phase 2.1: Removed 300ms delay useEffect - immediate static rendering\n // Update prevUnresolvedRef when unresolvedToolUseIDs changes\n useEffect(() => {\n prevUnresolvedRef.current = new Set(unresolvedToolUseIDs)\n }, [unresolvedToolUseIDs])\n\n const inProgressToolUseIDs = useMemo(\n () => getInProgressToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const erroredToolUseIDs = useMemo(\n () =>\n new Set(\n getErroredToolUseMessages(normalizedMessages).map(\n _ => (_.message.content[0]! as ToolUseBlockParam).id,\n ),\n ),\n [normalizedMessages],\n )\n\n // V1+ Message Groups - identifies parallel task groups for unified rendering\n const {\n groups: messageGroups,\n getGroupForMessage,\n getGroupForToolUse,\n shouldGroupBeStatic,\n displayConfig,\n } = useMessageGroups(\n normalizedMessages,\n unresolvedToolUseIDs,\n inProgressToolUseIDs,\n verbose,\n )\n\n // V1+ Agent Transcripts - real-time transcript access for task display\n // getTranscript enables lazy loading from disk for historical messages\n const { transcripts: agentTranscripts, getTranscript } = useAgentTranscripts()\n\n // V1+ Tool outputs map for group rendering\n const toolOutputs = useMemo(() => {\n const outputs = new Map<string, ToolResultBlockParam>()\n for (const msg of normalizedMessages) {\n if (msg.type === 'user' && msg.message.role === 'user') {\n for (const block of msg.message.content) {\n if (typeof block === 'object' && block.type === 'tool_result') {\n outputs.set(block.tool_use_id, block as ToolResultBlockParam)\n }\n }\n }\n }\n return outputs\n }, [normalizedMessages])\n\n // Type for message JSX items - pre-rendered JSX with static/transient type\n type MessageJSXItem = {\n type: 'static' | 'transient'\n jsx: React.ReactElement\n }\n\n // Static item type for Ink's Static component (requires id for deduplication)\n type StaticItem = { id: string; jsx: React.ReactElement }\n\n const messagesJSX = useMemo(() => {\n const reorderedMessages = reorderMessages(normalizedMessages)\n\n // Calculate how many messages to hide when resuming a conversation\n const hiddenMessageCount =\n isResumedConversation &&\n reorderedMessages.length > RESUME_VISIBLE_MESSAGE_COUNT\n ? reorderedMessages.length - RESUME_VISIBLE_MESSAGE_COUNT\n : 0\n\n // Only show recent messages when resuming, but keep all messages in memory for context\n const visibleMessages =\n hiddenMessageCount > 0\n ? reorderedMessages.slice(-RESUME_VISIBLE_MESSAGE_COUNT)\n : reorderedMessages\n\n // Build the result array\n const result: MessageJSXItem[] = [\n {\n type: 'static',\n jsx: (\n <Box flexDirection=\"column\" width=\"100%\" key=\"logo\">\n <Logo\n mcpClients={mcpClients}\n isDefaultModel={isDefaultModel}\n updateBannerVersion={updateAvailableVersion}\n updateBannerCommands={updateCommands}\n />\n <ProjectOnboarding workspaceDir={getOriginalCwd()} />\n </Box>\n ),\n },\n ]\n\n // Show collapsed history indicator when resuming with hidden messages\n if (hiddenMessageCount > 0) {\n result.push({\n type: 'static' as const,\n jsx: (\n <Box key=\"collapsed-history\" paddingLeft={2} marginBottom={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n \u00B7\u00B7\u00B7 {hiddenMessageCount} earlier messages hidden \u00B7\u00B7\u00B7\n </Text>\n </Box>\n ),\n })\n }\n\n // V1+ Track rendered groups to avoid duplicate rendering\n const renderedGroupIds = new Set<string>()\n // V1+ Track tool_use_ids that are part of groups (to skip their tool_result messages)\n const groupToolUseIds = new Set<string>()\n // V1+ Track TaskOutput tool_use_ids that reference grouped tasks (to skip their tool_result messages)\n const taskOutputToolUseIdsToSkip = new Set<string>()\n\n // Render all messages - with V1+ group detection for parallel-tasks and task groups\n for (const _ of visibleMessages) {\n const toolUseID = getToolUseID(_)\n\n // V1+ Check if this message belongs to a group (parallel-tasks or task)\n // For progress messages, use toolUseID to find the group (since progress messages have different UUIDs)\n // For assistant messages, use the message UUID directly\n let group = getGroupForMessage(_.uuid)\n if (!group && _.type === 'progress') {\n // This is a progress message for a task - look up by toolUseID\n group = getGroupForToolUse(_.toolUseID)\n }\n\n // V1+ Handle grouped messages (parallel-tasks and single task groups)\n if (group && (group.type === 'parallel-tasks' || group.type === 'task')) {\n // Skip if this group was already rendered\n if (renderedGroupIds.has(group.id)) {\n continue\n }\n renderedGroupIds.add(group.id)\n\n // Track all tool_use_ids in this group to skip their tool_result messages later\n if (group.metadata.siblingToolUseIds) {\n for (const id of group.metadata.siblingToolUseIds as string[]) {\n groupToolUseIds.add(id)\n }\n }\n if (group.metadata.toolUseId) {\n groupToolUseIds.add(group.metadata.toolUseId as string)\n }\n\n // Render the entire group using GroupRenderer\n const isGroupStatic = shouldGroupBeStatic(group)\n const groupType = isGroupStatic ? 'static' : 'transient'\n\n const shouldAnimate =\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !isGroupStatic\n\n result.push({\n type: groupType,\n jsx: (\n <Box key={`group-${group.id}`} width=\"100%\">\n <GroupRenderer\n group={group}\n context={{\n depth: 0,\n isLastChild: true,\n displayConfig,\n shouldAnimate,\n getTranscript,\n }}\n messages={normalizedMessages}\n transcripts={agentTranscripts}\n outputs={toolOutputs}\n />\n </Box>\n ),\n })\n continue\n }\n\n // V1+ Skip tool_result messages for tools that are part of a group\n // (their output is rendered within the group view)\n // Also skip tool_result messages for TaskOutput calls that reference grouped tasks\n if (_.type === 'user' && _.message.role === 'user') {\n const content = _.message.content\n if (Array.isArray(content)) {\n const toolResult = content.find(\n (block): block is ToolResultBlockParam =>\n typeof block === 'object' && block.type === 'tool_result',\n )\n if (\n toolResult &&\n (groupToolUseIds.has(toolResult.tool_use_id) ||\n taskOutputToolUseIdsToSkip.has(toolResult.tool_use_id))\n ) {\n continue\n }\n }\n }\n\n // V1+ Skip TaskOutput tool calls that reference agents belonging to a group\n // (their output is already rendered within the group view)\n if (_.type === 'assistant') {\n const content = _.message.content\n if (Array.isArray(content)) {\n const taskOutputCall = content.find(\n (block): block is ToolUseBlockParam =>\n typeof block === 'object' &&\n block.type === 'tool_use' &&\n block.name === 'TaskOutput',\n )\n if (taskOutputCall) {\n const taskId = (taskOutputCall.input as { task_id?: string })\n ?.task_id\n if (taskId) {\n // Check if this task_id (agentId) corresponds to a tool_use_id in a group\n const correspondingToolUseId = getToolUseIdByAgentId(taskId)\n if (\n correspondingToolUseId &&\n groupToolUseIds.has(correspondingToolUseId)\n ) {\n // Track this TaskOutput's tool_use_id so we can also skip its tool_result\n taskOutputToolUseIdsToSkip.add(taskOutputCall.id)\n continue\n }\n }\n }\n }\n }\n\n // Skip streaming progress messages when tool is already completed\n // The final tool_result message will show the complete output, avoiding duplicate display\n if (\n _.type === 'progress' &&\n 'type' in _.content &&\n _.content.type === 'streaming' &&\n !unresolvedToolUseIDs.has(_.toolUseID)\n ) {\n continue\n }\n\n // Normal message rendering\n const message =\n _.type === 'progress' ? (\n // Check if this is a streaming progress content (e.g., from BashTool)\n 'type' in _.content && _.content.type === 'streaming' ? (\n <BashStreamingProgress\n stdout={(_.content as StreamingProgressContent).stdout}\n stderr={(_.content as StreamingProgressContent).stderr}\n isStreaming={(_.content as StreamingProgressContent).isStreaming}\n />\n ) : (_.content as AssistantMessage).message.content[0]?.type ===\n 'text' &&\n // TaskTool interrupts use Progress messages without extra \u23BF\n // since <Message /> component already adds the margin\n (_.content as AssistantMessage).message.content[0].text ===\n INTERRUPT_MESSAGE ? (\n <Message\n message={_.content as AssistantMessage}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n ) : (\n <MessageResponse\n children={\n <Message\n message={_.content as AssistantMessage}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={\n new Set([\n (\n (_.content as AssistantMessage).message\n .content[0]! as ToolUseBlockParam\n ).id,\n ])\n }\n shouldAnimate={false}\n shouldShowDot={false}\n />\n }\n />\n )\n ) : (\n <Message\n message={_}\n messages={normalizedMessages}\n addMargin={true}\n tools={tools}\n verbose={verbose}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n shouldAnimate={\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n (!toolUseID || inProgressToolUseIDs.has(toolUseID))\n }\n shouldShowDot={true}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )\n\n const type = shouldRenderStatically(\n _,\n normalizedMessages,\n unresolvedToolUseIDs,\n )\n ? 'static'\n : 'transient'\n\n if (debug) {\n result.push({\n type,\n jsx: (\n <Box\n borderStyle=\"single\"\n borderColor={type === 'static' ? 'green' : 'red'}\n key={_.uuid}\n width=\"100%\"\n >\n {message}\n </Box>\n ),\n })\n } else {\n result.push({\n type,\n jsx: (\n <Box key={_.uuid} width=\"100%\">\n {message}\n </Box>\n ),\n })\n }\n }\n\n return result\n }, [\n forkNumber,\n normalizedMessages,\n tools,\n verbose,\n debug,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n toolJSX,\n toolUseConfirm,\n isMessageSelectorVisible,\n unresolvedToolUseIDs,\n mcpClients,\n isDefaultModel,\n isResumedConversation,\n // V1+ dependencies\n messageGroups,\n getGroupForMessage,\n getGroupForToolUse,\n shouldGroupBeStatic,\n displayConfig,\n agentTranscripts,\n toolOutputs,\n ])\n\n // only show the dialog once not loading\n const showingCostDialog = !isLoading && showCostDialog\n\n // Separate static and dynamic messages for proper Ink Static component usage\n // Static messages: completed messages that won't change - protected from Ink's clearTerminal\n // Dynamic messages: in-progress messages that need to re-render\n const { staticItems, dynamicItems } = useMemo(() => {\n const staticItems: StaticItem[] = []\n const dynamicItems: MessageJSXItem[] = []\n\n for (const item of messagesJSX) {\n if (item.type === 'static') {\n // Extract key from jsx element for Static component deduplication\n const key = item.jsx.key?.toString() || `static-${staticItems.length}`\n staticItems.push({ id: key, jsx: item.jsx })\n } else if (item.type === 'transient') {\n dynamicItems.push(item)\n }\n }\n\n return { staticItems, dynamicItems }\n }, [messagesJSX])\n\n // =========================================================================\n // Stable callback functions for PromptInput props\n // Using useCallback prevents memo invalidation on parent re-renders\n // =========================================================================\n\n // Toggle message selector visibility\n const handleShowMessageSelector = useCallback(() => {\n setIsMessageSelectorVisible(prev => !prev)\n }, [])\n\n // Toggle todo panel visibility\n const handleToggleTodoPanel = useCallback(() => {\n setIsTodoPanelVisible(prev => !prev)\n }, [])\n\n // Toggle background panel visibility\n const handleToggleBackgroundPanel = useCallback(() => {\n setShowBackgroundPanel(prev => !prev)\n }, [])\n\n // Handle model change (force re-render)\n const handleModelChange = useCallback(() => {\n setForkNumber(prev => prev + 1)\n }, [])\n\n // Verbose toggle handler - clear screen and force re-render\n // Must increment forkNumber to force Static component to re-render conversation history\n // Sets verboseToggleMessage to show feedback after PromptInput remounts\n //\n // Flow: Hide UI -> wait for empty render -> clear terminal -> update state -> restore UI\n // This prevents ghost artifacts from appearing during the transition\n const handleToggleVerbose = useCallback(async (newVerbose: boolean) => {\n // Set the feedback message BEFORE remount so it survives\n const message = `${getVerboseLabel(newVerbose)} (Ctrl+O)`\n setVerboseToggleMessage(message)\n // Clear after 2 seconds\n setTimeout(() => setVerboseToggleMessage(null), 2000)\n\n // Step 1: Hide all transient UI\n setIsResizeClearing(true)\n\n // Step 2: Wait for React to render the empty state\n await new Promise(resolve => setTimeout(resolve, 50))\n\n // Step 3: Clear the terminal to remove any ghost artifacts\n await clearTerminal()\n\n // Step 4: Update state and restore UI\n setVerbose(newVerbose)\n setForkNumber(prev => prev + 1)\n setIsResizeClearing(false)\n }, [])\n\n // Queue-aware onQuery handler - queues prompts when busy\n const handleQueueAwareQuery = useCallback(\n async (newMessages: MessageType[], abortController?: AbortController) => {\n // If not loading, process immediately\n if (!isLoading) {\n return onQuery(newMessages, abortController)\n }\n\n // Otherwise, extract the user prompt and queue it\n const userMessage = newMessages.find(m => m.type === 'user')\n if (userMessage && userMessage.type === 'user') {\n const promptText =\n typeof userMessage.message.content === 'string'\n ? userMessage.message.content\n : ''\n if (promptText) {\n setQueuedPrompts(prev => [...prev, promptText])\n }\n }\n },\n [isLoading],\n )\n\n // Process next queued prompt - called after current task completes\n useEffect(() => {\n processNextQueuedPromptRef.current = async () => {\n if (queuedPrompts.length === 0) return\n\n // Pop the first queued prompt\n const nextPrompt = queuedPrompts[0]\n setQueuedPrompts(prev => prev.slice(1))\n\n if (!nextPrompt) return\n\n // Process it like a normal user submission\n const userMessage: MessageType = {\n type: 'user',\n uuid: randomUUID(),\n message: {\n role: 'user',\n content: nextPrompt,\n },\n }\n\n // Start the query\n setIsLoading(true)\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n await onQuery([userMessage], newAbortController)\n }\n }, [queuedPrompts])\n\n return (\n <PermissionProvider\n isBypassPermissionsModeAvailable={!safeMode}\n children={\n <React.Fragment>\n {/* Update banner now renders inside Logo for stable placement */}\n {/* Wrap in fragment with key to ensure re-render on fullscreen exit */}\n <React.Fragment key={`mode-indicator-${forkNumber}`}>\n <ModeIndicator />\n </React.Fragment>\n {/*\n Static/Dynamic separation for proper Ink rendering:\n\n 1. Static messages use Ink's <Static> component:\n - Content written to terminal is PRESERVED (not cleared by Ink)\n - Items are deduped by `id` - same id = same output\n - Perfect for: completed messages, finished tool results\n\n 2. Dynamic messages render normally (below Static):\n - Can be re-rendered without affecting static content above\n - Used for: in-progress tools, current interaction\n\n This architecture solves the clearTerminal issue:\n - When outputHeight >= terminal rows, Ink calls clearTerminal + re-render\n - But Static content is already written to terminal, not affected by this\n - Only dynamic content below gets cleared and re-rendered\n */}\n {/* STATIC SECTION: Completed messages protected from Ink's clearTerminal */}\n {/* Note: Static component uses forkNumber in fragment key to force rebuild on verbose toggle */}\n <React.Fragment key={`static-wrapper-${forkNumber}`}>\n <Static<StaticItem>\n items={staticItems}\n children={item => (\n <React.Fragment key={item.id}>{item.jsx}</React.Fragment>\n )}\n />\n </React.Fragment>\n\n {/* DYNAMIC SECTION: In-progress content that can re-render */}\n <React.Fragment key={`dynamic-messages-${forkNumber}`}>\n {/* Render transient items */}\n {dynamicItems.map(item => item.jsx)}\n </React.Fragment>\n {/*\n IMPORTANT: Key prop tied to forkNumber ensures all transient UI components\n are properly re-rendered when exiting fullscreen mode. This prevents ghost\n artifacts from appearing when the terminal shrinks significantly.\n See useFullscreenExitCallback above which increments forkNumber on fullscreen exit.\n */}\n <Box\n key={`transient-ui-${forkNumber}`}\n borderColor=\"red\"\n borderStyle={debug ? 'single' : undefined}\n flexDirection=\"column\"\n width=\"100%\"\n >\n {/* Unified Spinner + TodoPanel - shows when loading OR when there are incomplete todos */}\n {/* Hidden during resize clearing to prevent ghost artifacts */}\n {!isResizeClearing &&\n !toolJSX &&\n !toolUseConfirm &&\n !binaryFeedbackContext && (\n <TodoPanel\n todos={getTodos()}\n isVisible={isTodoPanelVisible}\n isLoading={isLoading}\n showTodoList={isTodoPanelVisible}\n />\n )}\n {/* Turn completion indicator - shows \"Cogitated for Xm Ys\" after AI turn completes */}\n {!isResizeClearing &&\n !isLoading &&\n !toolJSX &&\n !toolUseConfirm &&\n !binaryFeedbackContext && (\n <TurnCompletionIndicator\n durationMs={lastTurnDurationMs}\n isVisible={lastTurnDurationMs !== null}\n />\n )}\n {/* Render toolJSX here only when it should hide PromptInput */}\n {toolJSX?.shouldHidePromptInput ? toolJSX.jsx : null}\n {!toolJSX && binaryFeedbackContext && !isMessageSelectorVisible && (\n <BinaryFeedback\n m1={binaryFeedbackContext.m1}\n m2={binaryFeedbackContext.m2}\n resolve={result => {\n binaryFeedbackContext.resolve(result)\n setTimeout(() => setBinaryFeedbackContext(null), 0)\n }}\n verbose={verbose}\n normalizedMessages={normalizedMessages}\n tools={tools}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )}\n {!toolJSX &&\n toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext && (\n <PermissionRequest\n toolUseConfirm={toolUseConfirm}\n onDone={() => setToolUseConfirm(null)}\n verbose={verbose}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n askUserQuestionContext && (\n <AskUserQuestionDialog\n context={askUserQuestionContext}\n onDone={() => setAskUserQuestionContext(null)}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext &&\n showingCostDialog && (\n <CostThresholdDialog\n onDone={() => {\n setShowCostDialog(false)\n setHaveShownCostDialog(true)\n const projectConfig = getGlobalConfig()\n saveGlobalConfig({\n ...projectConfig,\n hasAcknowledgedCostThreshold: true,\n })\n }}\n />\n )}\n\n {!toolUseConfirm &&\n !toolJSX?.shouldHidePromptInput &&\n shouldShowPromptInput &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !askUserQuestionContext &&\n !showingCostDialog && (\n <>\n {/* BackgroundTasksPanel */}\n <BackgroundTasksPanel\n shells={backgroundShells}\n isVisible={showBackgroundPanel}\n onSelect={shell => {\n // View shell details (could show detailed output)\n setShowBackgroundPanel(false)\n }}\n onKill={shell => {\n BackgroundShellManager.getInstance().kill(shell.id)\n }}\n onClose={() => setShowBackgroundPanel(false)}\n />\n <PromptInput\n commands={commands}\n forkNumber={forkNumber}\n messageLogName={messageLogName}\n tools={tools}\n isDisabled={apiKeyStatus === 'invalid'}\n isLoading={isLoading}\n onQuery={onQuery}\n debug={debug}\n verbose={verbose}\n verboseToggleMessage={verboseToggleMessage}\n messages={messages}\n setToolJSX={setToolJSX}\n input={inputValue}\n onInputChange={setInputValue}\n mode={inputMode}\n onModeChange={setInputMode}\n submitCount={submitCount}\n onSubmitCountChange={setSubmitCount}\n setIsLoading={setIsLoading}\n setAbortController={setAbortController}\n onShowMessageSelector={handleShowMessageSelector}\n setForkConvoWithMessagesOnTheNextRender={\n setForkConvoWithMessagesOnTheNextRender\n }\n readFileTimestamps={readFileTimestamps.current}\n abortController={abortController}\n onModelChange={handleModelChange}\n onRollbackConversation={rollbackConversation}\n onToggleTodoPanel={handleToggleTodoPanel}\n onToggleVerbose={handleToggleVerbose}\n onToggleBackgroundPanel={handleToggleBackgroundPanel}\n backgroundShellCount={\n backgroundShells.filter(s => s.status === 'running')\n .length\n }\n isBackgroundPanelOpen={showBackgroundPanel}\n fallbackMode={fallbackMode}\n queuedPrompts={queuedPrompts}\n onQueuePrompt={prompt =>\n setQueuedPrompts(prev => [...prev, prompt])\n }\n onPopQueuedPrompt={() => {\n if (queuedPrompts.length === 0) return undefined\n const lastPrompt = queuedPrompts[queuedPrompts.length - 1]\n setQueuedPrompts(prev => prev.slice(0, -1))\n return lastPrompt\n }}\n onInterrupt={onInterrupt}\n isOverlayActive={\n !!(toolJSX && !toolJSX.shouldHidePromptInput)\n }\n unmount={unmountREPL}\n />\n {/* Render toolJSX below PromptInput when shouldHidePromptInput is false */}\n {toolJSX && !toolJSX.shouldHidePromptInput && toolJSX.jsx}\n </>\n )}\n </Box>\n {isMessageSelectorVisible && (\n <React.Fragment key={`message-selector-wrapper-${forkNumber}`}>\n <MessageSelector\n erroredToolUseIDs={erroredToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n messages={normalizeMessagesForAPI(messages)}\n onSelect={async message => {\n setIsMessageSelectorVisible(false)\n\n // If the user selected the current prompt, do nothing\n if (!messages.includes(message)) {\n return\n }\n\n // Cancel tool use calls/requests\n onCancel()\n\n // Hack: make sure the \"Interrupted by user\" message is\n // rendered in response to the cancellation. Otherwise,\n // the screen will be cleared but there will remain a\n // vestigial \"Interrupted by user\" message at the top.\n setImmediate(async () => {\n // Clear messages, and re-render\n await clearTerminal()\n setMessages([])\n setForkConvoWithMessagesOnTheNextRender(\n messages.slice(0, messages.indexOf(message)),\n )\n\n // Populate/reset the prompt input\n if (typeof message.message.content === 'string') {\n setInputValue(message.message.content)\n }\n })\n }}\n onEscape={() => setIsMessageSelectorVisible(false)}\n tools={tools}\n />\n </React.Fragment>\n )}\n {/** Fix occasional rendering artifact */}\n <Newline />\n </React.Fragment>\n }\n />\n )\n}\n\nfunction shouldRenderStatically(\n message: NormalizedMessage,\n messages: NormalizedMessage[],\n unresolvedToolUseIDs: Set<string>,\n): boolean {\n switch (message.type) {\n case 'user':\n case 'assistant': {\n const toolUseID = getToolUseID(message)\n if (!toolUseID) {\n return true\n }\n if (unresolvedToolUseIDs.has(toolUseID)) {\n return false\n }\n // Phase 2.1: Removed delay - immediately mark as static when resolved\n\n const correspondingProgressMessage = messages.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n ) as ProgressMessage | null\n if (!correspondingProgressMessage) {\n return true\n }\n\n return !intersects(\n unresolvedToolUseIDs,\n correspondingProgressMessage.siblingToolUseIDs,\n )\n }\n case 'progress':\n // Phase 2.1: Immediately mark as static when resolved - no delay\n return !intersects(unresolvedToolUseIDs, message.siblingToolUseIDs)\n }\n}\n\nfunction intersects<A>(a: Set<A>, b: Set<A>): boolean {\n return a.size > 0 && b.size > 0 && [...a].some(_ => b.has(_))\n}\n"],
5
+ "mappings": "AAIA,SAAS,KAAK,SAAS,QAAQ,MAAM,cAAc;AACnD,OAAO;AAAA,EACL;AAAA,OACK;AAEP,SAAS,2BAA2B;AACpC,YAAY,WAAW;AACvB,SAAS,WAAW,SAAS,QAAQ,UAAU,mBAAmB;AAElE,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AACtC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,OAEK;AACP,OAAO,iBAAiB;AACxB,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAC3B,SAAS,cAAc,sBAAsB;AAC7C,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,6BAA6B;AAEtC,OAAO,mBAAmB;AAC1B,SAAS,gBAAgB,8BAA8B;AACvD,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,iCAAiC;AAC1C,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,+BAA+B;AACxC,SAAS,UAAU,uBAAuB;AAC1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAME;AAAA,OACK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAA0B,oBAAoB;AAC9C,SAAS,qBAA0C;AACnD,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAClC,SAAS,SAAS,mBAAmB;AACrC;AAAA,EACE;AAAA,OAGK;AACP,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AAEP,OAAO,gBAAgB;AAEvB,SAAS,wBAAwB;AACjC,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAIP,MAAM,+BAA+B;AAwC9B,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,oBAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA,aAAa,CAAC;AAAA,EACd,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,wBAAwB;AAC1B,GAA2B;AAGzB,QAAM,CAAC,SAAS,UAAU,IAAI;AAAA,IAC5B,mBAAmB,OAAO,OAAO;AAAA,EACnC;AAGA,QAAM,CAAC,YAAY,aAAa,IAAI;AAAA,IAClC,8BAA8B,gBAAgB,mBAAmB,CAAC;AAAA,EACpE;AAGA,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAG9D,QAAM,EAAE,MAAM,YAAY,IAAI,OAAO;AAIrC,4BAA0B,YAAY;AAEpC,wBAAoB,IAAI;AAGxB,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAGpD,UAAM,cAAc;AAGpB,kBAAc,UAAQ,OAAO,CAAC;AAC9B,wBAAoB,KAAK;AAAA,EAC3B,CAAC;AAED,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF,IAAI,SAA+B,IAAI;AAGvC,QAAM,CAAC,iBAAiB,kBAAkB,IACxC,SAAiC,IAAI;AACvC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,CAAC,SAAS,UAAU,IAAI,SAGpB,IAAI;AACd,QAAM,CAAC,gBAAgB,iBAAiB,IAAI;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,mBAAmB,CAAC,CAAC;AAG7E,QAAM,cAAc,OAAsB,mBAAmB,CAAC,CAAC;AAE/D,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAA0B,CAAC,CAAC;AACxE,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,EAAE;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAI;AAAA,IAChC;AAAA,EACF;AACA,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAChD,QAAM,CAAC,0BAA0B,2BAA2B,IAC1D,SAAS,KAAK;AAChB,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,CAAC,qBAAqB,sBAAsB,IAAI;AAAA,IACpD,gBAAgB,EAAE;AAAA,EACpB;AAEA,QAAM,CAAC,uBAAuB,wBAAwB,IACpD,SAAuC,IAAI;AAC7C,QAAM,CAAC,wBAAwB,yBAAyB,IACtD,SAAwC,IAAI;AAE9C,QAAM,yBAAyB,wBAAwB;AACvD,QAAM,iBAAiB,yBAAyB;AAIhD,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,IAAI;AAGjE,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,SAEtD,IAAI;AAGN,QAAM,mBAAmB,OAAsB,IAAI;AACnD,QAAM,CAAC,oBAAoB,qBAAqB,IAAI;AAAA,IAClD;AAAA,EACF;AAGA,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAmB,CAAC,CAAC;AAE/D,QAAM,mBAAmB,OAAiB,CAAC,CAAC;AAC5C,YAAU,MAAM;AACd,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,aAAa,CAAC;AAGlB,YAAU,MAAM;AACd,QAAI,WAAW;AAEb,uBAAiB,UAAU,KAAK,IAAI;AACpC,4BAAsB,IAAI;AAAA,IAC5B,WAAW,iBAAiB,YAAY,MAAM;AAE5C,YAAM,WAAW,KAAK,IAAI,IAAI,iBAAiB;AAC/C,4BAAsB,QAAQ;AAC9B,uBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,CAAC,kBAAkB,mBAAmB,IAAI;AAAA,IAC9C,CAAC;AAAA,EACH;AACA,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,SAAS,KAAK;AAGpE,QAAM,oBAAoB,OAAoB,oBAAI,IAAI,CAAC;AAGvD,QAAM,wBAAwB,OAAkC,IAAI;AAGpE,MAAI,sBAAsB,YAAY,MAAM;AAC1C,0BAAsB,UAAU,IAAI;AAAA,MAClC,qBAAmB;AACjB,oBAAY,UAAQ,CAAC,GAAG,MAAM,GAAG,eAAe,CAAC;AAAA,MACnD;AAAA,MACA;AAAA,QACE,eAAe;AAAA;AAAA,QACf,cAAc;AAAA;AAAA,QACd,OAAO;AAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,YAAU,MAAM;AACd,WAAO,MAAM;AACX,4BAAsB,SAAS,QAAQ;AAAA,IACzC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,4BAA4B;AAAA,IAChC,CACE,IACA,OACkC;AAClC,aAAO,IAAI,QAA8B,oBAAkB;AACzD,iCAAyB;AAAA,UACvB;AAAA,UACA;AAAA,UACA,SAAS;AAAA,QACX,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,qBAAqB,OAExB,CAAC,CAAC;AAGL,QAAM,iBAAiB,OAA2B,IAAI;AAEtD,QAAM,EAAE,QAAQ,cAAc,SAAS,IAAI,sBAAsB;AAGjE,WAAS,cAAc;AACrB,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAKA,UAAM,kBAAkB,YAAY;AACpC,QAAI,gBAAgB,SAAS,GAAG;AAC9B,YAAM,qBAAqB,gBAAgB,IAAI,sBAAsB;AACrE;AAAA,QACE,gBAAgB,gBAAgB,YAAY,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAGA,eAAW,IAAI;AACf,sBAAkB,IAAI;AACtB,6BAAyB,IAAI;AAC7B,iBAAa,KAAK;AAElB,QAAI,gBAAgB;AAClB,qBAAe,QAAQ;AAAA,IACzB,WAAW,mBAAmB,CAAC,gBAAgB,OAAO,SAAS;AAC7D,sBAAgB,MAAM;AAAA,IACxB;AAAA,EACF;AAGA,WAAS,WAAW;AAClB,gBAAY;AAAA,EACd;AAEA,YAAU,MAAM;AACd,QAAI,sCAAsC;AACxC,oBAAc,OAAK,IAAI,CAAC;AACxB,8CAAwC,IAAI;AAC5C,kBAAY,oCAAoC;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,oCAAoC,CAAC;AAEzC,YAAU,MAAM;AACd,UAAM,YAAY,aAAa;AAC/B,QAAI,aAAa,KAAc,CAAC,kBAAkB,CAAC,qBAAqB;AACtE,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,UAAU,gBAAgB,mBAAmB,CAAC;AAIlD,QAAM,aAAa,cAAc,iBAAiB;AAClD,QAAM,UAAU,WAAW,yBAAyB;AAEpD,iBAAe,SAAS;AACtB,aAAS;AAET,QAAI,CAAC,eAAe;AAClB;AAAA,IACF;AAEA,iBAAa,IAAI;AACjB,UAAM,qBAAqB,IAAI,gBAAgB;AAC/C,uBAAmB,kBAAkB;AAErC,QAAI;AAEF,YAAM,QAAQ,IAAI,aAAa,gBAAgB,CAAC,EAAE,aAAa,MAAM;AACrE,YAAM,cAAc,MAAM;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,SAAS;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,mBAAmB;AAAA,UACrB;AAAA,UACA,WAAW,0BAA0B,QAAQ;AAAA,UAC7C;AAAA,UACA,oBAAoB,mBAAmB;AAAA,QACzC;AAAA,QACA;AAAA,MACF;AAEA,UAAI,YAAY,QAAQ;AACtB,mBAAW,WAAW,aAAa;AACjC,cAAI,QAAQ,SAAS,QAAQ;AAC3B,yBAAa,aAAa;AAAA,UAE5B;AAAA,QACF;AACA,oBAAY,OAAK,CAAC,GAAG,GAAG,GAAG,WAAW,CAAC;AAIvC,cAAM,cAAc,YAAY,YAAY,SAAS,CAAC;AACtD,YAAI,YAAY,SAAS,aAAa;AACpC;AAAA,QACF;AAEA,cAAM,CAAC,cAAc,SAASA,QAAO,iBAAiB,IACpD,MAAM,QAAQ,IAAI;AAAA,UAChB,gBAAgB;AAAA,UAChB,WAAW;AAAA,UACX,IAAI,aAAa,gBAAgB,CAAC,EAAE,aAAa,MAAM;AAAA,UACvD,qBAAqB,CAAC,GAAG,UAAU,GAAG,WAAW,CAAC;AAAA,QACpD,CAAC;AAEH,yBAAiB,WAAW;AAAA,UAC1B,CAAC,GAAG,UAAU,GAAG,WAAW;AAAA,UAC5B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,YACE,SAAS;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,WAAW,0BAA0B,CAAC,GAAG,UAAU,GAAG,WAAW,CAAC;AAAA,YAClE,oBAAoB,mBAAmB;AAAA,YACvC,iBAAiB;AAAA,YACjB;AAAA,YACA;AAAA,UACF;AAAA,UACA;AAAA,QACF,GAAG;AAED,gCAAsB,SAAS,IAAI,OAAO;AAAA,QAC5C;AAGA,8BAAsB,SAAS,MAAM;AAAA,MACvC,OAAO;AACL,qBAAa,aAAa;AAAA,MAE5B;AAEA;AAAA,QACE,gBAAgB,EAAE,gCAAgC;AAAA,MACpD;AAAA,IACF,SAAS,OAAO;AAEd,eAAS,KAAK;AACd,kBAAY,iBAAe;AAAA,QACzB,GAAG;AAAA,QACH;AAAA,UACE,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC3E;AAAA,MACF,CAAC;AAAA,IACH,UAAE;AAEA,mBAAa,KAAK;AAClB,yBAAmB,IAAI;AAAA,IACzB;AAAA,EACF;AAGA,WAAS,uBAAgC;AACvC,QAAI,eAAe,WAAW,GAAG;AAC/B,aAAO;AAAA,IACT;AAGA,UAAM,mBAAmB,eAAe,eAAe,SAAS,CAAC;AACjE,gBAAY,gBAAgB;AAC5B,sBAAkB,aAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;AAEjD,WAAO;AAAA,EACT;AAIA,QAAM,6BAA6B,OAAqC,IAAI;AAE5E,iBAAe,QACb,aACA,uBACA;AAEA,UAAM,kBAAkB,yBAAyB,IAAI,gBAAgB;AACrE,QAAI,CAAC,uBAAuB;AAC1B,yBAAmB,eAAe;AAAA,IACpC;AAEA,iBAAa,IAAI;AAIjB,eAAW,KAAK;AAGhB,UAAM,kBACJ,YAAY,SAAS,KACrB,YAAY,CAAC,EAAE,SAAS,UACxB,aAAa,YAAY,CAAC,KAC1B,YAAY,CAAC,EAAE,SAAS,oBAAoB;AAG9C,gBAAY,iBAAe;AAEzB,wBAAkB,aAAW,CAAC,GAAG,SAAS,WAAW,EAAE,MAAM,GAAG,CAAC;AACjE,aAAO,CAAC,GAAG,aAAa,GAAG,WAAW;AAAA,IACxC,CAAC;AAGD,kCAA8B;AAI9B,UAAM,cAAc,YAAY,YAAY,SAAS,CAAC;AAGtD,QACE,YAAY,SAAS,UACrB,OAAO,YAAY,QAAQ,YAAY,UACvC;AAEA,wBAAkB,YAAY,QAAQ,OAAO;AAE7C,4BAAsB,CAAC;AAAA,IACzB;AAGA,QACE,YAAY,SAAS,UACrB,OAAO,YAAY,QAAQ,YAAY,UACvC;AAAA,IAEF;AACA,QAAI,YAAY,SAAS,aAAa;AACpC,yBAAmB,IAAI;AACvB,mBAAa,KAAK;AAClB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,CAAC,cAAc,SAAS,OAAO,iBAAiB,IACpD,MAAM,QAAQ,IAAI;AAAA,QAChB,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,IAAI,aAAa,gBAAgB,CAAC,EAAE,aAAa,MAAM;AAAA,QACvD,qBAAqB,CAAC,GAAG,UAAU,WAAW,CAAC;AAAA,MACjD,CAAC;AAEH,UAAI,uBAA2C;AAG/C,uBAAiB,WAAW;AAAA,QAC1B,CAAC,GAAG,UAAU,WAAW;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,SAAS;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,YAEA,iBAAiB,mBAAmB;AAAA,UACtC;AAAA,UACA,WAAW,0BAA0B,CAAC,GAAG,UAAU,WAAW,CAAC;AAAA,UAC/D,oBAAoB,mBAAmB;AAAA,UACvC,iBAAiB;AAAA,UACjB;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF,GAAG;AAED,8BAAsB,SAAS,IAAI,OAAO;AAG1C,YAAI,QAAQ,SAAS,aAAa;AAChC,iCAAuB;AAEvB,gCAAsB,CAAC;AAGvB,cAAI,MAAM,QAAQ,QAAQ,QAAQ,OAAO,GAAG;AAC1C,kBAAM,eAAe,QAAQ,QAAQ,QAAQ;AAAA,cAC3C,WAAS,OAAO,UAAU,YAAY,MAAM,SAAS;AAAA,YACvD,EAAE;AACF,gBAAI,eAAe,GAAG;AACpB,qCAAuB,YAAY;AAAA,YACrC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAIA,UACE,mBACA,wBACA,qBAAqB,SAAS,aAC9B;AACA,YAAI;AACF,gBAAM,UACJ,OAAO,qBAAqB,QAAQ,YAAY,WAC5C,qBAAqB,QAAQ,UAC7B,qBAAqB,QAAQ,QAC1B,OAAO,WAAS,MAAM,SAAS,MAAM,EACrC,IAAI,WAAU,MAAM,SAAS,SAAS,MAAM,OAAO,EAAG,EACtD,KAAK,IAAI;AAGlB,cAAI,WAAW,QAAQ,KAAK,EAAE,SAAS,GAAG;AACxC,8BAAkB,OAAO;AAAA,UAC3B;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,MAAM,0CAA0C,KAAK;AAAA,QAC/D;AAAA,MACF;AAGA,4BAAsB,SAAS,MAAM;AAAA,IACvC,SAAS,OAAO;AAEd,eAAS,KAAK;AAGd,4BAAsB,SAAS,MAAM;AACrC,kBAAY,iBAAe;AAAA,QACzB,GAAG;AAAA,QACH;AAAA,UACE,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC3E;AAAA,MACF,CAAC;AAAA,IACH,UAAE;AAEA,mBAAa,KAAK;AAClB,yBAAmB,IAAI;AAGvB,wBAAkB;AAGlB,UAAI,iBAAiB,QAAQ,SAAS,GAAG;AAEvC,mBAAW,MAAM;AACf,cAAI,2BAA2B,SAAS;AACtC,uCAA2B,QAAQ;AAAA,UACrC;AAAA,QACF,GAAG,GAAG;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,iBAAe;AAGf,YAAU,MAAM;AACd,UAAM,cAAc,MAAM;AAC1B,sBAAkB,WAAW;AAC7B,sBAAkB,WAAW;AAAA,EAC/B,GAAG,CAAC,QAAQ,CAAC;AAMb,YAAU,MAAM;AACd,UAAM,gBAAgB,GAAG,cAAc,IAAI,UAAU;AACrD,oBAAgB,aAAa;AAI7B,QAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,kCAA4B;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,gBAAgB,YAAY,eAAe,CAAC;AAGhD,YAAU,MAAM;AACd,gCAA4B,MAAM;AAChC,oBAAc,UAAQ,OAAO,CAAC;AAAA,IAChC,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAIL,YAAU,MAAM;AACd,6BAAyB,YAAY;AAEnC,0BAAoB,IAAI;AAGxB,YAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAGpD,YAAM,cAAc;AAGpB,oBAAc,UAAQ,OAAO,CAAC;AAC9B,0BAAoB,KAAK;AAAA,IAC3B,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,QAAQ,CAAC;AAGb,iBAAe,UAAU,gBAAgB,UAAU;AAGnD,oBAAkB;AAGlB,YAAU,MAAM;AACd,WAAO;AAAA,EAGT,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI;AACF,YAAM,UAAU,eAAe;AAC/B,YAAM,YAAY,WAAW;AAC7B,YAAM,iBAAiB,gBAAgB,gBAAgB,YAAY,CAAC;AAEpE,YAAM,cAAc;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,qBAAe,UAAU;AAGzB,yBAAmB,eAAe,CAAC;AAGnC,kBAAY,oBAAoB,EAAE,MAAM,SAAO;AAC7C,oBAAY,MAAM,6BAA6B,EAAE,OAAO,IAAI,CAAC;AAAA,MAC/D,CAAC;AAGD,aAAO,MAAM;AAEX,0BAAkB;AAClB,mBAAW,OAAO;AAElB,oBAAY,kBAAkB,OAAO,EAAE,MAAM,SAAO;AAClD,sBAAY,MAAM,2BAA2B,EAAE,OAAO,IAAI,CAAC;AAAA,QAC7D,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,MAAM,qCAAqC,EAAE,OAAO,IAAI,CAAC;AAAA,IACvE;AAAA,EACF,GAAG,CAAC,gBAAgB,UAAU,CAAC;AAG/B,YAAU,MAAM;AACd,UAAM,UAAU,uBAAuB,YAAY;AAEnD,wBAAoB,QAAQ,KAAK,CAAC;AAGlC,UAAM,mBAAmB,CAAC,WAA8B;AACtD,0BAAoB,MAAM;AAAA,IAC5B;AACA,YAAQ,GAAG,cAAc,gBAAgB;AAEzC,WAAO,MAAM;AACX,cAAQ,IAAI,cAAc,gBAAgB;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,CAAC;AAIL,QAAM,qBAAqB;AAAA,IACzB,MAAM,kBAAkB,QAAQ,EAAE,OAAO,iBAAiB;AAAA,IAC1D,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,uBAAuB;AAAA,IAC3B,MAAM,wBAAwB,kBAAkB;AAAA,IAChD,CAAC,kBAAkB;AAAA,EACrB;AAIA,YAAU,MAAM;AACd,sBAAkB,UAAU,IAAI,IAAI,oBAAoB;AAAA,EAC1D,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,uBAAuB;AAAA,IAC3B,MAAM,wBAAwB,kBAAkB;AAAA,IAChD,CAAC,kBAAkB;AAAA,EACrB;AAEA,QAAM,oBAAoB;AAAA,IACxB,MACE,IAAI;AAAA,MACF,0BAA0B,kBAAkB,EAAE;AAAA,QAC5C,OAAM,EAAE,QAAQ,QAAQ,CAAC,EAAyB;AAAA,MACpD;AAAA,IACF;AAAA,IACF,CAAC,kBAAkB;AAAA,EACrB;AAGA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,QAAM,EAAE,aAAa,kBAAkB,cAAc,IAAI,oBAAoB;AAG7E,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,UAAU,oBAAI,IAAkC;AACtD,eAAW,OAAO,oBAAoB;AACpC,UAAI,IAAI,SAAS,UAAU,IAAI,QAAQ,SAAS,QAAQ;AACtD,mBAAW,SAAS,IAAI,QAAQ,SAAS;AACvC,cAAI,OAAO,UAAU,YAAY,MAAM,SAAS,eAAe;AAC7D,oBAAQ,IAAI,MAAM,aAAa,KAA6B;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,kBAAkB,CAAC;AAWvB,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,oBAAoB,gBAAgB,kBAAkB;AAG5D,UAAM,qBACJ,yBACA,kBAAkB,SAAS,+BACvB,kBAAkB,SAAS,+BAC3B;AAGN,UAAM,kBACJ,qBAAqB,IACjB,kBAAkB,MAAM,CAAC,4BAA4B,IACrD;AAGN,UAAM,SAA2B;AAAA,MAC/B;AAAA,QACE,MAAM;AAAA,QACN,KACE,oCAAC,OAAI,eAAc,UAAS,OAAM,QAAO,KAAI,UAC3C;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,qBAAqB;AAAA,YACrB,sBAAsB;AAAA;AAAA,QACxB,GACA,oCAAC,qBAAkB,cAAc,eAAe,GAAG,CACrD;AAAA,MAEJ;AAAA,IACF;AAGA,QAAI,qBAAqB,GAAG;AAC1B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,KACE,oCAAC,OAAI,KAAI,qBAAoB,aAAa,GAAG,cAAc,KACzD,oCAAC,QAAK,OAAO,gBAAgB,OAAK,iBAC3B,oBAAmB,uCAC1B,CACF;AAAA,MAEJ,CAAC;AAAA,IACH;AAGA,UAAM,mBAAmB,oBAAI,IAAY;AAEzC,UAAM,kBAAkB,oBAAI,IAAY;AAExC,UAAM,6BAA6B,oBAAI,IAAY;AAGnD,eAAW,KAAK,iBAAiB;AAC/B,YAAM,YAAY,aAAa,CAAC;AAKhC,UAAI,QAAQ,mBAAmB,EAAE,IAAI;AACrC,UAAI,CAAC,SAAS,EAAE,SAAS,YAAY;AAEnC,gBAAQ,mBAAmB,EAAE,SAAS;AAAA,MACxC;AAGA,UAAI,UAAU,MAAM,SAAS,oBAAoB,MAAM,SAAS,SAAS;AAEvE,YAAI,iBAAiB,IAAI,MAAM,EAAE,GAAG;AAClC;AAAA,QACF;AACA,yBAAiB,IAAI,MAAM,EAAE;AAG7B,YAAI,MAAM,SAAS,mBAAmB;AACpC,qBAAW,MAAM,MAAM,SAAS,mBAA+B;AAC7D,4BAAgB,IAAI,EAAE;AAAA,UACxB;AAAA,QACF;AACA,YAAI,MAAM,SAAS,WAAW;AAC5B,0BAAgB,IAAI,MAAM,SAAS,SAAmB;AAAA,QACxD;AAGA,cAAM,gBAAgB,oBAAoB,KAAK;AAC/C,cAAM,YAAY,gBAAgB,WAAW;AAE7C,cAAM,gBACJ,CAAC,WACD,CAAC,kBACD,CAAC,4BACD,CAAC;AAEH,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,KACE,oCAAC,OAAI,KAAK,SAAS,MAAM,EAAE,IAAI,OAAM,UACnC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,SAAS;AAAA,gBACP,OAAO;AAAA,gBACP,aAAa;AAAA,gBACb;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,UAAU;AAAA,cACV,aAAa;AAAA,cACb,SAAS;AAAA;AAAA,UACX,CACF;AAAA,QAEJ,CAAC;AACD;AAAA,MACF;AAKA,UAAI,EAAE,SAAS,UAAU,EAAE,QAAQ,SAAS,QAAQ;AAClD,cAAM,UAAU,EAAE,QAAQ;AAC1B,YAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,gBAAM,aAAa,QAAQ;AAAA,YACzB,CAAC,UACC,OAAO,UAAU,YAAY,MAAM,SAAS;AAAA,UAChD;AACA,cACE,eACC,gBAAgB,IAAI,WAAW,WAAW,KACzC,2BAA2B,IAAI,WAAW,WAAW,IACvD;AACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAIA,UAAI,EAAE,SAAS,aAAa;AAC1B,cAAM,UAAU,EAAE,QAAQ;AAC1B,YAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,gBAAM,iBAAiB,QAAQ;AAAA,YAC7B,CAAC,UACC,OAAO,UAAU,YACjB,MAAM,SAAS,cACf,MAAM,SAAS;AAAA,UACnB;AACA,cAAI,gBAAgB;AAClB,kBAAM,SAAU,eAAe,OAC3B;AACJ,gBAAI,QAAQ;AAEV,oBAAM,yBAAyB,sBAAsB,MAAM;AAC3D,kBACE,0BACA,gBAAgB,IAAI,sBAAsB,GAC1C;AAEA,2CAA2B,IAAI,eAAe,EAAE;AAChD;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAIA,UACE,EAAE,SAAS,cACX,UAAU,EAAE,WACZ,EAAE,QAAQ,SAAS,eACnB,CAAC,qBAAqB,IAAI,EAAE,SAAS,GACrC;AACA;AAAA,MACF;AAGA,YAAM,UACJ,EAAE,SAAS;AAAA;AAAA,QAET,UAAU,EAAE,WAAW,EAAE,QAAQ,SAAS,cACxC;AAAA,UAAC;AAAA;AAAA,YACC,QAAS,EAAE,QAAqC;AAAA,YAChD,QAAS,EAAE,QAAqC;AAAA,YAChD,aAAc,EAAE,QAAqC;AAAA;AAAA,QACvD,IACG,EAAE,QAA6B,QAAQ,QAAQ,CAAC,GAAG,SACpD;AAAA;AAAA,QAGD,EAAE,QAA6B,QAAQ,QAAQ,CAAC,EAAE,SACjD,oBACF;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,EAAE;AAAA,YACX,UAAU,EAAE;AAAA,YACZ,WAAW;AAAA,YACX,OAAO,EAAE;AAAA,YACT,SAAS,WAAW;AAAA,YACpB;AAAA,YACA,mBAAmB,oBAAI,IAAI;AAAA,YAC3B,sBAAsB,oBAAI,IAAI;AAAA,YAC9B,sBAAsB,oBAAI,IAAI;AAAA,YAC9B,eAAe;AAAA,YACf,eAAe;AAAA;AAAA,QACjB,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,UACE;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,EAAE;AAAA,gBACX,UAAU,EAAE;AAAA,gBACZ,WAAW;AAAA,gBACX,OAAO,EAAE;AAAA,gBACT,SAAS,WAAW;AAAA,gBACpB;AAAA,gBACA,mBAAmB,oBAAI,IAAI;AAAA,gBAC3B,sBAAsB,oBAAI,IAAI;AAAA,gBAC9B,sBACE,oBAAI,IAAI;AAAA,kBAEH,EAAE,QAA6B,QAC7B,QAAQ,CAAC,EACZ;AAAA,gBACJ,CAAC;AAAA,gBAEH,eAAe;AAAA,gBACf,eAAe;AAAA;AAAA,YACjB;AAAA;AAAA,QAEJ;AAAA,UAGF;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,UAAU;AAAA,UACV,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,eACE,CAAC,WACD,CAAC,kBACD,CAAC,6BACA,CAAC,aAAa,qBAAqB,IAAI,SAAS;AAAA,UAEnD,eAAe;AAAA,UACf;AAAA;AAAA,MACF;AAGJ,YAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,IACI,WACA;AAEJ,UAAI,OAAO;AACT,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KACE;AAAA,YAAC;AAAA;AAAA,cACC,aAAY;AAAA,cACZ,aAAa,SAAS,WAAW,UAAU;AAAA,cAC3C,KAAK,EAAE;AAAA,cACP,OAAM;AAAA;AAAA,YAEL;AAAA,UACH;AAAA,QAEJ,CAAC;AAAA,MACH,OAAO;AACL,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KACE,oCAAC,OAAI,KAAK,EAAE,MAAM,OAAM,UACrB,OACH;AAAA,QAEJ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,oBAAoB,CAAC,aAAa;AAKxC,QAAM,EAAE,aAAa,aAAa,IAAI,QAAQ,MAAM;AAClD,UAAMC,eAA4B,CAAC;AACnC,UAAMC,gBAAiC,CAAC;AAExC,eAAW,QAAQ,aAAa;AAC9B,UAAI,KAAK,SAAS,UAAU;AAE1B,cAAM,MAAM,KAAK,IAAI,KAAK,SAAS,KAAK,UAAUD,aAAY,MAAM;AACpE,QAAAA,aAAY,KAAK,EAAE,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC;AAAA,MAC7C,WAAW,KAAK,SAAS,aAAa;AACpC,QAAAC,cAAa,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,WAAO,EAAE,aAAAD,cAAa,cAAAC,cAAa;AAAA,EACrC,GAAG,CAAC,WAAW,CAAC;AAQhB,QAAM,4BAA4B,YAAY,MAAM;AAClD,gCAA4B,UAAQ,CAAC,IAAI;AAAA,EAC3C,GAAG,CAAC,CAAC;AAGL,QAAM,wBAAwB,YAAY,MAAM;AAC9C,0BAAsB,UAAQ,CAAC,IAAI;AAAA,EACrC,GAAG,CAAC,CAAC;AAGL,QAAM,8BAA8B,YAAY,MAAM;AACpD,2BAAuB,UAAQ,CAAC,IAAI;AAAA,EACtC,GAAG,CAAC,CAAC;AAGL,QAAM,oBAAoB,YAAY,MAAM;AAC1C,kBAAc,UAAQ,OAAO,CAAC;AAAA,EAChC,GAAG,CAAC,CAAC;AAQL,QAAM,sBAAsB,YAAY,OAAO,eAAwB;AAErE,UAAM,UAAU,GAAG,gBAAgB,UAAU,CAAC;AAC9C,4BAAwB,OAAO;AAE/B,eAAW,MAAM,wBAAwB,IAAI,GAAG,GAAI;AAGpD,wBAAoB,IAAI;AAGxB,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAGpD,UAAM,cAAc;AAGpB,eAAW,UAAU;AACrB,kBAAc,UAAQ,OAAO,CAAC;AAC9B,wBAAoB,KAAK;AAAA,EAC3B,GAAG,CAAC,CAAC;AAGL,QAAM,wBAAwB;AAAA,IAC5B,OAAO,aAA4BC,qBAAsC;AAEvE,UAAI,CAAC,WAAW;AACd,eAAO,QAAQ,aAAaA,gBAAe;AAAA,MAC7C;AAGA,YAAM,cAAc,YAAY,KAAK,OAAK,EAAE,SAAS,MAAM;AAC3D,UAAI,eAAe,YAAY,SAAS,QAAQ;AAC9C,cAAM,aACJ,OAAO,YAAY,QAAQ,YAAY,WACnC,YAAY,QAAQ,UACpB;AACN,YAAI,YAAY;AACd,2BAAiB,UAAQ,CAAC,GAAG,MAAM,UAAU,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAGA,YAAU,MAAM;AACd,+BAA2B,UAAU,YAAY;AAC/C,UAAI,cAAc,WAAW,EAAG;AAGhC,YAAM,aAAa,cAAc,CAAC;AAClC,uBAAiB,UAAQ,KAAK,MAAM,CAAC,CAAC;AAEtC,UAAI,CAAC,WAAY;AAGjB,YAAM,cAA2B;AAAA,QAC/B,MAAM;AAAA,QACN,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAGA,mBAAa,IAAI;AACjB,YAAM,qBAAqB,IAAI,gBAAgB;AAC/C,yBAAmB,kBAAkB;AAErC,YAAM,QAAQ,CAAC,WAAW,GAAG,kBAAkB;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,kCAAkC,CAAC;AAAA,MACnC,UACE,oCAAC,MAAM,UAAN,MAGC,oCAAC,MAAM,UAAN,EAAe,KAAK,kBAAkB,UAAU,MAC/C,oCAAC,mBAAc,CACjB,GAoBA,oCAAC,MAAM,UAAN,EAAe,KAAK,kBAAkB,UAAU,MAC/C;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,UACR,oCAAC,MAAM,UAAN,EAAe,KAAK,KAAK,MAAK,KAAK,GAAI;AAAA;AAAA,MAE5C,CACF,GAGA,oCAAC,MAAM,UAAN,EAAe,KAAK,oBAAoB,UAAU,MAEhD,aAAa,IAAI,UAAQ,KAAK,GAAG,CACpC,GAOA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK,gBAAgB,UAAU;AAAA,UAC/B,aAAY;AAAA,UACZ,aAAa,QAAQ,WAAW;AAAA,UAChC,eAAc;AAAA,UACd,OAAM;AAAA;AAAA,QAIL,CAAC,oBACA,CAAC,WACD,CAAC,kBACD,CAAC,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,SAAS;AAAA,YAChB,WAAW;AAAA,YACX;AAAA,YACA,cAAc;AAAA;AAAA,QAChB;AAAA,QAGH,CAAC,oBACA,CAAC,aACD,CAAC,WACD,CAAC,kBACD,CAAC,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,YAAY;AAAA,YACZ,WAAW,uBAAuB;AAAA;AAAA,QACpC;AAAA,QAGH,SAAS,wBAAwB,QAAQ,MAAM;AAAA,QAC/C,CAAC,WAAW,yBAAyB,CAAC,4BACrC;AAAA,UAAC;AAAA;AAAA,YACC,IAAI,sBAAsB;AAAA,YAC1B,IAAI,sBAAsB;AAAA,YAC1B,SAAS,YAAU;AACjB,oCAAsB,QAAQ,MAAM;AACpC,yBAAW,MAAM,yBAAyB,IAAI,GAAG,CAAC;AAAA,YACpD;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAED,CAAC,WACA,kBACA,CAAC,4BACD,CAAC,yBACD,CAAC,0BACC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,QAAQ,MAAM,kBAAkB,IAAI;AAAA,YACpC;AAAA;AAAA,QACF;AAAA,QAEH,CAAC,WACA,CAAC,kBACD,CAAC,4BACD,CAAC,yBACD,0BACE;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,QAAQ,MAAM,0BAA0B,IAAI;AAAA;AAAA,QAC9C;AAAA,QAEH,CAAC,WACA,CAAC,kBACD,CAAC,4BACD,CAAC,yBACD,CAAC,0BACD,qBACE;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ,MAAM;AACZ,gCAAkB,KAAK;AACvB,qCAAuB,IAAI;AAC3B,oBAAM,gBAAgB,gBAAgB;AACtC,+BAAiB;AAAA,gBACf,GAAG;AAAA,gBACH,8BAA8B;AAAA,cAChC,CAAC;AAAA,YACH;AAAA;AAAA,QACF;AAAA,QAGH,CAAC,kBACA,CAAC,SAAS,yBACV,yBACA,CAAC,4BACD,CAAC,yBACD,CAAC,0BACD,CAAC,qBACC,0DAEE;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,UAAU,WAAS;AAEjB,qCAAuB,KAAK;AAAA,YAC9B;AAAA,YACA,QAAQ,WAAS;AACf,qCAAuB,YAAY,EAAE,KAAK,MAAM,EAAE;AAAA,YACpD;AAAA,YACA,SAAS,MAAM,uBAAuB,KAAK;AAAA;AAAA,QAC7C,GACA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY,iBAAiB;AAAA,YAC7B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO;AAAA,YACP,eAAe;AAAA,YACf,MAAM;AAAA,YACN,cAAc;AAAA,YACd;AAAA,YACA,qBAAqB;AAAA,YACrB;AAAA,YACA;AAAA,YACA,uBAAuB;AAAA,YACvB;AAAA,YAGA,oBAAoB,mBAAmB;AAAA,YACvC;AAAA,YACA,eAAe;AAAA,YACf,wBAAwB;AAAA,YACxB,mBAAmB;AAAA,YACnB,iBAAiB;AAAA,YACjB,yBAAyB;AAAA,YACzB,sBACE,iBAAiB,OAAO,OAAK,EAAE,WAAW,SAAS,EAChD;AAAA,YAEL,uBAAuB;AAAA,YACvB;AAAA,YACA;AAAA,YACA,eAAe,YACb,iBAAiB,UAAQ,CAAC,GAAG,MAAM,MAAM,CAAC;AAAA,YAE5C,mBAAmB,MAAM;AACvB,kBAAI,cAAc,WAAW,EAAG,QAAO;AACvC,oBAAM,aAAa,cAAc,cAAc,SAAS,CAAC;AACzD,+BAAiB,UAAQ,KAAK,MAAM,GAAG,EAAE,CAAC;AAC1C,qBAAO;AAAA,YACT;AAAA,YACA;AAAA,YACA,iBACE,CAAC,EAAE,WAAW,CAAC,QAAQ;AAAA,YAEzB,SAAS;AAAA;AAAA,QACX,GAEC,WAAW,CAAC,QAAQ,yBAAyB,QAAQ,GACxD;AAAA,MAEN,GACC,4BACC,oCAAC,MAAM,UAAN,EAAe,KAAK,4BAA4B,UAAU,MACzD;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,UAAU,wBAAwB,QAAQ;AAAA,UAC1C,UAAU,OAAM,YAAW;AACzB,wCAA4B,KAAK;AAGjC,gBAAI,CAAC,SAAS,SAAS,OAAO,GAAG;AAC/B;AAAA,YACF;AAGA,qBAAS;AAMT,yBAAa,YAAY;AAEvB,oBAAM,cAAc;AACpB,0BAAY,CAAC,CAAC;AACd;AAAA,gBACE,SAAS,MAAM,GAAG,SAAS,QAAQ,OAAO,CAAC;AAAA,cAC7C;AAGA,kBAAI,OAAO,QAAQ,QAAQ,YAAY,UAAU;AAC/C,8BAAc,QAAQ,QAAQ,OAAO;AAAA,cACvC;AAAA,YACF,CAAC;AAAA,UACH;AAAA,UACA,UAAU,MAAM,4BAA4B,KAAK;AAAA,UACjD;AAAA;AAAA,MACF,CACF,GAGF,oCAAC,aAAQ,CACX;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,uBACP,SACA,UACA,sBACS;AACT,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AAAA,IACL,KAAK,aAAa;AAChB,YAAM,YAAY,aAAa,OAAO;AACtC,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,UAAI,qBAAqB,IAAI,SAAS,GAAG;AACvC,eAAO;AAAA,MACT;AAGA,YAAM,+BAA+B,SAAS;AAAA,QAC5C,OAAK,EAAE,SAAS,cAAc,EAAE,cAAc;AAAA,MAChD;AACA,UAAI,CAAC,8BAA8B;AACjC,eAAO;AAAA,MACT;AAEA,aAAO,CAAC;AAAA,QACN;AAAA,QACA,6BAA6B;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,KAAK;AAEH,aAAO,CAAC,WAAW,sBAAsB,QAAQ,iBAAiB;AAAA,EACtE;AACF;AAEA,SAAS,WAAc,GAAW,GAAoB;AACpD,SAAO,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,OAAK,EAAE,IAAI,CAAC,CAAC;AAC9D;",
6
6
  "names": ["model", "staticItems", "dynamicItems", "abortController"]
7
7
  }
@@ -9,6 +9,7 @@ import { loadAllPlugins } from "../utils/pluginLoader.js";
9
9
  import {
10
10
  getCurrentProjectConfig
11
11
  } from "../utils/config.js";
12
+ import { substituteVariables } from "../utils/stringSubstitution.js";
12
13
  const execFileAsync = promisify(execFile);
13
14
  function isBashCommandAllowed(command) {
14
15
  const projectConfig = getCurrentProjectConfig();
@@ -233,9 +234,11 @@ function createCustomCommand(frontmatter, content, filePath, baseDir) {
233
234
  },
234
235
  async getPromptForCommand(args) {
235
236
  let prompt = content.trim();
236
- if (prompt.includes("$ARGUMENTS")) {
237
- prompt = prompt.replace(/\$ARGUMENTS/g, args || "");
238
- }
237
+ prompt = await substituteVariables(prompt, args || "", {
238
+ cwd: getCwd(),
239
+ allowDynamicCommands: false
240
+ // Security: disable !`command` by default
241
+ });
239
242
  if (argNames && argNames.length > 0) {
240
243
  const argValues = args.trim().split(/\s+/);
241
244
  argNames.forEach((argName, index) => {
@@ -243,7 +246,7 @@ function createCustomCommand(frontmatter, content, filePath, baseDir) {
243
246
  prompt = prompt.replace(new RegExp(`\\{${argName}\\}`, "g"), value);
244
247
  });
245
248
  }
246
- if (args.trim() && !prompt.includes("$ARGUMENTS") && (!argNames || argNames.length === 0)) {
249
+ if (args.trim() && !content.includes("$ARGUMENTS") && !content.includes("$0") && (!argNames || argNames.length === 0)) {
247
250
  prompt += `
248
251
 
249
252
  Additional context: ${args}`;
@@ -384,9 +387,11 @@ const loadPluginCommands = memoize(
384
387
  },
385
388
  async getPromptForCommand(args) {
386
389
  let prompt = pluginCommand.config.content.trim();
387
- if (prompt.includes("$ARGUMENTS")) {
388
- prompt = prompt.replace(/\$ARGUMENTS/g, args || "");
389
- }
390
+ prompt = await substituteVariables(prompt, args || "", {
391
+ cwd: getCwd(),
392
+ allowDynamicCommands: false
393
+ // Security: disable !`command` by default
394
+ });
390
395
  if (pluginCommand.config.argNames && pluginCommand.config.argNames.length > 0) {
391
396
  const argValues = args.trim().split(/\s+/);
392
397
  pluginCommand.config.argNames.forEach((argName, index) => {
@@ -397,7 +402,8 @@ const loadPluginCommands = memoize(
397
402
  );
398
403
  });
399
404
  }
400
- if (args.trim() && !prompt.includes("$ARGUMENTS") && (!pluginCommand.config.argNames || pluginCommand.config.argNames.length === 0)) {
405
+ const originalContent = pluginCommand.config.content;
406
+ if (args.trim() && !originalContent.includes("$ARGUMENTS") && !originalContent.includes("$0") && (!pluginCommand.config.argNames || pluginCommand.config.argNames.length === 0)) {
401
407
  prompt += `
402
408
 
403
409
  Additional context: ${args}`;