@anh3d0nic/qwen-code-termux-ice 16.0.4 → 16.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/qwen-ice +25 -5
- package/package.json +6 -5
- package/scripts/build.js +88 -0
- package/scripts/build_package.js +37 -0
- package/scripts/build_sandbox.js +174 -0
- package/scripts/build_vscode_companion.js +30 -0
- package/scripts/check-build-status.js +148 -0
- package/scripts/check-i18n.ts +462 -0
- package/scripts/check-lockfile.js +74 -0
- package/scripts/clean.js +59 -0
- package/scripts/copy_bundle_assets.js +90 -0
- package/scripts/copy_files.js +86 -0
- package/scripts/create_alias.sh +39 -0
- package/scripts/dev.js +109 -0
- package/scripts/esbuild-shims.js +29 -0
- package/scripts/generate-git-commit-info.js +71 -0
- package/scripts/generate-settings-schema.ts +146 -0
- package/scripts/get-release-version.js +411 -0
- package/scripts/ice-mobile.js +5 -0
- package/scripts/ice-session.js +6 -0
- package/scripts/ice-skills.js +31 -0
- package/scripts/ice-teams.js +34 -0
- package/scripts/ice-v10.js +276 -0
- package/scripts/ice-v11.js +276 -0
- package/scripts/ice-v12.js +568 -0
- package/scripts/ice-v13.js +824 -0
- package/scripts/ice-v14.js +1059 -0
- package/scripts/ice-v15.js +1501 -0
- package/scripts/ice-v2.js +26 -0
- package/scripts/ice-v3-core.js +261 -0
- package/scripts/ice-v3.js +46 -0
- package/scripts/ice-v4.js +657 -0
- package/scripts/ice-v5.js +371 -0
- package/scripts/ice-v6.js +305 -0
- package/scripts/ice-v7.js +291 -0
- package/scripts/ice-v8.js +550 -0
- package/scripts/ice-v9.js +546 -0
- package/scripts/install-ice.sh +70 -0
- package/scripts/install.sh +136 -0
- package/scripts/installation/INSTALLATION_GUIDE.md +250 -0
- package/scripts/installation/install-qwen-with-source.bat +302 -0
- package/scripts/installation/install-qwen-with-source.sh +570 -0
- package/scripts/lint.js +205 -0
- package/scripts/local_telemetry.js +219 -0
- package/scripts/postinstall.cjs +235 -0
- package/scripts/pre-commit.js +22 -0
- package/scripts/prepare-package.js +186 -0
- package/scripts/prepare-termux.cjs +26 -0
- package/scripts/sandbox_command.js +128 -0
- package/scripts/start.js +86 -0
- package/scripts/telemetry.js +85 -0
- package/scripts/telemetry_gcp.js +188 -0
- package/scripts/telemetry_utils.js +450 -0
- package/scripts/test-v10.js +18 -0
- package/scripts/test-v11.js +18 -0
- package/scripts/test-v12.js +18 -0
- package/scripts/test-v13.js +18 -0
- package/scripts/test-v14.js +18 -0
- package/scripts/test-v3.js +47 -0
- package/scripts/test-v4.js +47 -0
- package/scripts/test-v6.js +59 -0
- package/scripts/test-v8.js +42 -0
- package/scripts/test-v9.js +18 -0
- package/scripts/test-windows-paths.js +51 -0
- package/scripts/tests/get-release-version.test.js +186 -0
- package/scripts/tests/test-setup.ts +12 -0
- package/scripts/tests/vitest.config.ts +26 -0
- package/scripts/unused-keys-only-in-locales.json +62 -0
- package/scripts/version.js +112 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025 Google LLC
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Copyright 2025 Google LLC
|
|
10
|
+
//
|
|
11
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
// you may not use this file except in compliance with the License.
|
|
13
|
+
// You may obtain a copy of the License at
|
|
14
|
+
//
|
|
15
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
//
|
|
17
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
// See the License for the specific language governing permissions and
|
|
21
|
+
// limitations under the License.
|
|
22
|
+
|
|
23
|
+
import fs from 'node:fs';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
|
|
26
|
+
const sourceDir = path.join('src');
|
|
27
|
+
const targetDir = path.join('dist', 'src');
|
|
28
|
+
|
|
29
|
+
const extensionsToCopy = ['.md', '.json', '.sb'];
|
|
30
|
+
|
|
31
|
+
function copyFilesRecursive(source, target, rootSourceDir) {
|
|
32
|
+
if (!fs.existsSync(target)) {
|
|
33
|
+
fs.mkdirSync(target, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const items = fs.readdirSync(source, { withFileTypes: true });
|
|
37
|
+
|
|
38
|
+
for (const item of items) {
|
|
39
|
+
const sourcePath = path.join(source, item.name);
|
|
40
|
+
const targetPath = path.join(target, item.name);
|
|
41
|
+
|
|
42
|
+
if (item.isDirectory()) {
|
|
43
|
+
copyFilesRecursive(sourcePath, targetPath, rootSourceDir);
|
|
44
|
+
} else {
|
|
45
|
+
const ext = path.extname(item.name);
|
|
46
|
+
// Copy standard extensions, or .js files in i18n/locales directory
|
|
47
|
+
// Use path.relative for precise matching to avoid false positives
|
|
48
|
+
const relativePath = path.relative(rootSourceDir, sourcePath);
|
|
49
|
+
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
50
|
+
const isLocaleJs =
|
|
51
|
+
ext === '.js' && normalizedPath.startsWith('i18n/locales/');
|
|
52
|
+
if (extensionsToCopy.includes(ext) || isLocaleJs) {
|
|
53
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!fs.existsSync(sourceDir)) {
|
|
60
|
+
console.error(`Source directory ${sourceDir} not found.`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
copyFilesRecursive(sourceDir, targetDir, sourceDir);
|
|
65
|
+
|
|
66
|
+
// Copy example extensions into the bundle.
|
|
67
|
+
const packageName = path.basename(process.cwd());
|
|
68
|
+
if (packageName === 'cli') {
|
|
69
|
+
const examplesSource = path.join(
|
|
70
|
+
sourceDir,
|
|
71
|
+
'commands',
|
|
72
|
+
'extensions',
|
|
73
|
+
'examples',
|
|
74
|
+
);
|
|
75
|
+
const examplesTarget = path.join(
|
|
76
|
+
targetDir,
|
|
77
|
+
'commands',
|
|
78
|
+
'extensions',
|
|
79
|
+
'examples',
|
|
80
|
+
);
|
|
81
|
+
if (fs.existsSync(examplesSource)) {
|
|
82
|
+
fs.cpSync(examplesSource, examplesTarget, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.log('Successfully copied files.');
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# This script creates an alias for the Gemini CLI
|
|
5
|
+
|
|
6
|
+
# Determine the project directory
|
|
7
|
+
PROJECT_DIR=$(cd "$(dirname "$0")/.." && pwd)
|
|
8
|
+
ALIAS_COMMAND="alias qwen='node "${PROJECT_DIR}/scripts/start.js"'"
|
|
9
|
+
|
|
10
|
+
# Detect shell and set config file path
|
|
11
|
+
if [[ "${SHELL}" == *"/bash" ]]; then
|
|
12
|
+
CONFIG_FILE="${HOME}/.bashrc"
|
|
13
|
+
elif [[ "${SHELL}" == *"/zsh" ]]; then
|
|
14
|
+
CONFIG_FILE="${HOME}/.zshrc"
|
|
15
|
+
else
|
|
16
|
+
echo "Unsupported shell. Only bash and zsh are supported."
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
echo "This script will add the following alias to your shell configuration file (${CONFIG_FILE}):"
|
|
21
|
+
echo " ${ALIAS_COMMAND}"
|
|
22
|
+
echo ""
|
|
23
|
+
|
|
24
|
+
# Check if the alias already exists
|
|
25
|
+
if grep -q "alias qwen=" "${CONFIG_FILE}"; then
|
|
26
|
+
echo "A 'qwen' alias already exists in ${CONFIG_FILE}. No changes were made."
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
read -p "Do you want to proceed? (y/n) " -n 1 -r
|
|
31
|
+
echo ""
|
|
32
|
+
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
|
33
|
+
echo "${ALIAS_COMMAND}" >> "${CONFIG_FILE}"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "Alias added to ${CONFIG_FILE}."
|
|
36
|
+
echo "Please run 'source ${CONFIG_FILE}' or open a new terminal to use the 'qwen' command."
|
|
37
|
+
else
|
|
38
|
+
echo "Aborted. No changes were made."
|
|
39
|
+
fi
|
package/scripts/dev.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Qwen
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Development entry point for Qwen Code CLI.
|
|
9
|
+
*
|
|
10
|
+
* Runs the CLI directly from TypeScript source files without requiring a build step.
|
|
11
|
+
* Changes to packages/core or packages/cli are reflected immediately.
|
|
12
|
+
*
|
|
13
|
+
* Usage: npm run dev -- [args]
|
|
14
|
+
* Example: npm run dev -- help
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { spawn } from 'node:child_process';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
20
|
+
import { writeFileSync, mkdtempSync, rmSync } from 'node:fs';
|
|
21
|
+
import { tmpdir, platform } from 'node:os';
|
|
22
|
+
|
|
23
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const root = join(__dirname, '..');
|
|
25
|
+
const cliPackageDir = join(root, 'packages', 'cli');
|
|
26
|
+
|
|
27
|
+
// Entry point for the CLI
|
|
28
|
+
const cliEntry = join(cliPackageDir, 'index.ts');
|
|
29
|
+
|
|
30
|
+
// Create a temporary loader file
|
|
31
|
+
const tmpDir = mkdtempSync(join(tmpdir(), 'qwen-dev-'));
|
|
32
|
+
const loaderPath = join(tmpDir, 'loader.mjs');
|
|
33
|
+
|
|
34
|
+
const coreSourcePath = join(root, 'packages', 'core', 'index.ts');
|
|
35
|
+
const coreSourceUrl = pathToFileURL(coreSourcePath).href;
|
|
36
|
+
|
|
37
|
+
const loaderCode = `
|
|
38
|
+
import { pathToFileURL } from 'node:url';
|
|
39
|
+
|
|
40
|
+
const coreSourceUrl = '${coreSourceUrl}';
|
|
41
|
+
|
|
42
|
+
export function resolve(specifier, context, nextResolve) {
|
|
43
|
+
if (specifier === '@qwen-code/qwen-code-core') {
|
|
44
|
+
return {
|
|
45
|
+
shortCircuit: true,
|
|
46
|
+
url: coreSourceUrl,
|
|
47
|
+
format: 'module',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return nextResolve(specifier, context);
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
writeFileSync(loaderPath, loaderCode);
|
|
55
|
+
|
|
56
|
+
// Create the register script that uses the new register() API
|
|
57
|
+
const registerPath = join(tmpDir, 'register.mjs');
|
|
58
|
+
const loaderUrl = pathToFileURL(loaderPath).href;
|
|
59
|
+
const registerCode = `
|
|
60
|
+
import { register } from 'node:module';
|
|
61
|
+
import { pathToFileURL } from 'node:url';
|
|
62
|
+
|
|
63
|
+
register('${loaderUrl}', pathToFileURL('./'));
|
|
64
|
+
`;
|
|
65
|
+
writeFileSync(registerPath, registerCode);
|
|
66
|
+
|
|
67
|
+
// Preserve existing NODE_OPTIONS (e.g. VS Code debugger injects --inspect flags via NODE_OPTIONS)
|
|
68
|
+
const existingNodeOptions = process.env.NODE_OPTIONS || '';
|
|
69
|
+
const importFlag = `--import ${pathToFileURL(registerPath).href}`;
|
|
70
|
+
|
|
71
|
+
const env = {
|
|
72
|
+
...process.env,
|
|
73
|
+
DEV: 'true',
|
|
74
|
+
CLI_VERSION: 'dev',
|
|
75
|
+
NODE_ENV: 'development',
|
|
76
|
+
NODE_OPTIONS: `${existingNodeOptions} ${importFlag}`.trim(),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// On Windows, use tsx.cmd; on Unix, use tsx directly
|
|
80
|
+
const isWin = platform() === 'win32';
|
|
81
|
+
const tsxCmd = isWin ? 'tsx.cmd' : 'tsx';
|
|
82
|
+
const tsxArgs = [cliEntry, ...process.argv.slice(2)];
|
|
83
|
+
|
|
84
|
+
const child = spawn(tsxCmd, tsxArgs, {
|
|
85
|
+
stdio: 'inherit',
|
|
86
|
+
env,
|
|
87
|
+
cwd: process.cwd(),
|
|
88
|
+
shell: isWin, // Use shell on Windows to resolve .cmd files
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
child.on('error', (err) => {
|
|
92
|
+
console.error('Failed to start dev server:', err.message);
|
|
93
|
+
try {
|
|
94
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
95
|
+
} catch {
|
|
96
|
+
// Ignore cleanup errors
|
|
97
|
+
}
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
child.on('close', (code) => {
|
|
102
|
+
// Cleanup temp directory
|
|
103
|
+
try {
|
|
104
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
105
|
+
} catch {
|
|
106
|
+
// Ignore cleanup errors
|
|
107
|
+
}
|
|
108
|
+
process.exit(code ?? 0);
|
|
109
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Qwen
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shims for esbuild ESM bundles to support require() calls
|
|
9
|
+
* This file is injected into the bundle via esbuild's inject option
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { dirname } from 'node:path';
|
|
15
|
+
|
|
16
|
+
// Create require function for the current module and make it global
|
|
17
|
+
const _require = createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
// Make require available globally for dynamic requires
|
|
20
|
+
if (typeof globalThis.require === 'undefined') {
|
|
21
|
+
globalThis.require = _require;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Export for esbuild injection
|
|
25
|
+
export const require = _require;
|
|
26
|
+
|
|
27
|
+
// Setup __filename and __dirname for compatibility
|
|
28
|
+
export const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
export const __dirname = dirname(__filename);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
//
|
|
8
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
// you may not use this file except in compliance with the License.
|
|
10
|
+
// You may obtain a copy of the License at
|
|
11
|
+
//
|
|
12
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
//
|
|
14
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
// See the License for the specific language governing permissions and
|
|
18
|
+
// limitations under the License.
|
|
19
|
+
|
|
20
|
+
import { execSync } from 'node:child_process';
|
|
21
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { dirname, join, relative } from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
import { readPackageUp } from 'read-package-up';
|
|
25
|
+
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const root = join(__dirname, '..');
|
|
28
|
+
const scriptPath = relative(root, fileURLToPath(import.meta.url));
|
|
29
|
+
const generatedCliDir = join(root, 'packages/cli/src/generated');
|
|
30
|
+
const cliGitCommitFile = join(generatedCliDir, 'git-commit.ts');
|
|
31
|
+
const generatedCoreDir = join(root, 'packages/core/src/generated');
|
|
32
|
+
const coreGitCommitFile = join(generatedCoreDir, 'git-commit.ts');
|
|
33
|
+
let gitCommitInfo = 'N/A';
|
|
34
|
+
let cliVersion = 'UNKNOWN';
|
|
35
|
+
|
|
36
|
+
if (!existsSync(generatedCliDir)) {
|
|
37
|
+
mkdirSync(generatedCliDir, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!existsSync(generatedCoreDir)) {
|
|
41
|
+
mkdirSync(generatedCoreDir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const gitHash = execSync('git rev-parse --short HEAD', {
|
|
46
|
+
encoding: 'utf-8',
|
|
47
|
+
}).trim();
|
|
48
|
+
if (gitHash) {
|
|
49
|
+
gitCommitInfo = gitHash;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const result = await readPackageUp();
|
|
53
|
+
cliVersion = result?.packageJson?.version ?? 'UNKNOWN';
|
|
54
|
+
} catch {
|
|
55
|
+
// ignore
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fileContent = `/**
|
|
59
|
+
* @license
|
|
60
|
+
* Copyright ${new Date().getFullYear()} Google LLC
|
|
61
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
// This file is auto-generated by the build script (${scriptPath})
|
|
65
|
+
// Do not edit this file manually.
|
|
66
|
+
export const GIT_COMMIT_INFO = '${gitCommitInfo}';
|
|
67
|
+
export const CLI_VERSION = '${cliVersion}';
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
writeFileSync(cliGitCommitFile, fileContent);
|
|
71
|
+
writeFileSync(coreGitCommitFile, fileContent);
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Qwen team
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a JSON Schema from the internal SETTINGS_SCHEMA definition.
|
|
9
|
+
*
|
|
10
|
+
* Usage: npx tsx scripts/generate-settings-schema.ts
|
|
11
|
+
*
|
|
12
|
+
* This reads the TypeScript settings schema and converts it to a standard
|
|
13
|
+
* JSON Schema file that VS Code uses for IntelliSense in settings.json files.
|
|
14
|
+
*
|
|
15
|
+
* Prerequisites: npm run build (core package must be built first)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
SettingDefinition,
|
|
24
|
+
SettingsSchema,
|
|
25
|
+
} from '../packages/cli/src/config/settingsSchema.js';
|
|
26
|
+
import { getSettingsSchema } from '../packages/cli/src/config/settingsSchema.js';
|
|
27
|
+
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = path.dirname(__filename);
|
|
30
|
+
|
|
31
|
+
interface JsonSchemaProperty {
|
|
32
|
+
$schema?: string;
|
|
33
|
+
type?: string | string[];
|
|
34
|
+
description?: string;
|
|
35
|
+
properties?: Record<string, JsonSchemaProperty>;
|
|
36
|
+
items?: JsonSchemaProperty;
|
|
37
|
+
enum?: (string | number)[];
|
|
38
|
+
default?: unknown;
|
|
39
|
+
additionalProperties?: boolean | JsonSchemaProperty;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function convertSettingToJsonSchema(
|
|
43
|
+
setting: SettingDefinition,
|
|
44
|
+
): JsonSchemaProperty {
|
|
45
|
+
const schema: JsonSchemaProperty = {};
|
|
46
|
+
|
|
47
|
+
if (setting.description) {
|
|
48
|
+
schema.description = setting.description;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
switch (setting.type) {
|
|
52
|
+
case 'boolean':
|
|
53
|
+
schema.type = 'boolean';
|
|
54
|
+
break;
|
|
55
|
+
case 'string':
|
|
56
|
+
schema.type = 'string';
|
|
57
|
+
break;
|
|
58
|
+
case 'number':
|
|
59
|
+
schema.type = 'number';
|
|
60
|
+
break;
|
|
61
|
+
case 'array':
|
|
62
|
+
schema.type = 'array';
|
|
63
|
+
schema.items = { type: 'string' };
|
|
64
|
+
break;
|
|
65
|
+
case 'enum':
|
|
66
|
+
if (setting.options && setting.options.length > 0) {
|
|
67
|
+
schema.enum = setting.options.map((o) => o.value);
|
|
68
|
+
schema.description +=
|
|
69
|
+
' Options: ' + setting.options.map((o) => `${o.value}`).join(', ');
|
|
70
|
+
} else {
|
|
71
|
+
// Enum without predefined options - accept any string
|
|
72
|
+
schema.type = 'string';
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
case 'object':
|
|
76
|
+
schema.type = 'object';
|
|
77
|
+
if (setting.properties) {
|
|
78
|
+
schema.properties = {};
|
|
79
|
+
for (const [key, childDef] of Object.entries(setting.properties)) {
|
|
80
|
+
schema.properties[key] = convertSettingToJsonSchema(
|
|
81
|
+
childDef as SettingDefinition,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
schema.additionalProperties = true;
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Add default value for simple types only
|
|
91
|
+
if (setting.default !== undefined && setting.default !== null) {
|
|
92
|
+
const defaultVal = setting.default;
|
|
93
|
+
if (
|
|
94
|
+
typeof defaultVal === 'boolean' ||
|
|
95
|
+
typeof defaultVal === 'number' ||
|
|
96
|
+
typeof defaultVal === 'string'
|
|
97
|
+
) {
|
|
98
|
+
schema.default = defaultVal;
|
|
99
|
+
} else if (Array.isArray(defaultVal) && defaultVal.length > 0) {
|
|
100
|
+
schema.default = defaultVal;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return schema;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function generateJsonSchema(
|
|
108
|
+
settingsSchema: SettingsSchema,
|
|
109
|
+
): JsonSchemaProperty {
|
|
110
|
+
const jsonSchema: JsonSchemaProperty = {
|
|
111
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
112
|
+
type: 'object',
|
|
113
|
+
description: 'Qwen Code settings configuration',
|
|
114
|
+
properties: {},
|
|
115
|
+
additionalProperties: true,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
for (const [key, setting] of Object.entries(settingsSchema)) {
|
|
119
|
+
jsonSchema.properties![key] = convertSettingToJsonSchema(
|
|
120
|
+
setting as SettingDefinition,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Add $version property
|
|
125
|
+
jsonSchema.properties!['$version'] = {
|
|
126
|
+
type: 'number',
|
|
127
|
+
description: 'Settings schema version for migration tracking.',
|
|
128
|
+
default: 3,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return jsonSchema;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const schema = getSettingsSchema();
|
|
135
|
+
const jsonSchema = generateJsonSchema(schema as unknown as SettingsSchema);
|
|
136
|
+
|
|
137
|
+
const outputDir = path.resolve(
|
|
138
|
+
__dirname,
|
|
139
|
+
'../packages/vscode-ide-companion/schemas',
|
|
140
|
+
);
|
|
141
|
+
const outputPath = path.join(outputDir, 'settings.schema.json');
|
|
142
|
+
|
|
143
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
144
|
+
fs.writeFileSync(outputPath, JSON.stringify(jsonSchema, null, 2) + '\n');
|
|
145
|
+
|
|
146
|
+
console.log(`Generated settings JSON Schema at: ${outputPath}`);
|