chore: address PR comments

This commit is contained in:
Jack Wotherspoon
2026-03-09 23:53:31 +01:00
parent 7766b36411
commit e824cb897a
5 changed files with 81 additions and 59 deletions
+20 -10
View File
@@ -738,6 +738,14 @@ export async function main() {
} }
} }
// When this is an auto-restart (not explicit --resume), clear the
// original --prompt so it doesn't get submitted again — the resumed
// session already contains it.
if (isAutoRestart && resumedSessionData) {
config.clearQuestion();
input = undefined;
}
cliStartupHandle?.end(); cliStartupHandle?.end();
// Render UI, passing necessary config values. Check that there is no command line question. // Render UI, passing necessary config values. Check that there is no command line question.
if (config.isInteractive()) { if (config.isInteractive()) {
@@ -793,7 +801,7 @@ export async function main() {
await config.getHookSystem()?.fireSessionEndEvent(SessionEndReason.Exit); await config.getHookSystem()?.fireSessionEndEvent(SessionEndReason.Exit);
}); });
if (!input) { if (!input && !resumedSessionData) {
debugLogger.error( debugLogger.error(
`No input provided via stdin. Input can be provided by piping data into gemini or using the --prompt option.`, `No input provided via stdin. Input can be provided by piping data into gemini or using the --prompt option.`,
); );
@@ -802,15 +810,17 @@ export async function main() {
} }
const prompt_id = Math.random().toString(16).slice(2); const prompt_id = Math.random().toString(16).slice(2);
logUserPrompt( if (input) {
config, logUserPrompt(
new UserPromptEvent( config,
input.length, new UserPromptEvent(
prompt_id, input.length,
config.getContentGeneratorConfig()?.authType, prompt_id,
input, config.getContentGeneratorConfig()?.authType,
), input,
); ),
);
}
const authType = await validateNonInteractiveAuth( const authType = await validateNonInteractiveAuth(
settings.merged.security.auth.selectedType, settings.merged.security.auth.selectedType,
+51 -45
View File
@@ -50,7 +50,7 @@ import { TextOutput } from './ui/utils/textOutput.js';
interface RunNonInteractiveParams { interface RunNonInteractiveParams {
config: Config; config: Config;
settings: LoadedSettings; settings: LoadedSettings;
input: string; input?: string;
prompt_id: string; prompt_id: string;
resumedSessionData?: ResumedSessionData; resumedSessionData?: ResumedSessionData;
} }
@@ -237,56 +237,62 @@ export async function runNonInteractive({
}); });
} }
let query: Part[] | undefined; let currentMessages: Content[] = [];
if (isSlashCommand(input)) { // When resuming with no new input (e.g. auto-restart), skip sending
const slashCommandResult = await handleSlashCommand( // a new user message — the resumed session already contains it.
input, if (input) {
abortController, let query: Part[] | undefined;
config,
settings,
);
// If a slash command is found and returns a prompt, use it.
// Otherwise, slashCommandResult falls through to the default prompt
// handling.
if (slashCommandResult) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
query = slashCommandResult as Part[];
}
}
if (!query) { if (isSlashCommand(input)) {
const { processedQuery, error } = await handleAtCommand({ const slashCommandResult = await handleSlashCommand(
query: input, input,
config, abortController,
addItem: (_item, _timestamp) => 0, config,
onDebugMessage: () => {}, settings,
messageId: Date.now(),
signal: abortController.signal,
});
if (error || !processedQuery) {
// An error occurred during @include processing (e.g., file not found).
// The error message is already logged by handleAtCommand.
throw new FatalInputError(
error || 'Exiting due to an error processing the @ command.',
); );
// If a slash command is found and returns a prompt, use it.
// Otherwise, slashCommandResult falls through to the default prompt
// handling.
if (slashCommandResult) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
query = slashCommandResult as Part[];
}
} }
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
query = processedQuery as Part[];
}
// Emit user message event for streaming JSON if (!query) {
if (streamFormatter) { const { processedQuery, error } = await handleAtCommand({
streamFormatter.emitEvent({ query: input,
type: JsonStreamEventType.MESSAGE, config,
timestamp: new Date().toISOString(), addItem: (_item, _timestamp) => 0,
role: 'user', onDebugMessage: () => {},
content: input, messageId: Date.now(),
}); signal: abortController.signal,
} });
let currentMessages: Content[] = [{ role: 'user', parts: query }]; if (error || !processedQuery) {
// An error occurred during @include processing (e.g., file not found).
// The error message is already logged by handleAtCommand.
throw new FatalInputError(
error || 'Exiting due to an error processing the @ command.',
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
query = processedQuery as Part[];
}
// Emit user message event for streaming JSON
if (streamFormatter) {
streamFormatter.emitEvent({
type: JsonStreamEventType.MESSAGE,
timestamp: new Date().toISOString(),
role: 'user',
content: input,
});
}
currentMessages = [{ role: 'user', parts: query }];
}
let turnCount = 0; let turnCount = 0;
while (true) { while (true) {
+1 -1
View File
@@ -132,7 +132,7 @@ export function AuthDialog({
config.isBrowserLaunchSuppressed() config.isBrowserLaunchSuppressed()
) { ) {
setExiting(true); setExiting(true);
setTimeout(relaunchApp, 100); setTimeout(() => relaunchApp(config.getSessionId()), 100);
return; return;
} }
@@ -18,6 +18,7 @@ import * as process from 'node:process';
import * as path from 'node:path'; import * as path from 'node:path';
import { relaunchApp } from '../../utils/processUtils.js'; import { relaunchApp } from '../../utils/processUtils.js';
import { runExitCleanup } from '../../utils/cleanup.js'; import { runExitCleanup } from '../../utils/cleanup.js';
import { useConfig } from '../contexts/ConfigContext.js';
import { import {
ExitCodes, ExitCodes,
type FolderDiscoveryResults, type FolderDiscoveryResults,
@@ -45,6 +46,7 @@ export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({
isRestarting, isRestarting,
discoveryResults, discoveryResults,
}) => { }) => {
const config = useConfig();
const [exiting, setExiting] = useState(false); const [exiting, setExiting] = useState(false);
const { terminalHeight, terminalWidth, constrainHeight } = useUIState(); const { terminalHeight, terminalWidth, constrainHeight } = useUIState();
const isAlternateBuffer = useAlternateBuffer(); const isAlternateBuffer = useAlternateBuffer();
@@ -54,12 +56,12 @@ export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({
useEffect(() => { useEffect(() => {
let timer: ReturnType<typeof setTimeout>; let timer: ReturnType<typeof setTimeout>;
if (isRestarting) { if (isRestarting) {
timer = setTimeout(relaunchApp, 250); timer = setTimeout(() => relaunchApp(config.getSessionId()), 250);
} }
return () => { return () => {
if (timer) clearTimeout(timer); if (timer) clearTimeout(timer);
}; };
}, [isRestarting]); }, [isRestarting, config]);
const handleExit = useCallback(() => { const handleExit = useCallback(() => {
setExiting(true); setExiting(true);
+5 -1
View File
@@ -625,7 +625,7 @@ export class Config implements McpContext, AgentLoopContext {
private readonly targetDir: string; private readonly targetDir: string;
private workspaceContext: WorkspaceContext; private workspaceContext: WorkspaceContext;
private readonly debugMode: boolean; private readonly debugMode: boolean;
private readonly question: string | undefined; private question: string | undefined;
readonly enableConseca: boolean; readonly enableConseca: boolean;
private readonly coreTools: string[] | undefined; private readonly coreTools: string[] | undefined;
@@ -1655,6 +1655,10 @@ export class Config implements McpContext, AgentLoopContext {
return this.question; return this.question;
} }
clearQuestion(): void {
this.question = undefined;
}
getHasAccessToPreviewModel(): boolean { getHasAccessToPreviewModel(): boolean {
return this.hasAccessToPreviewModel !== false; return this.hasAccessToPreviewModel !== false;
} }