mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-23 00:01:24 -07:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbdfa50983 | |||
| 385fbbd9fb | |||
| c741ce328b | |||
| 2128019e70 | |||
| de8c2d8589 | |||
| 7c3b3ce219 | |||
| 652c1e2f5e | |||
| b6f9f07289 | |||
| fcb859d9ec | |||
| 8a8590c516 | |||
| 30b2af34c8 | |||
| 03da89ed63 | |||
| 48d7a7262b | |||
| 04f05459f8 |
@@ -6,9 +6,16 @@
|
||||
"gemma": true,
|
||||
"memoryManager": true,
|
||||
"topicUpdateNarration": true,
|
||||
"voiceMode": true
|
||||
"voiceMode": true,
|
||||
"enhanceCommand": true
|
||||
},
|
||||
"general": {
|
||||
"devtools": true
|
||||
"devtools": true,
|
||||
"plan": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"agents": {
|
||||
"overrides": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ they appear in the UI.
|
||||
| Auto Memory | `experimental.autoMemory` | Automatically extract reusable skills from past sessions in the background. Review results with /memory inbox. | `false` |
|
||||
| Use the generalist profile to manage agent contexts. | `experimental.generalistProfile` | Suitable for general coding and software development tasks. | `false` |
|
||||
| Enable Context Management | `experimental.contextManagement` | Enable logic for context management. | `false` |
|
||||
| Enhance Command | `experimental.enhanceCommand` | Enable the experimental /enhance slash command. | `false` |
|
||||
|
||||
### Skills
|
||||
|
||||
|
||||
@@ -1872,6 +1872,11 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Description:** Deprecated: Use general.topicUpdateNarration instead.
|
||||
- **Default:** `false`
|
||||
|
||||
- **`experimental.enhanceCommand`** (boolean):
|
||||
- **Description:** Enable the experimental /enhance slash command.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
#### `skills`
|
||||
|
||||
- **`skills.enabled`** (boolean):
|
||||
|
||||
@@ -94,6 +94,7 @@ available combinations.
|
||||
| `input.openExternalEditor` | Open the current prompt or the plan in an external editor. | `Ctrl+G`<br />`Ctrl+Shift+G` |
|
||||
| `input.deprecatedOpenExternalEditor` | Deprecated command to open external editor. | `Ctrl+X` |
|
||||
| `input.paste` | Paste from the clipboard. | `Ctrl+V`<br />`Cmd/Win+V`<br />`Alt+V` |
|
||||
| `input.enhancePrompt` | Enhance the current prompt using an LLM. | `Alt+E` |
|
||||
|
||||
#### App Controls
|
||||
|
||||
|
||||
@@ -1035,6 +1035,7 @@ export async function loadCliConfig(
|
||||
extensionRegistryURI,
|
||||
enableExtensionReloading: settings.experimental?.extensionReloading,
|
||||
enableAgents: settings.experimental?.enableAgents,
|
||||
enableEnhanceCommand: settings.experimental?.enhanceCommand ?? false,
|
||||
plan: settings.general?.plan?.enabled ?? true,
|
||||
voiceMode: settings.experimental?.voiceMode,
|
||||
tracker: settings.experimental?.taskTracker,
|
||||
|
||||
@@ -2437,6 +2437,15 @@ const SETTINGS_SCHEMA = {
|
||||
description: 'Deprecated: Use general.topicUpdateNarration instead.',
|
||||
showInDialog: false,
|
||||
},
|
||||
enhanceCommand: {
|
||||
type: 'boolean',
|
||||
label: 'Enhance Command',
|
||||
category: 'Experimental',
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
description: 'Enable the experimental /enhance slash command.',
|
||||
showInDialog: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
extensions: {
|
||||
|
||||
@@ -171,6 +171,7 @@ describe('BuiltinCommandLoader', () => {
|
||||
isAdminEnabled: vi.fn().mockReturnValue(true),
|
||||
}),
|
||||
isVoiceModeEnabled: vi.fn().mockReturnValue(true),
|
||||
isEnhanceCommandEnabled: vi.fn().mockReturnValue(true),
|
||||
getContentGeneratorConfig: vi.fn().mockReturnValue({
|
||||
authType: 'other',
|
||||
}),
|
||||
@@ -310,6 +311,22 @@ describe('BuiltinCommandLoader', () => {
|
||||
expect(agentsCmd).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should include enhance command when experimental enhance command is enabled', async () => {
|
||||
(mockConfig.isEnhanceCommandEnabled as Mock).mockReturnValue(true);
|
||||
const loader = new BuiltinCommandLoader(mockConfig);
|
||||
const commands = await loader.loadCommands(new AbortController().signal);
|
||||
const enhanceCmd = commands.find((c) => c.name === 'enhance');
|
||||
expect(enhanceCmd).toBeDefined();
|
||||
});
|
||||
|
||||
it('should exclude enhance command when experimental enhance command is disabled', async () => {
|
||||
(mockConfig.isEnhanceCommandEnabled as Mock).mockReturnValue(false);
|
||||
const loader = new BuiltinCommandLoader(mockConfig);
|
||||
const commands = await loader.loadCommands(new AbortController().signal);
|
||||
const enhanceCmd = commands.find((c) => c.name === 'enhance');
|
||||
expect(enhanceCmd).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('chat debug command', () => {
|
||||
it('should NOT add debug subcommand to chat/resume commands if not a nightly build', async () => {
|
||||
vi.mocked(isNightly).mockResolvedValue(false);
|
||||
@@ -398,6 +415,7 @@ describe('BuiltinCommandLoader profile', () => {
|
||||
isAdminEnabled: vi.fn().mockReturnValue(true),
|
||||
}),
|
||||
isVoiceModeEnabled: vi.fn().mockReturnValue(true),
|
||||
isEnhanceCommandEnabled: vi.fn().mockReturnValue(true),
|
||||
getContentGeneratorConfig: vi.fn().mockReturnValue({
|
||||
authType: 'other',
|
||||
}),
|
||||
|
||||
@@ -31,6 +31,7 @@ import { corgiCommand } from '../ui/commands/corgiCommand.js';
|
||||
import { docsCommand } from '../ui/commands/docsCommand.js';
|
||||
import { directoryCommand } from '../ui/commands/directoryCommand.js';
|
||||
import { editorCommand } from '../ui/commands/editorCommand.js';
|
||||
import { enhanceCommand } from '../ui/commands/enhanceCommand.js';
|
||||
import { extensionsCommand } from '../ui/commands/extensionsCommand.js';
|
||||
import { footerCommand } from '../ui/commands/footerCommand.js';
|
||||
import { helpCommand } from '../ui/commands/helpCommand.js';
|
||||
@@ -135,6 +136,7 @@ export class BuiltinCommandLoader implements ICommandLoader {
|
||||
docsCommand,
|
||||
directoryCommand,
|
||||
editorCommand,
|
||||
...(this.config?.isEnhanceCommandEnabled() ? [enhanceCommand] : []),
|
||||
...(this.config?.getExtensionsEnabled() === false
|
||||
? [
|
||||
{
|
||||
|
||||
@@ -58,6 +58,7 @@ export const createMockCommandContext = (
|
||||
pendingItem: null,
|
||||
setPendingItem: vi.fn(),
|
||||
loadHistory: vi.fn(),
|
||||
setInput: vi.fn(),
|
||||
toggleCorgiMode: vi.fn(),
|
||||
toggleShortcutsHelp: vi.fn(),
|
||||
toggleVimEnabled: vi.fn(),
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import { enhanceCommand } from './enhanceCommand.js';
|
||||
import { type CommandContext } from './types.js';
|
||||
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
||||
import { MessageType } from '../types.js';
|
||||
import { LlmRole } from '@google/gemini-cli-core';
|
||||
|
||||
describe('enhanceCommand', () => {
|
||||
let mockContext: CommandContext;
|
||||
let mockGenerateContent: Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
mockGenerateContent = vi.fn();
|
||||
mockContext = createMockCommandContext({
|
||||
services: {
|
||||
agentContext: {
|
||||
promptId: 'test-prompt-id',
|
||||
geminiClient: {
|
||||
getHistory: vi.fn().mockReturnValue([
|
||||
{ role: 'user', parts: [{ text: 'previous user msg' }] },
|
||||
{ role: 'model', parts: [{ text: 'previous model msg' }] },
|
||||
]),
|
||||
},
|
||||
config: {
|
||||
getModel: vi.fn().mockReturnValue('test-model'),
|
||||
getContentGenerator: vi.fn().mockReturnValue({
|
||||
generateContent: mockGenerateContent,
|
||||
}),
|
||||
getGemini31LaunchedSync: vi.fn().mockReturnValue(true),
|
||||
getHasAccessToPreviewModel: vi.fn().mockReturnValue(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
ui: {
|
||||
addItem: vi.fn(),
|
||||
setDebugMessage: vi.fn(),
|
||||
},
|
||||
} as unknown as CommandContext);
|
||||
});
|
||||
|
||||
it('should have the correct name and description', () => {
|
||||
expect(enhanceCommand.name).toBe('enhance');
|
||||
expect(enhanceCommand.description).toBe(
|
||||
'Enhance a prompt with additional context and rephrasing',
|
||||
);
|
||||
});
|
||||
|
||||
it('should show error if no prompt is provided', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
await enhanceCommand.action(mockContext, '');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.ERROR,
|
||||
text: expect.stringContaining('Please provide a prompt'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should call generateContent with correct parameters and show enhanced prompt', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
mockGenerateContent.mockResolvedValue({
|
||||
candidates: [
|
||||
{
|
||||
content: {
|
||||
parts: [{ text: 'Enhanced: do something' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await enhanceCommand.action(mockContext, 'do something');
|
||||
|
||||
expect(mockGenerateContent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
model: 'test-model',
|
||||
contents: [
|
||||
{ role: 'user', parts: [{ text: 'previous user msg' }] },
|
||||
{ role: 'model', parts: [{ text: 'previous model msg' }] },
|
||||
{ role: 'user', parts: [{ text: 'do something' }] },
|
||||
],
|
||||
config: {
|
||||
systemInstruction: {
|
||||
role: 'system',
|
||||
parts: [
|
||||
{
|
||||
text: expect.stringContaining(
|
||||
"Generate an enhanced version of the user's prompt",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
'test-prompt-id',
|
||||
LlmRole.UTILITY_TOOL,
|
||||
);
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: expect.stringContaining(
|
||||
'Enhanced prompt:\n\nEnhanced: do something',
|
||||
),
|
||||
}),
|
||||
);
|
||||
expect(mockContext.ui.setInput).toHaveBeenCalledWith(
|
||||
'Enhanced: do something',
|
||||
);
|
||||
});
|
||||
|
||||
it('should clean the response from markdown and quotes', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
mockGenerateContent.mockResolvedValue({
|
||||
candidates: [
|
||||
{
|
||||
content: {
|
||||
parts: [{ text: '```markdown\n"Clean me"\n```' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await enhanceCommand.action(mockContext, 'dirty prompt');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: expect.stringContaining('Enhanced prompt:\n\nClean me'),
|
||||
}),
|
||||
);
|
||||
expect(mockContext.ui.setInput).toHaveBeenCalledWith('Clean me');
|
||||
});
|
||||
|
||||
it('should handle API errors gracefully', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
mockGenerateContent.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
await enhanceCommand.action(mockContext, 'test prompt');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.ERROR,
|
||||
text: expect.stringContaining('Failed to enhance prompt: API Error'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle empty response from model', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
mockGenerateContent.mockResolvedValue({
|
||||
candidates: [],
|
||||
});
|
||||
|
||||
await enhanceCommand.action(mockContext, 'test prompt');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.ERROR,
|
||||
text: expect.stringContaining('Empty response from model'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
it('should ignore thought parts and sanitize the output', async () => {
|
||||
if (!enhanceCommand.action) throw new Error('Action must be defined');
|
||||
|
||||
mockGenerateContent.mockResolvedValue({
|
||||
candidates: [
|
||||
{
|
||||
content: {
|
||||
parts: [
|
||||
{ thought: true, text: 'This is a thought.' },
|
||||
{ text: 'Sanitized\nPrompt]' },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await enhanceCommand.action(mockContext, 'dirty prompt');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: expect.stringContaining('Enhanced prompt:\n\nSanitizedPrompt'),
|
||||
}),
|
||||
);
|
||||
expect(mockContext.ui.setInput).toHaveBeenCalledWith('SanitizedPrompt');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { CommandKind, type SlashCommand } from './types.js';
|
||||
import { MessageType } from '../types.js';
|
||||
import { LlmRole, resolveModel } from '@google/gemini-cli-core';
|
||||
import type { Content } from '@google/genai';
|
||||
|
||||
const INSTRUCTION =
|
||||
"Generate an enhanced version of the user's prompt, using the preceding conversation as context. Reply with ONLY the enhanced prompt - no conversation, explanations, lead-in, bullet points, placeholders, or surrounding quotes.";
|
||||
|
||||
function clean(text: string) {
|
||||
const stripped = text.replace(/^```\w*\n?|```$/g, '').trim();
|
||||
return stripped.replace(/^(['"])([\s\S]*)\1$/, '$2').trim();
|
||||
}
|
||||
|
||||
export const enhanceCommand: SlashCommand = {
|
||||
name: 'enhance',
|
||||
description: 'Enhance a prompt with additional context and rephrasing',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
autoExecute: false,
|
||||
action: async (context, args) => {
|
||||
const draft = args.trim();
|
||||
if (!draft) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: 'Please provide a prompt to enhance. Usage: /enhance <prompt>',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const agentContext = context.services.agentContext;
|
||||
if (!agentContext) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: 'Agent context not available.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const config = agentContext.config;
|
||||
const contentGenerator = config.getContentGenerator();
|
||||
const promptId = agentContext.promptId;
|
||||
|
||||
const model = resolveModel(
|
||||
config.getModel(),
|
||||
config.getGemini31LaunchedSync?.() ?? false,
|
||||
false,
|
||||
false,
|
||||
config.getHasAccessToPreviewModel?.() ?? true,
|
||||
config,
|
||||
);
|
||||
|
||||
context.ui.setDebugMessage('Enhancing prompt...');
|
||||
|
||||
try {
|
||||
const history = agentContext.geminiClient?.getHistory() ?? [];
|
||||
const contents: Content[] = [
|
||||
...history,
|
||||
{ role: 'user', parts: [{ text: draft }] },
|
||||
];
|
||||
|
||||
const response = await contentGenerator.generateContent(
|
||||
{
|
||||
model,
|
||||
contents,
|
||||
config: {
|
||||
systemInstruction: {
|
||||
role: 'system',
|
||||
parts: [{ text: INSTRUCTION }],
|
||||
},
|
||||
},
|
||||
},
|
||||
promptId,
|
||||
LlmRole.UTILITY_TOOL,
|
||||
);
|
||||
|
||||
const parts = response.candidates?.[0]?.content?.parts;
|
||||
const enhancedText = parts
|
||||
?.find((part) => 'text' in part && !('thought' in part))
|
||||
?.text?.replace(/\n/g, '')
|
||||
?.replace(/]/g, '');
|
||||
|
||||
if (enhancedText) {
|
||||
const cleanedText = clean(enhancedText);
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `Enhanced prompt:\n\n${cleanedText}`,
|
||||
});
|
||||
context.ui.setInput(cleanedText);
|
||||
} else {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: 'Failed to enhance prompt: Empty response from model.',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: `Failed to enhance prompt: ${error instanceof Error ? error.message : String(error)}`,
|
||||
});
|
||||
} finally {
|
||||
context.ui.setDebugMessage('');
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -70,6 +70,12 @@ export interface CommandContext {
|
||||
* @param postLoadInput Optional text to set in the input buffer after loading history.
|
||||
*/
|
||||
loadHistory: (history: HistoryItem[], postLoadInput?: string) => void;
|
||||
/**
|
||||
* Sets the text in the input buffer.
|
||||
*
|
||||
* @param text The text to set.
|
||||
*/
|
||||
setInput: (text: string) => void;
|
||||
/** Toggles a special display mode. */
|
||||
toggleCorgiMode: () => void;
|
||||
toggleVoiceMode: () => void;
|
||||
|
||||
@@ -153,6 +153,12 @@ export const Help: React.FC<Help> = ({ commands }) => (
|
||||
</Text>{' '}
|
||||
- Open input in external editor
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
{formatCommand(Command.ENHANCE_PROMPT)}
|
||||
</Text>{' '}
|
||||
- Enhance the current prompt using an LLM
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
{formatCommand(Command.TOGGLE_YOLO)}
|
||||
|
||||
@@ -1287,6 +1287,16 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
return true;
|
||||
}
|
||||
|
||||
// Alt+E for enhance prompt
|
||||
if (keyMatchers[Command.ENHANCE_PROMPT](key)) {
|
||||
const enhanceCmd = slashCommands.find((cmd) => cmd.name === 'enhance');
|
||||
if (enhanceCmd && enhanceCmd.action) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
enhanceCmd.action(commandContext, buffer.text);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyMatchers[Command.DEPRECATED_OPEN_EXTERNAL_EDITOR](key)) {
|
||||
const cmdKey = formatCommand(Command.OPEN_EXTERNAL_EDITOR);
|
||||
appEvents.emit(AppEvent.TransientMessage, {
|
||||
@@ -1352,6 +1362,8 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
inputHistory,
|
||||
handleSubmit,
|
||||
shellHistory,
|
||||
slashCommands,
|
||||
commandContext,
|
||||
reverseSearchCompletion,
|
||||
handleClipboardPaste,
|
||||
resetCompletionState,
|
||||
|
||||
@@ -44,6 +44,10 @@ const buildShortcutItems = (): ShortcutItem[] => [
|
||||
key: formatCommand(Command.OPEN_EXTERNAL_EDITOR),
|
||||
description: 'open external editor',
|
||||
},
|
||||
{
|
||||
key: formatCommand(Command.ENHANCE_PROMPT),
|
||||
description: 'enhance prompt',
|
||||
},
|
||||
];
|
||||
|
||||
const Shortcut: React.FC<{ item: ShortcutItem }> = ({ item }) => (
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'linux' 1`] = `
|
||||
Alt+M raw markdown mode
|
||||
Ctrl+R reverse-search history
|
||||
Ctrl+G open external editor
|
||||
Alt+E enhance prompt
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -29,6 +30,7 @@ exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'mac' 1`] = `
|
||||
Option+M raw markdown mode
|
||||
Ctrl+R reverse-search history
|
||||
Ctrl+G open external editor
|
||||
Option+E enhance prompt
|
||||
"
|
||||
`;
|
||||
|
||||
|
||||
@@ -230,6 +230,7 @@ export const useSlashCommandProcessor = (
|
||||
actions.setText(postLoadInput);
|
||||
}
|
||||
},
|
||||
setInput: (text) => actions.setText(text),
|
||||
setDebugMessage: actions.setDebugMessage,
|
||||
pendingItem,
|
||||
setPendingItem,
|
||||
|
||||
@@ -79,6 +79,7 @@ export enum Command {
|
||||
OPEN_EXTERNAL_EDITOR = 'input.openExternalEditor',
|
||||
DEPRECATED_OPEN_EXTERNAL_EDITOR = 'input.deprecatedOpenExternalEditor',
|
||||
PASTE_CLIPBOARD = 'input.paste',
|
||||
ENHANCE_PROMPT = 'input.enhancePrompt',
|
||||
|
||||
// App Controls
|
||||
SHOW_ERROR_DETAILS = 'app.showErrorDetails',
|
||||
@@ -382,6 +383,7 @@ export const defaultKeyBindingConfig: KeyBindingConfig = new Map([
|
||||
[new KeyBinding('ctrl+g'), new KeyBinding('ctrl+shift+g')],
|
||||
],
|
||||
[Command.DEPRECATED_OPEN_EXTERNAL_EDITOR, [new KeyBinding('ctrl+x')]],
|
||||
[Command.ENHANCE_PROMPT, [new KeyBinding('alt+e')]],
|
||||
[
|
||||
Command.PASTE_CLIPBOARD,
|
||||
[
|
||||
@@ -520,6 +522,7 @@ export const commandCategories: readonly CommandCategory[] = [
|
||||
Command.OPEN_EXTERNAL_EDITOR,
|
||||
Command.DEPRECATED_OPEN_EXTERNAL_EDITOR,
|
||||
Command.PASTE_CLIPBOARD,
|
||||
Command.ENHANCE_PROMPT,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -639,6 +642,7 @@ export const commandDescriptions: Readonly<Record<Command, string>> = {
|
||||
[Command.DEPRECATED_OPEN_EXTERNAL_EDITOR]:
|
||||
'Deprecated command to open external editor.',
|
||||
[Command.PASTE_CLIPBOARD]: 'Paste from the clipboard.',
|
||||
[Command.ENHANCE_PROMPT]: 'Enhance the current prompt using an LLM.',
|
||||
|
||||
// App Controls
|
||||
[Command.SHOW_ERROR_DETAILS]:
|
||||
|
||||
@@ -29,6 +29,7 @@ export function createNonInteractiveUI(): CommandContext['ui'] {
|
||||
clear: () => {},
|
||||
setDebugMessage: (_message) => {},
|
||||
loadHistory: (_newHistory) => {},
|
||||
setInput: (_text) => {},
|
||||
pendingItem: null,
|
||||
setPendingItem: (_item) => {},
|
||||
toggleCorgiMode: () => {},
|
||||
|
||||
@@ -165,45 +165,6 @@ exports[`TableRenderer > renders a complex table with mixed content lengths corr
|
||||
└─────────────────────────────┴──────────────────────────────┴─────────────────────────────┴──────────────────────────────┴─────┴────────┴─────────┴───────┘"
|
||||
`;
|
||||
|
||||
exports[`TableRenderer > renders a complex table with mixed content lengths correctly 2`] = `
|
||||
"
|
||||
┌─────────────────────────────┬──────────────────────────────┬─────────────────────────────┬──────────────────────────────┬─────┬────────┬─────────┬───────┐
|
||||
│ Comprehensive Architectural │ Implementation Details for │ Longitudinal Performance │ Strategic Security Framework │ Key │ Status │ Version │ Owner │
|
||||
│ Specification for the │ the High-Throughput │ Analysis Across │ for Mitigating Sophisticated │ │ │ │ │
|
||||
│ Distributed Infrastructure │ Asynchronous Message │ Multi-Regional Cloud │ Cross-Site Scripting │ │ │ │ │
|
||||
│ Layer │ Processing Pipeline with │ Deployment Clusters │ Vulnerabilities │ │ │ │ │
|
||||
│ │ Extended Scalability │ │ │ │ │ │ │
|
||||
│ │ Features and Redundancy │ │ │ │ │ │ │
|
||||
│ │ Protocols │ │ │ │ │ │ │
|
||||
├─────────────────────────────┼──────────────────────────────┼─────────────────────────────┼──────────────────────────────┼─────┼────────┼─────────┼───────┤
|
||||
│ The primary architecture │ Each message is processed │ Historical data indicates a │ A multi-layered defense │ INF │ Active │ v2.4 │ J. │
|
||||
│ utilizes a decoupled │ through a series of │ significant reduction in │ strategy incorporates │ │ │ │ Doe │
|
||||
│ microservices approach, │ specialized workers that │ tail latency when utilizing │ content security policies, │ │ │ │ │
|
||||
│ leveraging container │ handle data transformation, │ edge computing nodes closer │ input sanitization │ │ │ │ │
|
||||
│ orchestration for │ validation, and persistent │ to the geographic location │ libraries, and regular │ │ │ │ │
|
||||
│ scalability and fault │ storage using a persistent │ of the end-user base. │ automated penetration │ │ │ │ │
|
||||
│ tolerance in high-load │ queue. │ │ testing routines. │ │ │ │ │
|
||||
│ scenarios. │ │ Monitoring tools have │ │ │ │ │ │
|
||||
│ │ The pipeline features │ captured a steady increase │ Developers are required to │ │ │ │ │
|
||||
│ This layer provides the │ built-in retry mechanisms │ in throughput efficiency │ undergo mandatory security │ │ │ │ │
|
||||
│ fundamental building blocks │ with exponential backoff to │ since the introduction of │ training focusing on the │ │ │ │ │
|
||||
│ for service discovery, load │ ensure message delivery │ the vectorized query engine │ OWASP Top Ten to ensure that │ │ │ │ │
|
||||
│ balancing, and │ integrity even during │ in the primary data │ security is integrated into │ │ │ │ │
|
||||
│ inter-service communication │ transient network or service │ warehouse. │ the initial design phase. │ │ │ │ │
|
||||
│ via highly efficient │ failures. │ │ │ │ │ │ │
|
||||
│ protocol buffers. │ │ Resource utilization │ The implementation of a │ │ │ │ │
|
||||
│ │ Horizontal autoscaling is │ metrics demonstrate that │ robust Identity and Access │ │ │ │ │
|
||||
│ Advanced telemetry and │ triggered automatically │ the transition to │ Management system ensures │ │ │ │ │
|
||||
│ logging integrations allow │ based on the depth of the │ serverless compute for │ that the principle of least │ │ │ │ │
|
||||
│ for real-time monitoring of │ processing queue, ensuring │ intermittent tasks has │ privilege is strictly │ │ │ │ │
|
||||
│ system health and rapid │ consistent performance │ resulted in a thirty │ enforced across all │ │ │ │ │
|
||||
│ identification of │ during unexpected traffic │ percent cost optimization. │ environments. │ │ │ │ │
|
||||
│ bottlenecks within the │ spikes. │ │ │ │ │ │ │
|
||||
│ service mesh. │ │ │ │ │ │ │ │
|
||||
└─────────────────────────────┴──────────────────────────────┴─────────────────────────────┴──────────────────────────────┴─────┴────────┴─────────┴───────┘
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`TableRenderer > renders a table with long headers and 4 columns correctly 1`] = `
|
||||
"┌───────────────┬───────────────┬──────────────────┬──────────────────┐
|
||||
│ Very Long │ Very Long │ Very Long Column │ Very Long Column │
|
||||
|
||||
@@ -709,6 +709,7 @@ export interface ConfigParameters {
|
||||
disabledSkills?: string[];
|
||||
adminSkillsEnabled?: boolean;
|
||||
experimentalJitContext?: boolean;
|
||||
enableEnhanceCommand?: boolean;
|
||||
autoDistillation?: boolean;
|
||||
experimentalMemoryV2?: boolean;
|
||||
experimentalAutoMemory?: boolean;
|
||||
@@ -950,6 +951,7 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
private readonly vertexAiRouting: VertexAiRoutingConfig | undefined;
|
||||
|
||||
private readonly enableAgents: boolean;
|
||||
private readonly enableEnhanceCommand: boolean;
|
||||
private agents: AgentSettings;
|
||||
private readonly enableEventDrivenScheduler: boolean;
|
||||
private readonly skillsSupport: boolean;
|
||||
@@ -1116,6 +1118,7 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
this.disableLoopDetection = params.disableLoopDetection ?? false;
|
||||
this._activeModel = params.model;
|
||||
this.enableAgents = params.enableAgents ?? true;
|
||||
this.enableEnhanceCommand = params.enableEnhanceCommand ?? false;
|
||||
this.agents = params.agents ?? {};
|
||||
this.disableLLMCorrection = params.disableLLMCorrection ?? true;
|
||||
this.planEnabled = params.plan ?? true;
|
||||
@@ -2972,6 +2975,10 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
return this.planEnabled;
|
||||
}
|
||||
|
||||
isEnhanceCommandEnabled(): boolean {
|
||||
return this.enableEnhanceCommand;
|
||||
}
|
||||
|
||||
isVoiceModeEnabled(): boolean {
|
||||
return this.voiceMode;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export class SimulationHarness {
|
||||
);
|
||||
|
||||
// 3. Yield to event loop to allow internal async subscribers and orchestrator to finish
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
|
||||
// 3.1 Simulate what projectCompressedHistory does with the sync handlers
|
||||
let currentView = this.contextManager.getNodes();
|
||||
|
||||
@@ -3181,6 +3181,13 @@
|
||||
"markdownDescription": "Deprecated: Use general.topicUpdateNarration instead.\n\n- Category: `Experimental`\n- Requires restart: `no`\n- Default: `false`",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"enhanceCommand": {
|
||||
"title": "Enhance Command",
|
||||
"description": "Enable the experimental /enhance slash command.",
|
||||
"markdownDescription": "Enable the experimental /enhance slash command.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `false`",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
Reference in New Issue
Block a user