@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vybestack/llxprt-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
4
4
|
"description": "LLxprt Code",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -44,24 +44,24 @@
|
|
|
44
44
|
"!**/__snapshots__/**"
|
|
45
45
|
],
|
|
46
46
|
"config": {
|
|
47
|
-
"sandboxImageUri": "ghcr.io/vybestack/llxprt-code/sandbox:0.
|
|
47
|
+
"sandboxImageUri": "ghcr.io/vybestack/llxprt-code/sandbox:0.11.0-nightly.260728.ffaa8d5d7"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@vybestack/llxprt-code-storage": "0.
|
|
51
|
-
"@agentclientprotocol/sdk": "^
|
|
50
|
+
"@vybestack/llxprt-code-storage": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
51
|
+
"@agentclientprotocol/sdk": "^1.2.1",
|
|
52
52
|
"@anthropic-ai/sdk": "^0.55.1",
|
|
53
53
|
"@dqbd/tiktoken": "^1.0.21",
|
|
54
54
|
"@iarna/toml": "^2.2.5",
|
|
55
55
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
56
|
-
"@vybestack/llxprt-code-auth": "0.
|
|
57
|
-
"@vybestack/llxprt-code-core": "0.
|
|
58
|
-
"@vybestack/llxprt-code-ide-integration": "0.
|
|
59
|
-
"@vybestack/llxprt-code-mcp": "0.
|
|
60
|
-
"@vybestack/llxprt-code-providers": "0.
|
|
61
|
-
"@vybestack/llxprt-code-agents": "0.
|
|
62
|
-
"@vybestack/llxprt-code-settings": "0.
|
|
63
|
-
"@vybestack/llxprt-code-telemetry": "0.
|
|
64
|
-
"@vybestack/llxprt-code-tools": "0.
|
|
56
|
+
"@vybestack/llxprt-code-auth": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
57
|
+
"@vybestack/llxprt-code-core": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
58
|
+
"@vybestack/llxprt-code-ide-integration": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
59
|
+
"@vybestack/llxprt-code-mcp": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
60
|
+
"@vybestack/llxprt-code-providers": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
61
|
+
"@vybestack/llxprt-code-agents": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
62
|
+
"@vybestack/llxprt-code-settings": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
63
|
+
"@vybestack/llxprt-code-telemetry": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
64
|
+
"@vybestack/llxprt-code-tools": "0.11.0-nightly.260728.ffaa8d5d7",
|
|
65
65
|
"ansi-regex": "^6.2.2",
|
|
66
66
|
"bun": "1.3.14",
|
|
67
67
|
"chalk": "^5.3.0",
|
package/src/commands/mcp/add.ts
CHANGED
|
@@ -78,7 +78,7 @@ function parseEnvEntries(
|
|
|
78
78
|
|
|
79
79
|
function createHttpServerConfig(
|
|
80
80
|
commandOrUrl: string,
|
|
81
|
-
type: 'sse' | 'http',
|
|
81
|
+
type: 'sse' | 'http' | 'streamable-http',
|
|
82
82
|
headers: Record<string, string> | undefined,
|
|
83
83
|
options: SharedServerOptions,
|
|
84
84
|
): Partial<MCPServerConfig> {
|
|
@@ -117,7 +117,11 @@ function createServerConfig(
|
|
|
117
117
|
excludeTools: options.excludeTools,
|
|
118
118
|
};
|
|
119
119
|
const headers = parseHeaderEntries(options.header);
|
|
120
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
options.transport === 'sse' ||
|
|
122
|
+
options.transport === 'http' ||
|
|
123
|
+
options.transport === 'streamable-http'
|
|
124
|
+
) {
|
|
121
125
|
return createHttpServerConfig(
|
|
122
126
|
commandOrUrl,
|
|
123
127
|
options.transport,
|
|
@@ -216,10 +220,10 @@ export const addCommand: CommandModule = {
|
|
|
216
220
|
})
|
|
217
221
|
.option('transport', {
|
|
218
222
|
alias: ['t', 'type'],
|
|
219
|
-
describe: 'Transport type (stdio, sse, http)',
|
|
223
|
+
describe: 'Transport type (stdio, sse, http, streamable-http)',
|
|
220
224
|
type: 'string',
|
|
221
225
|
default: 'stdio',
|
|
222
|
-
choices: ['stdio', 'sse', 'http'],
|
|
226
|
+
choices: ['stdio', 'sse', 'http', 'streamable-http'],
|
|
223
227
|
})
|
|
224
228
|
.option('env', {
|
|
225
229
|
alias: 'e',
|
|
@@ -37,6 +37,7 @@ export interface CliArgs {
|
|
|
37
37
|
prompt: string | undefined;
|
|
38
38
|
promptInteractive: string | undefined;
|
|
39
39
|
outputFormat: string | undefined;
|
|
40
|
+
quiet: boolean | undefined;
|
|
40
41
|
|
|
41
42
|
showMemoryUsage: boolean | undefined;
|
|
42
43
|
yolo: boolean | undefined;
|
|
@@ -161,6 +162,7 @@ function mapParsedArgsToCliArgs(result: Record<string, unknown>): CliArgs {
|
|
|
161
162
|
),
|
|
162
163
|
promptInteractive: result['promptInteractive'] as string | undefined,
|
|
163
164
|
outputFormat: result['outputFormat'] as string | undefined,
|
|
165
|
+
quiet: result['quiet'] as boolean | undefined,
|
|
164
166
|
showMemoryUsage: result['showMemoryUsage'] as boolean | undefined,
|
|
165
167
|
yolo: result['yolo'] as boolean | undefined,
|
|
166
168
|
approvalMode: result['approvalMode'] as string | undefined,
|
package/src/config/config.ts
CHANGED
|
@@ -63,6 +63,7 @@ type ConfigBuildPieces = {
|
|
|
63
63
|
extensionsEnabled: boolean;
|
|
64
64
|
adminSkillsEnabled: boolean;
|
|
65
65
|
outputFormat: Parameters<typeof buildConfig>[0]['outputFormat'];
|
|
66
|
+
quiet: boolean;
|
|
66
67
|
allowedTools: readonly string[];
|
|
67
68
|
};
|
|
68
69
|
|
|
@@ -267,6 +268,7 @@ function buildLoadedConfig(
|
|
|
267
268
|
extensionsEnabled: pieces.extensionsEnabled,
|
|
268
269
|
adminSkillsEnabled: pieces.adminSkillsEnabled,
|
|
269
270
|
outputFormat: pieces.outputFormat,
|
|
271
|
+
quiet: pieces.quiet,
|
|
270
272
|
allowedTools: pieces.allowedTools,
|
|
271
273
|
});
|
|
272
274
|
}
|
|
@@ -72,6 +72,7 @@ export interface ConfigBuildInput {
|
|
|
72
72
|
readonly extensionsEnabled: boolean;
|
|
73
73
|
readonly adminSkillsEnabled: boolean;
|
|
74
74
|
readonly outputFormat: OutputFormat;
|
|
75
|
+
readonly quiet: boolean;
|
|
75
76
|
readonly allowedTools: readonly string[];
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -194,6 +195,7 @@ function buildSessionBaseArgs(
|
|
|
194
195
|
filePaths,
|
|
195
196
|
screenReader,
|
|
196
197
|
outputFormat,
|
|
198
|
+
quiet,
|
|
197
199
|
question,
|
|
198
200
|
extensionsEnabled,
|
|
199
201
|
adminSkillsEnabled,
|
|
@@ -209,6 +211,7 @@ function buildSessionBaseArgs(
|
|
|
209
211
|
context.resolvedLoadMemoryFromIncludeDirectories,
|
|
210
212
|
debugMode: context.debugMode,
|
|
211
213
|
outputFormat,
|
|
214
|
+
quiet,
|
|
212
215
|
question,
|
|
213
216
|
...toolConfig,
|
|
214
217
|
extensionsEnabled,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ConfigFileError {
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function formatConfigFileErrors(
|
|
13
|
+
errors: readonly ConfigFileError[],
|
|
14
|
+
fileDescription = 'configuration file(s)',
|
|
15
|
+
): string {
|
|
16
|
+
const details = errors.map(
|
|
17
|
+
(error) => `Error in ${error.path}: ${error.message}`,
|
|
18
|
+
);
|
|
19
|
+
const instruction = `Please fix the ${fileDescription} and try again.`;
|
|
20
|
+
return details.length === 0
|
|
21
|
+
? instruction
|
|
22
|
+
: `${details.join('\n')}\n${instruction}`;
|
|
23
|
+
}
|
|
@@ -202,7 +202,16 @@ export class ExtensionEnablementManager {
|
|
|
202
202
|
private readRuntimeConfig(): RuntimeAllExtensionsEnablementConfig {
|
|
203
203
|
try {
|
|
204
204
|
const content = fs.readFileSync(this.configFilePath, 'utf-8');
|
|
205
|
-
|
|
205
|
+
const parsed: unknown = JSON.parse(content);
|
|
206
|
+
const validated = parseRuntimeEnablementConfig(parsed);
|
|
207
|
+
if (validated === null) {
|
|
208
|
+
coreEvents.emitFeedback(
|
|
209
|
+
'error',
|
|
210
|
+
'Invalid extension enablement config; ignoring malformed file.',
|
|
211
|
+
);
|
|
212
|
+
return {};
|
|
213
|
+
}
|
|
214
|
+
return validated;
|
|
206
215
|
} catch (error) {
|
|
207
216
|
if (
|
|
208
217
|
error instanceof Error &&
|
|
@@ -289,3 +298,55 @@ export class ExtensionEnablementManager {
|
|
|
289
298
|
this.sessionState.clear();
|
|
290
299
|
}
|
|
291
300
|
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Validates a single extension enablement entry.
|
|
304
|
+
* Returns `undefined` to skip, `null` if invalid, otherwise the entry.
|
|
305
|
+
*/
|
|
306
|
+
function parseExtensionEntry(
|
|
307
|
+
entry: unknown,
|
|
308
|
+
): ExtensionEnablementConfig | null | undefined {
|
|
309
|
+
if (entry === undefined) {
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
if (entry === null || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
const overrides = (entry as { overrides?: unknown }).overrides;
|
|
316
|
+
if (overrides === undefined) {
|
|
317
|
+
return { overrides: [] };
|
|
318
|
+
}
|
|
319
|
+
if (
|
|
320
|
+
!Array.isArray(overrides) ||
|
|
321
|
+
!overrides.every((rule) => typeof rule === 'string')
|
|
322
|
+
) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
return { overrides };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Validates extension-enablement.json. Returns null for structurally invalid
|
|
330
|
+
* JSON so callers can fall back safely instead of throwing at startup.
|
|
331
|
+
*/
|
|
332
|
+
function parseRuntimeEnablementConfig(
|
|
333
|
+
value: unknown,
|
|
334
|
+
): RuntimeAllExtensionsEnablementConfig | null {
|
|
335
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const result: RuntimeAllExtensionsEnablementConfig = {};
|
|
340
|
+
for (const [name, entry] of Object.entries(
|
|
341
|
+
value as Record<string, unknown>,
|
|
342
|
+
)) {
|
|
343
|
+
const parsed = parseExtensionEntry(entry);
|
|
344
|
+
if (parsed === null) {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
if (parsed !== undefined) {
|
|
348
|
+
result[name] = parsed;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
@@ -92,7 +92,8 @@ function resolveTrustAndIdeContext(
|
|
|
92
92
|
|
|
93
93
|
// Trust uses originalSettings (not profile-merged) — security critical
|
|
94
94
|
const folderTrust = originalSettings.folderTrust ?? false;
|
|
95
|
-
const trustedFolder =
|
|
95
|
+
const trustedFolder =
|
|
96
|
+
isWorkspaceTrusted(originalSettings, input.cwd) ?? false;
|
|
96
97
|
|
|
97
98
|
return { debugMode, memoryImportFormat, ideMode, folderTrust, trustedFolder };
|
|
98
99
|
}
|
|
@@ -30,6 +30,7 @@ export interface IntermediateConfig {
|
|
|
30
30
|
readonly profileSettingsWithTools: Settings;
|
|
31
31
|
readonly policyEngineConfig: PolicyEngineConfig;
|
|
32
32
|
readonly outputFormat: OutputFormat;
|
|
33
|
+
readonly quiet: boolean;
|
|
33
34
|
readonly useRipgrepSetting: boolean | undefined;
|
|
34
35
|
readonly mcpEnabled: boolean;
|
|
35
36
|
readonly extensionsEnabled: boolean;
|
|
@@ -84,9 +85,11 @@ export async function resolveIntermediateConfig(
|
|
|
84
85
|
const policyEngineConfig = await createPolicyEngineConfig(
|
|
85
86
|
profileSettingsWithTools,
|
|
86
87
|
approvalMode,
|
|
88
|
+
context.trustedFolder,
|
|
87
89
|
);
|
|
88
90
|
|
|
89
91
|
const outputFormat = resolveOutputFormat(argv);
|
|
92
|
+
const quiet = argv.quiet ?? false;
|
|
90
93
|
|
|
91
94
|
const useRipgrepSetting = await resolveRipgrepSetting(profileMergedSettings);
|
|
92
95
|
|
|
@@ -116,6 +119,7 @@ export async function resolveIntermediateConfig(
|
|
|
116
119
|
profileSettingsWithTools,
|
|
117
120
|
policyEngineConfig,
|
|
118
121
|
outputFormat,
|
|
122
|
+
quiet,
|
|
119
123
|
useRipgrepSetting,
|
|
120
124
|
mcpEnabled,
|
|
121
125
|
extensionsEnabled,
|
|
@@ -65,6 +65,7 @@ export enum Command {
|
|
|
65
65
|
|
|
66
66
|
// Text Input
|
|
67
67
|
SUBMIT = 'submit',
|
|
68
|
+
STEER = 'steer', // LLXPRT-SPECIFIC: mid-turn steering (Ctrl+Enter while streaming)
|
|
68
69
|
NEWLINE = 'newline',
|
|
69
70
|
OPEN_EXTERNAL_EDITOR = 'openExternalEditor',
|
|
70
71
|
PASTE_CLIPBOARD = 'pasteClipboard',
|
|
@@ -73,6 +74,7 @@ export enum Command {
|
|
|
73
74
|
SHOW_ERROR_DETAILS = 'showErrorDetails',
|
|
74
75
|
TOGGLE_TOOL_DESCRIPTIONS = 'toggleToolDescriptions', // LLXPRT-SPECIFIC
|
|
75
76
|
TOGGLE_TODO_DIALOG = 'toggleTodoDialog', // LLXPRT-SPECIFIC
|
|
77
|
+
TOGGLE_QUEUED_MESSAGES = 'toggleQueuedMessages', // LLXPRT-SPECIFIC
|
|
76
78
|
SHOW_IDE_CONTEXT_DETAIL = 'showIDEContextDetail',
|
|
77
79
|
TOGGLE_MARKDOWN = 'toggleMarkdown',
|
|
78
80
|
TOGGLE_COPY_MODE = 'toggleCopyMode',
|
|
@@ -223,7 +225,7 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
|
|
223
225
|
[Command.COLLAPSE_SUGGESTION]: [{ key: 'left' }],
|
|
224
226
|
|
|
225
227
|
// Text Input
|
|
226
|
-
// Must also exclude shift to allow shift+enter for
|
|
228
|
+
// Must also exclude shift to allow shift+enter for multi-line input
|
|
227
229
|
[Command.SUBMIT]: [
|
|
228
230
|
{
|
|
229
231
|
key: 'return',
|
|
@@ -232,8 +234,11 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
|
|
232
234
|
shift: false,
|
|
233
235
|
},
|
|
234
236
|
],
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
+
// Mid-turn steering: Ctrl+Enter while the agent is streaming injects the
|
|
238
|
+
// typed text at the next tool-call boundary. When not streaming, Ctrl+Enter
|
|
239
|
+
// falls through to NEWLINE (both match the same key; the handler checks
|
|
240
|
+
// STEER first and only consumes it when streaming).
|
|
241
|
+
[Command.STEER]: [{ key: 'return', ctrl: true }],
|
|
237
242
|
[Command.NEWLINE]: [
|
|
238
243
|
{ key: 'return', ctrl: true },
|
|
239
244
|
{ key: 'return', command: true },
|
|
@@ -250,6 +255,7 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
|
|
250
255
|
[Command.SHOW_ERROR_DETAILS]: [{ key: 'o', ctrl: true }],
|
|
251
256
|
[Command.TOGGLE_TOOL_DESCRIPTIONS]: [{ key: 't', ctrl: true }],
|
|
252
257
|
[Command.TOGGLE_TODO_DIALOG]: [{ key: 'q', ctrl: true }],
|
|
258
|
+
[Command.TOGGLE_QUEUED_MESSAGES]: [{ key: ']', ctrl: true }],
|
|
253
259
|
[Command.SHOW_IDE_CONTEXT_DETAIL]: [{ key: 'g', ctrl: true }],
|
|
254
260
|
[Command.TOGGLE_MARKDOWN]: [{ key: 'm', command: true }],
|
|
255
261
|
[Command.TOGGLE_COPY_MODE]: [{ key: 's', ctrl: true }],
|
|
@@ -273,6 +279,17 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
|
|
273
279
|
],
|
|
274
280
|
};
|
|
275
281
|
|
|
282
|
+
export function getDefaultKeyBindingHint(command: Command): string {
|
|
283
|
+
const binding = defaultKeyBindings[command][0];
|
|
284
|
+
const modifiers = [
|
|
285
|
+
binding.ctrl === true ? 'Ctrl' : undefined,
|
|
286
|
+
binding.command === true ? 'Cmd' : undefined,
|
|
287
|
+
binding.shift === true ? 'Shift' : undefined,
|
|
288
|
+
].filter((modifier): modifier is string => modifier !== undefined);
|
|
289
|
+
const key = binding.key ?? binding.sequence ?? '';
|
|
290
|
+
return [...modifiers, key].join('+');
|
|
291
|
+
}
|
|
292
|
+
|
|
276
293
|
interface CommandCategory {
|
|
277
294
|
readonly title: string;
|
|
278
295
|
readonly commands: readonly Command[];
|
|
@@ -357,6 +374,7 @@ export const commandCategories: readonly CommandCategory[] = [
|
|
|
357
374
|
title: 'Text Input',
|
|
358
375
|
commands: [
|
|
359
376
|
Command.SUBMIT,
|
|
377
|
+
Command.STEER,
|
|
360
378
|
Command.NEWLINE,
|
|
361
379
|
Command.OPEN_EXTERNAL_EDITOR,
|
|
362
380
|
Command.PASTE_CLIPBOARD,
|
|
@@ -383,6 +401,10 @@ export const commandCategories: readonly CommandCategory[] = [
|
|
|
383
401
|
title: 'Todo Dialog',
|
|
384
402
|
commands: [Command.TOGGLE_TODO_DIALOG, Command.TOGGLE_TOOL_DESCRIPTIONS],
|
|
385
403
|
},
|
|
404
|
+
{
|
|
405
|
+
title: 'Queued Messages',
|
|
406
|
+
commands: [Command.TOGGLE_QUEUED_MESSAGES],
|
|
407
|
+
},
|
|
386
408
|
{
|
|
387
409
|
title: 'Mouse',
|
|
388
410
|
commands: [Command.TOGGLE_MOUSE_EVENTS],
|
|
@@ -452,6 +474,8 @@ export const commandDescriptions: Readonly<Record<Command, string>> = {
|
|
|
452
474
|
|
|
453
475
|
// Text Input
|
|
454
476
|
[Command.SUBMIT]: 'Submit the current prompt.',
|
|
477
|
+
[Command.STEER]:
|
|
478
|
+
'Steer the active agent mid-turn by injecting input at the next tool-call boundary (only during streaming).',
|
|
455
479
|
[Command.NEWLINE]: 'Insert a newline without submitting.',
|
|
456
480
|
[Command.OPEN_EXTERNAL_EDITOR]:
|
|
457
481
|
'Open the current prompt in an external editor.',
|
|
@@ -462,6 +486,8 @@ export const commandDescriptions: Readonly<Record<Command, string>> = {
|
|
|
462
486
|
[Command.SHOW_ERROR_DETAILS]: 'Toggle detailed error information.',
|
|
463
487
|
[Command.TOGGLE_TOOL_DESCRIPTIONS]: 'Toggle tool descriptions display.',
|
|
464
488
|
[Command.TOGGLE_TODO_DIALOG]: 'Toggle the TODO dialog visibility.',
|
|
489
|
+
[Command.TOGGLE_QUEUED_MESSAGES]:
|
|
490
|
+
'Toggle the queued messages panel visibility.',
|
|
465
491
|
[Command.SHOW_IDE_CONTEXT_DETAIL]: 'Show IDE context details.',
|
|
466
492
|
[Command.TOGGLE_MARKDOWN]: 'Toggle Markdown rendering.',
|
|
467
493
|
[Command.TOGGLE_COPY_MODE]: 'Toggle copy mode when in alternate buffer mode.',
|
package/src/config/policy.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { type Settings } from './settings.js';
|
|
|
18
18
|
export async function createPolicyEngineConfig(
|
|
19
19
|
settings: Settings,
|
|
20
20
|
approvalMode: ApprovalMode,
|
|
21
|
+
trustedFolder = true,
|
|
21
22
|
): Promise<PolicyEngineConfig> {
|
|
22
23
|
// Explicitly construct PolicySettings from Settings to ensure type safety
|
|
23
24
|
// and avoid accidental leakage of other settings properties.
|
|
@@ -38,7 +39,12 @@ export async function createPolicyEngineConfig(
|
|
|
38
39
|
mcpServers: settings.mcpServers,
|
|
39
40
|
};
|
|
40
41
|
|
|
41
|
-
return createCorePolicyEngineConfig(
|
|
42
|
+
return createCorePolicyEngineConfig(
|
|
43
|
+
policySettings,
|
|
44
|
+
approvalMode,
|
|
45
|
+
undefined,
|
|
46
|
+
trustedFolder,
|
|
47
|
+
);
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
export function createPolicyUpdater(
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
} from '@vybestack/llxprt-code-core';
|
|
15
15
|
import { DebugLogger } from '@vybestack/llxprt-code-telemetry';
|
|
16
16
|
import { ProfileManager } from '@vybestack/llxprt-code-settings';
|
|
17
|
-
import type {
|
|
17
|
+
import type {
|
|
18
|
+
EphemeralSettings,
|
|
19
|
+
SettingsService,
|
|
20
|
+
} from '@vybestack/llxprt-code-settings';
|
|
18
21
|
import {
|
|
19
22
|
getCliRuntimeContext,
|
|
20
23
|
setCliRuntimeContext,
|
|
@@ -51,7 +54,7 @@ export interface PostConfigInput {
|
|
|
51
54
|
readonly bootstrapArgs: BootstrapProfileArgs;
|
|
52
55
|
readonly argv: CliArgs;
|
|
53
56
|
readonly settings: Settings;
|
|
54
|
-
readonly profileSettingsWithTools: Settings;
|
|
57
|
+
readonly profileSettingsWithTools: Settings & EphemeralSettings;
|
|
55
58
|
readonly profileLoadResult: ProfileLoadResult;
|
|
56
59
|
readonly providerModelResult: ProviderModelResult;
|
|
57
60
|
readonly defaultDisabledTools: readonly string[];
|
|
@@ -152,7 +155,11 @@ interface ProfileEphemeralSettingsInput {
|
|
|
152
155
|
readonly bootstrapArgs: Pick<BootstrapProfileArgs, 'profileJson'>;
|
|
153
156
|
readonly argv: Pick<CliArgs, 'provider'>;
|
|
154
157
|
readonly settings: StreamTimeoutSettingsInput;
|
|
155
|
-
|
|
158
|
+
// profileSettingsWithTools carries both the public JSON settings and the
|
|
159
|
+
// ephemeral tool-governance keys (e.g. 'tools.allowed') that
|
|
160
|
+
// applyGlobalAndProfileEphemeralSettings forwards to applyToolPolicies.
|
|
161
|
+
readonly profileSettingsWithTools: StreamTimeoutSettingsInput &
|
|
162
|
+
EphemeralSettings;
|
|
156
163
|
readonly profileLoadResult: Pick<ProfileLoadResult, 'profileToLoad'>;
|
|
157
164
|
}
|
|
158
165
|
|
|
@@ -472,9 +479,9 @@ function applyToolPolicies(input: ApplyToolPoliciesInput): void {
|
|
|
472
479
|
: (profileSettingsWithTools.allowedTools ?? []),
|
|
473
480
|
);
|
|
474
481
|
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
);
|
|
482
|
+
const rawProfileAllowedTools = profileSettingsWithTools['tools.allowed'];
|
|
483
|
+
const profileAllowedExplicit = Array.isArray(rawProfileAllowedTools);
|
|
484
|
+
const profileAllowedTools = buildNormalizedToolSet(rawProfileAllowedTools);
|
|
478
485
|
|
|
479
486
|
const applyPolicy = (allowedSet: Set<string> | undefined): void => {
|
|
480
487
|
if (allowedSet === undefined) {
|
|
@@ -491,7 +498,7 @@ function applyToolPolicies(input: ApplyToolPoliciesInput): void {
|
|
|
491
498
|
|
|
492
499
|
if (interactive !== true && experimentalAcp !== true) {
|
|
493
500
|
if (approvalMode === ApprovalMode.YOLO) {
|
|
494
|
-
if (
|
|
501
|
+
if (profileAllowedExplicit || explicitAllowedTools.size > 0) {
|
|
495
502
|
const finalAllowed = new Set(profileAllowedTools);
|
|
496
503
|
explicitAllowedTools.forEach((tool) => finalAllowed.add(tool));
|
|
497
504
|
applyPolicy(finalAllowed);
|
|
@@ -507,16 +514,15 @@ function applyToolPolicies(input: ApplyToolPoliciesInput): void {
|
|
|
507
514
|
baseAllowed.add(EDIT_TOOL_NAME);
|
|
508
515
|
}
|
|
509
516
|
|
|
510
|
-
const finalAllowed =
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
: baseAllowed;
|
|
517
|
+
const finalAllowed = profileAllowedExplicit
|
|
518
|
+
? new Set(
|
|
519
|
+
[...baseAllowed].filter((tool) => profileAllowedTools.has(tool)),
|
|
520
|
+
)
|
|
521
|
+
: baseAllowed;
|
|
516
522
|
|
|
517
523
|
applyPolicy(finalAllowed);
|
|
518
524
|
}
|
|
519
|
-
} else if (
|
|
525
|
+
} else if (profileAllowedExplicit || explicitAllowedTools.size > 0) {
|
|
520
526
|
const finalAllowed = new Set(profileAllowedTools);
|
|
521
527
|
explicitAllowedTools.forEach((tool) => finalAllowed.add(tool));
|
|
522
528
|
applyPolicy(finalAllowed);
|
|
@@ -192,6 +192,15 @@ export const UI_SETTINGS_SCHEMA = {
|
|
|
192
192
|
description: 'Display memory usage information in the UI',
|
|
193
193
|
showInDialog: true,
|
|
194
194
|
},
|
|
195
|
+
alwaysDisplayFullShellCommand: {
|
|
196
|
+
type: 'boolean',
|
|
197
|
+
label: 'Always Display Full Shell Command',
|
|
198
|
+
category: 'UI',
|
|
199
|
+
requiresRestart: false,
|
|
200
|
+
default: true,
|
|
201
|
+
description: 'Display complete shell commands without truncation.',
|
|
202
|
+
showInDialog: true,
|
|
203
|
+
},
|
|
195
204
|
showLineNumbers: {
|
|
196
205
|
type: 'boolean',
|
|
197
206
|
label: 'Show Line Numbers',
|
|
@@ -11,6 +11,7 @@ import type { Settings } from './settingsSchema.js';
|
|
|
11
11
|
import { resolveEnvVarsInObject } from '../utils/envVarResolver.js';
|
|
12
12
|
import { USER_SETTINGS_PATH } from './paths.js';
|
|
13
13
|
import { mergeSettings } from './settingsMerge.js';
|
|
14
|
+
import { formatConfigFileErrors } from './configError.js';
|
|
14
15
|
import {
|
|
15
16
|
migrateHooksConfig,
|
|
16
17
|
migrateLegacyInteractiveShellSetting,
|
|
@@ -100,12 +101,11 @@ function loadOptionalSettingsFile(
|
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
function resolveRealWorkspaceDir(workspaceDir: string): string {
|
|
104
|
-
const resolvedWorkspaceDir = path.resolve(workspaceDir);
|
|
104
|
+
function resolveRealWorkspaceDir(workspaceDir: string): string | undefined {
|
|
105
105
|
try {
|
|
106
|
-
return fs.realpathSync(
|
|
106
|
+
return fs.realpathSync(path.resolve(workspaceDir));
|
|
107
107
|
} catch {
|
|
108
|
-
return
|
|
108
|
+
return undefined;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -115,7 +115,7 @@ function loadSettingsFiles(
|
|
|
115
115
|
): {
|
|
116
116
|
settings: SettingsState;
|
|
117
117
|
errors: SettingsError[];
|
|
118
|
-
realWorkspaceDir: string;
|
|
118
|
+
realWorkspaceDir: string | undefined;
|
|
119
119
|
realHomeDir: string;
|
|
120
120
|
} {
|
|
121
121
|
const errors: SettingsError[] = [];
|
|
@@ -133,7 +133,7 @@ function loadSettingsFiles(
|
|
|
133
133
|
legacyTheme: true,
|
|
134
134
|
});
|
|
135
135
|
const workspace =
|
|
136
|
-
realWorkspaceDir === realHomeDir
|
|
136
|
+
realWorkspaceDir === undefined || realWorkspaceDir === realHomeDir
|
|
137
137
|
? {}
|
|
138
138
|
: loadOptionalSettingsFile(paths.workspace, errors, {
|
|
139
139
|
legacyTheme: true,
|
|
@@ -156,7 +156,10 @@ function shouldCheckFolderTrust(settings: SettingsState): boolean {
|
|
|
156
156
|
return folderTrustFeature && folderTrustEnabled;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
function resolveTrustedState(
|
|
159
|
+
function resolveTrustedState(
|
|
160
|
+
settings: SettingsState,
|
|
161
|
+
workspaceDir: string | undefined,
|
|
162
|
+
): boolean {
|
|
160
163
|
const tempSettingsForTrust = mergeSettings(
|
|
161
164
|
settings.system,
|
|
162
165
|
settings.systemDefaults,
|
|
@@ -164,9 +167,12 @@ function resolveTrustedState(settings: SettingsState): boolean {
|
|
|
164
167
|
settings.workspace,
|
|
165
168
|
true,
|
|
166
169
|
);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
+
if (!shouldCheckFolderTrust(settings)) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return workspaceDir === undefined
|
|
174
|
+
? false
|
|
175
|
+
: (isWorkspaceTrusted(tempSettingsForTrust, workspaceDir) ?? false);
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
function loadEnvironmentAndResolveSettings(
|
|
@@ -193,12 +199,7 @@ function throwSettingsErrors(errors: SettingsError[]): void {
|
|
|
193
199
|
if (errors.length === 0) {
|
|
194
200
|
return;
|
|
195
201
|
}
|
|
196
|
-
|
|
197
|
-
(error) => `Error in ${error.path}: ${error.message}`,
|
|
198
|
-
);
|
|
199
|
-
throw new FatalConfigError(
|
|
200
|
-
`${errorMessages.join('\n')}\nPlease fix the configuration file(s) and try again.`,
|
|
201
|
-
);
|
|
202
|
+
throw new FatalConfigError(formatConfigFileErrors(errors));
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
function migrateLoadedSettings(settings: SettingsState): void {
|
|
@@ -237,7 +238,10 @@ export function loadSettings(
|
|
|
237
238
|
workspace: new Storage(workspaceDir).getWorkspaceSettingsPath(),
|
|
238
239
|
};
|
|
239
240
|
const loaded = loadSettingsFiles(workspaceDir, paths);
|
|
240
|
-
const isTrusted = resolveTrustedState(
|
|
241
|
+
const isTrusted = resolveTrustedState(
|
|
242
|
+
loaded.settings,
|
|
243
|
+
loaded.realWorkspaceDir,
|
|
244
|
+
);
|
|
241
245
|
const settings = loadEnvironmentAndResolveSettings(
|
|
242
246
|
loaded.settings,
|
|
243
247
|
isTrusted,
|
|
@@ -76,8 +76,8 @@ export const SETTINGS_SCHEMA_DEFINITIONS: Record<
|
|
|
76
76
|
type: {
|
|
77
77
|
type: 'string',
|
|
78
78
|
description:
|
|
79
|
-
'Transport type. Use "stdio" for local command, "sse" for Server-Sent Events,
|
|
80
|
-
enum: ['stdio', 'sse', 'http'],
|
|
79
|
+
'Transport type. Use "stdio" for local command, "sse" for Server-Sent Events, "http" for Streamable HTTP, or "streamable-http" as an alias for "http".',
|
|
80
|
+
enum: ['stdio', 'sse', 'http', 'streamable-http'],
|
|
81
81
|
},
|
|
82
82
|
timeout: {
|
|
83
83
|
type: 'number',
|