mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 04:00:36 +00:00
feat(storage): support configurable runtime output directory (#2127)
Some checks failed
Qwen Code CI / Lint (push) Failing after 12s
Qwen Code CI / Test (push) Has been skipped
Qwen Code CI / Test-1 (push) Has been skipped
Qwen Code CI / Test-2 (push) Has been skipped
Qwen Code CI / Test-3 (push) Has been skipped
Qwen Code CI / Test-4 (push) Has been skipped
Qwen Code CI / Test-5 (push) Has been skipped
Qwen Code CI / Test-6 (push) Has been skipped
Qwen Code CI / Test-7 (push) Has been skipped
Qwen Code CI / Test-8 (push) Has been skipped
Qwen Code CI / CodeQL (push) Failing after 6s
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Failing after 5s
Qwen Code CI / Post Coverage Comment (push) Has been skipped
E2E Tests / E2E Test (Linux) - sandbox:none (push) Failing after 10m36s
E2E Tests / E2E Test - macOS (push) Has been cancelled
Some checks failed
Qwen Code CI / Lint (push) Failing after 12s
Qwen Code CI / Test (push) Has been skipped
Qwen Code CI / Test-1 (push) Has been skipped
Qwen Code CI / Test-2 (push) Has been skipped
Qwen Code CI / Test-3 (push) Has been skipped
Qwen Code CI / Test-4 (push) Has been skipped
Qwen Code CI / Test-5 (push) Has been skipped
Qwen Code CI / Test-6 (push) Has been skipped
Qwen Code CI / Test-7 (push) Has been skipped
Qwen Code CI / Test-8 (push) Has been skipped
Qwen Code CI / CodeQL (push) Failing after 6s
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Failing after 5s
Qwen Code CI / Post Coverage Comment (push) Has been skipped
E2E Tests / E2E Test (Linux) - sandbox:none (push) Failing after 10m36s
E2E Tests / E2E Test - macOS (push) Has been cancelled
* feat(storage): support configurable runtime output directory (#2014) Add `advanced.runtimeOutputDir` setting and `QWEN_RUNTIME_DIR` env var to redirect runtime output (temp files, debug logs, session data, todos, insights) to a custom directory while keeping config files at ~/.qwen. - Introduce `Storage.setRuntimeBaseDir()` / `getRuntimeBaseDir()` with tilde expansion and relative path resolution - Add `AsyncLocalStorage`-based `runWithRuntimeBaseDir()` for concurrent session isolation in ACP integration - Update all runtime path methods to use `getRuntimeBaseDir()` instead of `getGlobalQwenDir()` (temp, debug, ide, projects, history dirs) - Config paths (settings, oauth, installation_id, etc.) remain pinned to `~/.qwen` regardless of runtime dir configuration - Add comprehensive tests covering path resolution, env var priority, async context isolation, and config path stability * fix(core/storage): 支持 Windows 风格波浪号路径 扩展 setRuntimeBaseDir 以支持 Windows 风格的波浪号路径 (~\), 使用统一的路径分割逻辑处理 Unix 和 Windows 风格的路径分隔符 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core/debugLogger): runtime base dir 变更时创建新 debug 目录 添加 ensuredDebugDirPath 追踪变量,当 runtime base dir 发生变更时, 确保在新的目录下创建 debug 子目录 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * feat(cli/acp): 支持 ACP runtime output dir 配置 新增 runWithAcpRuntimeOutputDir 辅助函数,在 ACP Agent 的 loadSession 和 listSessions 操作中应用配置的 runtimeOutputDir Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(vscode-ide-companion/acpConnection): 补充 this 别名的使用说明 为 self = this 的用法添加解释性注释,说明在嵌套回调中需要使用 this Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * feat(cli): add runtime output directory configuration support * fix(core): update test to use getUserSkillsDirs method Update storage.test.ts to call getUserSkillsDirs() instead of the non-existent getUserSkillsDir() method. The method was renamed to return an array of skill directories. * fix(core/todoWrite): use path.join for cross-platform path assertion in test Replace hardcoded forward-slash path `.qwen/todos/` with `path.join('.qwen', 'todos')` to fix Windows CI failure where paths use backslashes. Made-with: Cursor --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
87f03cf2e9
commit
fbf5ed57d6
23 changed files with 1088 additions and 171 deletions
|
|
@ -14,6 +14,7 @@ import {
|
|||
DEFAULT_QWEN_MODEL,
|
||||
OutputFormat,
|
||||
NativeLspService,
|
||||
Storage,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import { loadCliConfig, parseArguments, type CliArgs } from './config.js';
|
||||
import type { Settings } from './settings.js';
|
||||
|
|
@ -2439,3 +2440,79 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadCliConfig runtimeOutputDir', () => {
|
||||
const originalArgv = process.argv;
|
||||
const originalRuntimeEnv = process.env['QWEN_RUNTIME_DIR'];
|
||||
|
||||
beforeEach(() => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
Storage.setRuntimeBaseDir(null);
|
||||
delete process.env['QWEN_RUNTIME_DIR'];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = originalArgv;
|
||||
Storage.setRuntimeBaseDir(null);
|
||||
if (originalRuntimeEnv !== undefined) {
|
||||
process.env['QWEN_RUNTIME_DIR'] = originalRuntimeEnv;
|
||||
} else {
|
||||
delete process.env['QWEN_RUNTIME_DIR'];
|
||||
}
|
||||
vi.unstubAllEnvs();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should set runtime base dir from settings with absolute path', async () => {
|
||||
const runtimeDir = path.resolve('custom', 'runtime');
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
advanced: { runtimeOutputDir: runtimeDir },
|
||||
};
|
||||
await loadCliConfig(settings, argv);
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(runtimeDir);
|
||||
});
|
||||
|
||||
it('should resolve relative runtimeOutputDir against cwd', async () => {
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
advanced: { runtimeOutputDir: '.qwen' },
|
||||
};
|
||||
const cwd = path.resolve('workspace', 'my-project');
|
||||
await loadCliConfig(settings, argv, cwd);
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(path.join(cwd, '.qwen'));
|
||||
});
|
||||
|
||||
it('should not set runtime base dir when runtimeOutputDir is absent', async () => {
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {};
|
||||
await loadCliConfig(settings, argv);
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(Storage.getGlobalQwenDir());
|
||||
});
|
||||
|
||||
it('should let QWEN_RUNTIME_DIR env var take priority over settings', async () => {
|
||||
const envDir = path.resolve('from-env');
|
||||
const settingsDir = path.resolve('from-settings');
|
||||
process.env['QWEN_RUNTIME_DIR'] = envDir;
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
advanced: { runtimeOutputDir: settingsDir },
|
||||
};
|
||||
await loadCliConfig(settings, argv);
|
||||
// getRuntimeBaseDir checks env var first at call time
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(envDir);
|
||||
});
|
||||
|
||||
it('should reset runtime base dir on subsequent load when runtimeOutputDir is absent', async () => {
|
||||
const argv = await parseArguments();
|
||||
const firstRuntimeDir = path.resolve('first', 'runtime');
|
||||
await loadCliConfig(
|
||||
{ advanced: { runtimeOutputDir: firstRuntimeDir } },
|
||||
argv,
|
||||
);
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(firstRuntimeDir);
|
||||
|
||||
await loadCliConfig({}, argv);
|
||||
expect(Storage.getRuntimeBaseDir()).toBe(Storage.getGlobalQwenDir());
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -708,6 +708,11 @@ export async function loadCliConfig(
|
|||
): Promise<Config> {
|
||||
const debugMode = isDebugMode(argv);
|
||||
|
||||
// Set runtime output directory from settings (env var QWEN_RUNTIME_DIR
|
||||
// is auto-detected inside getRuntimeBaseDir() at each call site).
|
||||
// Pass cwd so that relative paths like ".qwen" resolve per-project.
|
||||
Storage.setRuntimeBaseDir(settings.advanced?.runtimeOutputDir, cwd);
|
||||
|
||||
const ideMode = settings.ide?.enabled ?? false;
|
||||
|
||||
const folderTrust = settings.security?.folderTrust?.enabled ?? false;
|
||||
|
|
|
|||
|
|
@ -1263,6 +1263,17 @@ const SETTINGS_SCHEMA = {
|
|||
description: 'Configuration for the bug report command.',
|
||||
showInDialog: false,
|
||||
},
|
||||
runtimeOutputDir: {
|
||||
type: 'string',
|
||||
label: 'Runtime Output Directory',
|
||||
category: 'Advanced',
|
||||
requiresRestart: true,
|
||||
default: undefined as string | undefined,
|
||||
description:
|
||||
'Custom directory for runtime output (temp files, debug logs, session data, todos, etc.). ' +
|
||||
'Config files remain at ~/.qwen. Env var QWEN_RUNTIME_DIR takes priority.',
|
||||
showInDialog: false,
|
||||
},
|
||||
tavilyApiKey: {
|
||||
type: 'string',
|
||||
label: 'Tavily API Key (Deprecated)',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue