@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.
- package/package.json +13 -13
- package/src/commands/mcp/add.ts +8 -4
- package/src/config/cliArgParser.ts +2 -0
- package/src/config/config.ts +2 -0
- package/src/config/configBuilder.ts +3 -0
- package/src/config/configError.ts +23 -0
- package/src/config/extensions/extensionEnablement.ts +62 -1
- package/src/config/interactiveContext.ts +2 -1
- package/src/config/intermediateConfig.ts +4 -0
- package/src/config/keyBindings.ts +29 -3
- package/src/config/policy.ts +7 -1
- package/src/config/postConfigRuntime.ts +20 -14
- package/src/config/settings-schema/schema-ui.ts +9 -0
- package/src/config/settingsLoader.ts +21 -17
- package/src/config/settingsSchema.ts +2 -2
- package/src/config/trustedFolders.ts +275 -58
- package/src/config/yargsOptions.ts +7 -0
- package/src/generated/git-commit.json +1 -1
- package/src/nonInteractiveCli.ts +1 -0
- package/src/nonInteractiveCliSupport.ts +171 -51
- package/src/runtime/interactiveToolScheduler.ts +6 -6
- package/src/services/BuiltinCommandLoader.ts +33 -25
- package/src/services/FileCommandLoader.ts +34 -7
- package/src/test-utils/async.ts +20 -0
- package/src/test-utils/render.tsx +10 -1
- package/src/ui/App.tsx +17 -10
- package/src/ui/AppContainerRuntime.tsx +7 -9
- package/src/ui/cliUiRuntime.ts +28 -0
- package/src/ui/commands/authCommand.ts +240 -3
- package/src/ui/commands/compressCommand.ts +9 -1
- package/src/ui/commands/directoryCommand.tsx +1 -1
- package/src/ui/commands/logoutCommand.ts +2 -2
- package/src/ui/commands/permissionsCommand.ts +77 -20
- package/src/ui/commands/policiesCommand.ts +6 -1
- package/src/ui/commands/quotaCommand.ts +501 -0
- package/src/ui/commands/statsCommand.ts +2 -2
- package/src/ui/commands/statsQuota.ts +1 -1
- package/src/ui/commands/subagentCommand.ts +59 -27
- package/src/ui/components/AuthDialog.tsx +3 -3
- package/src/ui/components/Composer.tsx +1 -0
- package/src/ui/components/DialogManager.tsx +9 -2
- package/src/ui/components/FolderTrustDialog.tsx +71 -60
- package/src/ui/components/PermissionsModifyTrustDialog.tsx +211 -146
- package/src/ui/components/ProfileCreateWizard/constants.ts +13 -1
- package/src/ui/components/QueuedMessagesPanel.tsx +388 -0
- package/src/ui/components/inputPromptHooks.ts +2 -0
- package/src/ui/components/inputPromptKeyHandlers.ts +14 -0
- package/src/ui/components/inputPromptTypes.ts +6 -0
- package/src/ui/components/messages/AiMessage.tsx +24 -12
- package/src/ui/components/messages/ToolMessage.tsx +26 -40
- package/src/ui/containers/AppContainer/builders/buildUIActions.ts +3 -1
- package/src/ui/containers/AppContainer/builders/buildUIState.ts +5 -4
- package/src/ui/containers/AppContainer/hooks/useAppBootstrap.ts +3 -33
- package/src/ui/containers/AppContainer/hooks/useAppDialogs.ts +2 -14
- package/src/ui/containers/AppContainer/hooks/useAppInput.ts +31 -25
- package/src/ui/containers/AppContainer/hooks/useAppLayout.ts +90 -60
- package/src/ui/containers/AppContainer/hooks/useDisplayPreferences.ts +10 -0
- package/src/ui/containers/AppContainer/hooks/useInputHandling.ts +3 -17
- package/src/ui/containers/AppContainer/hooks/useKeybindings.ts +51 -38
- package/src/ui/containers/AppContainer/hooks/useSteer.ts +51 -0
- package/src/ui/contexts/KeypressContext.tsx +13 -2
- package/src/ui/contexts/ShellCommandDisplayContext.tsx +103 -0
- package/src/ui/contexts/TodoContext.tsx +0 -13
- package/src/ui/contexts/TodoProvider.tsx +1 -34
- package/src/ui/contexts/UIActionsContext.tsx +2 -1
- package/src/ui/contexts/UIStateContext.tsx +3 -2
- package/src/ui/hooks/agentStream/streamUtils.ts +0 -24
- package/src/ui/hooks/agentStream/thoughtState.ts +110 -30
- package/src/ui/hooks/agentStream/types.ts +1 -0
- package/src/ui/hooks/agentStream/useAgentEventStream.ts +8 -17
- package/src/ui/hooks/agentStream/useAgentStream.ts +2 -2
- package/src/ui/hooks/agentStream/useAgentStreamLifecycle.ts +4 -5
- package/src/ui/hooks/agentStream/useAgentStreamOrchestration.ts +12 -5
- package/src/ui/hooks/agentStream/useQueuedSubmissions.ts +99 -0
- package/src/ui/hooks/agentStream/useStreamEventHandlers.ts +4 -13
- package/src/ui/hooks/agentStream/useStreamState.ts +60 -41
- package/src/ui/hooks/agentStream/useSubmitQuery.ts +284 -59
- package/src/ui/hooks/slashCommandProcessorSupport.ts +4 -0
- package/src/ui/hooks/useAgentStream-test-helpers.ts +1 -0
- package/src/ui/hooks/useAutoAcceptIndicator.ts +13 -0
- package/src/ui/hooks/useFolderTrust.ts +118 -81
- package/src/ui/hooks/useGitBranchName.ts +79 -33
- package/src/ui/hooks/useIdeTrustListener.ts +5 -19
- package/src/ui/hooks/usePermissionsModifyTrust.ts +223 -85
- package/src/ui/hooks/useReactToolScheduler.ts +13 -17
- package/src/ui/hooks/useTodoPausePreserver.ts +0 -55
- package/src/ui/layouts/DefaultAppLayout.tsx +2 -0
- package/src/ui/layouts/DefaultAppLayoutHelpers.tsx +37 -162
- package/src/ui/layouts/InlineContent.tsx +198 -0
- package/src/ui/trustDialogHelpers.ts +190 -0
- package/src/utils/cleanup-state.ts +115 -0
- package/src/utils/cleanup.ts +32 -34
- package/src/utils/sandbox-containers.ts +183 -53
- package/src/utils/sandbox-exec.ts +9 -3
- package/src/zed-integration/acp-terminal-shell-host.ts +112 -0
- package/src/zed-integration/acp-types.ts +35 -0
- package/src/zed-integration/fileSystemService.ts +1 -1
- package/src/zed-integration/runZedIntegration.ts +142 -0
- package/src/zed-integration/zed-agent-event-handler.ts +179 -0
- package/src/zed-integration/zed-agent-setup.ts +43 -0
- package/src/zed-integration/zed-command-registry.ts +167 -0
- package/src/zed-integration/zed-config-options.ts +280 -0
- package/src/zed-integration/zed-content-utils.ts +2 -2
- package/src/zed-integration/zed-helpers.ts +132 -0
- package/src/zed-integration/zed-initialize.ts +64 -0
- package/src/zed-integration/zed-plan-update.ts +20 -0
- package/src/zed-integration/zed-prompt-command.ts +77 -0
- package/src/zed-integration/zed-session-config.ts +119 -0
- package/src/zed-integration/zed-session-errors.ts +337 -0
- package/src/zed-integration/zed-session-events.ts +216 -0
- package/src/zed-integration/zed-session-info.ts +255 -0
- package/src/zed-integration/zed-session-lifecycle.ts +186 -0
- package/src/zed-integration/zed-session-listing.ts +153 -0
- package/src/zed-integration/zed-session-loader.ts +193 -0
- package/src/zed-integration/zed-session-pagination.ts +240 -0
- package/src/zed-integration/zed-session-replay.ts +564 -0
- package/src/zed-integration/zed-stream-batcher.ts +236 -0
- package/src/zed-integration/zed-terminal-manager.ts +416 -0
- package/src/zed-integration/zed-terminal-setup.ts +72 -0
- package/src/zed-integration/zed-test-helpers.ts +349 -4
- package/src/zed-integration/zed-tool-handler.ts +47 -5
- package/src/zed-integration/zedIntegration.ts +538 -587
- package/src/services/todo-continuation/todoContinuationService.ts +0 -610
- package/src/ui/containers/AppContainer/hooks/useIdeRestartHotkey.ts +0 -33
- package/src/ui/containers/AppContainer/hooks/useTodoContinuationFlow.ts +0 -160
- package/src/ui/hooks/useTodoContinuation.ts +0 -299
|
@@ -4,28 +4,71 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { useState, useCallback, useMemo } from 'react';
|
|
7
|
+
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
8
8
|
import * as path from 'node:path';
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
import {
|
|
10
|
+
loadTrustedFolders,
|
|
11
|
+
resolveLocalWorkspaceTrust,
|
|
12
|
+
type LoadedTrustedFolders,
|
|
13
|
+
TrustLevel,
|
|
14
|
+
type TrustedFolderSnapshot,
|
|
15
|
+
} from '../../config/trustedFolders.js';
|
|
16
|
+
import type { CliUiRuntime } from '../cliUiRuntime.js';
|
|
17
|
+
import { useIdeTrustListener } from './useIdeTrustListener.js';
|
|
18
|
+
import { combineTrustUpdateFailure } from '../trustDialogHelpers.js';
|
|
19
|
+
import process from 'node:process';
|
|
20
|
+
|
|
21
|
+
export type PermissionsTrustRuntime = Pick<
|
|
22
|
+
CliUiRuntime,
|
|
23
|
+
| 'getWorkingDir'
|
|
24
|
+
| 'getFolderTrust'
|
|
25
|
+
| 'getIdeClient'
|
|
26
|
+
| 'isTrustedFolder'
|
|
27
|
+
| 'setTrustedFolderLive'
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
const emptyIdeState: Pick<PermissionsTrustRuntime, 'getIdeClient'> = {
|
|
31
|
+
getIdeClient: () => undefined,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function useMountedRef() {
|
|
35
|
+
const mountedRef = useRef(true);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
mountedRef.current = true;
|
|
38
|
+
return () => {
|
|
39
|
+
mountedRef.current = false;
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
return mountedRef;
|
|
43
|
+
}
|
|
13
44
|
|
|
14
45
|
export interface UsePermissionsModifyTrustReturn {
|
|
15
|
-
/** Current trust level for the working directory */
|
|
16
|
-
currentTrustLevel: TrustLevel | undefined;
|
|
17
46
|
/** Pending trust level change (before commit) */
|
|
18
47
|
pendingTrustLevel: TrustLevel | undefined;
|
|
19
48
|
/** Set a pending trust level change */
|
|
20
49
|
setPendingTrustLevel: (level: TrustLevel) => void;
|
|
21
50
|
/** Commit the pending trust level change */
|
|
22
|
-
commitTrustLevel: (level?: TrustLevel) =>
|
|
51
|
+
commitTrustLevel: (level?: TrustLevel) => Promise<
|
|
52
|
+
| { success: true }
|
|
53
|
+
| {
|
|
54
|
+
success: false;
|
|
55
|
+
phase: 'persistence' | 'live';
|
|
56
|
+
error: unknown;
|
|
57
|
+
rollbackSucceeded: boolean;
|
|
58
|
+
}
|
|
59
|
+
>;
|
|
60
|
+
/** Effective local trust level, including inherited rules */
|
|
61
|
+
effectiveLocalTrustLevel: TrustLevel | undefined;
|
|
23
62
|
/** Whether the workspace is trusted through IDE */
|
|
24
|
-
isIdeTrusted: boolean;
|
|
25
|
-
/** Whether the
|
|
63
|
+
isIdeTrusted: boolean | undefined;
|
|
64
|
+
/** Whether the winning local rule is inherited */
|
|
26
65
|
isParentTrusted: boolean;
|
|
27
|
-
/** Whether a
|
|
28
|
-
|
|
66
|
+
/** Whether a trust change was committed */
|
|
67
|
+
trustChanged: boolean;
|
|
68
|
+
/** The local trust level saved during this dialog session */
|
|
69
|
+
committedTrustLevel: TrustLevel | undefined;
|
|
70
|
+
/** The live effective trust state after the change */
|
|
71
|
+
effectiveTrust: boolean | undefined;
|
|
29
72
|
/** The current working directory */
|
|
30
73
|
workingDirectory: string;
|
|
31
74
|
/** The parent folder name */
|
|
@@ -34,101 +77,196 @@ export interface UsePermissionsModifyTrustReturn {
|
|
|
34
77
|
trustedFolders: LoadedTrustedFolders;
|
|
35
78
|
}
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const settings = useSettings();
|
|
44
|
-
const cwd = process.cwd();
|
|
45
|
-
const parentFolderName = path.basename(path.dirname(cwd));
|
|
46
|
-
|
|
47
|
-
const trustedFolders = useMemo(() => loadTrustedFolders(), []);
|
|
48
|
-
|
|
49
|
-
// Determine current trust level for the working directory
|
|
50
|
-
const currentTrustLevel = useMemo((): TrustLevel | undefined => {
|
|
51
|
-
// Find exact match for current directory
|
|
52
|
-
const rule = trustedFolders.rules.find(
|
|
53
|
-
(r) => path.normalize(r.path) === path.normalize(cwd),
|
|
54
|
-
);
|
|
55
|
-
return rule?.trustLevel;
|
|
56
|
-
}, [trustedFolders, cwd]);
|
|
80
|
+
function restoreSavedTrustLevel(
|
|
81
|
+
trustedFolders: LoadedTrustedFolders,
|
|
82
|
+
snapshot: TrustedFolderSnapshot,
|
|
83
|
+
): void {
|
|
84
|
+
trustedFolders.restoreSnapshot(snapshot);
|
|
85
|
+
}
|
|
57
86
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
async function applyLiveTrustLevel(
|
|
88
|
+
config: PermissionsTrustRuntime,
|
|
89
|
+
trustedFolders: LoadedTrustedFolders,
|
|
90
|
+
folderPath: string,
|
|
91
|
+
): Promise<boolean> {
|
|
92
|
+
await config.setTrustedFolderLive(
|
|
93
|
+
resolveLocalWorkspaceTrust(
|
|
94
|
+
{ folderTrust: config.getFolderTrust() },
|
|
95
|
+
trustedFolders,
|
|
96
|
+
folderPath,
|
|
97
|
+
) ?? false,
|
|
98
|
+
);
|
|
99
|
+
return config.isTrustedFolder();
|
|
100
|
+
}
|
|
63
101
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
102
|
+
type TrustCommitResult =
|
|
103
|
+
| { success: true }
|
|
104
|
+
| {
|
|
105
|
+
success: false;
|
|
106
|
+
phase: 'persistence' | 'live';
|
|
107
|
+
error: unknown;
|
|
108
|
+
rollbackSucceeded: boolean;
|
|
109
|
+
};
|
|
67
110
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
111
|
+
async function commitSavedTrustLevel(
|
|
112
|
+
config: PermissionsTrustRuntime | undefined,
|
|
113
|
+
trustedFolders: LoadedTrustedFolders,
|
|
114
|
+
folderPath: string,
|
|
115
|
+
nextLevel: TrustLevel,
|
|
116
|
+
): Promise<{ result: TrustCommitResult; effectiveTrust?: boolean }> {
|
|
117
|
+
let savedSnapshot: TrustedFolderSnapshot;
|
|
118
|
+
try {
|
|
119
|
+
savedSnapshot = trustedFolders.snapshotValue(folderPath);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
result: {
|
|
123
|
+
success: false,
|
|
124
|
+
phase: 'persistence',
|
|
125
|
+
error,
|
|
126
|
+
rollbackSucceeded: true,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const previousLiveTrust = config?.isTrustedFolder() ?? false;
|
|
131
|
+
try {
|
|
132
|
+
trustedFolders.setValue(folderPath, nextLevel);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
return {
|
|
135
|
+
result: {
|
|
136
|
+
success: false,
|
|
137
|
+
phase: 'persistence',
|
|
138
|
+
error,
|
|
139
|
+
rollbackSucceeded: true,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (config === undefined) {
|
|
144
|
+
return {
|
|
145
|
+
result: { success: true },
|
|
146
|
+
effectiveTrust: nextLevel !== TrustLevel.DO_NOT_TRUST,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
return {
|
|
151
|
+
result: { success: true },
|
|
152
|
+
effectiveTrust: await applyLiveTrustLevel(
|
|
153
|
+
config,
|
|
154
|
+
trustedFolders,
|
|
155
|
+
folderPath,
|
|
156
|
+
),
|
|
157
|
+
};
|
|
158
|
+
} catch (error) {
|
|
159
|
+
const rollbackFailures: unknown[] = [];
|
|
160
|
+
try {
|
|
161
|
+
restoreSavedTrustLevel(trustedFolders, savedSnapshot);
|
|
162
|
+
} catch (rollbackError) {
|
|
163
|
+
rollbackFailures.push(rollbackError);
|
|
86
164
|
}
|
|
87
|
-
|
|
88
|
-
|
|
165
|
+
try {
|
|
166
|
+
await config.setTrustedFolderLive(previousLiveTrust);
|
|
167
|
+
} catch (rollbackError) {
|
|
168
|
+
rollbackFailures.push(rollbackError);
|
|
169
|
+
}
|
|
170
|
+
const failure = combineTrustUpdateFailure(
|
|
171
|
+
error,
|
|
172
|
+
rollbackFailures,
|
|
173
|
+
'Live trust update and rollback failed',
|
|
174
|
+
);
|
|
175
|
+
return {
|
|
176
|
+
result: {
|
|
177
|
+
success: false,
|
|
178
|
+
phase: 'live',
|
|
179
|
+
error: failure.error,
|
|
180
|
+
rollbackSucceeded: failure.rollbackSucceeded,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
89
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Hook that manages folder trust settings for the permissions dialog.
|
|
188
|
+
* Handles current trust level state, pending changes, inherited trust detection,
|
|
189
|
+
* and live Config updates via setTrustedFolderLive.
|
|
190
|
+
*/
|
|
191
|
+
export function usePermissionsModifyTrust(
|
|
192
|
+
config?: PermissionsTrustRuntime,
|
|
193
|
+
): UsePermissionsModifyTrustReturn {
|
|
194
|
+
const normalizedCwd = path.resolve(config?.getWorkingDir() ?? process.cwd());
|
|
195
|
+
const trustedFolders = useMemo(() => loadTrustedFolders(), []);
|
|
196
|
+
const winningRule = trustedFolders.resolvePathTrust(normalizedCwd);
|
|
197
|
+
const currentEffectiveTrust =
|
|
198
|
+
config?.isTrustedFolder() ?? winningRule?.trusted;
|
|
199
|
+
const { isIdeTrusted } = useIdeTrustListener(config ?? emptyIdeState);
|
|
200
|
+
const isParentTrusted =
|
|
201
|
+
isIdeTrusted === undefined && winningRule?.provenance === 'inherited';
|
|
90
202
|
const [pendingTrustLevel, setPendingTrustLevel] = useState<
|
|
91
203
|
TrustLevel | undefined
|
|
92
|
-
>(
|
|
93
|
-
|
|
94
|
-
const [
|
|
95
|
-
|
|
204
|
+
>(() => trustedFolders.getValue(normalizedCwd));
|
|
205
|
+
const [committedLevel, setCommittedLevel] = useState<TrustLevel>();
|
|
206
|
+
const [effectiveTrust, setEffectiveTrust] = useState(currentEffectiveTrust);
|
|
207
|
+
const commitQueueRef = useRef<Promise<void>>(Promise.resolve());
|
|
208
|
+
const mountedRef = useMountedRef();
|
|
209
|
+
const currentWorkingDirectoryRef = useRef(normalizedCwd);
|
|
210
|
+
currentWorkingDirectoryRef.current = normalizedCwd;
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
setPendingTrustLevel(trustedFolders.getValue(normalizedCwd));
|
|
213
|
+
setCommittedLevel(undefined);
|
|
214
|
+
}, [normalizedCwd, trustedFolders]);
|
|
215
|
+
useEffect(
|
|
216
|
+
() => setEffectiveTrust(currentEffectiveTrust),
|
|
217
|
+
[currentEffectiveTrust],
|
|
218
|
+
);
|
|
96
219
|
const commitTrustLevel = useCallback(
|
|
97
|
-
(level?: TrustLevel) => {
|
|
220
|
+
(level?: TrustLevel): Promise<TrustCommitResult> => {
|
|
98
221
|
const nextLevel = level ?? pendingTrustLevel;
|
|
99
222
|
if (nextLevel === undefined) {
|
|
100
|
-
return;
|
|
223
|
+
return Promise.resolve({ success: true });
|
|
101
224
|
}
|
|
102
225
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
226
|
+
const runCommit = async (): Promise<TrustCommitResult> => {
|
|
227
|
+
const commit = await commitSavedTrustLevel(
|
|
228
|
+
config,
|
|
229
|
+
trustedFolders,
|
|
230
|
+
normalizedCwd,
|
|
231
|
+
nextLevel,
|
|
232
|
+
);
|
|
233
|
+
if (!commit.result.success) {
|
|
234
|
+
return commit.result;
|
|
235
|
+
}
|
|
236
|
+
if (
|
|
237
|
+
mountedRef.current &&
|
|
238
|
+
currentWorkingDirectoryRef.current === normalizedCwd
|
|
239
|
+
) {
|
|
240
|
+
setEffectiveTrust(commit.effectiveTrust);
|
|
241
|
+
setPendingTrustLevel(nextLevel);
|
|
242
|
+
setCommittedLevel(nextLevel);
|
|
243
|
+
}
|
|
244
|
+
return { success: true };
|
|
245
|
+
};
|
|
246
|
+
const commit = commitQueueRef.current.then(runCommit, runCommit);
|
|
247
|
+
commitQueueRef.current = commit.then(
|
|
248
|
+
() => undefined,
|
|
249
|
+
() => undefined,
|
|
250
|
+
);
|
|
251
|
+
return commit;
|
|
106
252
|
},
|
|
107
|
-
[pendingTrustLevel, trustedFolders,
|
|
253
|
+
[pendingTrustLevel, trustedFolders, normalizedCwd, config, mountedRef],
|
|
108
254
|
);
|
|
109
255
|
|
|
110
|
-
|
|
111
|
-
const requiresRestart = useMemo(() => {
|
|
112
|
-
if (!hasCommitted) return false;
|
|
113
|
-
|
|
114
|
-
// Check if folder trust feature is enabled
|
|
115
|
-
const folderTrustEnabled = settings.merged.folderTrust ?? false;
|
|
116
|
-
if (!folderTrustEnabled) return false;
|
|
117
|
-
|
|
118
|
-
// A restart is required if we changed the trust level
|
|
119
|
-
return pendingTrustLevel !== currentTrustLevel;
|
|
120
|
-
}, [hasCommitted, pendingTrustLevel, currentTrustLevel, settings]);
|
|
256
|
+
const trustChanged = committedLevel !== undefined;
|
|
121
257
|
|
|
122
258
|
return {
|
|
123
|
-
currentTrustLevel,
|
|
124
259
|
pendingTrustLevel,
|
|
125
260
|
setPendingTrustLevel,
|
|
126
261
|
commitTrustLevel,
|
|
262
|
+
effectiveLocalTrustLevel: winningRule?.rule.trustLevel,
|
|
127
263
|
isIdeTrusted,
|
|
128
264
|
isParentTrusted,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
265
|
+
trustChanged,
|
|
266
|
+
committedTrustLevel: committedLevel,
|
|
267
|
+
effectiveTrust,
|
|
268
|
+
workingDirectory: normalizedCwd,
|
|
269
|
+
parentFolderName: path.basename(path.dirname(normalizedCwd)),
|
|
132
270
|
trustedFolders,
|
|
133
271
|
};
|
|
134
272
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
type CancelledToolCall,
|
|
15
15
|
type ToolCall,
|
|
16
16
|
type EditorType,
|
|
17
|
-
type
|
|
17
|
+
type LiveOutputUpdate,
|
|
18
18
|
type MessageBus,
|
|
19
19
|
accumulateLiveOutput,
|
|
20
20
|
} from '@vybestack/llxprt-code-core';
|
|
@@ -86,7 +86,7 @@ export type CancelAllFn = () => void;
|
|
|
86
86
|
export type ReplaceToolCallsFn = (calls: ToolCall[]) => void;
|
|
87
87
|
export type UpdateToolOutputFn = (
|
|
88
88
|
toolCallId: string,
|
|
89
|
-
|
|
89
|
+
update: LiveOutputUpdate,
|
|
90
90
|
) => void;
|
|
91
91
|
export type ReactToolSchedulerResult = readonly [
|
|
92
92
|
TrackedToolCall[],
|
|
@@ -104,7 +104,7 @@ export type ReactToolSchedulerResult = readonly [
|
|
|
104
104
|
function updatePendingItemWithOutput(
|
|
105
105
|
prevItem: HistoryItemWithoutId | null,
|
|
106
106
|
toolCallId: string,
|
|
107
|
-
|
|
107
|
+
update: LiveOutputUpdate,
|
|
108
108
|
): HistoryItemWithoutId | null {
|
|
109
109
|
if (prevItem?.type !== 'tool_group') return prevItem;
|
|
110
110
|
return {
|
|
@@ -116,7 +116,7 @@ function updatePendingItemWithOutput(
|
|
|
116
116
|
...toolDisplay,
|
|
117
117
|
resultDisplay: accumulateLiveOutput(
|
|
118
118
|
toolDisplay.resultDisplay,
|
|
119
|
-
|
|
119
|
+
update,
|
|
120
120
|
),
|
|
121
121
|
}
|
|
122
122
|
: toolDisplay,
|
|
@@ -148,13 +148,13 @@ function mapCallsWithDisplayClearedFlag(
|
|
|
148
148
|
function updateCallsWithLiveOutput(
|
|
149
149
|
prevCalls: TrackedToolCall[],
|
|
150
150
|
toolCallId: string,
|
|
151
|
-
|
|
151
|
+
update: LiveOutputUpdate,
|
|
152
152
|
): TrackedToolCall[] {
|
|
153
153
|
return prevCalls.map((call) =>
|
|
154
154
|
call.request.callId === toolCallId && call.status === 'executing'
|
|
155
155
|
? {
|
|
156
156
|
...call,
|
|
157
|
-
liveOutput: accumulateLiveOutput(call.liveOutput,
|
|
157
|
+
liveOutput: accumulateLiveOutput(call.liveOutput, update),
|
|
158
158
|
}
|
|
159
159
|
: call,
|
|
160
160
|
);
|
|
@@ -209,7 +209,7 @@ function useToolCallUpdaters(
|
|
|
209
209
|
updateToolCallOutput: (
|
|
210
210
|
schedulerId: symbol,
|
|
211
211
|
toolCallId: string,
|
|
212
|
-
|
|
212
|
+
update: LiveOutputUpdate,
|
|
213
213
|
) => void;
|
|
214
214
|
replaceToolCallsForScheduler: (
|
|
215
215
|
schedulerId: symbol,
|
|
@@ -240,23 +240,19 @@ function useToolCallUpdaters(
|
|
|
240
240
|
);
|
|
241
241
|
|
|
242
242
|
const updateToolCallOutput = useCallback(
|
|
243
|
-
(
|
|
244
|
-
schedulerId: symbol,
|
|
245
|
-
toolCallId: string,
|
|
246
|
-
outputChunk: string | AnsiOutput,
|
|
247
|
-
) => {
|
|
243
|
+
(schedulerId: symbol, toolCallId: string, update: LiveOutputUpdate) => {
|
|
248
244
|
updateToolCallsForScheduler(schedulerId, (prevCalls) => {
|
|
249
245
|
const nextCalls = updateCallsWithLiveOutput(
|
|
250
246
|
prevCalls,
|
|
251
247
|
toolCallId,
|
|
252
|
-
|
|
248
|
+
update,
|
|
253
249
|
);
|
|
254
250
|
return nextCalls.some((call, index) => call !== prevCalls[index])
|
|
255
251
|
? nextCalls
|
|
256
252
|
: prevCalls;
|
|
257
253
|
});
|
|
258
254
|
setPendingHistoryItem((prev) =>
|
|
259
|
-
updatePendingItemWithOutput(prev, toolCallId,
|
|
255
|
+
updatePendingItemWithOutput(prev, toolCallId, update),
|
|
260
256
|
);
|
|
261
257
|
},
|
|
262
258
|
[updateToolCallsForScheduler, setPendingHistoryItem],
|
|
@@ -378,7 +374,7 @@ function useSchedulerRefs(
|
|
|
378
374
|
updateToolCallOutput: (
|
|
379
375
|
schedulerId: symbol,
|
|
380
376
|
toolCallId: string,
|
|
381
|
-
|
|
377
|
+
update: LiveOutputUpdate,
|
|
382
378
|
) => void;
|
|
383
379
|
replaceToolCallsForScheduler: (
|
|
384
380
|
schedulerId: symbol,
|
|
@@ -470,8 +466,8 @@ function useBoundDisplayUpdaters(
|
|
|
470
466
|
[replaceToolCallsForScheduler, mainSchedulerId],
|
|
471
467
|
);
|
|
472
468
|
const updateToolOutput = useCallback(
|
|
473
|
-
(toolCallId: string,
|
|
474
|
-
updateToolCallOutput(mainSchedulerId, toolCallId,
|
|
469
|
+
(toolCallId: string, update: LiveOutputUpdate) =>
|
|
470
|
+
updateToolCallOutput(mainSchedulerId, toolCallId, update),
|
|
475
471
|
[updateToolCallOutput, mainSchedulerId],
|
|
476
472
|
);
|
|
477
473
|
return { replaceToolCalls, updateToolOutput };
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { useCallback } from 'react';
|
|
8
7
|
import { type Todo } from '@vybestack/llxprt-code-core';
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -20,57 +19,3 @@ export function shouldClearTodos(todos: Todo[]): boolean {
|
|
|
20
19
|
}
|
|
21
20
|
return todos.every((t) => t.status === 'completed');
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
export class TodoPausePreserver {
|
|
25
|
-
private preserveNextSubmission = false;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @plan PLAN-20260129-TODOPERSIST.P01
|
|
29
|
-
* Modified to accept todos parameter for conditional clearing logic.
|
|
30
|
-
*/
|
|
31
|
-
handleSubmit(onClear: () => void, todos: Todo[]): void {
|
|
32
|
-
if (this.preserveNextSubmission) {
|
|
33
|
-
this.preserveNextSubmission = false;
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (shouldClearTodos(todos)) {
|
|
37
|
-
onClear();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
registerTodoPause(): void {
|
|
42
|
-
this.preserveNextSubmission = true;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
interface UseTodoPausePreserverOptions {
|
|
47
|
-
controller: TodoPausePreserver;
|
|
48
|
-
updateTodos: (todos: Todo[]) => void;
|
|
49
|
-
handleFinalSubmit: (submittedValue: string) => void;
|
|
50
|
-
/**
|
|
51
|
-
* @plan PLAN-20260129-TODOPERSIST.P01
|
|
52
|
-
* Current todos list required for conditional clearing.
|
|
53
|
-
*/
|
|
54
|
-
todos: Todo[];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const useTodoPausePreserver = ({
|
|
58
|
-
controller,
|
|
59
|
-
updateTodos,
|
|
60
|
-
handleFinalSubmit,
|
|
61
|
-
todos,
|
|
62
|
-
}: UseTodoPausePreserverOptions) => {
|
|
63
|
-
const handleUserInputSubmit = useCallback(
|
|
64
|
-
(submittedValue: string) => {
|
|
65
|
-
controller.handleSubmit(() => {
|
|
66
|
-
updateTodos([]);
|
|
67
|
-
}, todos);
|
|
68
|
-
handleFinalSubmit(submittedValue);
|
|
69
|
-
},
|
|
70
|
-
[controller, updateTodos, handleFinalSubmit, todos],
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
handleUserInputSubmit,
|
|
75
|
-
};
|
|
76
|
-
};
|
|
@@ -224,6 +224,8 @@ function buildMainControlsProps(
|
|
|
224
224
|
history: uiState.history,
|
|
225
225
|
inputWidth: uiState.inputWidth,
|
|
226
226
|
isTodoPanelCollapsed: uiState.isTodoPanelCollapsed,
|
|
227
|
+
isQueuedMessagesPanelCollapsed: uiState.isQueuedMessagesPanelCollapsed,
|
|
228
|
+
queuedSubmissions: uiState.queuedSubmissions,
|
|
227
229
|
showTodoPanelSetting: layoutSettings.showTodoPanelSetting,
|
|
228
230
|
dialogsVisible: hasActiveDialog(uiState),
|
|
229
231
|
hideContextSummary: layoutSettings.hideContextSummary,
|