@mmmbuto/qwen-code-termux 0.6.4-termux → 0.6.401
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/README.md +3 -3
- package/dist/cli.js +4 -4
- package/package.json +3 -2
- package/scripts/build.js +55 -0
- package/scripts/build_package.js +37 -0
- package/scripts/build_sandbox.js +196 -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 +128 -0
- package/scripts/copy_files.js +86 -0
- package/scripts/create_alias.sh +39 -0
- package/scripts/esbuild-shims.js +29 -0
- package/scripts/generate-git-commit-info.js +71 -0
- package/scripts/get-release-version.js +411 -0
- package/scripts/lint.js +205 -0
- package/scripts/local_telemetry.js +219 -0
- package/scripts/postinstall.cjs +13 -0
- package/scripts/pre-commit.js +22 -0
- package/scripts/prepare-package.js +162 -0
- package/scripts/sandbox_command.js +126 -0
- package/scripts/start.js +83 -0
- package/scripts/telemetry.js +85 -0
- package/scripts/telemetry_gcp.js +188 -0
- package/scripts/telemetry_utils.js +439 -0
- package/scripts/termux-tools/call.sh +206 -0
- package/scripts/termux-tools/discovery.sh +382 -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 +61 -0
- package/scripts/version.js +112 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ pkg update && pkg upgrade -y
|
|
|
24
24
|
pkg install nodejs-lts -y
|
|
25
25
|
npm install -g @mmmbuto/qwen-code-termux
|
|
26
26
|
|
|
27
|
-
qwen --version # expected: 0.6.
|
|
27
|
+
qwen --version # expected: 0.6.401
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Build from source:
|
|
@@ -82,7 +82,7 @@ export OPENAI_MODEL="gpt-4o" # optional
|
|
|
82
82
|
## Documentation & Fixes
|
|
83
83
|
|
|
84
84
|
- **Test Suite**: [`QWEN_TEST_SUITE.md`](./QWEN_TEST_SUITE.md)
|
|
85
|
-
- **Test Report**: [`QWEN_TEST_REPORT_v0.6.
|
|
85
|
+
- **Test Report**: [`QWEN_TEST_REPORT_v0.6.401.md`](./QWEN_TEST_REPORT_v0.6.401.md)
|
|
86
86
|
- **Patches**: [`docs/patches/README.md`](./docs/patches/README.md)
|
|
87
87
|
- **Termux Fixes**: [`docs/patches/TERMUX_FIXES.md`](./docs/patches/TERMUX_FIXES.md)
|
|
88
88
|
|
|
@@ -153,7 +153,7 @@ npm install -g @mmmbuto/qwen-code-termux@latest
|
|
|
153
153
|
|
|
154
154
|
### Versions
|
|
155
155
|
|
|
156
|
-
- **latest / stable**: 0.6.
|
|
156
|
+
- **latest / stable**: 0.6.401
|
|
157
157
|
|
|
158
158
|
## Benchmark Results
|
|
159
159
|
|
package/dist/cli.js
CHANGED
|
@@ -155008,7 +155008,7 @@ __export(geminiContentGenerator_exports, {
|
|
|
155008
155008
|
createGeminiContentGenerator: () => createGeminiContentGenerator
|
|
155009
155009
|
});
|
|
155010
155010
|
function createGeminiContentGenerator(config2, gcConfig) {
|
|
155011
|
-
const version2 = "0.6.
|
|
155011
|
+
const version2 = "0.6.401";
|
|
155012
155012
|
const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
|
|
155013
155013
|
const baseHeaders = {
|
|
155014
155014
|
"User-Agent": userAgent2
|
|
@@ -356998,7 +356998,7 @@ __name(getPackageJson, "getPackageJson");
|
|
|
356998
356998
|
// packages/cli/src/utils/version.ts
|
|
356999
356999
|
async function getCliVersion() {
|
|
357000
357000
|
const pkgJson = await getPackageJson();
|
|
357001
|
-
return "0.6.
|
|
357001
|
+
return "0.6.401";
|
|
357002
357002
|
}
|
|
357003
357003
|
__name(getCliVersion, "getCliVersion");
|
|
357004
357004
|
|
|
@@ -365081,7 +365081,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
|
|
|
365081
365081
|
|
|
365082
365082
|
// packages/cli/src/generated/git-commit.ts
|
|
365083
365083
|
init_esbuild_shims();
|
|
365084
|
-
var GIT_COMMIT_INFO2 = "
|
|
365084
|
+
var GIT_COMMIT_INFO2 = "9a107ed7";
|
|
365085
365085
|
|
|
365086
365086
|
// packages/cli/src/utils/systemInfo.ts
|
|
365087
365087
|
async function getNpmVersion() {
|
|
@@ -416299,7 +416299,7 @@ var GeminiAgent = class {
|
|
|
416299
416299
|
name: APPROVAL_MODE_INFO[mode].name,
|
|
416300
416300
|
description: APPROVAL_MODE_INFO[mode].description
|
|
416301
416301
|
}));
|
|
416302
|
-
const version2 = "0.6.
|
|
416302
|
+
const version2 = "0.6.401";
|
|
416303
416303
|
return {
|
|
416304
416304
|
protocolVersion: PROTOCOL_VERSION,
|
|
416305
416305
|
agentInfo: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmmbuto/qwen-code-termux",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.401",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.0.0"
|
|
6
6
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "git+https://github.com/DioNanos/qwen-code-termux.git"
|
|
14
14
|
},
|
|
15
15
|
"config": {
|
|
16
|
-
"sandboxImageUri": "ghcr.io/mmmbuto/qwen-code-termux:0.6.
|
|
16
|
+
"sandboxImageUri": "ghcr.io/mmmbuto/qwen-code-termux:0.6.401"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"start": "cross-env node scripts/start.js",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"qwen": "dist/cli.js"
|
|
70
70
|
},
|
|
71
71
|
"files": [
|
|
72
|
+
"scripts",
|
|
72
73
|
"dist/",
|
|
73
74
|
"README.md",
|
|
74
75
|
"LICENSE"
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
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 } from 'node:fs';
|
|
22
|
+
import { dirname, join } from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
|
|
25
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const root = join(__dirname, '..');
|
|
27
|
+
|
|
28
|
+
// npm install if node_modules was removed (e.g. via npm run clean or scripts/clean.js)
|
|
29
|
+
if (!existsSync(join(root, 'node_modules'))) {
|
|
30
|
+
execSync('npm install', { stdio: 'inherit', cwd: root });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// build all workspaces/packages
|
|
34
|
+
execSync('npm run generate', { stdio: 'inherit', cwd: root });
|
|
35
|
+
execSync('npm run build --workspaces', { stdio: 'inherit', cwd: root });
|
|
36
|
+
|
|
37
|
+
// also build container image if sandboxing is enabled
|
|
38
|
+
// skip (-s) npm install + build since we did that above
|
|
39
|
+
try {
|
|
40
|
+
execSync('node scripts/sandbox_command.js -q', {
|
|
41
|
+
stdio: 'inherit',
|
|
42
|
+
cwd: root,
|
|
43
|
+
});
|
|
44
|
+
if (
|
|
45
|
+
process.env.BUILD_SANDBOX === '1' ||
|
|
46
|
+
process.env.BUILD_SANDBOX === 'true'
|
|
47
|
+
) {
|
|
48
|
+
execSync('node scripts/build_sandbox.js -s', {
|
|
49
|
+
stdio: 'inherit',
|
|
50
|
+
cwd: root,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// ignore
|
|
55
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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 { writeFileSync } from 'node:fs';
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
|
|
24
|
+
if (!process.cwd().includes('packages')) {
|
|
25
|
+
console.error('must be invoked from a package directory');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// build typescript files
|
|
30
|
+
execSync('tsc --build', { stdio: 'inherit' });
|
|
31
|
+
|
|
32
|
+
// copy .{md,json} files
|
|
33
|
+
execSync('node ../../scripts/copy_files.js', { stdio: 'inherit' });
|
|
34
|
+
|
|
35
|
+
// touch dist/.last_build
|
|
36
|
+
writeFileSync(join(process.cwd(), 'dist', '.last_build'), '');
|
|
37
|
+
process.exit(0);
|
|
@@ -0,0 +1,196 @@
|
|
|
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 {
|
|
22
|
+
chmodSync,
|
|
23
|
+
existsSync,
|
|
24
|
+
readFileSync,
|
|
25
|
+
rmSync,
|
|
26
|
+
writeFileSync,
|
|
27
|
+
} from 'node:fs';
|
|
28
|
+
import { join } from 'node:path';
|
|
29
|
+
import os from 'node:os';
|
|
30
|
+
import yargs from 'yargs';
|
|
31
|
+
import { hideBin } from 'yargs/helpers';
|
|
32
|
+
import cliPkgJson from '../packages/cli/package.json' with { type: 'json' };
|
|
33
|
+
|
|
34
|
+
const argv = yargs(hideBin(process.argv))
|
|
35
|
+
.option('s', {
|
|
36
|
+
alias: 'skip-npm-install-build',
|
|
37
|
+
type: 'boolean',
|
|
38
|
+
default: false,
|
|
39
|
+
description: 'skip npm install + npm run build',
|
|
40
|
+
})
|
|
41
|
+
.option('f', {
|
|
42
|
+
alias: 'dockerfile',
|
|
43
|
+
type: 'string',
|
|
44
|
+
default: 'Dockerfile',
|
|
45
|
+
description: 'use <dockerfile> for custom image',
|
|
46
|
+
})
|
|
47
|
+
.option('i', {
|
|
48
|
+
alias: 'image',
|
|
49
|
+
type: 'string',
|
|
50
|
+
default: cliPkgJson.config.sandboxImageUri,
|
|
51
|
+
description: 'use <image> name for custom image',
|
|
52
|
+
})
|
|
53
|
+
.option('output-file', {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description:
|
|
56
|
+
'Path to write the final image URI. Used for CI/CD pipeline integration.',
|
|
57
|
+
}).argv;
|
|
58
|
+
|
|
59
|
+
let sandboxCommand;
|
|
60
|
+
try {
|
|
61
|
+
sandboxCommand = execSync('node scripts/sandbox_command.js')
|
|
62
|
+
.toString()
|
|
63
|
+
.trim();
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.warn('ERROR: could not detect sandbox container command');
|
|
66
|
+
console.error(e);
|
|
67
|
+
process.exit(process.env.CI ? 1 : 0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sandboxCommand === 'sandbox-exec') {
|
|
71
|
+
console.warn(
|
|
72
|
+
'WARNING: container-based sandboxing is disabled (see README.md#sandboxing)',
|
|
73
|
+
);
|
|
74
|
+
process.exit(0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`using ${sandboxCommand} for sandboxing`);
|
|
78
|
+
|
|
79
|
+
const image = argv.i;
|
|
80
|
+
const dockerFile = argv.f;
|
|
81
|
+
|
|
82
|
+
if (!image.length) {
|
|
83
|
+
console.warn(
|
|
84
|
+
'No default image tag specified in gemini-cli/packages/cli/package.json',
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!argv.s) {
|
|
89
|
+
execSync('npm install', { stdio: 'inherit' });
|
|
90
|
+
execSync('npm run build --workspaces', { stdio: 'inherit' });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('packing @qwen-code/qwen-code ...');
|
|
94
|
+
const cliPackageDir = join('packages', 'cli');
|
|
95
|
+
rmSync(join(cliPackageDir, 'dist', 'qwen-code-*.tgz'), { force: true });
|
|
96
|
+
execSync(
|
|
97
|
+
`npm pack -w @qwen-code/qwen-code --pack-destination ./packages/cli/dist`,
|
|
98
|
+
{
|
|
99
|
+
stdio: 'ignore',
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
console.log('packing @qwen-code/qwen-code-core ...');
|
|
104
|
+
const corePackageDir = join('packages', 'core');
|
|
105
|
+
rmSync(join(corePackageDir, 'dist', 'qwen-code-core-*.tgz'), {
|
|
106
|
+
force: true,
|
|
107
|
+
});
|
|
108
|
+
execSync(
|
|
109
|
+
`npm pack -w @qwen-code/qwen-code-core --pack-destination ./packages/core/dist`,
|
|
110
|
+
{ stdio: 'ignore' },
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const packageVersion = JSON.parse(
|
|
114
|
+
readFileSync(join(process.cwd(), 'package.json'), 'utf-8'),
|
|
115
|
+
).version;
|
|
116
|
+
|
|
117
|
+
chmodSync(
|
|
118
|
+
join(cliPackageDir, 'dist', `qwen-code-qwen-code-${packageVersion}.tgz`),
|
|
119
|
+
0o755,
|
|
120
|
+
);
|
|
121
|
+
chmodSync(
|
|
122
|
+
join(
|
|
123
|
+
corePackageDir,
|
|
124
|
+
'dist',
|
|
125
|
+
`qwen-code-qwen-code-core-${packageVersion}.tgz`,
|
|
126
|
+
),
|
|
127
|
+
0o755,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const buildStdout = process.env.VERBOSE ? 'inherit' : 'ignore';
|
|
131
|
+
|
|
132
|
+
// Determine the appropriate shell based on OS
|
|
133
|
+
const isWindows = os.platform() === 'win32';
|
|
134
|
+
const shellToUse = isWindows ? 'powershell.exe' : '/bin/bash';
|
|
135
|
+
|
|
136
|
+
function buildImage(imageName, dockerfile) {
|
|
137
|
+
console.log(`building ${imageName} ... (can be slow first time)`);
|
|
138
|
+
|
|
139
|
+
let buildCommandArgs = '';
|
|
140
|
+
let tempAuthFile = '';
|
|
141
|
+
|
|
142
|
+
if (sandboxCommand === 'podman') {
|
|
143
|
+
if (isWindows) {
|
|
144
|
+
// PowerShell doesn't support <() process substitution.
|
|
145
|
+
// Create a temporary auth file that we will clean up after.
|
|
146
|
+
tempAuthFile = join(os.tmpdir(), `qwen-auth-${Date.now()}.json`);
|
|
147
|
+
writeFileSync(tempAuthFile, '{}');
|
|
148
|
+
buildCommandArgs = `--authfile="${tempAuthFile}"`;
|
|
149
|
+
} else {
|
|
150
|
+
// Use bash-specific syntax for Linux/macOS
|
|
151
|
+
buildCommandArgs = `--authfile=<(echo '{}')`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const npmPackageVersion = JSON.parse(
|
|
156
|
+
readFileSync(join(process.cwd(), 'package.json'), 'utf-8'),
|
|
157
|
+
).version;
|
|
158
|
+
|
|
159
|
+
const imageTag =
|
|
160
|
+
process.env.GEMINI_SANDBOX_IMAGE_TAG || imageName.split(':')[1];
|
|
161
|
+
const finalImageName = `${imageName.split(':')[0]}:${imageTag}`;
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
execSync(
|
|
165
|
+
`${sandboxCommand} build ${buildCommandArgs} ${
|
|
166
|
+
process.env.BUILD_SANDBOX_FLAGS || ''
|
|
167
|
+
} --build-arg CLI_VERSION_ARG=${npmPackageVersion} -f "${dockerfile}" -t "${finalImageName}" .`,
|
|
168
|
+
{ stdio: buildStdout, shell: shellToUse },
|
|
169
|
+
);
|
|
170
|
+
console.log(`built ${finalImageName}`);
|
|
171
|
+
|
|
172
|
+
// If an output file path was provided via command-line, write the final image URI to it.
|
|
173
|
+
if (argv.outputFile) {
|
|
174
|
+
console.log(
|
|
175
|
+
`Writing final image URI for CI artifact to: ${argv.outputFile}`,
|
|
176
|
+
);
|
|
177
|
+
// The publish step only supports one image. If we build multiple, only the last one
|
|
178
|
+
// will be published. Throw an error to make this failure explicit if the file already exists.
|
|
179
|
+
if (existsSync(argv.outputFile)) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`CI artifact file ${argv.outputFile} already exists. Refusing to overwrite.`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
writeFileSync(argv.outputFile, finalImageName);
|
|
185
|
+
}
|
|
186
|
+
} finally {
|
|
187
|
+
// If we created a temp file, delete it now.
|
|
188
|
+
if (tempAuthFile) {
|
|
189
|
+
rmSync(tempAuthFile, { force: true });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
buildImage(image, dockerFile);
|
|
195
|
+
|
|
196
|
+
execSync(`${sandboxCommand} image prune -f`, { stdio: 'ignore' });
|
|
@@ -0,0 +1,30 @@
|
|
|
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 { dirname, join } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
|
|
24
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
const root = join(__dirname, '..');
|
|
26
|
+
|
|
27
|
+
execSync('npm --workspace=qwen-code-vscode-ide-companion run package', {
|
|
28
|
+
stdio: 'inherit',
|
|
29
|
+
cwd: root,
|
|
30
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import os from 'node:os'; // Import os module
|
|
10
|
+
|
|
11
|
+
// --- Configuration ---
|
|
12
|
+
const cliPackageDir = path.resolve('packages', 'cli'); // Base directory for the CLI package
|
|
13
|
+
const buildTimestampPath = path.join(cliPackageDir, 'dist', '.last_build'); // Path to the timestamp file within the CLI package
|
|
14
|
+
const sourceDirs = [path.join(cliPackageDir, 'src')]; // Source directory within the CLI package
|
|
15
|
+
const filesToWatch = [
|
|
16
|
+
path.join(cliPackageDir, 'package.json'),
|
|
17
|
+
path.join(cliPackageDir, 'tsconfig.json'),
|
|
18
|
+
]; // Specific files within the CLI package
|
|
19
|
+
const buildDir = path.join(cliPackageDir, 'dist'); // Build output directory within the CLI package
|
|
20
|
+
const warningsFilePath = path.join(os.tmpdir(), 'qwen-code-warnings.txt'); // Temp file for warnings
|
|
21
|
+
// ---------------------
|
|
22
|
+
|
|
23
|
+
function getMtime(filePath) {
|
|
24
|
+
try {
|
|
25
|
+
return fs.statSync(filePath).mtimeMs; // Use mtimeMs for higher precision
|
|
26
|
+
} catch (err) {
|
|
27
|
+
if (err.code === 'ENOENT') {
|
|
28
|
+
return null; // File doesn't exist
|
|
29
|
+
}
|
|
30
|
+
console.error(`Error getting stats for ${filePath}:`, err);
|
|
31
|
+
process.exit(1); // Exit on unexpected errors getting stats
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function findSourceFiles(dir, allFiles = []) {
|
|
36
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
const fullPath = path.join(dir, entry.name);
|
|
39
|
+
// Simple check to avoid recursing into node_modules or build dir itself
|
|
40
|
+
if (
|
|
41
|
+
entry.isDirectory() &&
|
|
42
|
+
entry.name !== 'node_modules' &&
|
|
43
|
+
fullPath !== buildDir
|
|
44
|
+
) {
|
|
45
|
+
findSourceFiles(fullPath, allFiles);
|
|
46
|
+
} else if (entry.isFile()) {
|
|
47
|
+
allFiles.push(fullPath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return allFiles;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Checking build status...');
|
|
54
|
+
|
|
55
|
+
// Clean up old warnings file before check
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync(warningsFilePath)) {
|
|
58
|
+
fs.unlinkSync(warningsFilePath);
|
|
59
|
+
}
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.warn(
|
|
62
|
+
`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const buildMtime = getMtime(buildTimestampPath);
|
|
67
|
+
if (!buildMtime) {
|
|
68
|
+
// If build is missing, write that as a warning and exit(0) so app can display it
|
|
69
|
+
const errorMessage = `ERROR: Build timestamp file (${path.relative(process.cwd(), buildTimestampPath)}) not found. Run \`npm run build\` first.`;
|
|
70
|
+
console.error(errorMessage); // Still log error here
|
|
71
|
+
try {
|
|
72
|
+
fs.writeFileSync(warningsFilePath, errorMessage);
|
|
73
|
+
} catch (writeErr) {
|
|
74
|
+
console.error(
|
|
75
|
+
`[Check Script] Error writing missing build warning file: ${writeErr.message}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
process.exit(0); // Allow app to start and show the error
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let newerSourceFileFound = false;
|
|
82
|
+
const warningMessages = []; // Collect warnings here
|
|
83
|
+
const allSourceFiles = [];
|
|
84
|
+
|
|
85
|
+
// Collect files from specified directories
|
|
86
|
+
sourceDirs.forEach((dir) => {
|
|
87
|
+
const dirPath = path.resolve(dir);
|
|
88
|
+
if (fs.existsSync(dirPath)) {
|
|
89
|
+
findSourceFiles(dirPath, allSourceFiles);
|
|
90
|
+
} else {
|
|
91
|
+
console.warn(`Warning: Source directory "${dir}" not found.`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Add specific files
|
|
96
|
+
filesToWatch.forEach((file) => {
|
|
97
|
+
const filePath = path.resolve(file);
|
|
98
|
+
if (fs.existsSync(filePath)) {
|
|
99
|
+
allSourceFiles.push(filePath);
|
|
100
|
+
} else {
|
|
101
|
+
console.warn(`Warning: Watched file "${file}" not found.`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Check modification times
|
|
106
|
+
for (const file of allSourceFiles) {
|
|
107
|
+
const sourceMtime = getMtime(file);
|
|
108
|
+
const relativePath = path.relative(process.cwd(), file);
|
|
109
|
+
const isNewer = sourceMtime && sourceMtime > buildMtime;
|
|
110
|
+
|
|
111
|
+
if (isNewer) {
|
|
112
|
+
const warning = `Warning: Source file "${relativePath}" has been modified since the last build.`;
|
|
113
|
+
console.warn(warning); // Keep console warning for script debugging
|
|
114
|
+
warningMessages.push(warning);
|
|
115
|
+
newerSourceFileFound = true;
|
|
116
|
+
// break; // Uncomment to stop checking after the first newer file
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (newerSourceFileFound) {
|
|
121
|
+
const finalWarning =
|
|
122
|
+
'\nRun "npm run build" to incorporate changes before starting.';
|
|
123
|
+
warningMessages.push(finalWarning);
|
|
124
|
+
console.warn(finalWarning);
|
|
125
|
+
|
|
126
|
+
// Write warnings to the temp file
|
|
127
|
+
try {
|
|
128
|
+
fs.writeFileSync(warningsFilePath, warningMessages.join('\n'));
|
|
129
|
+
// Removed debug log
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error(`[Check Script] Error writing warnings file: ${err.message}`);
|
|
132
|
+
// Proceed without writing, app won't show warnings
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
console.log('Build is up-to-date.');
|
|
136
|
+
// Ensure no stale warning file exists if build is ok
|
|
137
|
+
try {
|
|
138
|
+
if (fs.existsSync(warningsFilePath)) {
|
|
139
|
+
fs.unlinkSync(warningsFilePath);
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {
|
|
142
|
+
console.warn(
|
|
143
|
+
`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
process.exit(0); // Always exit successfully so the app starts
|