fix(core): harden env loading, OpenAI compatibility, and runtime recovery
This commit is contained in:
@@ -49,6 +49,7 @@ function minimalTuiPrivates(value: MinimalTui): {
|
||||
};
|
||||
activePromptCancel: (() => void) | null;
|
||||
activeOperationCancel: (() => void) | null;
|
||||
commandInFlight: boolean;
|
||||
running: boolean;
|
||||
} {
|
||||
return value as unknown as {
|
||||
@@ -70,6 +71,7 @@ function minimalTuiPrivates(value: MinimalTui): {
|
||||
};
|
||||
activePromptCancel: (() => void) | null;
|
||||
activeOperationCancel: (() => void) | null;
|
||||
commandInFlight: boolean;
|
||||
running: boolean;
|
||||
};
|
||||
}
|
||||
@@ -469,6 +471,38 @@ describe('MinimalTui prompt cancellation', () => {
|
||||
expect(minimalTuiPrivates(tui).activePromptCancel).toBeNull();
|
||||
});
|
||||
|
||||
it('returns empty string when readline is already closed during question', async () => {
|
||||
const mockSession = {
|
||||
id: 'test',
|
||||
getHistory: () => [],
|
||||
addMessage: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
replaceHistory: vi.fn(),
|
||||
};
|
||||
|
||||
const tui = new MinimalTui({
|
||||
session: asSession(mockSession),
|
||||
modelClient: asRouter({}),
|
||||
systemPrompt: 'test',
|
||||
});
|
||||
|
||||
const questionError = new Error('readline was closed');
|
||||
(questionError as Error & { code?: string }).code = 'ERR_USE_AFTER_CLOSE';
|
||||
|
||||
minimalTuiPrivates(tui).rl = {
|
||||
once: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
question: vi.fn(() => {
|
||||
throw questionError;
|
||||
}),
|
||||
write: vi.fn(),
|
||||
prompt: vi.fn(),
|
||||
};
|
||||
|
||||
await expect(minimalTuiPrivates(tui).prompt('Confirm? ')).resolves.toBe('');
|
||||
expect(minimalTuiPrivates(tui).activePromptCancel).toBeNull();
|
||||
});
|
||||
|
||||
it('uses Esc to cancel active running operation', () => {
|
||||
const mockSession = {
|
||||
id: 'test',
|
||||
@@ -530,4 +564,46 @@ describe('MinimalTui prompt cancellation', () => {
|
||||
logSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('exits immediately on Ctrl+C when a command is in flight', () => {
|
||||
const mockSession = {
|
||||
id: 'test',
|
||||
getHistory: () => [],
|
||||
addMessage: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
replaceHistory: vi.fn(),
|
||||
};
|
||||
|
||||
const write = vi.fn();
|
||||
const prompt = vi.fn();
|
||||
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
try {
|
||||
const tui = new MinimalTui({
|
||||
session: asSession(mockSession),
|
||||
modelClient: asRouter({}),
|
||||
systemPrompt: 'test',
|
||||
});
|
||||
minimalTuiPrivates(tui).rl = {
|
||||
once: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
question: vi.fn(),
|
||||
write,
|
||||
prompt,
|
||||
};
|
||||
minimalTuiPrivates(tui).running = true;
|
||||
minimalTuiPrivates(tui).commandInFlight = true;
|
||||
const cancel = vi.fn();
|
||||
minimalTuiPrivates(tui).activeOperationCancel = cancel;
|
||||
|
||||
const shouldExit = minimalTuiPrivates(tui).handleCtrlCPress(1000);
|
||||
|
||||
expect(shouldExit).toBe(true);
|
||||
expect(cancel).toHaveBeenCalledOnce();
|
||||
expect(write).not.toHaveBeenCalled();
|
||||
expect(prompt).not.toHaveBeenCalled();
|
||||
expect(logSpy).not.toHaveBeenCalledWith(expect.stringContaining('Press Ctrl+C again to quit'));
|
||||
} finally {
|
||||
logSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user