@vybestack/llxprt-code 0.10.0 → 0.11.0-nightly.260728.ffaa8d5d7

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 (126) hide show
  1. package/package.json +13 -13
  2. package/src/commands/mcp/add.ts +8 -4
  3. package/src/config/cliArgParser.ts +2 -0
  4. package/src/config/config.ts +2 -0
  5. package/src/config/configBuilder.ts +3 -0
  6. package/src/config/configError.ts +23 -0
  7. package/src/config/extensions/extensionEnablement.ts +62 -1
  8. package/src/config/interactiveContext.ts +2 -1
  9. package/src/config/intermediateConfig.ts +4 -0
  10. package/src/config/keyBindings.ts +29 -3
  11. package/src/config/policy.ts +7 -1
  12. package/src/config/postConfigRuntime.ts +20 -14
  13. package/src/config/settings-schema/schema-ui.ts +9 -0
  14. package/src/config/settingsLoader.ts +21 -17
  15. package/src/config/settingsSchema.ts +2 -2
  16. package/src/config/trustedFolders.ts +275 -58
  17. package/src/config/yargsOptions.ts +7 -0
  18. package/src/generated/git-commit.json +1 -1
  19. package/src/nonInteractiveCli.ts +1 -0
  20. package/src/nonInteractiveCliSupport.ts +171 -51
  21. package/src/runtime/interactiveToolScheduler.ts +6 -6
  22. package/src/services/BuiltinCommandLoader.ts +33 -25
  23. package/src/services/FileCommandLoader.ts +34 -7
  24. package/src/test-utils/async.ts +20 -0
  25. package/src/test-utils/render.tsx +10 -1
  26. package/src/ui/App.tsx +17 -10
  27. package/src/ui/AppContainerRuntime.tsx +7 -9
  28. package/src/ui/cliUiRuntime.ts +28 -0
  29. package/src/ui/commands/authCommand.ts +240 -3
  30. package/src/ui/commands/compressCommand.ts +9 -1
  31. package/src/ui/commands/directoryCommand.tsx +1 -1
  32. package/src/ui/commands/logoutCommand.ts +2 -2
  33. package/src/ui/commands/permissionsCommand.ts +77 -20
  34. package/src/ui/commands/policiesCommand.ts +6 -1
  35. package/src/ui/commands/quotaCommand.ts +501 -0
  36. package/src/ui/commands/statsCommand.ts +2 -2
  37. package/src/ui/commands/statsQuota.ts +1 -1
  38. package/src/ui/commands/subagentCommand.ts +59 -27
  39. package/src/ui/components/AuthDialog.tsx +3 -3
  40. package/src/ui/components/Composer.tsx +1 -0
  41. package/src/ui/components/DialogManager.tsx +9 -2
  42. package/src/ui/components/FolderTrustDialog.tsx +71 -60
  43. package/src/ui/components/PermissionsModifyTrustDialog.tsx +211 -146
  44. package/src/ui/components/ProfileCreateWizard/constants.ts +13 -1
  45. package/src/ui/components/QueuedMessagesPanel.tsx +388 -0
  46. package/src/ui/components/inputPromptHooks.ts +2 -0
  47. package/src/ui/components/inputPromptKeyHandlers.ts +14 -0
  48. package/src/ui/components/inputPromptTypes.ts +6 -0
  49. package/src/ui/components/messages/AiMessage.tsx +24 -12
  50. package/src/ui/components/messages/ToolMessage.tsx +26 -40
  51. package/src/ui/containers/AppContainer/builders/buildUIActions.ts +3 -1
  52. package/src/ui/containers/AppContainer/builders/buildUIState.ts +5 -4
  53. package/src/ui/containers/AppContainer/hooks/useAppBootstrap.ts +3 -33
  54. package/src/ui/containers/AppContainer/hooks/useAppDialogs.ts +2 -14
  55. package/src/ui/containers/AppContainer/hooks/useAppInput.ts +31 -25
  56. package/src/ui/containers/AppContainer/hooks/useAppLayout.ts +90 -60
  57. package/src/ui/containers/AppContainer/hooks/useDisplayPreferences.ts +10 -0
  58. package/src/ui/containers/AppContainer/hooks/useInputHandling.ts +3 -17
  59. package/src/ui/containers/AppContainer/hooks/useKeybindings.ts +51 -38
  60. package/src/ui/containers/AppContainer/hooks/useSteer.ts +51 -0
  61. package/src/ui/contexts/KeypressContext.tsx +13 -2
  62. package/src/ui/contexts/ShellCommandDisplayContext.tsx +103 -0
  63. package/src/ui/contexts/TodoContext.tsx +0 -13
  64. package/src/ui/contexts/TodoProvider.tsx +1 -34
  65. package/src/ui/contexts/UIActionsContext.tsx +2 -1
  66. package/src/ui/contexts/UIStateContext.tsx +3 -2
  67. package/src/ui/hooks/agentStream/streamUtils.ts +0 -24
  68. package/src/ui/hooks/agentStream/thoughtState.ts +110 -30
  69. package/src/ui/hooks/agentStream/types.ts +1 -0
  70. package/src/ui/hooks/agentStream/useAgentEventStream.ts +8 -17
  71. package/src/ui/hooks/agentStream/useAgentStream.ts +2 -2
  72. package/src/ui/hooks/agentStream/useAgentStreamLifecycle.ts +4 -5
  73. package/src/ui/hooks/agentStream/useAgentStreamOrchestration.ts +12 -5
  74. package/src/ui/hooks/agentStream/useQueuedSubmissions.ts +99 -0
  75. package/src/ui/hooks/agentStream/useStreamEventHandlers.ts +4 -13
  76. package/src/ui/hooks/agentStream/useStreamState.ts +60 -41
  77. package/src/ui/hooks/agentStream/useSubmitQuery.ts +284 -59
  78. package/src/ui/hooks/slashCommandProcessorSupport.ts +4 -0
  79. package/src/ui/hooks/useAgentStream-test-helpers.ts +1 -0
  80. package/src/ui/hooks/useAutoAcceptIndicator.ts +13 -0
  81. package/src/ui/hooks/useFolderTrust.ts +118 -81
  82. package/src/ui/hooks/useGitBranchName.ts +79 -33
  83. package/src/ui/hooks/useIdeTrustListener.ts +5 -19
  84. package/src/ui/hooks/usePermissionsModifyTrust.ts +223 -85
  85. package/src/ui/hooks/useReactToolScheduler.ts +13 -17
  86. package/src/ui/hooks/useTodoPausePreserver.ts +0 -55
  87. package/src/ui/layouts/DefaultAppLayout.tsx +2 -0
  88. package/src/ui/layouts/DefaultAppLayoutHelpers.tsx +37 -162
  89. package/src/ui/layouts/InlineContent.tsx +198 -0
  90. package/src/ui/trustDialogHelpers.ts +190 -0
  91. package/src/utils/cleanup-state.ts +115 -0
  92. package/src/utils/cleanup.ts +32 -34
  93. package/src/utils/sandbox-containers.ts +183 -53
  94. package/src/utils/sandbox-exec.ts +9 -3
  95. package/src/zed-integration/acp-terminal-shell-host.ts +112 -0
  96. package/src/zed-integration/acp-types.ts +35 -0
  97. package/src/zed-integration/fileSystemService.ts +1 -1
  98. package/src/zed-integration/runZedIntegration.ts +142 -0
  99. package/src/zed-integration/zed-agent-event-handler.ts +179 -0
  100. package/src/zed-integration/zed-agent-setup.ts +43 -0
  101. package/src/zed-integration/zed-command-registry.ts +167 -0
  102. package/src/zed-integration/zed-config-options.ts +280 -0
  103. package/src/zed-integration/zed-content-utils.ts +2 -2
  104. package/src/zed-integration/zed-helpers.ts +132 -0
  105. package/src/zed-integration/zed-initialize.ts +64 -0
  106. package/src/zed-integration/zed-plan-update.ts +20 -0
  107. package/src/zed-integration/zed-prompt-command.ts +77 -0
  108. package/src/zed-integration/zed-session-config.ts +119 -0
  109. package/src/zed-integration/zed-session-errors.ts +337 -0
  110. package/src/zed-integration/zed-session-events.ts +216 -0
  111. package/src/zed-integration/zed-session-info.ts +255 -0
  112. package/src/zed-integration/zed-session-lifecycle.ts +186 -0
  113. package/src/zed-integration/zed-session-listing.ts +153 -0
  114. package/src/zed-integration/zed-session-loader.ts +193 -0
  115. package/src/zed-integration/zed-session-pagination.ts +240 -0
  116. package/src/zed-integration/zed-session-replay.ts +564 -0
  117. package/src/zed-integration/zed-stream-batcher.ts +236 -0
  118. package/src/zed-integration/zed-terminal-manager.ts +416 -0
  119. package/src/zed-integration/zed-terminal-setup.ts +72 -0
  120. package/src/zed-integration/zed-test-helpers.ts +349 -4
  121. package/src/zed-integration/zed-tool-handler.ts +47 -5
  122. package/src/zed-integration/zedIntegration.ts +538 -587
  123. package/src/services/todo-continuation/todoContinuationService.ts +0 -610
  124. package/src/ui/containers/AppContainer/hooks/useIdeRestartHotkey.ts +0 -33
  125. package/src/ui/containers/AppContainer/hooks/useTodoContinuationFlow.ts +0 -160
  126. package/src/ui/hooks/useTodoContinuation.ts +0 -299
@@ -23,6 +23,7 @@ import type {
23
23
  } from '@vybestack/llxprt-code-core';
24
24
  import type { ToolInfo } from '@vybestack/llxprt-code-agents';
25
25
  import type { SlashCommandRuntime } from '../../../cliUiRuntime.js';
26
+ import type { QueuedSubmission } from '../../../hooks/agentStream/types.js';
26
27
  import type { SlashCommand, CommandContext } from '../../../commands/types.js';
27
28
  import type { LoadedSettings } from '../../../../config/settings.js';
28
29
  import type {
@@ -135,7 +136,6 @@ export interface UIStateParams {
135
136
  ctrlCPressedOnce: boolean;
136
137
  ctrlDPressedOnce: boolean;
137
138
  showEscapePrompt: boolean;
138
- showIdeRestartPrompt: boolean;
139
139
  quittingMessages: HistoryItem[] | null;
140
140
 
141
141
  // Display options
@@ -143,6 +143,8 @@ export interface UIStateParams {
143
143
  showErrorDetails: boolean;
144
144
  showToolDescriptions: boolean;
145
145
  isTodoPanelCollapsed: boolean;
146
+ isQueuedMessagesPanelCollapsed: boolean;
147
+ queuedSubmissions: readonly QueuedSubmission[];
146
148
  isNarrow: boolean;
147
149
  vimModeEnabled: boolean;
148
150
  vimMode: string | undefined;
@@ -195,7 +197,6 @@ export interface UIStateParams {
195
197
  currentIDE: IdeInfo | undefined;
196
198
 
197
199
  // Trust
198
- isRestarting: boolean;
199
200
  isTrustedFolder: boolean;
200
201
 
201
202
  // Welcome onboarding
@@ -316,7 +317,6 @@ function buildConfirmationAndExit(p: UIStateParams) {
316
317
  ctrlCPressedOnce: p.ctrlCPressedOnce,
317
318
  ctrlDPressedOnce: p.ctrlDPressedOnce,
318
319
  showEscapePrompt: p.showEscapePrompt,
319
- showIdeRestartPrompt: p.showIdeRestartPrompt,
320
320
  quittingMessages: p.quittingMessages,
321
321
  };
322
322
  }
@@ -327,6 +327,8 @@ function buildDisplayAndContext(p: UIStateParams) {
327
327
  showErrorDetails: p.showErrorDetails,
328
328
  showToolDescriptions: p.showToolDescriptions,
329
329
  isTodoPanelCollapsed: p.isTodoPanelCollapsed,
330
+ isQueuedMessagesPanelCollapsed: p.isQueuedMessagesPanelCollapsed,
331
+ queuedSubmissions: p.queuedSubmissions,
330
332
  isNarrow: p.isNarrow,
331
333
  vimModeEnabled: p.vimModeEnabled,
332
334
  vimMode: p.vimMode,
@@ -365,7 +367,6 @@ function buildProcessingAndCommands(p: UIStateParams) {
365
367
  commandContext: p.commandContext,
366
368
  shouldShowIdePrompt: p.shouldShowIdePrompt,
367
369
  currentIDE: p.currentIDE,
368
- isRestarting: p.isRestarting,
369
370
  isTrustedFolder: p.isTrustedFolder,
370
371
  };
371
372
  }
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import type React from 'react';
8
- import { useCallback, useEffect, useMemo, useState, useRef } from 'react';
8
+ import { useEffect, useMemo, useState } from 'react';
9
9
  import { useStdin, useStdout } from 'ink';
10
10
  import { useResponsive } from '../../../hooks/useResponsive.js';
11
11
  import { useBracketedPaste } from '../../../hooks/useBracketedPaste.js';
@@ -18,7 +18,6 @@ import {
18
18
  } from '../../../../constants/historyLimits.js';
19
19
  import { useHistory } from '../../../hooks/useHistoryManager.js';
20
20
  import { useMemoryMonitor } from '../../../hooks/useMemoryMonitor.js';
21
- import { TodoPausePreserver } from '../../../hooks/useTodoPausePreserver.js';
22
21
  import {
23
22
  type IContent,
24
23
  type IdeInfo,
@@ -41,7 +40,6 @@ import { registerCleanup } from '../../../../utils/cleanup.js';
41
40
  import type { Agent } from '@vybestack/llxprt-code-agents';
42
41
  import type { LoadedSettings } from '../../../../config/settings.js';
43
42
  import type { HistoryItem } from '../../../types.js';
44
- import type { TodoContinuationHook } from './useTodoContinuationFlow.js';
45
43
  import type {
46
44
  AgentClientSource,
47
45
  StreamRuntime,
@@ -106,13 +104,6 @@ export interface AppBootstrapResult {
106
104
  tokenMetrics: ReturnType<typeof useTokenMetricsTracking>['tokenMetrics'];
107
105
  todos: ReturnType<typeof useTodoContext>['todos'];
108
106
  updateTodos: ReturnType<typeof useTodoContext>['updateTodos'];
109
- todoPauseController: TodoPausePreserver;
110
- todoContinuationRef: React.MutableRefObject<Pick<
111
- TodoContinuationHook,
112
- 'handleTodoPause' | 'clearPause'
113
- > | null>;
114
- hadToolCallsRef: React.MutableRefObject<boolean>;
115
- registerTodoPause: () => void;
116
107
  recordingIntegrationRef: React.MutableRefObject<RecordingIntegration | null>;
117
108
  recordingSwapCallbacks: ReturnType<
118
109
  typeof useRecordingInfrastructure
@@ -192,27 +183,10 @@ function useBootstrapHistory(props: AppBootstrapProps) {
192
183
  };
193
184
  }
194
185
 
195
- /** Initializes task-list state and pause controller */
186
+ /** Initializes task-list state */
196
187
  function useBootstrapTodo() {
197
188
  const { todos, updateTodos } = useTodoContext();
198
- const todoPauseController = useMemo(() => new TodoPausePreserver(), []);
199
- const todoContinuationRef = useRef<Pick<
200
- TodoContinuationHook,
201
- 'handleTodoPause' | 'clearPause'
202
- > | null>(null);
203
- const hadToolCallsRef = useRef<boolean>(false);
204
- const registerTodoPause = useCallback(() => {
205
- todoPauseController.registerTodoPause();
206
- todoContinuationRef.current?.handleTodoPause('paused by model');
207
- }, [todoPauseController]);
208
- return {
209
- todos,
210
- updateTodos,
211
- todoPauseController,
212
- todoContinuationRef,
213
- hadToolCallsRef,
214
- registerTodoPause,
215
- };
189
+ return { todos, updateTodos };
216
190
  }
217
191
 
218
192
  /** Initializes recording, IDE prompt, messages, and token metrics */
@@ -324,10 +298,6 @@ export function useAppBootstrap(props: AppBootstrapProps): AppBootstrapResult {
324
298
  stdout: h.stdout,
325
299
  todos: t.todos,
326
300
  updateTodos: t.updateTodos,
327
- todoPauseController: t.todoPauseController,
328
- todoContinuationRef: t.todoContinuationRef,
329
- hadToolCallsRef: t.hadToolCallsRef,
330
- registerTodoPause: t.registerTodoPause,
331
301
  recordingIntegrationRef: e.recordingIntegrationRef,
332
302
  recordingSwapCallbacks: e.recordingSwapCallbacks,
333
303
  idePromptAnswered: e.idePromptAnswered,
@@ -11,7 +11,6 @@ import { useThemeCommand } from '../../../hooks/useThemeCommand.js';
11
11
  import { useAuthCommand } from '../../../hooks/useAuthCommand.js';
12
12
  import { useFolderTrust } from '../../../hooks/useFolderTrust.js';
13
13
  import { useWelcomeOnboarding } from '../../../hooks/useWelcomeOnboarding.js';
14
- import { useIdeTrustListener } from '../../../hooks/useIdeTrustListener.js';
15
14
  import { useEditorSettings } from '../../../hooks/useEditorSettings.js';
16
15
  import { useExtensionUpdates } from '../../../hooks/useExtensionUpdates.js';
17
16
  import { useOAuthOrchestration } from '../../../hooks/useOAuthOrchestration.js';
@@ -27,7 +26,6 @@ import { useDisplayPreferences } from './useDisplayPreferences.js';
27
26
  import { useModelTracking } from './useModelTracking.js';
28
27
  import { useIdeContextBridge } from './useIdeContextBridge.js';
29
28
  import { useQueueErrorTimeout } from './useQueueErrorTimeout.js';
30
- import { useIdeRestartHotkey } from './useIdeRestartHotkey.js';
31
29
  import { useMemoryRefreshAction } from './useMemoryRefreshAction.js';
32
30
  import { useModelRuntimeSync } from './useModelRuntimeSync.js';
33
31
  import { useAppEventHandlers } from './useAppEventHandlers.js';
@@ -73,7 +71,6 @@ function useDialogsState() {
73
71
  IdeContext | undefined
74
72
  >();
75
73
  const [showEscapePrompt, setShowEscapePrompt] = useState(false);
76
- const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
77
74
  const [isProcessing, setIsProcessing] = useState<boolean>(false);
78
75
  const [embeddedShellFocused, setEmbeddedShellFocused] = useState(false);
79
76
  const [queueErrorMessage, setQueueErrorMessage] = useState<string | null>(
@@ -115,8 +112,6 @@ function useDialogsState() {
115
112
  setIdeContextState,
116
113
  showEscapePrompt,
117
114
  setShowEscapePrompt,
118
- showIdeRestartPrompt,
119
- setShowIdeRestartPrompt,
120
115
  isProcessing,
121
116
  setIsProcessing,
122
117
  embeddedShellFocused,
@@ -183,16 +178,11 @@ function useIdeTrustEffect(
183
178
  config: AppDialogsParams['config'],
184
179
  st: ReturnType<typeof useDialogsState>,
185
180
  ) {
186
- const { needsRestart: ideNeedsRestart } = useIdeTrustListener(config);
187
- useEffect(() => {
188
- if (ideNeedsRestart) st.setShowIdeRestartPrompt(true);
189
- }, [ideNeedsRestart, st]);
190
181
  useQueueErrorTimeout({
191
182
  queueErrorMessage: st.queueErrorMessage,
192
183
  setQueueErrorMessage: st.setQueueErrorMessage,
193
184
  timeoutMs: QUEUE_ERROR_DISPLAY_DURATION_MS,
194
185
  });
195
- useIdeRestartHotkey({ isActive: st.showIdeRestartPrompt });
196
186
  }
197
187
 
198
188
  function useDialogsAuthProviders(
@@ -280,11 +270,10 @@ function useDialogsAuth(
280
270
  const { config, settings, appState, addItem } = p;
281
271
  const theme = useThemeCommand(settings, appState, addItem);
282
272
  const settingsCmd = useSettingsCommand();
283
- const folderTrust = useFolderTrust(settings, addItem);
273
+ const folderTrust = useFolderTrust(settings, addItem, config);
284
274
  const welcome = useWelcomeOnboarding({
285
275
  settings,
286
- isFolderTrustComplete:
287
- !folderTrust.isFolderTrustDialogOpen && !folderTrust.isRestarting,
276
+ isFolderTrustComplete: !folderTrust.isFolderTrustDialogOpen,
288
277
  agent: p.agent,
289
278
  });
290
279
  useIdeTrustEffect(config, st);
@@ -309,7 +298,6 @@ function useDialogsAuth(
309
298
  closeSettingsDialog: settingsCmd.closeSettingsDialog,
310
299
  isFolderTrustDialogOpen: folderTrust.isFolderTrustDialogOpen,
311
300
  handleFolderTrustSelect: folderTrust.handleFolderTrustSelect,
312
- isRestarting: folderTrust.isRestarting,
313
301
  isWelcomeDialogOpen: welcome.showWelcome,
314
302
  welcomeState: welcome.state,
315
303
  welcomeActions: welcome.actions,
@@ -15,7 +15,7 @@ import { useVimMode } from '../../../contexts/VimModeContext.js';
15
15
  import { useVim } from '../../../hooks/vim.js';
16
16
  import { useTextBuffer } from '../../../components/shared/text-buffer.js';
17
17
  import { useInputHistoryStore } from '../../../hooks/useInputHistoryStore.js';
18
- import { useTodoPausePreserver } from '../../../hooks/useTodoPausePreserver.js';
18
+ import { shouldClearTodos } from '../../../hooks/useTodoPausePreserver.js';
19
19
  import { StreamingState, type HistoryItem } from '../../../types.js';
20
20
  import { submitOAuthCode } from '../../../oauth-submission.js';
21
21
  import { getPendingOAuthProvider } from '../../../oauthGlobalState.js';
@@ -28,6 +28,7 @@ import { useSlashCommandActions } from './useSlashCommandActions.js';
28
28
  import { useExitHandling } from './useExitHandling.js';
29
29
  import { useInputHandling } from './useInputHandling.js';
30
30
  import { useShellFocusAutoReset } from './useShellFocusAutoReset.js';
31
+ import { useSteer } from './useSteer.js';
31
32
  import * as fs from 'fs';
32
33
  import type { AppBootstrapResult } from './useAppBootstrap.js';
33
34
  import type { AppDialogsResult } from './useAppDialogs.js';
@@ -46,10 +47,6 @@ export interface AppInputParams {
46
47
  loadHistory: AppBootstrapResult['loadHistory'];
47
48
  todos: AppBootstrapResult['todos'];
48
49
  updateTodos: AppBootstrapResult['updateTodos'];
49
- todoPauseController: AppBootstrapResult['todoPauseController'];
50
- todoContinuationRef: AppBootstrapResult['todoContinuationRef'];
51
- hadToolCallsRef: AppBootstrapResult['hadToolCallsRef'];
52
- registerTodoPause: AppBootstrapResult['registerTodoPause'];
53
50
  recordingIntegrationRef: AppBootstrapResult['recordingIntegrationRef'];
54
51
  recordingSwapCallbacks: AppBootstrapResult['recordingSwapCallbacks'];
55
52
  recordingIntegration: AppBootstrapResult['recordingIntegration'];
@@ -313,7 +310,6 @@ function useInputStreamSetup(
313
310
  settings,
314
311
  history,
315
312
  addItem,
316
- registerTodoPause,
317
313
  recordingIntegration,
318
314
  runtimeMessageBus,
319
315
  stdout,
@@ -345,7 +341,6 @@ function useInputStreamSetup(
345
341
  setEmbeddedShellFocused,
346
342
  stdout.columns,
347
343
  stdout.rows,
348
- registerTodoPause,
349
344
  handleExternalEditorOpen,
350
345
  recordingIntegration,
351
346
  runtimeMessageBus,
@@ -358,21 +353,15 @@ function useInputStreamWiring(
358
353
  core: ReturnType<typeof useInputCore>,
359
354
  setup: ReturnType<typeof useInputStreamSetup>,
360
355
  ) {
361
- const {
362
- todos,
363
- updateTodos,
364
- todoPauseController,
365
- todoContinuationRef,
366
- hadToolCallsRef,
367
- embeddedShellFocused,
368
- setEmbeddedShellFocused,
369
- } = p;
356
+ const { todos, updateTodos, embeddedShellFocused, setEmbeddedShellFocused } =
357
+ p;
370
358
  const {
371
359
  buffer,
372
360
  inputHistoryStore,
373
361
  lastSubmittedPromptRef,
374
362
  agentStreamResult,
375
363
  } = setup;
364
+ const { submitQuery } = agentStreamResult;
376
365
  const pendingHistoryItems = useMemo(
377
366
  () => [
378
367
  ...(core.pendingHistoryItems as HistoryItem[]),
@@ -390,30 +379,47 @@ function useInputStreamWiring(
390
379
  const { handleFinalSubmit } = useInputHandling({
391
380
  buffer,
392
381
  inputHistoryStore,
393
- submitQuery: agentStreamResult.submitQuery,
382
+ submitQuery,
394
383
  pendingHistoryItems,
395
384
  lastSubmittedPromptRef,
396
- hadToolCallsRef,
397
- todoContinuationRef,
398
385
  needsRelogin: p.appState.needsRelogin,
399
386
  appDispatch: p.appDispatch,
400
387
  });
401
- const { handleUserInputSubmit } = useTodoPausePreserver({
402
- controller: todoPauseController,
403
- updateTodos,
404
- handleFinalSubmit,
405
- todos,
406
- });
388
+ const handleUserInputSubmit = useCallback(
389
+ (submittedValue: string) => {
390
+ if (shouldClearTodos(todos)) {
391
+ updateTodos([]);
392
+ }
393
+ handleFinalSubmit(submittedValue);
394
+ },
395
+ [todos, updateTodos, handleFinalSubmit],
396
+ );
397
+ const enqueueSteer = useCallback(
398
+ (message: string) => {
399
+ void submitQuery(message);
400
+ },
401
+ [submitQuery],
402
+ );
403
+ const handleSteer = useSteer(
404
+ p.agent,
405
+ agentStreamResult.streamingState,
406
+ agentStreamResult.sanitizeContent,
407
+ pendingHistoryItems,
408
+ enqueueSteer,
409
+ );
407
410
  const {
408
411
  activeShellPtyId: _ptyIdFromStream,
409
412
  pendingHistoryItems: _pendingFromStream,
413
+ queuedSubmissions,
410
414
  ...streamRest
411
415
  } = agentStreamResult;
412
416
  return {
413
417
  handleFinalSubmit,
414
418
  handleUserInputSubmit,
419
+ handleSteer,
415
420
  pendingHistoryItems,
416
421
  activeShellPtyId,
422
+ queuedSubmissions,
417
423
  ...streamRest,
418
424
  };
419
425
  }
@@ -12,7 +12,6 @@ import { getAllLlxprtMdFilenames } from '@vybestack/llxprt-code-core';
12
12
  import { useKeybindings } from './useKeybindings.js';
13
13
  import { useLayoutMeasurement } from './useLayoutMeasurement.js';
14
14
  import { useFlickerDetector } from '../../../hooks/useFlickerDetector.js';
15
- import { useTodoContinuationFlow } from './useTodoContinuationFlow.js';
16
15
  import { useSelectionDebugLogger } from './useSelectionDebugLogger.js';
17
16
  import { useClearScreenAction } from './useClearScreenAction.js';
18
17
  import { useConfirmationSelection } from './useConfirmationSelection.js';
@@ -29,10 +28,7 @@ import type { UiRuntime } from '../../../cliUiRuntime.js';
29
28
  export interface AppLayoutParams {
30
29
  // From bootstrap
31
30
  uiRuntime: UiRuntime;
32
- agent: AppBootstrapResult['agent'];
33
31
  settings: AppBootstrapResult['settings'];
34
- todoContinuationRef: AppBootstrapResult['todoContinuationRef'];
35
- hadToolCallsRef: AppBootstrapResult['hadToolCallsRef'];
36
32
  runtimeMessageBus: AppBootstrapResult['runtimeMessageBus'];
37
33
  consoleMessages: AppBootstrapResult['consoleMessages'];
38
34
  clearConsoleMessagesState: AppBootstrapResult['clearConsoleMessagesState'];
@@ -52,6 +48,8 @@ export interface AppLayoutParams {
52
48
  setRenderMarkdown: AppDialogsResult['setRenderMarkdown'];
53
49
  isTodoPanelCollapsed: AppDialogsResult['isTodoPanelCollapsed'];
54
50
  setIsTodoPanelCollapsed: AppDialogsResult['setIsTodoPanelCollapsed'];
51
+ isQueuedMessagesPanelCollapsed: AppDialogsResult['isQueuedMessagesPanelCollapsed'];
52
+ setIsQueuedMessagesPanelCollapsed: AppDialogsResult['setIsQueuedMessagesPanelCollapsed'];
55
53
  setFooterHeight: AppDialogsResult['setFooterHeight'];
56
54
  footerHeight: AppDialogsResult['footerHeight'];
57
55
  copyModeEnabled: AppDialogsResult['copyModeEnabled'];
@@ -84,6 +82,7 @@ export interface AppLayoutParams {
84
82
  handleSlashCommand: AppInputResult['handleSlashCommand'];
85
83
  inputHistoryStore: AppInputResult['inputHistoryStore'];
86
84
  handleUserInputSubmit: AppInputResult['handleUserInputSubmit'];
85
+ handleSteer: AppInputResult['handleSteer'];
87
86
  interactiveRuntimeReady: AppInputResult['interactiveRuntimeReady'];
88
87
  vimModeEnabled: AppInputResult['vimModeEnabled'];
89
88
  terminalHeight: AppInputResult['terminalHeight'];
@@ -98,6 +97,59 @@ function pickCopyModeKeybindingState(p: AppLayoutParams) {
98
97
  };
99
98
  }
100
99
 
100
+ function buildKeybindingsConfig(
101
+ p: AppLayoutParams,
102
+ exitState: {
103
+ requestCtrlCExit: AppLayoutParams['requestCtrlCExit'];
104
+ requestCtrlDExit: AppLayoutParams['requestCtrlDExit'];
105
+ ctrlCPressedOnce: AppLayoutParams['ctrlCPressedOnce'];
106
+ cancelOngoingRequest: AppLayoutParams['cancelOngoingRequest'];
107
+ bufferTextLength: number;
108
+ },
109
+ displayState: {
110
+ showErrorDetails: AppLayoutParams['showErrorDetails'];
111
+ setShowErrorDetails: AppLayoutParams['setShowErrorDetails'];
112
+ showToolDescriptions: AppLayoutParams['showToolDescriptions'];
113
+ setShowToolDescriptions: AppLayoutParams['setShowToolDescriptions'];
114
+ renderMarkdown: AppLayoutParams['renderMarkdown'];
115
+ setRenderMarkdown: AppLayoutParams['setRenderMarkdown'];
116
+ isTodoPanelCollapsed: AppLayoutParams['isTodoPanelCollapsed'];
117
+ setIsTodoPanelCollapsed: AppLayoutParams['setIsTodoPanelCollapsed'];
118
+ isQueuedMessagesPanelCollapsed: AppLayoutParams['isQueuedMessagesPanelCollapsed'];
119
+ setIsQueuedMessagesPanelCollapsed: AppLayoutParams['setIsQueuedMessagesPanelCollapsed'];
120
+ constrainHeight: AppLayoutParams['constrainHeight'];
121
+ setConstrainHeight: AppLayoutParams['setConstrainHeight'];
122
+ refreshStatic: AppLayoutParams['refreshStatic'];
123
+ addItem: AppLayoutParams['addItem'];
124
+ handleSlashCommand: AppLayoutParams['handleSlashCommand'];
125
+ },
126
+ shellState: {
127
+ activeShellPtyId: AppLayoutParams['activeShellPtyId'];
128
+ setEmbeddedShellFocused: AppLayoutParams['setEmbeddedShellFocused'];
129
+ ideContextState: AppLayoutParams['ideContextState'];
130
+ },
131
+ ) {
132
+ const { uiRuntime } = p;
133
+ return {
134
+ exit: exitState,
135
+ display: displayState,
136
+ shell: {
137
+ activeShellPtyId: shellState.activeShellPtyId,
138
+ setEmbeddedShellFocused: shellState.setEmbeddedShellFocused,
139
+ getEnableInteractiveShell: () =>
140
+ uiRuntime.shell.getEnableInteractiveShell(),
141
+ },
142
+ copyMode: pickCopyModeKeybindingState(p),
143
+ ideContext: {
144
+ getIdeMode: () => uiRuntime.ide.getIdeMode(),
145
+ ideContextState: shellState.ideContextState,
146
+ },
147
+ mcp: {
148
+ getMcpServers: () => uiRuntime.mcp.getMcpServers(),
149
+ },
150
+ };
151
+ }
152
+
101
153
  function useLayoutKeybindingsAndHistory(p: AppLayoutParams) {
102
154
  const {
103
155
  uiRuntime,
@@ -114,6 +166,8 @@ function useLayoutKeybindingsAndHistory(p: AppLayoutParams) {
114
166
  setRenderMarkdown,
115
167
  isTodoPanelCollapsed,
116
168
  setIsTodoPanelCollapsed,
169
+ isQueuedMessagesPanelCollapsed,
170
+ setIsQueuedMessagesPanelCollapsed,
117
171
  ideContextState,
118
172
  activeShellPtyId,
119
173
  setEmbeddedShellFocused,
@@ -127,44 +181,36 @@ function useLayoutKeybindingsAndHistory(p: AppLayoutParams) {
127
181
  buffer,
128
182
  useAlternateBuffer,
129
183
  } = p;
130
- useKeybindings({
131
- exit: {
132
- requestCtrlCExit,
133
- requestCtrlDExit,
134
- ctrlCPressedOnce,
135
- cancelOngoingRequest,
136
- bufferTextLength: buffer.text.length,
137
- },
138
- display: {
139
- showErrorDetails,
140
- setShowErrorDetails,
141
- showToolDescriptions,
142
- setShowToolDescriptions,
143
- renderMarkdown,
144
- setRenderMarkdown,
145
- isTodoPanelCollapsed,
146
- setIsTodoPanelCollapsed,
147
- constrainHeight,
148
- setConstrainHeight,
149
- refreshStatic,
150
- addItem,
151
- handleSlashCommand,
152
- },
153
- shell: {
154
- activeShellPtyId,
155
- setEmbeddedShellFocused,
156
- getEnableInteractiveShell: () =>
157
- uiRuntime.shell.getEnableInteractiveShell(),
158
- },
159
- copyMode: pickCopyModeKeybindingState(p),
160
- ideContext: {
161
- getIdeMode: () => uiRuntime.ide.getIdeMode(),
162
- ideContextState,
163
- },
164
- mcp: {
165
- getMcpServers: () => uiRuntime.mcp.getMcpServers(),
166
- },
167
- });
184
+ useKeybindings(
185
+ buildKeybindingsConfig(
186
+ p,
187
+ {
188
+ requestCtrlCExit,
189
+ requestCtrlDExit,
190
+ ctrlCPressedOnce,
191
+ cancelOngoingRequest,
192
+ bufferTextLength: buffer.text.length,
193
+ },
194
+ {
195
+ showErrorDetails,
196
+ setShowErrorDetails,
197
+ showToolDescriptions,
198
+ setShowToolDescriptions,
199
+ renderMarkdown,
200
+ setRenderMarkdown,
201
+ isTodoPanelCollapsed,
202
+ setIsTodoPanelCollapsed,
203
+ isQueuedMessagesPanelCollapsed,
204
+ setIsQueuedMessagesPanelCollapsed,
205
+ constrainHeight,
206
+ setConstrainHeight,
207
+ refreshStatic,
208
+ addItem,
209
+ handleSlashCommand,
210
+ },
211
+ { activeShellPtyId, setEmbeddedShellFocused, ideContextState },
212
+ ),
213
+ );
168
214
  const logger = useLogger(uiRuntime.storage);
169
215
  useInputHistoryBootstrap({ inputHistoryStore, logger });
170
216
  const handleClearScreen = useClearScreenAction({
@@ -178,19 +224,11 @@ function useLayoutKeybindingsAndHistory(p: AppLayoutParams) {
178
224
 
179
225
  function useLayoutMeasure(p: AppLayoutParams) {
180
226
  const {
181
- uiRuntime,
182
- agent,
183
- todoContinuationRef,
184
- hadToolCallsRef,
185
227
  consoleMessages,
186
228
  constrainHeight,
187
229
  setFooterHeight,
188
230
  footerHeight,
189
- streamingState,
190
- history,
191
- pendingHistoryItems,
192
231
  confirmationRequest,
193
- setDebugMessage,
194
232
  terminalHeight,
195
233
  } = p;
196
234
  useSelectionDebugLogger({ confirmationRequest });
@@ -212,16 +250,6 @@ function useLayoutMeasure(p: AppLayoutParams) {
212
250
  [terminalHeight, footerHeight],
213
251
  );
214
252
  useFlickerDetector(rootUiRef, terminalHeight, constrainHeight);
215
- useTodoContinuationFlow({
216
- uiRuntime,
217
- agent,
218
- streamingState,
219
- history,
220
- pendingHistoryItems,
221
- setDebugMessage,
222
- todoContinuationRef,
223
- hadToolCallsRef,
224
- });
225
253
  return {
226
254
  mainControlsRef,
227
255
  pendingHistoryItemRef,
@@ -249,6 +277,7 @@ function useLayoutContext(p: AppLayoutParams) {
249
277
  terminalHeight,
250
278
  terminalWidth,
251
279
  handleUserInputSubmit,
280
+ handleSteer,
252
281
  interactiveRuntimeReady,
253
282
  vimModeEnabled,
254
283
  startupGuardsInitialized,
@@ -298,6 +327,7 @@ function useLayoutContext(p: AppLayoutParams) {
298
327
  mainAreaWidth,
299
328
  placeholder,
300
329
  activeHooks,
330
+ handleSteer,
301
331
  };
302
332
  }
303
333
 
@@ -43,6 +43,10 @@ export interface UseDisplayPreferencesResult {
43
43
  isTodoPanelCollapsed: boolean;
44
44
  setIsTodoPanelCollapsed: (collapsed: boolean) => void;
45
45
 
46
+ // Queued messages panel collapse state
47
+ isQueuedMessagesPanelCollapsed: boolean;
48
+ setIsQueuedMessagesPanelCollapsed: (collapsed: boolean) => void;
49
+
46
50
  // Settings nonce for forcing re-renders when settings change
47
51
  settingsNonce: number;
48
52
  }
@@ -55,6 +59,8 @@ export function useDisplayPreferences(): UseDisplayPreferencesResult {
55
59
  const [copyModeEnabled, setCopyModeEnabled] = useState(false);
56
60
  const [renderMarkdown, setRenderMarkdown] = useState<boolean>(true);
57
61
  const [isTodoPanelCollapsed, setIsTodoPanelCollapsed] = useState(false);
62
+ const [isQueuedMessagesPanelCollapsed, setIsQueuedMessagesPanelCollapsed] =
63
+ useState(false);
58
64
  const [settingsNonce, setSettingsNonce] = useState(0);
59
65
 
60
66
  const toggleDebugProfiler = useCallback(() => {
@@ -98,6 +104,10 @@ export function useDisplayPreferences(): UseDisplayPreferencesResult {
98
104
  isTodoPanelCollapsed,
99
105
  setIsTodoPanelCollapsed,
100
106
 
107
+ // Queued messages panel collapse state
108
+ isQueuedMessagesPanelCollapsed,
109
+ setIsQueuedMessagesPanelCollapsed,
110
+
101
111
  // Settings nonce
102
112
  settingsNonce,
103
113
  };
@@ -18,10 +18,6 @@ export interface UseInputHandlingParams {
18
18
  submitQuery: (query: string) => Promise<void>;
19
19
  pendingHistoryItems: HistoryItemWithoutId[];
20
20
  lastSubmittedPromptRef: React.MutableRefObject<string | null>;
21
- hadToolCallsRef: React.MutableRefObject<boolean>;
22
- todoContinuationRef: React.MutableRefObject<{
23
- clearPause: () => void;
24
- } | null>;
25
21
  /** Whether the user needs to re-authenticate before continuing. */
26
22
  needsRelogin: boolean;
27
23
  /** Dispatch app actions (e.g., open auth dialog). */
@@ -39,7 +35,9 @@ export interface UseInputHandlingResult {
39
35
  /**
40
36
  * Checks if any tool is currently executing in pending history items.
41
37
  */
42
- function isToolExecuting(pendingHistoryItems: HistoryItemWithoutId[]): boolean {
38
+ export function isToolExecuting(
39
+ pendingHistoryItems: HistoryItemWithoutId[],
40
+ ): boolean {
43
41
  return pendingHistoryItems.some((item) => {
44
42
  if (item.type === 'tool_group') {
45
43
  return item.tools.some(
@@ -80,8 +78,6 @@ function useFinalSubmitHandler({
80
78
  inputHistoryStore,
81
79
  submitQuery,
82
80
  lastSubmittedPromptRef,
83
- hadToolCallsRef,
84
- todoContinuationRef,
85
81
  needsRelogin,
86
82
  appDispatch,
87
83
  }: UseInputHandlingParams): (submittedValue: string) => void {
@@ -101,14 +97,6 @@ function useFinalSubmitHandler({
101
97
  return;
102
98
  }
103
99
 
104
- /**
105
- * @plan PLAN-20260129-TODOPERSIST.P12
106
- * Reset continuation attempt counter when user submits a new prompt.
107
- * This prevents the continuation limit from blocking future continuations
108
- * after user interaction.
109
- */
110
- hadToolCallsRef.current = false;
111
- todoContinuationRef.current?.clearPause();
112
100
  lastSubmittedPromptRef.current = trimmedValue;
113
101
  inputHistoryStore.addInput(trimmedValue);
114
102
  void submitQuery(trimmedValue);
@@ -116,8 +104,6 @@ function useFinalSubmitHandler({
116
104
  [
117
105
  submitQuery,
118
106
  inputHistoryStore,
119
- hadToolCallsRef,
120
- todoContinuationRef,
121
107
  lastSubmittedPromptRef,
122
108
  needsRelogin,
123
109
  appDispatch,