@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
@@ -1,160 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Vybestack LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @hook useTodoContinuationFlow
9
- * @description Task-list continuation detection and prompts
10
- * @inputs uiRuntime, streamingState, history, pendingHistoryItems, setDebugMessage, todoContinuationRef, hadToolCallsRef
11
- * @outputs todoContinuationRef
12
- * @sideEffects Effect watching streaming state
13
- * @cleanup N/A
14
- * @strictMode Safe - effect deps are stable
15
- * @subscriptionStrategy Resubscribe
16
- */
17
-
18
- import { useEffect, useMemo, useRef } from 'react';
19
- import {
20
- StreamingState,
21
- type HistoryItem,
22
- type HistoryItemWithoutId,
23
- } from '../../../types.js';
24
-
25
- import {
26
- useTodoContinuation,
27
- type TodoContinuationHook,
28
- } from '../../../hooks/useTodoContinuation.js';
29
- import type { UiRuntime } from '../../../cliUiRuntime.js';
30
- import type { Agent } from '@vybestack/llxprt-code-agents';
31
-
32
- export type { TodoContinuationHook };
33
-
34
- interface UseTodoContinuationFlowOptions {
35
- uiRuntime: UiRuntime;
36
- agent: Agent;
37
- streamingState: StreamingState;
38
- history: HistoryItem[];
39
- pendingHistoryItems: HistoryItemWithoutId[];
40
- setDebugMessage: (message: string) => void;
41
- todoContinuationRef?: React.MutableRefObject<Pick<
42
- TodoContinuationHook,
43
- 'handleTodoPause' | 'clearPause'
44
- > | null>;
45
- hadToolCallsRef?: React.MutableRefObject<boolean>;
46
- }
47
-
48
- export interface UseTodoContinuationFlowResult {
49
- todoContinuationRef: React.MutableRefObject<Pick<
50
- TodoContinuationHook,
51
- 'handleTodoPause' | 'clearPause'
52
- > | null>;
53
- hadToolCallsRef: React.MutableRefObject<boolean>;
54
- }
55
-
56
- export function useTodoContinuationFlow({
57
- uiRuntime,
58
- agent,
59
- streamingState,
60
- history,
61
- pendingHistoryItems,
62
- setDebugMessage,
63
- todoContinuationRef: externalTodoContinuationRef,
64
- hadToolCallsRef: externalHadToolCallsRef,
65
- }: UseTodoContinuationFlowOptions): UseTodoContinuationFlowResult {
66
- const internalTodoContinuationRef = useRef<Pick<
67
- TodoContinuationHook,
68
- 'handleTodoPause' | 'clearPause'
69
- > | null>(null);
70
- const todoContinuationRef =
71
- externalTodoContinuationRef ?? internalTodoContinuationRef;
72
-
73
- /**
74
- * @plan PLAN-20260129-TODOPERSIST.P12
75
- * Wire up task-list continuation detection to trigger continuation prompts
76
- * when streams complete without tool calls and active tasks exist.
77
- */
78
- const continuationRuntime = useMemo(
79
- () => ({
80
- getEphemeralSettings: () => uiRuntime.app.getEphemeralSettings(),
81
- getApprovalMode: () => uiRuntime.approval.getApprovalMode(),
82
- }),
83
- [uiRuntime.app, uiRuntime.approval],
84
- );
85
- const todoContinuation = useTodoContinuation(
86
- agent,
87
- continuationRuntime,
88
- streamingState === StreamingState.Responding ||
89
- streamingState === StreamingState.WaitingForConfirmation,
90
- setDebugMessage,
91
- );
92
-
93
- todoContinuationRef.current = todoContinuation;
94
-
95
- // Track previous streaming state to detect turn completion
96
- const prevStreamingStateRef = useRef<StreamingState>(streamingState);
97
-
98
- /**
99
- * @plan PLAN-20260129-TODOPERSIST.P12
100
- * Track whether tool calls were made during the turn for continuation decision.
101
- * Tool calls signal the AI made progress, so we don't need continuation.
102
- */
103
- const internalHadToolCallsRef = useRef<boolean>(false);
104
- const hadToolCallsRef = externalHadToolCallsRef ?? internalHadToolCallsRef;
105
-
106
- /**
107
- * @plan PLAN-20260129-TODOPERSIST.P12
108
- * Track tool calls by detecting tool_group items in history and pending items.
109
- * Reset hadToolCallsRef when a new turn starts (streamingState transitions TO Responding)
110
- * so that tool calls from previous turns don't suppress continuation prompts.
111
- */
112
- useEffect(() => {
113
- // Detect transition into Responding (new turn start) and reset the flag.
114
- const wasIdle = prevStreamingStateRef.current === StreamingState.Idle;
115
- const isNowResponding = streamingState === StreamingState.Responding;
116
- if (wasIdle && isNowResponding) {
117
- hadToolCallsRef.current = false;
118
- }
119
-
120
- const hasToolCalls =
121
- history.some((item) => item.type === 'tool_group') ||
122
- pendingHistoryItems.some((item) => item.type === 'tool_group');
123
-
124
- if (
125
- hasToolCalls &&
126
- (streamingState === StreamingState.Responding ||
127
- streamingState === StreamingState.WaitingForConfirmation)
128
- ) {
129
- hadToolCallsRef.current = true;
130
- }
131
- }, [history, pendingHistoryItems, streamingState, hadToolCallsRef]);
132
-
133
- // Detect turn completion (streaming goes idle) for continuation logic
134
- useEffect(() => {
135
- const wasActive =
136
- prevStreamingStateRef.current === StreamingState.Responding ||
137
- prevStreamingStateRef.current === StreamingState.WaitingForConfirmation;
138
- const isNowIdle = streamingState === StreamingState.Idle;
139
- prevStreamingStateRef.current = streamingState;
140
-
141
- if (!wasActive || !isNowIdle) {
142
- return;
143
- }
144
-
145
- /**
146
- * @plan PLAN-20260129-TODOPERSIST.P12
147
- * Notify continuation logic that stream completed.
148
- * Pass hadToolCalls to determine if continuation is needed.
149
- */
150
- todoContinuation.handleStreamCompleted(hadToolCallsRef.current);
151
-
152
- // Reset for next turn
153
- hadToolCallsRef.current = false;
154
- }, [streamingState, todoContinuation, hadToolCallsRef]);
155
-
156
- return {
157
- todoContinuationRef,
158
- hadToolCallsRef,
159
- };
160
- }
@@ -1,299 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Vybestack LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import { useState, useRef, useCallback, useEffect } from 'react';
8
- import type { Todo } from '@vybestack/llxprt-code-core';
9
- import { ApprovalMode } from '@vybestack/llxprt-code-core';
10
- import type { Agent } from '@vybestack/llxprt-code-agents';
11
- import { useTodoContext } from '../contexts/TodoContext.js';
12
-
13
- export interface TodoContinuationRuntime {
14
- getEphemeralSettings(): Record<string, unknown>;
15
- getApprovalMode(): ApprovalMode;
16
- }
17
-
18
- export interface ContinuationState {
19
- isActive: boolean;
20
- taskDescription?: string;
21
- attemptCount: number;
22
- lastPromptTime?: Date;
23
- }
24
-
25
- export interface ContinuationOptions {
26
- taskDescription: string;
27
- isYoloMode: boolean;
28
- }
29
-
30
- interface ContinuationConditions {
31
- streamCompleted: boolean;
32
- noToolCallsMade: boolean;
33
- hasActiveTodos: boolean;
34
- continuationEnabled: boolean;
35
- notAlreadyContinuing: boolean;
36
- todoPaused: boolean;
37
- }
38
-
39
- export interface TodoContinuationHook {
40
- handleStreamCompleted: (hadToolCalls: boolean) => void;
41
- continuationState: ContinuationState;
42
- handleTodoPause: (reason: string) => {
43
- type: 'pause';
44
- reason: string;
45
- message: string;
46
- };
47
- clearPause: () => void;
48
- }
49
-
50
- function evaluateConditions(
51
- hadToolCalls: boolean,
52
- todoPaused: boolean,
53
- config: TodoContinuationRuntime,
54
- todos: Todo[],
55
- isActive: boolean,
56
- ): ContinuationConditions {
57
- const ephemeralSettings = config.getEphemeralSettings();
58
- const isEnabled = ephemeralSettings['todo-continuation'] === true;
59
- const hasActiveTodos = todos.some(
60
- (todo) => todo.status === 'pending' || todo.status === 'in_progress',
61
- );
62
- const hadBlockingToolCalls = hadToolCalls && (todoPaused || !hasActiveTodos);
63
-
64
- return {
65
- streamCompleted: true,
66
- noToolCallsMade: !hadBlockingToolCalls,
67
- hasActiveTodos,
68
- continuationEnabled: isEnabled,
69
- notAlreadyContinuing: !isActive,
70
- todoPaused,
71
- };
72
- }
73
-
74
- function shouldTrigger(
75
- conditions: ContinuationConditions,
76
- isResponding: boolean,
77
- ): boolean {
78
- if (isResponding) {
79
- return false;
80
- }
81
-
82
- const baseConditionsMet =
83
- conditions.streamCompleted &&
84
- conditions.noToolCallsMade &&
85
- conditions.hasActiveTodos;
86
- const continuationReady =
87
- conditions.continuationEnabled && conditions.notAlreadyContinuing;
88
- return baseConditionsMet && continuationReady && !conditions.todoPaused;
89
- }
90
-
91
- function findMostRelevantTodo(todos: Todo[]): Todo | null {
92
- const inProgressTodos = todos.filter((todo) => todo.status === 'in_progress');
93
-
94
- if (inProgressTodos.length > 0) {
95
- return inProgressTodos[0];
96
- }
97
-
98
- const pendingTodos = todos.filter((todo) => todo.status === 'pending');
99
-
100
- if (pendingTodos.length > 0) {
101
- return pendingTodos[0];
102
- }
103
-
104
- return null;
105
- }
106
-
107
- function generatePrompt(todo: Todo, config: TodoContinuationRuntime): string {
108
- const isYoloMode = config.getApprovalMode() === ApprovalMode.YOLO;
109
-
110
- if (isYoloMode) {
111
- return `Continue to proceed with the active task without waiting for confirmation: "${todo.content}"`;
112
- }
113
-
114
- return `Please continue working on the following task: "${todo.content}"`;
115
- }
116
-
117
- function sendContinuationPrompt(
118
- agent: Agent,
119
- taskDescription: string,
120
- continuationPrompt: string,
121
- onDebugMessage: (message: string) => void,
122
- setContinuationState: React.Dispatch<React.SetStateAction<ContinuationState>>,
123
- continuationInProgressRef: React.MutableRefObject<boolean>,
124
- abortControllerRef: React.MutableRefObject<AbortController | undefined>,
125
- ): void {
126
- if (continuationInProgressRef.current) {
127
- return;
128
- }
129
-
130
- continuationInProgressRef.current = true;
131
-
132
- setContinuationState((prev) => ({
133
- isActive: true,
134
- taskDescription,
135
- attemptCount: prev.attemptCount + 1,
136
- lastPromptTime: new Date(),
137
- }));
138
-
139
- const abortController = new AbortController();
140
- abortControllerRef.current = abortController;
141
- const promptId = `todo-continuation-${Date.now().toString(16)}`;
142
-
143
- void (async () => {
144
- try {
145
- const stream = agent.stream(continuationPrompt, {
146
- signal: abortController.signal,
147
- promptId,
148
- });
149
- for await (const _event of stream) {
150
- // Continuation prompts are submitted for side effects; the main stream
151
- // UI owns rendering for user-initiated turns.
152
- }
153
- } catch (error: unknown) {
154
- if (!abortController.signal.aborted) {
155
- onDebugMessage(
156
- `[TodoContinuation] Error sending continuation prompt: ${error instanceof Error ? error.message : String(error)}`,
157
- );
158
- setContinuationState((prev) => ({
159
- isActive: false,
160
- attemptCount: prev.attemptCount,
161
- lastPromptTime: prev.lastPromptTime,
162
- taskDescription: prev.taskDescription,
163
- }));
164
- }
165
- } finally {
166
- continuationInProgressRef.current = false;
167
- if (abortControllerRef.current === abortController) {
168
- abortControllerRef.current = undefined;
169
- }
170
- }
171
- })();
172
- }
173
-
174
- function processContinuation(
175
- hadToolCalls: boolean,
176
- todoContext: { todos: Todo[]; paused: boolean },
177
- config: TodoContinuationRuntime,
178
- isResponding: boolean,
179
- continuationState: ContinuationState,
180
- continuationInProgressRef: React.MutableRefObject<boolean>,
181
- abortControllerRef: React.MutableRefObject<AbortController | undefined>,
182
- agent: Agent,
183
- onDebugMessage: (message: string) => void,
184
- setContinuationState: React.Dispatch<React.SetStateAction<ContinuationState>>,
185
- ): void {
186
- if (hadToolCalls) {
187
- setContinuationState((prev) => ({ ...prev, isActive: false }));
188
- }
189
-
190
- const conditions = evaluateConditions(
191
- hadToolCalls,
192
- todoContext.paused,
193
- config,
194
- todoContext.todos,
195
- continuationState.isActive,
196
- );
197
-
198
- if (!shouldTrigger(conditions, isResponding)) {
199
- return;
200
- }
201
-
202
- const activeTodo = findMostRelevantTodo(todoContext.todos);
203
-
204
- if (!activeTodo?.content || activeTodo.content.trim() === '') {
205
- return;
206
- }
207
-
208
- if (continuationState.isActive || continuationInProgressRef.current) {
209
- return;
210
- }
211
-
212
- const continuationPrompt = generatePrompt(activeTodo, config);
213
- sendContinuationPrompt(
214
- agent,
215
- activeTodo.content,
216
- continuationPrompt,
217
- onDebugMessage,
218
- setContinuationState,
219
- continuationInProgressRef,
220
- abortControllerRef,
221
- );
222
- }
223
-
224
- /**
225
- * React hook for task continuation - monitors stream completion and triggers continuation
226
- * prompts when active tasks exist but no tool calls were made.
227
- * [REQ-001] Task Continuation Detection, [REQ-002] Continuation Prompting
228
- */
229
- export const useTodoContinuation = (
230
- agent: Agent,
231
- config: TodoContinuationRuntime,
232
- isResponding: boolean,
233
- onDebugMessage: (message: string) => void,
234
- ): TodoContinuationHook => {
235
- const [continuationState, setContinuationState] = useState<ContinuationState>(
236
- { isActive: false, attemptCount: 0 },
237
- );
238
-
239
- const continuationInProgressRef = useRef<boolean>(false);
240
- const todoContext = useTodoContext();
241
- const abortControllerRef = useRef<AbortController | undefined>(undefined);
242
- const continuationTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
243
-
244
- const handleStreamCompleted = useCallback(
245
- (hadToolCalls: boolean): void => {
246
- processContinuation(
247
- hadToolCalls,
248
- todoContext,
249
- config,
250
- isResponding,
251
- continuationState,
252
- continuationInProgressRef,
253
- abortControllerRef,
254
- agent,
255
- onDebugMessage,
256
- setContinuationState,
257
- );
258
- },
259
- [
260
- config,
261
- todoContext,
262
- continuationState,
263
- isResponding,
264
- agent,
265
- onDebugMessage,
266
- ],
267
- );
268
-
269
- const handleTodoPause = useCallback(
270
- (reason: string): { type: 'pause'; reason: string; message: string } => {
271
- todoContext.setPaused(true);
272
- return {
273
- type: 'pause' as const,
274
- reason,
275
- message: `Task paused: ${reason}`,
276
- };
277
- },
278
- [todoContext],
279
- );
280
-
281
- const clearPause = useCallback(() => {
282
- todoContext.setPaused(false);
283
- }, [todoContext]);
284
-
285
- useEffect(
286
- () => () => {
287
- abortControllerRef.current?.abort();
288
- clearTimeout(continuationTimeoutRef.current);
289
- },
290
- [],
291
- );
292
-
293
- return {
294
- handleStreamCompleted,
295
- continuationState,
296
- handleTodoPause,
297
- clearPause,
298
- };
299
- };