diff --git a/packages/cli/src/test-utils/render.tsx b/packages/cli/src/test-utils/render.tsx index 0c8eac325e..2625e7d6b6 100644 --- a/packages/cli/src/test-utils/render.tsx +++ b/packages/cli/src/test-utils/render.tsx @@ -160,6 +160,8 @@ const baseMockUiState = { proQuotaRequest: null, validationRequest: null, }, + hintMode: false, + hintBuffer: '', }; export const mockAppState: AppState = { @@ -209,6 +211,10 @@ const mockUIActions: UIActions = { setActiveBackgroundShellPid: vi.fn(), setIsBackgroundShellListOpen: vi.fn(), setAuthContext: vi.fn(), + onHintInput: vi.fn(), + onHintBackspace: vi.fn(), + onHintClear: vi.fn(), + onHintSubmit: vi.fn(), handleRestart: vi.fn(), handleNewAgentsSelect: vi.fn(), }; diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index c18b9f24e8..d761af49fe 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -94,7 +94,11 @@ import { basename } from 'node:path'; import { computeTerminalTitle } from '../utils/windowTitle.js'; import { useTextBuffer } from './components/shared/text-buffer.js'; import { useLogger } from './hooks/useLogger.js'; -import { useGeminiStream } from './hooks/useGeminiStream.js'; +import { + buildUserSteeringHintPrompt, + generateSteeringAckMessage, + useGeminiStream, +} from './hooks/useGeminiStream.js'; import { type BackgroundShell } from './hooks/shellCommandProcessor.js'; import { useVim } from './hooks/vim.js'; import { type LoadableSettingScope, SettingScope } from '../config/settings.js'; @@ -963,6 +967,18 @@ Logging in with Google... Restarting Gemini CLI to continue. } }, [pendingRestorePrompt, inputHistory, historyManager.history]); + const consumePendingHints = useCallback(() => { + const userHints = config.consumeUserHints(); + if (userHints.length === 0) { + return null; + } + return userHints.join('\n'); + }, [config]); + const getUserHint = useCallback( + () => consumePendingHints(), + [consumePendingHints], + ); + const { streamingState, submitQuery, @@ -1001,6 +1017,7 @@ Logging in with Google... Restarting Gemini CLI to continue. terminalWidth, terminalHeight, embeddedShellFocused, + getUserHint, ); toggleBackgroundShellRef.current = toggleBackgroundShell; @@ -1103,10 +1120,38 @@ Logging in with Google... Restarting Gemini CLI to continue. ], ); + const handleHintSubmit = useCallback( + (hint: string) => { + const trimmed = hint.trim(); + if (!trimmed) { + return; + } + config.addUserHint(trimmed); + // Render hints as regular user input so they look like normal commands. + historyManager.addItem({ + type: MessageType.USER, + text: trimmed, + }); + }, + [config, historyManager], + ); + const handleFinalSubmit = useCallback( async (submittedValue: string) => { const isSlash = isSlashCommand(submittedValue.trim()); const isIdle = streamingState === StreamingState.Idle; + const isAgentRunning = + streamingState === StreamingState.Responding || + isToolExecuting([ + ...pendingSlashCommandHistoryItems, + ...pendingGeminiHistoryItems, + ]); + + if (isAgentRunning && !isSlash) { + handleHintSubmit(submittedValue); + addInput(submittedValue); + return; + } if (isSlash || (isIdle && isMcpReady)) { if (!isSlash) { @@ -1148,7 +1193,10 @@ Logging in with Google... Restarting Gemini CLI to continue. isMcpReady, streamingState, messageQueue.length, + pendingSlashCommandHistoryItems, + pendingGeminiHistoryItems, config, + handleHintSubmit, ], ); @@ -1814,6 +1862,43 @@ Logging in with Google... Restarting Gemini CLI to continue. [pendingSlashCommandHistoryItems, pendingGeminiHistoryItems], ); + useEffect(() => { + if ( + !isConfigInitialized || + streamingState !== StreamingState.Idle || + !isMcpReady + ) { + return; + } + + const pendingHint = consumePendingHints(); + if (!pendingHint) { + return; + } + + const geminiClient = config.getGeminiClient(); + void generateSteeringAckMessage(geminiClient, pendingHint).then( + (ackText) => { + historyManager.addItem({ + type: 'info', + icon: '· ', + color: 'gray', + marginBottom: 1, + text: ackText, + } as Omit); + }, + ); + void submitQuery([{ text: buildUserSteeringHintPrompt(pendingHint) }]); + }, [ + config, + consumePendingHints, + historyManager, + isConfigInitialized, + isMcpReady, + streamingState, + submitQuery, + ]); + const allToolCalls = useMemo( () => pendingHistoryItems @@ -1975,6 +2060,8 @@ Logging in with Google... Restarting Gemini CLI to continue. isBackgroundShellListOpen, adminSettingsChanged, newAgents, + hintMode: false, + hintBuffer: '', }), [ isThemeDialogOpen, @@ -2137,6 +2224,10 @@ Logging in with Google... Restarting Gemini CLI to continue. setActiveBackgroundShellPid, setIsBackgroundShellListOpen, setAuthContext, + onHintInput: () => {}, + onHintBackspace: () => {}, + onHintClear: () => {}, + onHintSubmit: () => {}, handleRestart: async () => { if (process.send) { const remoteSettings = config.getRemoteAdminSettings(); diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index 3fc830c1b7..a36848b8c6 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -71,7 +71,8 @@ export const Footer: React.FC = () => { const justifyContent = hideCWD && hideModelInfo ? 'center' : 'space-between'; const displayVimMode = vimEnabled ? vimMode : undefined; - const showDebugProfiler = debugMode || isDevelopment; + const showDebugProfiler = + debugMode || (isDevelopment && settings.merged.general.devtools); return ( ', () => { }, background: { primary: '', + hintMode: '', diff: { added: '', removed: '' }, }, border: { diff --git a/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx b/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx index b232ff948a..df772e9410 100644 --- a/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx +++ b/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx @@ -44,6 +44,18 @@ describe('', () => { expect(lastFrame()).toContain('Hello'); }); + it('renders HintMessage for "hint" type', () => { + const item: HistoryItem = { + ...baseItem, + type: 'hint', + text: 'Try using ripgrep first', + }; + const { lastFrame } = renderWithProviders( + , + ); + expect(lastFrame()).toContain('Try using ripgrep first'); + }); + it('renders UserMessage for "user" type with slash command', () => { const item: HistoryItem = { ...baseItem, diff --git a/packages/cli/src/ui/components/HistoryItemDisplay.tsx b/packages/cli/src/ui/components/HistoryItemDisplay.tsx index 41340c1b08..c12dd2edfb 100644 --- a/packages/cli/src/ui/components/HistoryItemDisplay.tsx +++ b/packages/cli/src/ui/components/HistoryItemDisplay.tsx @@ -35,6 +35,7 @@ import { ChatList } from './views/ChatList.js'; import { HooksList } from './views/HooksList.js'; import { ModelMessage } from './messages/ModelMessage.js'; import { ThinkingMessage } from './messages/ThinkingMessage.js'; +import { HintMessage } from './messages/HintMessage.js'; import { getInlineThinkingMode } from '../utils/inlineThinkingMode.js'; import { useSettings } from '../contexts/SettingsContext.js'; @@ -71,6 +72,9 @@ export const HistoryItemDisplay: React.FC = ({ {itemForDisplay.type === 'thinking' && inlineThinkingMode !== 'off' && ( )} + {itemForDisplay.type === 'hint' && ( + + )} {itemForDisplay.type === 'user' && ( )} @@ -102,6 +106,7 @@ export const HistoryItemDisplay: React.FC = ({ text={itemForDisplay.text} icon={itemForDisplay.icon} color={itemForDisplay.color} + marginBottom={itemForDisplay.marginBottom} /> )} {itemForDisplay.type === 'warning' && ( diff --git a/packages/cli/src/ui/components/messages/InfoMessage.tsx b/packages/cli/src/ui/components/messages/InfoMessage.tsx index d092e292b1..e725a23993 100644 --- a/packages/cli/src/ui/components/messages/InfoMessage.tsx +++ b/packages/cli/src/ui/components/messages/InfoMessage.tsx @@ -13,19 +13,21 @@ interface InfoMessageProps { text: string; icon?: string; color?: string; + marginBottom?: number; } export const InfoMessage: React.FC = ({ text, icon, color, + marginBottom, }) => { color ??= theme.status.warning; const prefix = icon ?? 'ℹ '; const prefixWidth = prefix.length; return ( - + {prefix} diff --git a/packages/cli/src/ui/contexts/UIActionsContext.tsx b/packages/cli/src/ui/contexts/UIActionsContext.tsx index 8ad79f6b25..f5b3653d7a 100644 --- a/packages/cli/src/ui/contexts/UIActionsContext.tsx +++ b/packages/cli/src/ui/contexts/UIActionsContext.tsx @@ -73,6 +73,10 @@ export interface UIActions { setActiveBackgroundShellPid: (pid: number) => void; setIsBackgroundShellListOpen: (isOpen: boolean) => void; setAuthContext: (context: { requiresRestart?: boolean }) => void; + onHintInput: (char: string) => void; + onHintBackspace: () => void; + onHintClear: () => void; + onHintSubmit: (hint: string) => void; handleRestart: () => void; handleNewAgentsSelect: (choice: NewAgentsChoice) => Promise; } diff --git a/packages/cli/src/ui/contexts/UIStateContext.tsx b/packages/cli/src/ui/contexts/UIStateContext.tsx index cf41896232..10d4f82d50 100644 --- a/packages/cli/src/ui/contexts/UIStateContext.tsx +++ b/packages/cli/src/ui/contexts/UIStateContext.tsx @@ -173,6 +173,8 @@ export interface UIState { isBackgroundShellListOpen: boolean; adminSettingsChanged: boolean; newAgents: AgentDefinition[] | null; + hintMode: boolean; + hintBuffer: string; transientMessage: { text: string; type: TransientMessageType; diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx index 294c537af4..a6a7543e9e 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx +++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx @@ -56,6 +56,11 @@ const MockedGeminiClientClass = vi.hoisted(() => this.startChat = mockStartChat; this.sendMessageStream = mockSendMessageStream; this.addHistory = vi.fn(); + this.generateContent = vi.fn().mockResolvedValue({ + candidates: [ + { content: { parts: [{ text: 'Got it. Focusing on tests only.' }] } }, + ], + }); this.getCurrentSequenceModel = vi.fn().mockReturnValue('test-model'); this.getChat = vi.fn().mockReturnValue({ recordCompletedToolCalls: vi.fn(), @@ -661,6 +666,113 @@ describe('useGeminiStream', () => { ); }); + it('should inject steering hint prompt for continuation', async () => { + const toolCallResponseParts: Part[] = [{ text: 'tool final response' }]; + const completedToolCalls: TrackedToolCall[] = [ + { + request: { + callId: 'call1', + name: 'tool1', + args: {}, + isClientInitiated: false, + prompt_id: 'prompt-id-ack', + }, + status: 'success', + responseSubmittedToGemini: false, + response: { + callId: 'call1', + responseParts: toolCallResponseParts, + errorType: undefined, + }, + tool: { + displayName: 'MockTool', + }, + invocation: { + getDescription: () => `Mock description`, + } as unknown as AnyToolInvocation, + } as TrackedCompletedToolCall, + ]; + + mockSendMessageStream.mockReturnValue( + (async function* () { + yield { + type: ServerGeminiEventType.Content, + value: 'Applied the requested adjustment.', + }; + })(), + ); + + let capturedOnComplete: + | ((completedTools: TrackedToolCall[]) => Promise) + | null = null; + mockUseToolScheduler.mockImplementation((onComplete) => { + capturedOnComplete = onComplete; + return [ + [], + mockScheduleToolCalls, + mockMarkToolsAsSubmitted, + vi.fn(), + mockCancelAllToolCalls, + 0, + ]; + }); + + renderHookWithProviders(() => + useGeminiStream( + new MockedGeminiClientClass(mockConfig), + [], + mockAddItem, + mockConfig, + mockLoadedSettings, + mockOnDebugMessage, + mockHandleSlashCommand, + false, + () => 'vscode' as EditorType, + () => {}, + () => Promise.resolve(), + false, + () => {}, + () => {}, + () => {}, + 80, + 24, + undefined, + () => 'focus on tests only', + ), + ); + + await act(async () => { + if (capturedOnComplete) { + await new Promise((resolve) => setTimeout(resolve, 0)); + await capturedOnComplete(completedToolCalls); + } + }); + + await waitFor(() => { + expect(mockSendMessageStream).toHaveBeenCalledTimes(1); + }); + + const sentParts = mockSendMessageStream.mock.calls[0][0] as Part[]; + const injectedHintPart = sentParts[0] as { text?: string }; + expect(injectedHintPart.text).toContain( + 'User steering update: "focus on tests only"', + ); + expect(injectedHintPart.text).toContain( + 'Classify it as ADD_TASK, MODIFY_TASK, CANCEL_TASK, or EXTRA_CONTEXT.', + ); + expect(injectedHintPart.text).toContain( + 'Do not cancel/skip tasks unless the user explicitly cancels them.', + ); + expect( + mockAddItem.mock.calls.some( + ([item]) => + item?.type === 'info' && + typeof item.text === 'string' && + item.text.includes('Got it. Focusing on tests only.'), + ), + ).toBe(true); + }); + it('should handle all tool calls being cancelled', async () => { const cancelledToolCalls: TrackedToolCall[] = [ { diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index bba6977ffa..4e0d874961 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -8,6 +8,7 @@ import { useState, useRef, useCallback, useEffect, useMemo } from 'react'; import { GeminiEventType as ServerGeminiEventType, getErrorMessage, + getResponseText, isNodeError, MessageSenderType, logUserPrompt, @@ -47,7 +48,12 @@ import type { GeminiErrorEventValue, RetryAttemptPayload, } from '@google/gemini-cli-core'; -import { type Part, type PartListUnion, FinishReason } from '@google/genai'; +import { + type Content, + type Part, + type PartListUnion, + FinishReason, +} from '@google/genai'; import type { HistoryItem, HistoryItemThinking, @@ -81,6 +87,7 @@ import path from 'node:path'; import { useSessionStats } from '../contexts/SessionContext.js'; import { useKeypress } from './useKeypress.js'; import type { LoadedSettings } from '../../config/settings.js'; +import { theme } from '../semantic-colors.js'; type ToolResponseWithParts = ToolCallResponseInfo & { llmContent?: PartListUnion; @@ -98,6 +105,102 @@ enum StreamProcessingStatus { Error, } +const USER_STEERING_INSTRUCTION = + 'Internal instruction: Re-evaluate the active plan using this user steering update. ' + + 'Classify it as ADD_TASK, MODIFY_TASK, CANCEL_TASK, or EXTRA_CONTEXT. ' + + 'Apply minimal-diff changes only to affected tasks and keep unaffected tasks active. ' + + 'Do not cancel/skip tasks unless the user explicitly cancels them. ' + + 'Acknowledge the steering briefly and state the course correction.'; + +export function buildUserSteeringHintPrompt(hintText: string): string { + const trimmedText = hintText.trim(); + return `User steering update: "${trimmedText}"\n${USER_STEERING_INSTRUCTION}`; +} + +const STEERING_ACK_INSTRUCTION = + 'Write one short, friendly sentence acknowledging a user steering update for an in-progress task. ' + + 'Be concrete when possible (e.g., mention skipped/cancelled item numbers). ' + + 'Do not apologize, do not mention internal policy, and do not add extra steps.'; +const STEERING_ACK_TIMEOUT_MS = 1200; +const STEERING_ACK_MAX_INPUT_CHARS = 320; +const STEERING_ACK_MAX_OUTPUT_CHARS = 90; +const STEERING_ACK_INPUT_TRUNCATION_SUFFIX = '\n...[truncated]'; + +function buildSteeringFallbackMessage(hintText: string): string { + const normalized = hintText.replace(/\s+/g, ' ').trim(); + if (!normalized) { + return 'Understood. Adjusting the plan.'; + } + if (normalized.length <= 64) { + return `Understood. ${normalized}`; + } + return `Understood. ${normalized.slice(0, 61)}...`; +} + +export async function generateSteeringAckMessage( + geminiClient: GeminiClient, + hintText: string, +): Promise { + const truncateSteeringAckInput = (input: string): string => { + if (input.length <= STEERING_ACK_MAX_INPUT_CHARS) { + return input; + } + if ( + STEERING_ACK_MAX_INPUT_CHARS <= + STEERING_ACK_INPUT_TRUNCATION_SUFFIX.length + ) { + return input.slice(0, STEERING_ACK_MAX_INPUT_CHARS); + } + return ( + input.slice( + 0, + STEERING_ACK_MAX_INPUT_CHARS - + STEERING_ACK_INPUT_TRUNCATION_SUFFIX.length, + ) + STEERING_ACK_INPUT_TRUNCATION_SUFFIX + ); + }; + + const fallbackText = buildSteeringFallbackMessage(hintText); + const safeHint = truncateSteeringAckInput( + hintText.replace(/\s+/g, ' ').trim(), + ); + const contents: Content[] = [ + { + role: 'user', + parts: [ + { + text: `${STEERING_ACK_INSTRUCTION}\n\nUser input:\n"""${safeHint}"""`, + }, + ], + }, + ]; + + const abortController = new AbortController(); + const timeout = setTimeout( + () => abortController.abort(), + STEERING_ACK_TIMEOUT_MS, + ); + try { + const response = await geminiClient.generateContent( + { model: 'flash-lite-helper' }, + contents, + abortController.signal, + ); + const responseText = getResponseText(response)?.replace(/\s+/g, ' ').trim(); + if (!responseText) { + return fallbackText; + } + if (responseText.length > STEERING_ACK_MAX_OUTPUT_CHARS) { + return responseText.slice(0, STEERING_ACK_MAX_OUTPUT_CHARS).trimEnd(); + } + return responseText; + } catch { + return fallbackText; + } finally { + clearTimeout(timeout); + } +} + function isShellToolData(data: unknown): data is ShellToolData { if (typeof data !== 'object' || data === null) { return false; @@ -185,6 +288,7 @@ export const useGeminiStream = ( terminalWidth: number, terminalHeight: number, isShellFocused?: boolean, + getUserHint?: () => string | null, ) => { const [initError, setInitError] = useState(null); const [retryStatus, setRetryStatus] = useState( @@ -1561,6 +1665,28 @@ export const useGeminiStream = ( const responsesToSend: Part[] = geminiTools.flatMap( (toolCall) => toolCall.response.responseParts, ); + + if (getUserHint) { + const userHint = getUserHint(); + if (userHint && userHint.trim().length > 0) { + const hintText = userHint.trim(); + responsesToSend.unshift({ + text: buildUserSteeringHintPrompt(hintText), + }); + void generateSteeringAckMessage(geminiClient, hintText).then( + (ackText) => { + addItem({ + type: 'info', + icon: '· ', + color: theme.text.secondary, + marginBottom: 1, + text: ackText, + } as Omit); + }, + ); + } + } + const callIdsToMarkAsSubmitted = geminiTools.map( (toolCall) => toolCall.request.callId, ); @@ -1593,6 +1719,7 @@ export const useGeminiStream = ( modelSwitchedFromQuotaError, addItem, registerBackgroundShell, + getUserHint, ], ); diff --git a/packages/cli/src/ui/themes/no-color.ts b/packages/cli/src/ui/themes/no-color.ts index 7c22e68b9a..5d2a4fbb58 100644 --- a/packages/cli/src/ui/themes/no-color.ts +++ b/packages/cli/src/ui/themes/no-color.ts @@ -36,6 +36,7 @@ const noColorSemanticColors: SemanticColors = { }, background: { primary: '', + hintMode: '', diff: { added: '', removed: '', diff --git a/packages/cli/src/ui/themes/semantic-tokens.ts b/packages/cli/src/ui/themes/semantic-tokens.ts index 3e95aee188..557ccd0ffa 100644 --- a/packages/cli/src/ui/themes/semantic-tokens.ts +++ b/packages/cli/src/ui/themes/semantic-tokens.ts @@ -16,6 +16,7 @@ export interface SemanticColors { }; background: { primary: string; + hintMode: string; diff: { added: string; removed: string; @@ -48,6 +49,7 @@ export const lightSemanticColors: SemanticColors = { }, background: { primary: lightTheme.Background, + hintMode: '#E8E0F0', diff: { added: lightTheme.DiffAdded, removed: lightTheme.DiffRemoved, @@ -80,6 +82,7 @@ export const darkSemanticColors: SemanticColors = { }, background: { primary: darkTheme.Background, + hintMode: '#352A45', diff: { added: darkTheme.DiffAdded, removed: darkTheme.DiffRemoved, diff --git a/packages/cli/src/ui/themes/theme.ts b/packages/cli/src/ui/themes/theme.ts index 2e39b1b6c7..61061b866d 100644 --- a/packages/cli/src/ui/themes/theme.ts +++ b/packages/cli/src/ui/themes/theme.ts @@ -131,6 +131,7 @@ export class Theme { }, background: { primary: this.colors.Background, + hintMode: this.type === 'light' ? '#E8E0F0' : '#352A45', diff: { added: this.colors.DiffAdded, removed: this.colors.DiffRemoved, @@ -400,6 +401,7 @@ export function createCustomTheme(customTheme: CustomTheme): Theme { }, background: { primary: customTheme.background?.primary ?? colors.Background, + hintMode: 'magenta', diff: { added: customTheme.background?.diff?.added ?? colors.DiffAdded, removed: customTheme.background?.diff?.removed ?? colors.DiffRemoved, diff --git a/packages/cli/src/ui/types.ts b/packages/cli/src/ui/types.ts index c48b81bf9c..d578622bb7 100644 --- a/packages/cli/src/ui/types.ts +++ b/packages/cli/src/ui/types.ts @@ -123,6 +123,7 @@ export type HistoryItemInfo = HistoryItemBase & { text: string; icon?: string; color?: string; + marginBottom?: number; }; export type HistoryItemError = HistoryItemBase & { @@ -225,6 +226,11 @@ export type HistoryItemThinking = HistoryItemBase & { thought: ThoughtSummary; }; +export type HistoryItemHint = HistoryItemBase & { + type: 'hint'; + text: string; +}; + export type HistoryItemChatList = HistoryItemBase & { type: 'chat_list'; chats: ChatDetail[]; @@ -349,6 +355,7 @@ export type HistoryItemWithoutId = | HistoryItemMcpStatus | HistoryItemChatList | HistoryItemThinking + | HistoryItemHint | HistoryItemHooksList; export type HistoryItem = HistoryItemWithoutId & { id: number }; diff --git a/packages/core/src/agents/local-executor.ts b/packages/core/src/agents/local-executor.ts index e9fee219e3..91cf2f958a 100644 --- a/packages/core/src/agents/local-executor.ts +++ b/packages/core/src/agents/local-executor.ts @@ -462,7 +462,14 @@ export class LocalAgentExecutor { const query = this.definition.promptConfig.query ? templateString(this.definition.promptConfig.query, augmentedInputs) : DEFAULT_QUERY_STRING; - let currentMessage: Content = { role: 'user', parts: [{ text: query }] }; + const userHints = this.runtimeContext.peekUserHints(); + const hintText = userHints.map((hint) => `- ${hint}`).join('\n'); + let currentMessage: Content = hintText + ? { + role: 'user', + parts: [{ text: `User hints:\n${hintText}` }, { text: query }], + } + : { role: 'user', parts: [{ text: query }] }; while (true) { // Check for termination conditions like max turns. diff --git a/packages/core/src/agents/subagent-tool.ts b/packages/core/src/agents/subagent-tool.ts index f311b60562..4a3eeb74c8 100644 --- a/packages/core/src/agents/subagent-tool.ts +++ b/packages/core/src/agents/subagent-tool.ts @@ -88,7 +88,10 @@ class SubAgentInvocation extends BaseToolInvocation { override async shouldConfirmExecute( abortSignal: AbortSignal, ): Promise { - const invocation = this.buildSubInvocation(this.definition, this.params); + const invocation = this.buildSubInvocation( + this.definition, + this.withUserHints(this.params), + ); return invocation.shouldConfirmExecute(abortSignal); } @@ -107,11 +110,36 @@ class SubAgentInvocation extends BaseToolInvocation { ); } - const invocation = this.buildSubInvocation(this.definition, this.params); + const invocation = this.buildSubInvocation( + this.definition, + this.withUserHints(this.params), + ); return invocation.execute(signal, updateOutput); } + private withUserHints(agentArgs: AgentInputs): AgentInputs { + if (this.definition.kind !== 'remote') { + return agentArgs; + } + + const userHints = this.config.peekUserHints(); + if (userHints.length === 0) { + return agentArgs; + } + + const hintText = userHints.map((hint) => `- ${hint}`).join('\n'); + const query = agentArgs['query']; + if (typeof query !== 'string' || query.trim().length === 0) { + return agentArgs; + } + + return { + ...agentArgs, + query: `User hints:\n${hintText}\n\n${query}`, + }; + } + private buildSubInvocation( definition: AgentDefinition, agentArgs: AgentInputs, diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 886e722ba0..bbae8dca2a 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -2583,4 +2583,29 @@ describe('syncPlanModeTools', () => { expect(setToolsSpy).toHaveBeenCalled(); }); + + describe('user hints', () => { + it('stores trimmed hints and exposes them via peek/consume', () => { + const config = new Config(baseParams); + + config.addUserHint(' first hint '); + config.addUserHint('second hint'); + config.addUserHint(' '); + + expect(config.peekUserHints()).toEqual(['first hint', 'second hint']); + expect(config.consumeUserHints()).toEqual(['first hint', 'second hint']); + expect(config.peekUserHints()).toEqual([]); + }); + + it('tracks the last hint timestamp', () => { + const config = new Config(baseParams); + + expect(config.getLastUserHintAt()).toBeNull(); + config.addUserHint('hint'); + + const timestamp = config.getLastUserHintAt(); + expect(timestamp).not.toBeNull(); + expect(typeof timestamp).toBe('number'); + }); + }); }); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 45a3a953b5..b3482f37c6 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -668,6 +668,8 @@ export class Config { private remoteAdminSettings: AdminControlsSettings | undefined; private latestApiRequest: GenerateContentParameters | undefined; private lastModeSwitchTime: number = Date.now(); + private pendingUserHints: string[] = []; + private lastUserHintAt: number | null = null; private approvedPlanPath: string | undefined; @@ -2486,6 +2488,29 @@ export class Config { return this.hookSystem; } + addUserHint(hint: string): void { + const trimmed = hint.trim(); + if (trimmed.length === 0) { + return; + } + this.pendingUserHints.push(trimmed); + this.lastUserHintAt = Date.now(); + } + + peekUserHints(): string[] { + return [...this.pendingUserHints]; + } + + consumeUserHints(): string[] { + const hints = this.pendingUserHints; + this.pendingUserHints = []; + return hints; + } + + getLastUserHintAt(): number | null { + return this.lastUserHintAt; + } + /** * Get hooks configuration */ diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index 773223dc0c..5edc8a1212 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -121,6 +121,19 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { }, }, }, + 'flash-lite-helper': { + extends: 'base', + modelConfig: { + model: 'gemini-2.5-flash-lite', + generateContentConfig: { + temperature: 0.2, + maxOutputTokens: 120, + thinkingConfig: { + thinkingBudget: 0, + }, + }, + }, + }, 'edit-corrector': { extends: 'base', modelConfig: { diff --git a/packages/core/src/core/__snapshots__/prompts.test.ts.snap b/packages/core/src/core/__snapshots__/prompts.test.ts.snap index 610d681c6e..db720ee296 100644 --- a/packages/core/src/core/__snapshots__/prompts.test.ts.snap +++ b/packages/core/src/core/__snapshots__/prompts.test.ts.snap @@ -11,6 +11,7 @@ exports[`Core System Prompt (prompts.ts) > ApprovalMode in System Prompt > Appro - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -142,6 +143,7 @@ exports[`Core System Prompt (prompts.ts) > ApprovalMode in System Prompt > Appro - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -278,6 +280,7 @@ exports[`Core System Prompt (prompts.ts) > ApprovalMode in System Prompt > shoul - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -390,6 +393,7 @@ exports[`Core System Prompt (prompts.ts) > ApprovalMode in System Prompt > shoul - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -526,6 +530,7 @@ exports[`Core System Prompt (prompts.ts) > should append userMemory with separat - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -652,6 +657,7 @@ exports[`Core System Prompt (prompts.ts) > should handle CodebaseInvestigator wi - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, you must work autonomously as no further user input is available. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Handle Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, do not perform it automatically. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -743,6 +749,7 @@ exports[`Core System Prompt (prompts.ts) > should handle CodebaseInvestigator wi - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, you must work autonomously as no further user input is available. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Handle Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, do not perform it automatically. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -829,6 +836,7 @@ exports[`Core System Prompt (prompts.ts) > should handle git instructions when i - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -941,6 +949,7 @@ exports[`Core System Prompt (prompts.ts) > should handle git instructions when i - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1071,6 +1080,7 @@ exports[`Core System Prompt (prompts.ts) > should include approved plan instruct - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1173,6 +1183,7 @@ exports[`Core System Prompt (prompts.ts) > should include available_skills when - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1303,6 +1314,7 @@ exports[`Core System Prompt (prompts.ts) > should include correct sandbox instru - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1416,6 +1428,7 @@ exports[`Core System Prompt (prompts.ts) > should include correct sandbox instru - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1529,6 +1542,7 @@ exports[`Core System Prompt (prompts.ts) > should include correct sandbox instru - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1638,6 +1652,7 @@ exports[`Core System Prompt (prompts.ts) > should include planning phase suggest - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1747,6 +1762,7 @@ exports[`Core System Prompt (prompts.ts) > should include sub-agents in XML for - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1851,6 +1867,7 @@ exports[`Core System Prompt (prompts.ts) > should match snapshot on Windows 1`] - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -1964,6 +1981,7 @@ exports[`Core System Prompt (prompts.ts) > should render hierarchical memory wit - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. - **Conflict Resolution:** Instructions are provided in hierarchical context tags: \`\`, \`\`, and \`\`. In case of contradictory instructions, follow this priority: \`\` (highest) > \`\` > \`\` (lowest). +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2095,6 +2113,7 @@ exports[`Core System Prompt (prompts.ts) > should return the base prompt when us - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2204,6 +2223,7 @@ exports[`Core System Prompt (prompts.ts) > should return the base prompt when us - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2308,6 +2328,7 @@ exports[`Core System Prompt (prompts.ts) > should return the interactive avoidan - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Handle Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, do not perform it automatically. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2424,6 +2445,7 @@ exports[`Core System Prompt (prompts.ts) > should use chatty system prompt for p - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2533,6 +2555,7 @@ exports[`Core System Prompt (prompts.ts) > should use chatty system prompt for p - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. For Directives, only clarify if critically underspecified; otherwise, work autonomously. You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. @@ -2637,6 +2660,7 @@ exports[`Core System Prompt (prompts.ts) > should use legacy system prompt for n - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise. +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If the user implies a change (e.g., reports a bug) without explicitly asking for a fix, **ask for confirmation first**. If asked *how* to do something, explain first, don't just do it. - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes. diff --git a/packages/core/src/core/prompts.test.ts b/packages/core/src/core/prompts.test.ts index 2f4d70c86c..020d69a286 100644 --- a/packages/core/src/core/prompts.test.ts +++ b/packages/core/src/core/prompts.test.ts @@ -198,6 +198,7 @@ describe('Core System Prompt (prompts.ts)', () => { expect(prompt).not.toContain('No sub-agents are currently available.'); expect(prompt).toContain('# Core Mandates'); expect(prompt).toContain('- **Conventions:**'); + expect(prompt).toContain('- **User Hints:**'); expect(prompt).toContain('# Outside of Sandbox'); expect(prompt).toContain('# Final Reminder'); expect(prompt).toMatchSnapshot(); @@ -207,6 +208,7 @@ describe('Core System Prompt (prompts.ts)', () => { vi.mocked(mockConfig.getActiveModel).mockReturnValue(PREVIEW_GEMINI_MODEL); const prompt = getCoreSystemPrompt(mockConfig); expect(prompt).toContain('You are Gemini CLI, an interactive CLI agent'); // Check for core content + expect(prompt).toContain('- **User Hints:**'); expect(prompt).toContain('No Chitchat:'); expect(prompt).toMatchSnapshot(); }); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 8232f73570..b0fef2cf6b 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -88,6 +88,7 @@ export * from './utils/formatters.js'; export * from './utils/generateContentResponseUtilities.js'; export * from './utils/filesearch/fileSearch.js'; export * from './utils/errorParsing.js'; +export * from './utils/flashLiteHelper.js'; export * from './utils/workspaceContext.js'; export * from './utils/environmentContext.js'; export * from './utils/ignorePatterns.js'; diff --git a/packages/core/src/prompts/snippets.legacy.ts b/packages/core/src/prompts/snippets.legacy.ts index 8d46fd6a1a..3671490089 100644 --- a/packages/core/src/prompts/snippets.legacy.ts +++ b/packages/core/src/prompts/snippets.legacy.ts @@ -159,6 +159,7 @@ export function renderCoreMandates(options?: CoreMandatesOptions): string { - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically. - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments. - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise.${mandateConflictResolution(options.hasHierarchicalMemory)} +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - ${mandateConfirm(options.interactive)} - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.${mandateSkillGuidance(options.hasSkills)}${mandateExplainBeforeActing(options.isGemini3)}${mandateContinueWork(options.interactive)} diff --git a/packages/core/src/prompts/snippets.ts b/packages/core/src/prompts/snippets.ts index 2508181816..aed3c668d1 100644 --- a/packages/core/src/prompts/snippets.ts +++ b/packages/core/src/prompts/snippets.ts @@ -171,6 +171,7 @@ export function renderCoreMandates(options?: CoreMandatesOptions): string { - **Technical Integrity:** You are responsible for the entire lifecycle: implementation, testing, and validation. Within the scope of your changes, prioritize readability and long-term maintainability by consolidating logic into clean abstractions rather than threading state across unrelated layers. Align strictly with the requested architectural direction, ensuring the final implementation is focused and free of redundant "just-in-case" alternatives. Validation is not merely running tests; it is the exhaustive process of ensuring that every aspect of your change—behavioral, structural, and stylistic—is correct and fully compatible with the broader project. For bug fixes, you must empirically reproduce the failure with a new test case or reproduction script before applying the fix. - **Expertise & Intent Alignment:** Provide proactive technical opinions grounded in research while strictly adhering to the user's intended workflow. Distinguish between **Directives** (unambiguous requests for action or implementation) and **Inquiries** (requests for analysis, advice, or observations). Assume all requests are Inquiries unless they contain an explicit instruction to perform a task. For Inquiries, your scope is strictly limited to research and analysis; you may propose a solution or strategy, but you MUST NOT modify files until a corresponding Directive is issued. Do not initiate implementation based on observations of bugs or statements of fact. Once an Inquiry is resolved, or while waiting for a Directive, stop and wait for the next user instruction. ${options.interactive ? 'For Directives, only clarify if critically underspecified; otherwise, work autonomously.' : 'For Directives, you must work autonomously as no further user input is available.'} You should only seek user intervention if you have exhausted all possible routes or if a proposed solution would take the workspace in a significantly different architectural direction. - **Proactiveness:** When executing a Directive, persist through errors and obstacles by diagnosing failures in the execution phase and, if necessary, backtracking to the research or strategy phases to adjust your approach until a successful, verified outcome is achieved. Fulfill the user's request thoroughly, including adding tests when adding features or fixing bugs. Take reasonable liberties to fulfill broad goals while staying within the requested scope; however, prioritize simplicity and the removal of redundant logic over providing "just-in-case" alternatives that diverge from the established path.${mandateConflictResolution(options.hasHierarchicalMemory)} +- **User Hints:** During execution, the user may provide real-time hints (marked as "User hint:" or "User hints:"). Treat these as high-priority but scope-preserving course corrections: apply the minimal plan change needed, keep unaffected user tasks active, and never cancel/skip tasks unless cancellation is explicit for those tasks. Hints may add new tasks, modify one or more tasks, cancel specific tasks, or provide extra context only. If scope is ambiguous, ask for clarification before dropping work. - ${mandateConfirm(options.interactive)} - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked. - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.${mandateSkillGuidance(options.hasSkills)} diff --git a/packages/core/src/services/test-data/resolved-aliases-retry.golden.json b/packages/core/src/services/test-data/resolved-aliases-retry.golden.json index 3b38b909d8..cca52aec89 100644 --- a/packages/core/src/services/test-data/resolved-aliases-retry.golden.json +++ b/packages/core/src/services/test-data/resolved-aliases-retry.golden.json @@ -126,6 +126,17 @@ } } }, + "flash-lite-helper": { + "model": "gemini-2.5-flash-lite", + "generateContentConfig": { + "temperature": 0.2, + "topP": 1, + "maxOutputTokens": 120, + "thinkingConfig": { + "thinkingBudget": 0 + } + } + }, "edit-corrector": { "model": "gemini-2.5-flash-lite", "generateContentConfig": { diff --git a/packages/core/src/services/test-data/resolved-aliases.golden.json b/packages/core/src/services/test-data/resolved-aliases.golden.json index 3b38b909d8..cca52aec89 100644 --- a/packages/core/src/services/test-data/resolved-aliases.golden.json +++ b/packages/core/src/services/test-data/resolved-aliases.golden.json @@ -126,6 +126,17 @@ } } }, + "flash-lite-helper": { + "model": "gemini-2.5-flash-lite", + "generateContentConfig": { + "temperature": 0.2, + "topP": 1, + "maxOutputTokens": 120, + "thinkingConfig": { + "thinkingBudget": 0 + } + } + }, "edit-corrector": { "model": "gemini-2.5-flash-lite", "generateContentConfig": { diff --git a/packages/core/src/utils/flashLiteHelper.test.ts b/packages/core/src/utils/flashLiteHelper.test.ts new file mode 100644 index 0000000000..f8120232e4 --- /dev/null +++ b/packages/core/src/utils/flashLiteHelper.test.ts @@ -0,0 +1,107 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect, vi } from 'vitest'; +import type { GeminiClient } from '../core/client.js'; +import { + DEFAULT_FLASH_LITE_MODEL_CONFIG_KEY, + generateFlashLiteText, + truncateFlashLiteInput, +} from './flashLiteHelper.js'; + +describe('truncateFlashLiteInput', () => { + it('returns input as-is when below limit', () => { + expect(truncateFlashLiteInput('hello', 10)).toBe('hello'); + }); + + it('truncates and appends suffix when above limit', () => { + const input = 'abcdefghijklmnopqrstuvwxyz'; + const result = truncateFlashLiteInput(input, 20); + expect(result.length).toBe(20); + expect(result).toContain('...[truncated]'); + }); +}); + +describe('generateFlashLiteText', () => { + const abortSignal = new AbortController().signal; + + it('uses the default flash-lite helper model config and returns response text', async () => { + const geminiClient = { + generateContent: vi.fn().mockResolvedValue({ + candidates: [ + { content: { parts: [{ text: ' Got it. Skipping #2. ' }] } }, + ], + }), + } as unknown as GeminiClient; + + const result = await generateFlashLiteText(geminiClient, { + instruction: 'Write a short acknowledgement sentence.', + input: 'skip #2', + fallbackText: 'Got it.', + abortSignal, + }); + + expect(result).toBe('Got it. Skipping #2.'); + expect(geminiClient.generateContent).toHaveBeenCalledWith( + DEFAULT_FLASH_LITE_MODEL_CONFIG_KEY, + expect.any(Array), + abortSignal, + ); + }); + + it('returns fallback text when response text is empty', async () => { + const geminiClient = { + generateContent: vi.fn().mockResolvedValue({}), + } as unknown as GeminiClient; + + const result = await generateFlashLiteText(geminiClient, { + instruction: 'Return one sentence.', + input: 'cancel task 2', + fallbackText: 'Understood. Cancelling task 2.', + abortSignal, + }); + + expect(result).toBe('Understood. Cancelling task 2.'); + }); + + it('returns fallback text when generation throws', async () => { + const geminiClient = { + generateContent: vi.fn().mockRejectedValue(new Error('boom')), + } as unknown as GeminiClient; + + const result = await generateFlashLiteText(geminiClient, { + instruction: 'Return one sentence.', + input: 'cancel task 2', + fallbackText: 'Understood.', + abortSignal, + }); + + expect(result).toBe('Understood.'); + }); + + it('truncates the input before sending to the model', async () => { + const geminiClient = { + generateContent: vi.fn().mockResolvedValue({ + candidates: [{ content: { parts: [{ text: 'Ack.' }] } }], + }), + } as unknown as GeminiClient; + + const longInput = 'x'.repeat(200); + await generateFlashLiteText(geminiClient, { + instruction: 'Return one sentence.', + input: longInput, + fallbackText: 'Understood.', + abortSignal, + maxInputChars: 64, + }); + + const [, contents] = ( + geminiClient.generateContent as ReturnType + ).mock.calls[0]; + const promptText = contents[0].parts[0].text as string; + expect(promptText).toContain('...[truncated]'); + }); +}); diff --git a/packages/core/src/utils/flashLiteHelper.ts b/packages/core/src/utils/flashLiteHelper.ts new file mode 100644 index 0000000000..d43189dadd --- /dev/null +++ b/packages/core/src/utils/flashLiteHelper.ts @@ -0,0 +1,89 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { Content } from '@google/genai'; +import type { GeminiClient } from '../core/client.js'; +import type { ModelConfigKey } from '../services/modelConfigService.js'; +import { debugLogger } from './debugLogger.js'; +import { getResponseText } from './partUtils.js'; + +export const DEFAULT_FLASH_LITE_MODEL_CONFIG_KEY: ModelConfigKey = { + model: 'flash-lite-helper', +}; + +export const DEFAULT_FLASH_LITE_MAX_INPUT_CHARS = 1200; +export const DEFAULT_FLASH_LITE_MAX_OUTPUT_CHARS = 180; +const INPUT_TRUNCATION_SUFFIX = '\n...[truncated]'; + +export interface GenerateFlashLiteTextOptions { + instruction: string; + input: string; + fallbackText: string; + abortSignal: AbortSignal; + modelConfigKey?: ModelConfigKey; + maxInputChars?: number; + maxOutputChars?: number; +} + +export function truncateFlashLiteInput( + input: string, + maxInputChars: number = DEFAULT_FLASH_LITE_MAX_INPUT_CHARS, +): string { + if (maxInputChars <= INPUT_TRUNCATION_SUFFIX.length) { + return input.slice(0, Math.max(maxInputChars, 0)); + } + if (input.length <= maxInputChars) { + return input; + } + const keepChars = maxInputChars - INPUT_TRUNCATION_SUFFIX.length; + return input.slice(0, keepChars) + INPUT_TRUNCATION_SUFFIX; +} + +export async function generateFlashLiteText( + geminiClient: GeminiClient, + options: GenerateFlashLiteTextOptions, +): Promise { + const { + instruction, + input, + fallbackText, + abortSignal, + modelConfigKey = DEFAULT_FLASH_LITE_MODEL_CONFIG_KEY, + maxInputChars = DEFAULT_FLASH_LITE_MAX_INPUT_CHARS, + maxOutputChars = DEFAULT_FLASH_LITE_MAX_OUTPUT_CHARS, + } = options; + + const safeInstruction = instruction.trim(); + if (!safeInstruction) { + return fallbackText; + } + + const safeInput = truncateFlashLiteInput(input.trim(), maxInputChars); + const prompt = `${safeInstruction}\n\nUser input:\n"""${safeInput}"""`; + const contents: Content[] = [{ role: 'user', parts: [{ text: prompt }] }]; + + try { + const response = await geminiClient.generateContent( + modelConfigKey, + contents, + abortSignal, + ); + const responseText = getResponseText(response)?.replace(/\s+/g, ' ').trim(); + if (!responseText) { + return fallbackText; + } + + if (maxOutputChars > 0 && responseText.length > maxOutputChars) { + return responseText.slice(0, maxOutputChars).trimEnd(); + } + return responseText; + } catch (error) { + debugLogger.debug( + `[FlashLiteHelper] Generation failed: ${error instanceof Error ? error.message : String(error)}`, + ); + return fallbackText; + } +}