mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-04 22:51:08 +00:00
Merge remote-tracking branch 'origin/main' into feat/debug-logging-refactor
This commit is contained in:
commit
4abec5c055
331 changed files with 19546 additions and 7771 deletions
|
|
@ -10,7 +10,8 @@ import * as os from 'node:os';
|
|||
import * as path from 'node:path';
|
||||
import { Session } from './Session.js';
|
||||
import type { Config, GeminiChat } from '@qwen-code/qwen-code-core';
|
||||
import { ApprovalMode } from '@qwen-code/qwen-code-core';
|
||||
import { ApprovalMode, AuthType } from '@qwen-code/qwen-code-core';
|
||||
import * as core from '@qwen-code/qwen-code-core';
|
||||
import type * as acp from '../acp.js';
|
||||
import type { LoadedSettings } from '../../config/settings.js';
|
||||
import * as nonInteractiveCliCommands from '../../nonInteractiveCliCommands.js';
|
||||
|
|
@ -27,14 +28,19 @@ describe('Session', () => {
|
|||
let mockSettings: LoadedSettings;
|
||||
let session: Session;
|
||||
let currentModel: string;
|
||||
let setModelSpy: ReturnType<typeof vi.fn>;
|
||||
let currentAuthType: AuthType;
|
||||
let switchModelSpy: ReturnType<typeof vi.fn>;
|
||||
let getAvailableCommandsSpy: ReturnType<typeof vi.fn>;
|
||||
|
||||
beforeEach(() => {
|
||||
currentModel = 'qwen3-code-plus';
|
||||
setModelSpy = vi.fn().mockImplementation(async (modelId: string) => {
|
||||
currentModel = modelId;
|
||||
});
|
||||
currentAuthType = AuthType.USE_OPENAI;
|
||||
switchModelSpy = vi
|
||||
.fn()
|
||||
.mockImplementation(async (authType: AuthType, modelId: string) => {
|
||||
currentAuthType = authType;
|
||||
currentModel = modelId;
|
||||
});
|
||||
|
||||
mockChat = {
|
||||
sendMessageStream: vi.fn(),
|
||||
|
|
@ -46,7 +52,7 @@ describe('Session', () => {
|
|||
|
||||
mockConfig = {
|
||||
setApprovalMode: vi.fn(),
|
||||
setModel: setModelSpy,
|
||||
switchModel: switchModelSpy,
|
||||
getModel: vi.fn().mockImplementation(() => currentModel),
|
||||
getSessionId: vi.fn().mockReturnValue('test-session-id'),
|
||||
getTelemetryLogPromptsEnabled: vi.fn().mockReturnValue(false),
|
||||
|
|
@ -62,6 +68,7 @@ describe('Session', () => {
|
|||
getEnableRecursiveFileSearch: vi.fn().mockReturnValue(false),
|
||||
getTargetDir: vi.fn().mockReturnValue(process.cwd()),
|
||||
getDebugMode: vi.fn().mockReturnValue(false),
|
||||
getAuthType: vi.fn().mockImplementation(() => currentAuthType),
|
||||
} as unknown as Config;
|
||||
|
||||
mockClient = {
|
||||
|
|
@ -108,17 +115,21 @@ describe('Session', () => {
|
|||
|
||||
describe('setModel', () => {
|
||||
it('sets model via config and returns current model', async () => {
|
||||
const requested = `qwen3-coder-plus(${AuthType.USE_OPENAI})`;
|
||||
const result = await session.setModel({
|
||||
sessionId: 'test-session-id',
|
||||
modelId: ' qwen3-coder-plus ',
|
||||
modelId: ` ${requested} `,
|
||||
});
|
||||
|
||||
expect(mockConfig.setModel).toHaveBeenCalledWith('qwen3-coder-plus', {
|
||||
reason: 'user_request_acp',
|
||||
context: 'session/set_model',
|
||||
});
|
||||
expect(mockConfig.switchModel).toHaveBeenCalledWith(
|
||||
AuthType.USE_OPENAI,
|
||||
'qwen3-coder-plus',
|
||||
undefined,
|
||||
);
|
||||
expect(mockConfig.getModel).toHaveBeenCalled();
|
||||
expect(result).toEqual({ modelId: 'qwen3-coder-plus' });
|
||||
expect(result).toEqual({
|
||||
modelId: `qwen3-coder-plus(${AuthType.USE_OPENAI})`,
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects empty/whitespace model IDs', async () => {
|
||||
|
|
@ -129,17 +140,17 @@ describe('Session', () => {
|
|||
}),
|
||||
).rejects.toThrow('Invalid params');
|
||||
|
||||
expect(mockConfig.setModel).not.toHaveBeenCalled();
|
||||
expect(mockConfig.switchModel).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('propagates errors from config.setModel', async () => {
|
||||
it('propagates errors from config.switchModel', async () => {
|
||||
const configError = new Error('Invalid model');
|
||||
setModelSpy.mockRejectedValueOnce(configError);
|
||||
switchModelSpy.mockRejectedValueOnce(configError);
|
||||
|
||||
await expect(
|
||||
session.setModel({
|
||||
sessionId: 'test-session-id',
|
||||
modelId: 'invalid-model',
|
||||
modelId: `invalid-model(${AuthType.USE_OPENAI})`,
|
||||
}),
|
||||
).rejects.toThrow('Invalid model');
|
||||
});
|
||||
|
|
@ -198,24 +209,14 @@ describe('Session', () => {
|
|||
try {
|
||||
await fs.writeFile(filePath, '# Test\n', 'utf8');
|
||||
|
||||
const readManyFilesTool = {
|
||||
buildAndExecute: vi.fn().mockResolvedValue({
|
||||
llmContent: 'file content',
|
||||
returnDisplay: 'ok',
|
||||
}),
|
||||
};
|
||||
const toolRegistry = {
|
||||
getTool: vi.fn((name: string) =>
|
||||
name === 'read_many_files' ? readManyFilesTool : undefined,
|
||||
),
|
||||
};
|
||||
const fileService = {
|
||||
shouldGitIgnoreFile: vi.fn().mockReturnValue(false),
|
||||
};
|
||||
const readManyFilesSpy = vi
|
||||
.spyOn(core, 'readManyFiles')
|
||||
.mockResolvedValue({
|
||||
contentParts: 'file content',
|
||||
files: [],
|
||||
});
|
||||
|
||||
mockConfig.getTargetDir = vi.fn().mockReturnValue(tempDir);
|
||||
mockConfig.getToolRegistry = vi.fn().mockReturnValue(toolRegistry);
|
||||
mockConfig.getFileService = vi.fn().mockReturnValue(fileService);
|
||||
mockChat.sendMessageStream = vi
|
||||
.fn()
|
||||
.mockResolvedValue((async function* () {})());
|
||||
|
|
@ -234,10 +235,10 @@ describe('Session', () => {
|
|||
|
||||
await session.prompt(promptRequest);
|
||||
|
||||
expect(readManyFilesTool.buildAndExecute).toHaveBeenCalledWith(
|
||||
{ paths: [fileName] },
|
||||
expect.any(AbortSignal),
|
||||
);
|
||||
expect(readManyFilesSpy).toHaveBeenCalledWith(mockConfig, {
|
||||
paths: [fileName],
|
||||
signal: expect.any(AbortSignal),
|
||||
});
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue