@within-7/minto 0.3.6 → 0.3.10

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 (238) hide show
  1. package/{cli.js → cli.cjs} +25 -23
  2. package/dist/commands/agents/AgentsCommand.js +459 -655
  3. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  4. package/dist/commands/agents/types.js +1 -0
  5. package/dist/commands/agents/types.js.map +2 -2
  6. package/dist/commands/agents/utils/fileOperations.js +96 -36
  7. package/dist/commands/agents/utils/fileOperations.js.map +3 -3
  8. package/dist/commands/agents/utils/index.js +3 -1
  9. package/dist/commands/agents/utils/index.js.map +2 -2
  10. package/dist/commands/context.js +54 -23
  11. package/dist/commands/context.js.map +2 -2
  12. package/dist/commands/export.js +673 -93
  13. package/dist/commands/export.js.map +2 -2
  14. package/dist/commands/language.js +110 -0
  15. package/dist/commands/language.js.map +7 -0
  16. package/dist/commands/mcp-interactive.js +419 -217
  17. package/dist/commands/mcp-interactive.js.map +2 -2
  18. package/dist/commands/model.js +415 -66
  19. package/dist/commands/model.js.map +2 -2
  20. package/dist/commands/new.js +56 -0
  21. package/dist/commands/new.js.map +7 -0
  22. package/dist/commands/permissions.js +75 -49
  23. package/dist/commands/permissions.js.map +2 -2
  24. package/dist/commands/plugin.js +882 -185
  25. package/dist/commands/plugin.js.map +3 -3
  26. package/dist/commands/resume.js +251 -16
  27. package/dist/commands/resume.js.map +2 -2
  28. package/dist/commands/sandbox.js +168 -70
  29. package/dist/commands/sandbox.js.map +2 -2
  30. package/dist/commands/sessions.js +224 -0
  31. package/dist/commands/sessions.js.map +7 -0
  32. package/dist/commands/setup.js +596 -109
  33. package/dist/commands/setup.js.map +2 -2
  34. package/dist/commands/stats.js +292 -0
  35. package/dist/commands/stats.js.map +7 -0
  36. package/dist/commands/status.js +75 -7
  37. package/dist/commands/status.js.map +2 -2
  38. package/dist/commands/undo.js +154 -180
  39. package/dist/commands/undo.js.map +2 -2
  40. package/dist/commands.js +6 -0
  41. package/dist/commands.js.map +2 -2
  42. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  43. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  44. package/dist/components/Config.js +9 -8
  45. package/dist/components/Config.js.map +2 -2
  46. package/dist/components/HeaderBar.js +2 -1
  47. package/dist/components/HeaderBar.js.map +2 -2
  48. package/dist/components/Help.js +166 -32
  49. package/dist/components/Help.js.map +2 -2
  50. package/dist/components/HotkeyHelpPanel.js +46 -44
  51. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  52. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  53. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  54. package/dist/components/InfoPanel/index.js +5 -0
  55. package/dist/components/InfoPanel/index.js.map +7 -0
  56. package/dist/components/InfoPanel/types.js +1 -0
  57. package/dist/components/InfoPanel/types.js.map +7 -0
  58. package/dist/components/Logo.js +5 -2
  59. package/dist/components/Logo.js.map +2 -2
  60. package/dist/components/MCPServerApprovalDialog.js +6 -5
  61. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  62. package/dist/components/MCPServerMultiselectDialog.js +5 -4
  63. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  64. package/dist/components/MessageSelector.js +4 -3
  65. package/dist/components/MessageSelector.js.map +2 -2
  66. package/dist/components/ModelConfig.js +13 -12
  67. package/dist/components/ModelConfig.js.map +2 -2
  68. package/dist/components/ModelListManager.js +4 -3
  69. package/dist/components/ModelListManager.js.map +2 -2
  70. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  71. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  72. package/dist/components/ModelSelector/ModelSelector.js +419 -501
  73. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  74. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  75. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  76. package/dist/components/ModelSelector/index.js +1 -3
  77. package/dist/components/ModelSelector/index.js.map +2 -2
  78. package/dist/components/PromptInput.js +77 -44
  79. package/dist/components/PromptInput.js.map +2 -2
  80. package/dist/components/SensitiveFileWarning.js +12 -8
  81. package/dist/components/SensitiveFileWarning.js.map +2 -2
  82. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  83. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  84. package/dist/components/SimpleSelector/index.js +5 -0
  85. package/dist/components/SimpleSelector/index.js.map +7 -0
  86. package/dist/components/SimpleSelector/types.js +1 -0
  87. package/dist/components/SimpleSelector/types.js.map +7 -0
  88. package/dist/components/StatusOverlayContent.js +21 -0
  89. package/dist/components/StatusOverlayContent.js.map +7 -0
  90. package/dist/components/TabbedListView/ScrollableList.js +117 -0
  91. package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
  92. package/dist/components/TabbedListView/SearchInput.js +23 -0
  93. package/dist/components/TabbedListView/SearchInput.js.map +7 -0
  94. package/dist/components/TabbedListView/TabBar.js +20 -0
  95. package/dist/components/TabbedListView/TabBar.js.map +7 -0
  96. package/dist/components/TabbedListView/TabbedListView.js +246 -0
  97. package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
  98. package/dist/components/TabbedListView/index.js +11 -0
  99. package/dist/components/TabbedListView/index.js.map +7 -0
  100. package/dist/components/TabbedListView/types.js +1 -0
  101. package/dist/components/TabbedListView/types.js.map +7 -0
  102. package/dist/components/TodoChangeBlock.js +6 -5
  103. package/dist/components/TodoChangeBlock.js.map +3 -3
  104. package/dist/components/TodoPanel.js +6 -3
  105. package/dist/components/TodoPanel.js.map +3 -3
  106. package/dist/components/TrustDialog.js +6 -5
  107. package/dist/components/TrustDialog.js.map +2 -2
  108. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
  109. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
  110. package/dist/constants/macros.js +1 -1
  111. package/dist/constants/macros.js.map +1 -1
  112. package/dist/constants/product.js +2 -2
  113. package/dist/constants/product.js.map +1 -1
  114. package/dist/constants/prompts.js +17 -0
  115. package/dist/constants/prompts.js.map +2 -2
  116. package/dist/constants/toolInputExamples.js +5 -1
  117. package/dist/constants/toolInputExamples.js.map +2 -2
  118. package/dist/core/backupHook.js +29 -0
  119. package/dist/core/backupHook.js.map +7 -0
  120. package/dist/core/config/defaults.js +8 -2
  121. package/dist/core/config/defaults.js.map +2 -2
  122. package/dist/core/config/schema.js +14 -2
  123. package/dist/core/config/schema.js.map +2 -2
  124. package/dist/core/costTracker.js +0 -16
  125. package/dist/core/costTracker.js.map +2 -2
  126. package/dist/core/tokenStatsManager.js +5 -0
  127. package/dist/core/tokenStatsManager.js.map +2 -2
  128. package/dist/cost-tracker.js +0 -16
  129. package/dist/cost-tracker.js.map +2 -2
  130. package/dist/entrypoints/bootstrap.js +56 -0
  131. package/dist/entrypoints/bootstrap.js.map +7 -0
  132. package/dist/entrypoints/cli.js +164 -23
  133. package/dist/entrypoints/cli.js.map +3 -3
  134. package/dist/history.js +75 -15
  135. package/dist/history.js.map +2 -2
  136. package/dist/i18n/index.js +2 -2
  137. package/dist/i18n/index.js.map +2 -2
  138. package/dist/i18n/locales/en.js +582 -1
  139. package/dist/i18n/locales/en.js.map +2 -2
  140. package/dist/i18n/locales/zh-CN.js +582 -1
  141. package/dist/i18n/locales/zh-CN.js.map +2 -2
  142. package/dist/i18n/types.js.map +1 -1
  143. package/dist/index.js +1 -1
  144. package/dist/index.js.map +2 -2
  145. package/dist/messages.js +11 -0
  146. package/dist/messages.js.map +2 -2
  147. package/dist/permissions.js.map +2 -2
  148. package/dist/query.js +9 -0
  149. package/dist/query.js.map +2 -2
  150. package/dist/screens/REPL.js +45 -7
  151. package/dist/screens/REPL.js.map +2 -2
  152. package/dist/services/customCommands.js +44 -16
  153. package/dist/services/customCommands.js.map +2 -2
  154. package/dist/services/plugins/lspServers.js +1 -1
  155. package/dist/services/plugins/lspServers.js.map +2 -2
  156. package/dist/services/plugins/pluginRuntime.js +2 -1
  157. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  158. package/dist/services/plugins/pluginValidation.js +10 -3
  159. package/dist/services/plugins/pluginValidation.js.map +2 -2
  160. package/dist/services/plugins/skillMarketplace.js +16 -8
  161. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  162. package/dist/services/systemReminder.js +17 -6
  163. package/dist/services/systemReminder.js.map +2 -2
  164. package/dist/tools/FileEditTool/FileEditTool.js +7 -0
  165. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  166. package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
  167. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  168. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  169. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  170. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  171. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  172. package/dist/tools/TaskTool/TaskTool.js +179 -1
  173. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  174. package/dist/tools/TodoWriteTool/prompt.js +21 -0
  175. package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
  176. package/dist/tools/URLFetcherTool/prompt.js +14 -9
  177. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  178. package/dist/tools/WebSearchTool/prompt.js +12 -6
  179. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  180. package/dist/types/PermissionMode.js +30 -1
  181. package/dist/types/PermissionMode.js.map +2 -2
  182. package/dist/types/plugin.js +2 -4
  183. package/dist/types/plugin.js.map +2 -2
  184. package/dist/utils/agentHookExecutor.js +103 -0
  185. package/dist/utils/agentHookExecutor.js.map +7 -0
  186. package/dist/utils/agentLoader.js +272 -32
  187. package/dist/utils/agentLoader.js.map +2 -2
  188. package/dist/utils/agentMemory.js +134 -0
  189. package/dist/utils/agentMemory.js.map +7 -0
  190. package/dist/utils/claudeCodeSync.js +439 -0
  191. package/dist/utils/claudeCodeSync.js.map +7 -0
  192. package/dist/utils/config.js +52 -24
  193. package/dist/utils/config.js.map +2 -2
  194. package/dist/utils/configPaths.js +199 -0
  195. package/dist/utils/configPaths.js.map +7 -0
  196. package/dist/utils/execFileNoThrow.js +2 -1
  197. package/dist/utils/execFileNoThrow.js.map +2 -2
  198. package/dist/utils/historyManager.js +234 -0
  199. package/dist/utils/historyManager.js.map +7 -0
  200. package/dist/utils/marketplaceManager.js +80 -43
  201. package/dist/utils/marketplaceManager.js.map +2 -2
  202. package/dist/utils/messages.js +13 -8
  203. package/dist/utils/messages.js.map +2 -2
  204. package/dist/utils/migration/index.js +37 -0
  205. package/dist/utils/migration/index.js.map +7 -0
  206. package/dist/utils/migration/migrateHistory.js +273 -0
  207. package/dist/utils/migration/migrateHistory.js.map +7 -0
  208. package/dist/utils/migration/migrateTodos.js +323 -0
  209. package/dist/utils/migration/migrateTodos.js.map +7 -0
  210. package/dist/utils/pasteCache.js +309 -0
  211. package/dist/utils/pasteCache.js.map +7 -0
  212. package/dist/utils/pluginInstaller.js +34 -24
  213. package/dist/utils/pluginInstaller.js.map +2 -2
  214. package/dist/utils/pluginLoader.js +54 -28
  215. package/dist/utils/pluginLoader.js.map +2 -2
  216. package/dist/utils/repoFetcher.js +110 -0
  217. package/dist/utils/repoFetcher.js.map +7 -0
  218. package/dist/utils/sessionIndex.js +192 -0
  219. package/dist/utils/sessionIndex.js.map +7 -0
  220. package/dist/utils/sessionTracker.js +170 -0
  221. package/dist/utils/sessionTracker.js.map +7 -0
  222. package/dist/utils/skillLoader.js +103 -5
  223. package/dist/utils/skillLoader.js.map +2 -2
  224. package/dist/utils/stats.js +417 -0
  225. package/dist/utils/stats.js.map +7 -0
  226. package/dist/utils/stringSubstitution.js +106 -0
  227. package/dist/utils/stringSubstitution.js.map +7 -0
  228. package/dist/utils/teamConfig.js +156 -14
  229. package/dist/utils/teamConfig.js.map +2 -2
  230. package/dist/utils/terminal.js +1 -1
  231. package/dist/utils/terminal.js.map +2 -2
  232. package/dist/utils/todoStorage.js +51 -19
  233. package/dist/utils/todoStorage.js.map +2 -2
  234. package/dist/utils/tooling/safeRender.js.map +2 -2
  235. package/dist/version.js +2 -2
  236. package/dist/version.js.map +1 -1
  237. package/package.json +71 -28
  238. package/scripts/{postinstall.js → postinstall.cjs} +1 -1
@@ -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": "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",
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();
@@ -195,7 +196,8 @@ function createCustomCommand(frontmatter, content, filePath, baseDir) {
195
196
  const pathParts = relativePath.split("/");
196
197
  const fileName = pathParts[pathParts.length - 1].replace(".md", "");
197
198
  const userMintoDir = join(homedir(), ".minto", "commands");
198
- const scope = baseDir === userMintoDir ? "user" : "project";
199
+ const userClaudeDir = join(homedir(), ".claude", "commands");
200
+ const scope = baseDir === userMintoDir || baseDir === userClaudeDir ? "user" : "project";
199
201
  const prefix = scope === "user" ? "user" : "project";
200
202
  let finalName;
201
203
  if (frontmatter.name) {
@@ -233,9 +235,11 @@ function createCustomCommand(frontmatter, content, filePath, baseDir) {
233
235
  },
234
236
  async getPromptForCommand(args) {
235
237
  let prompt = content.trim();
236
- if (prompt.includes("$ARGUMENTS")) {
237
- prompt = prompt.replace(/\$ARGUMENTS/g, args || "");
238
- }
238
+ prompt = await substituteVariables(prompt, args || "", {
239
+ cwd: getCwd(),
240
+ allowDynamicCommands: false
241
+ // Security: disable !`command` by default
242
+ });
239
243
  if (argNames && argNames.length > 0) {
240
244
  const argValues = args.trim().split(/\s+/);
241
245
  argNames.forEach((argName, index) => {
@@ -243,7 +247,7 @@ function createCustomCommand(frontmatter, content, filePath, baseDir) {
243
247
  prompt = prompt.replace(new RegExp(`\\{${argName}\\}`, "g"), value);
244
248
  });
245
249
  }
246
- if (args.trim() && !prompt.includes("$ARGUMENTS") && (!argNames || argNames.length === 0)) {
250
+ if (args.trim() && !content.includes("$ARGUMENTS") && !content.includes("$0") && (!argNames || argNames.length === 0)) {
247
251
  prompt += `
248
252
 
249
253
  Additional context: ${args}`;
@@ -267,26 +271,43 @@ IMPORTANT: You are restricted to using only these tools: ${allowedToolsStr}. Do
267
271
  }
268
272
  const loadCustomCommands = memoize(
269
273
  async () => {
274
+ const userClaudeDir = join(homedir(), ".claude", "commands");
270
275
  const userMintoDir = join(homedir(), ".minto", "commands");
276
+ const projectClaudeDir = join(getCwd(), ".claude", "commands");
271
277
  const projectMintoDir = join(getCwd(), ".minto", "commands");
272
278
  const abortController = new AbortController();
273
279
  const timeout = setTimeout(() => abortController.abort(), 3e3);
274
280
  try {
275
281
  const startTime = Date.now();
276
- const [projectMintoFiles, userMintoFiles] = await Promise.all([
282
+ const [
283
+ projectClaudeFiles,
284
+ projectMintoFiles,
285
+ userClaudeFiles,
286
+ userMintoFiles
287
+ ] = await Promise.all([
288
+ existsSync(projectClaudeDir) ? scanMarkdownFiles(
289
+ ["--files", "--hidden", "--glob", "*.md"],
290
+ projectClaudeDir,
291
+ abortController.signal
292
+ ) : Promise.resolve([]),
277
293
  existsSync(projectMintoDir) ? scanMarkdownFiles(
278
294
  ["--files", "--hidden", "--glob", "*.md"],
279
295
  projectMintoDir,
280
296
  abortController.signal
281
297
  ) : Promise.resolve([]),
298
+ existsSync(userClaudeDir) ? scanMarkdownFiles(
299
+ ["--files", "--glob", "*.md"],
300
+ userClaudeDir,
301
+ abortController.signal
302
+ ) : Promise.resolve([]),
282
303
  existsSync(userMintoDir) ? scanMarkdownFiles(
283
304
  ["--files", "--glob", "*.md"],
284
305
  userMintoDir,
285
306
  abortController.signal
286
307
  ) : Promise.resolve([])
287
308
  ]);
288
- const projectFiles = [...projectMintoFiles];
289
- const userFiles = [...userMintoFiles];
309
+ const projectFiles = [...projectClaudeFiles, ...projectMintoFiles];
310
+ const userFiles = [...userClaudeFiles, ...userMintoFiles];
290
311
  const allFiles = [...projectFiles, ...userFiles];
291
312
  const duration = Date.now() - startTime;
292
313
  const commands = [];
@@ -338,8 +359,10 @@ const loadCustomCommands = memoize(
338
359
  () => {
339
360
  const cwd = getCwd();
340
361
  const userMintoDir = join(homedir(), ".minto", "commands");
362
+ const userClaudeDir = join(homedir(), ".claude", "commands");
341
363
  const projectMintoDir = join(cwd, ".minto", "commands");
342
- return `${cwd}:${existsSync(userMintoDir)}:${existsSync(projectMintoDir)}:${Math.floor(Date.now() / 6e4)}`;
364
+ const projectClaudeDir = join(cwd, ".claude", "commands");
365
+ return `${cwd}:${existsSync(userMintoDir)}:${existsSync(userClaudeDir)}:${existsSync(projectMintoDir)}:${existsSync(projectClaudeDir)}:${Math.floor(Date.now() / 6e4)}`;
343
366
  }
344
367
  );
345
368
  const reloadCustomCommands = () => {
@@ -348,12 +371,14 @@ const reloadCustomCommands = () => {
348
371
  function getCustomCommandDirectories() {
349
372
  return {
350
373
  user: join(homedir(), ".minto", "commands"),
351
- project: join(getCwd(), ".minto", "commands")
374
+ userClaude: join(homedir(), ".claude", "commands"),
375
+ project: join(getCwd(), ".minto", "commands"),
376
+ projectClaude: join(getCwd(), ".claude", "commands")
352
377
  };
353
378
  }
354
379
  function hasCustomCommands() {
355
- const { user, project } = getCustomCommandDirectories();
356
- return existsSync(user) || existsSync(project);
380
+ const { user, userClaude, project, projectClaude } = getCustomCommandDirectories();
381
+ return existsSync(user) || existsSync(userClaude) || existsSync(project) || existsSync(projectClaude);
357
382
  }
358
383
  const loadPluginCommands = memoize(
359
384
  async () => {
@@ -384,9 +409,11 @@ const loadPluginCommands = memoize(
384
409
  },
385
410
  async getPromptForCommand(args) {
386
411
  let prompt = pluginCommand.config.content.trim();
387
- if (prompt.includes("$ARGUMENTS")) {
388
- prompt = prompt.replace(/\$ARGUMENTS/g, args || "");
389
- }
412
+ prompt = await substituteVariables(prompt, args || "", {
413
+ cwd: getCwd(),
414
+ allowDynamicCommands: false
415
+ // Security: disable !`command` by default
416
+ });
390
417
  if (pluginCommand.config.argNames && pluginCommand.config.argNames.length > 0) {
391
418
  const argValues = args.trim().split(/\s+/);
392
419
  pluginCommand.config.argNames.forEach((argName, index) => {
@@ -397,7 +424,8 @@ const loadPluginCommands = memoize(
397
424
  );
398
425
  });
399
426
  }
400
- if (args.trim() && !prompt.includes("$ARGUMENTS") && (!pluginCommand.config.argNames || pluginCommand.config.argNames.length === 0)) {
427
+ const originalContent = pluginCommand.config.content;
428
+ if (args.trim() && !originalContent.includes("$ARGUMENTS") && !originalContent.includes("$0") && (!pluginCommand.config.argNames || pluginCommand.config.argNames.length === 0)) {
401
429
  prompt += `
402
430
 
403
431
  Additional context: ${args}`;