mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-25 16:44:36 +00:00
* refactor: centralize cross-package contracts * fix(build): harden cross-package contract checks * docs(core): clarify sub-session prompt limit scope
114 lines
3.2 KiB
JavaScript
114 lines
3.2 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2026 Qwen Team
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { execFileSync } from 'node:child_process';
|
|
import { readFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { expect, it } from 'vitest';
|
|
|
|
const root = join(dirname(fileURLToPath(import.meta.url)), '../..');
|
|
|
|
function definitionFiles(pattern) {
|
|
return execFileSync(
|
|
'git',
|
|
['grep', '--untracked', '-l', '-E', pattern, '--', 'packages'],
|
|
{ cwd: root, encoding: 'utf8' },
|
|
)
|
|
.trim()
|
|
.split(/\r?\n/)
|
|
.filter(Boolean);
|
|
}
|
|
|
|
const definitions = [
|
|
{
|
|
symbol: 'LIVE_TASK_TOOL_NAMES',
|
|
pattern: '^(export )?(const|let|var) LIVE_TASK_TOOL_NAMES[[:space:]]*[:=]',
|
|
owner: 'packages/acp-bridge/src/bridgeOptions.ts',
|
|
},
|
|
{
|
|
symbol: 'LiveTaskToolName',
|
|
pattern:
|
|
'^(export )?type LiveTaskToolName[[:space:]]*(<[^>]+>)?[[:space:]]*=',
|
|
owner: 'packages/acp-bridge/src/bridgeOptions.ts',
|
|
},
|
|
{
|
|
symbol: 'MAX_SUB_SESSION_PROMPT_CHARS',
|
|
pattern:
|
|
'^(export )?(const|let|var) MAX_SUB_SESSION_PROMPT_CHARS[[:space:]]*[:=]',
|
|
owner: 'packages/core/src/tools/sub-session-constants.ts',
|
|
},
|
|
];
|
|
|
|
it.each(definitions)('$symbol has one owner', ({ pattern, owner }) => {
|
|
expect(definitionFiles(pattern)).toEqual([owner]);
|
|
});
|
|
|
|
const imports = [
|
|
[
|
|
'LIVE_TASK_TOOL_NAMES',
|
|
'packages/acp-bridge/src/bridgeClient.ts',
|
|
'./bridgeOptions.js',
|
|
],
|
|
[
|
|
'LIVE_TASK_TOOL_NAMES',
|
|
'packages/cli/src/serve/live/live-task-tools.ts',
|
|
'@qwen-code/acp-bridge/bridgeOptions',
|
|
],
|
|
[
|
|
'LIVE_TASK_TOOL_NAMES',
|
|
'packages/cli/src/serve/live/live-task-service.ts',
|
|
'@qwen-code/acp-bridge/bridgeOptions',
|
|
],
|
|
[
|
|
'LiveTaskToolName',
|
|
'packages/cli/src/serve/live/live-task-tools.ts',
|
|
'@qwen-code/acp-bridge/bridgeOptions',
|
|
],
|
|
[
|
|
'LiveTaskToolName',
|
|
'packages/cli/src/serve/live/live-task-service.ts',
|
|
'@qwen-code/acp-bridge/bridgeOptions',
|
|
],
|
|
[
|
|
'MAX_SUB_SESSION_PROMPT_CHARS',
|
|
'packages/core/src/tools/create-sub-session.ts',
|
|
'./sub-session-constants.js',
|
|
],
|
|
[
|
|
'MAX_SUB_SESSION_PROMPT_CHARS',
|
|
'packages/acp-bridge/src/bridgeOptions.ts',
|
|
'@qwen-code/qwen-code-core/subSessionConstants',
|
|
],
|
|
[
|
|
'MAX_SUB_SESSION_PROMPT_CHARS',
|
|
'packages/acp-bridge/src/bridgeClient.ts',
|
|
'./bridgeOptions.js',
|
|
],
|
|
];
|
|
|
|
it.each(imports)('%s is imported by %s', (symbol, path, source) => {
|
|
const text = readFileSync(join(root, path), 'utf8');
|
|
const escapedSource = source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
const statements =
|
|
text.replace(/\/\/.*$/gm, '').match(/^import[\s\S]*?;$/gm) ?? [];
|
|
expect(
|
|
statements.some(
|
|
(statement) =>
|
|
new RegExp(`\\b${symbol}\\b`).test(statement) &&
|
|
new RegExp(`from ['"]${escapedSource}['"]`).test(statement),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('distinguishes locale resolution from prompt sanitization', () => {
|
|
expect(
|
|
definitionFiles('^export function getExtensionDisplayName[(]'),
|
|
).toEqual(['packages/core/src/extension/i18n.ts']);
|
|
expect(
|
|
definitionFiles('^export function getSanitizedExtensionDisplayName[(]'),
|
|
).toEqual(['packages/cli/src/utils/extension-mention.ts']);
|
|
});
|