feat(cli): route non-interactive output to stderr (#5624)
This commit is contained in:
parent
268627469b
commit
2141b39c3d
|
@ -70,6 +70,7 @@ describe('runNonInteractive', () => {
|
||||||
getIdeMode: vi.fn().mockReturnValue(false),
|
getIdeMode: vi.fn().mockReturnValue(false),
|
||||||
getFullContext: vi.fn().mockReturnValue(false),
|
getFullContext: vi.fn().mockReturnValue(false),
|
||||||
getContentGeneratorConfig: vi.fn().mockReturnValue({}),
|
getContentGeneratorConfig: vi.fn().mockReturnValue({}),
|
||||||
|
getDebugMode: vi.fn().mockReturnValue(false),
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,28 +17,37 @@ import {
|
||||||
import { Content, Part, FunctionCall } from '@google/genai';
|
import { Content, Part, FunctionCall } from '@google/genai';
|
||||||
|
|
||||||
import { parseAndFormatApiError } from './ui/utils/errorParsing.js';
|
import { parseAndFormatApiError } from './ui/utils/errorParsing.js';
|
||||||
|
import { ConsolePatcher } from './ui/utils/ConsolePatcher.js';
|
||||||
|
|
||||||
export async function runNonInteractive(
|
export async function runNonInteractive(
|
||||||
config: Config,
|
config: Config,
|
||||||
input: string,
|
input: string,
|
||||||
prompt_id: string,
|
prompt_id: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await config.initialize();
|
const consolePatcher = new ConsolePatcher({
|
||||||
// Handle EPIPE errors when the output is piped to a command that closes early.
|
stderr: true,
|
||||||
process.stdout.on('error', (err: NodeJS.ErrnoException) => {
|
debugMode: config.getDebugMode(),
|
||||||
if (err.code === 'EPIPE') {
|
|
||||||
// Exit gracefully if the pipe is closed.
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const geminiClient = config.getGeminiClient();
|
|
||||||
const toolRegistry: ToolRegistry = await config.getToolRegistry();
|
|
||||||
|
|
||||||
const abortController = new AbortController();
|
|
||||||
let currentMessages: Content[] = [{ role: 'user', parts: [{ text: input }] }];
|
|
||||||
let turnCount = 0;
|
|
||||||
try {
|
try {
|
||||||
|
await config.initialize();
|
||||||
|
consolePatcher.patch();
|
||||||
|
// Handle EPIPE errors when the output is piped to a command that closes early.
|
||||||
|
process.stdout.on('error', (err: NodeJS.ErrnoException) => {
|
||||||
|
if (err.code === 'EPIPE') {
|
||||||
|
// Exit gracefully if the pipe is closed.
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const geminiClient = config.getGeminiClient();
|
||||||
|
const toolRegistry: ToolRegistry = await config.getToolRegistry();
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
let currentMessages: Content[] = [
|
||||||
|
{ role: 'user', parts: [{ text: input }] },
|
||||||
|
];
|
||||||
|
let turnCount = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
turnCount++;
|
turnCount++;
|
||||||
if (
|
if (
|
||||||
|
@ -133,6 +142,7 @@ export async function runNonInteractive(
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} finally {
|
} finally {
|
||||||
|
consolePatcher.cleanup();
|
||||||
if (isTelemetrySdkInitialized()) {
|
if (isTelemetrySdkInitialized()) {
|
||||||
await shutdownTelemetry();
|
await shutdownTelemetry();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,9 @@ import util from 'util';
|
||||||
import { ConsoleMessageItem } from '../types.js';
|
import { ConsoleMessageItem } from '../types.js';
|
||||||
|
|
||||||
interface ConsolePatcherParams {
|
interface ConsolePatcherParams {
|
||||||
onNewMessage: (message: Omit<ConsoleMessageItem, 'id'>) => void;
|
onNewMessage?: (message: Omit<ConsoleMessageItem, 'id'>) => void;
|
||||||
debugMode: boolean;
|
debugMode: boolean;
|
||||||
|
stderr?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ConsolePatcher {
|
export class ConsolePatcher {
|
||||||
|
@ -46,16 +47,22 @@ export class ConsolePatcher {
|
||||||
originalMethod: (...args: unknown[]) => void,
|
originalMethod: (...args: unknown[]) => void,
|
||||||
) =>
|
) =>
|
||||||
(...args: unknown[]) => {
|
(...args: unknown[]) => {
|
||||||
if (this.params.debugMode) {
|
if (this.params.stderr) {
|
||||||
originalMethod.apply(console, args);
|
if (type !== 'debug' || this.params.debugMode) {
|
||||||
}
|
this.originalConsoleError(this.formatArgs(args));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.params.debugMode) {
|
||||||
|
originalMethod.apply(console, args);
|
||||||
|
}
|
||||||
|
|
||||||
if (type !== 'debug' || this.params.debugMode) {
|
if (type !== 'debug' || this.params.debugMode) {
|
||||||
this.params.onNewMessage({
|
this.params.onNewMessage?.({
|
||||||
type,
|
type,
|
||||||
content: this.formatArgs(args),
|
content: this.formatArgs(args),
|
||||||
count: 1,
|
count: 1,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue