mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 07:10:55 +00:00
Merge branch 'main' into feature/arena-agent-collaboration
This commit is contained in:
commit
74b342623c
172 changed files with 12390 additions and 3258 deletions
|
|
@ -74,14 +74,6 @@ const mockParseAndFormatApiError = vi.hoisted(() =>
|
|||
);
|
||||
const mockLogApiCancel = vi.hoisted(() => vi.fn());
|
||||
|
||||
// Vision auto-switch mocks (hoisted)
|
||||
const mockHandleVisionSwitch = vi.hoisted(() =>
|
||||
vi.fn().mockResolvedValue({ shouldProceed: true }),
|
||||
);
|
||||
const mockRestoreOriginalModel = vi.hoisted(() =>
|
||||
vi.fn().mockResolvedValue(undefined),
|
||||
);
|
||||
|
||||
vi.mock('@qwen-code/qwen-code-core', async (importOriginal) => {
|
||||
const actualCoreModule = (await importOriginal()) as any;
|
||||
return {
|
||||
|
|
@ -104,13 +96,6 @@ vi.mock('./useReactToolScheduler.js', async (importOriginal) => {
|
|||
};
|
||||
});
|
||||
|
||||
vi.mock('./useVisionAutoSwitch.js', () => ({
|
||||
useVisionAutoSwitch: vi.fn(() => ({
|
||||
handleVisionSwitch: mockHandleVisionSwitch,
|
||||
restoreOriginalModel: mockRestoreOriginalModel,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('./shellCommandProcessor.js', () => ({
|
||||
useShellCommandProcessor: vi.fn().mockReturnValue({
|
||||
handleShellCommand: vi.fn(),
|
||||
|
|
@ -307,7 +292,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -473,7 +457,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -558,7 +541,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -671,7 +653,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -785,7 +766,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -902,7 +882,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
cancelSubmitSpy,
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -946,7 +925,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
vi.fn(),
|
||||
false,
|
||||
setShellInputFocusedSpy, // Pass the spy here
|
||||
80,
|
||||
24,
|
||||
|
|
@ -1274,7 +1252,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -1332,7 +1309,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -1826,7 +1802,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -1882,7 +1857,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -1939,7 +1913,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2036,7 +2009,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(),
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2091,7 +2063,6 @@ describe('useGeminiStream', () => {
|
|||
vi.fn(), // setModelSwitched
|
||||
vi.fn(), // onEditorClose
|
||||
vi.fn(), // onCancelSubmit
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80, // terminalWidth
|
||||
24, // terminalHeight
|
||||
|
|
@ -2165,7 +2136,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2257,7 +2227,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2318,7 +2287,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2419,7 +2387,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2490,7 +2457,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2549,7 +2515,6 @@ describe('useGeminiStream', () => {
|
|||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
() => {},
|
||||
80,
|
||||
24,
|
||||
|
|
@ -2737,187 +2702,6 @@ describe('useGeminiStream', () => {
|
|||
});
|
||||
|
||||
// --- New tests focused on recent modifications ---
|
||||
describe('Vision Auto Switch Integration', () => {
|
||||
it('should call handleVisionSwitch and proceed to send when allowed', async () => {
|
||||
mockHandleVisionSwitch.mockResolvedValueOnce({ shouldProceed: true });
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: ServerGeminiEventType.Content, value: 'ok' };
|
||||
yield { type: ServerGeminiEventType.Finished, value: 'STOP' };
|
||||
})(),
|
||||
);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGeminiStream(
|
||||
new MockedGeminiClientClass(mockConfig),
|
||||
[],
|
||||
mockAddItem,
|
||||
mockConfig,
|
||||
mockLoadedSettings,
|
||||
mockOnDebugMessage,
|
||||
mockHandleSlashCommand,
|
||||
false,
|
||||
() => 'vscode' as EditorType,
|
||||
() => {},
|
||||
() => Promise.resolve(),
|
||||
false,
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80,
|
||||
24,
|
||||
),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('image prompt');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockHandleVisionSwitch).toHaveBeenCalled();
|
||||
expect(mockSendMessageStream).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should gate submission when handleVisionSwitch returns shouldProceed=false', async () => {
|
||||
mockHandleVisionSwitch.mockResolvedValueOnce({ shouldProceed: false });
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGeminiStream(
|
||||
new MockedGeminiClientClass(mockConfig),
|
||||
[],
|
||||
mockAddItem,
|
||||
mockConfig,
|
||||
mockLoadedSettings,
|
||||
mockOnDebugMessage,
|
||||
mockHandleSlashCommand,
|
||||
false,
|
||||
() => 'vscode' as EditorType,
|
||||
() => {},
|
||||
() => Promise.resolve(),
|
||||
false,
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80,
|
||||
24,
|
||||
),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('vision-gated');
|
||||
});
|
||||
|
||||
// No call to API, no restoreOriginalModel needed since no override occurred
|
||||
expect(mockSendMessageStream).not.toHaveBeenCalled();
|
||||
expect(mockRestoreOriginalModel).not.toHaveBeenCalled();
|
||||
|
||||
// Next call allowed (flag reset path)
|
||||
mockHandleVisionSwitch.mockResolvedValueOnce({ shouldProceed: true });
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: ServerGeminiEventType.Content, value: 'ok' };
|
||||
yield { type: ServerGeminiEventType.Finished, value: 'STOP' };
|
||||
})(),
|
||||
);
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('after-gate');
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(mockSendMessageStream).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model restore on completion and errors', () => {
|
||||
it('should restore model after successful stream completion', async () => {
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: ServerGeminiEventType.Content, value: 'content' };
|
||||
yield { type: ServerGeminiEventType.Finished, value: 'STOP' };
|
||||
})(),
|
||||
);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGeminiStream(
|
||||
new MockedGeminiClientClass(mockConfig),
|
||||
[],
|
||||
mockAddItem,
|
||||
mockConfig,
|
||||
mockLoadedSettings,
|
||||
mockOnDebugMessage,
|
||||
mockHandleSlashCommand,
|
||||
false,
|
||||
() => 'vscode' as EditorType,
|
||||
() => {},
|
||||
() => Promise.resolve(),
|
||||
false,
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80,
|
||||
24,
|
||||
),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('restore-success');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockRestoreOriginalModel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should restore model when an error occurs during streaming', async () => {
|
||||
const testError = new Error('stream failure');
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: ServerGeminiEventType.Content, value: 'content' };
|
||||
throw testError;
|
||||
})(),
|
||||
);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGeminiStream(
|
||||
new MockedGeminiClientClass(mockConfig),
|
||||
[],
|
||||
mockAddItem,
|
||||
mockConfig,
|
||||
mockLoadedSettings,
|
||||
mockOnDebugMessage,
|
||||
mockHandleSlashCommand,
|
||||
false,
|
||||
() => 'vscode' as EditorType,
|
||||
() => {},
|
||||
() => Promise.resolve(),
|
||||
false,
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
false, // visionModelPreviewEnabled
|
||||
vi.fn(), // setShellInputFocused
|
||||
80,
|
||||
24,
|
||||
),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('restore-error');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockRestoreOriginalModel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Loop Detection Confirmation', () => {
|
||||
beforeEach(() => {
|
||||
// Add mock for getLoopDetectionService to the config
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue