@qoder-ai/qoder-agent-sdk 1.0.4 → 1.0.6
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 +119 -73
- package/dist/browser/index.js +3 -3
- package/dist/browser/websocket-transport.d.ts +3 -1
- package/dist/core/default-runtime.d.ts +8 -0
- package/dist/core/process-transport.d.ts +5 -31
- package/dist/core/query-transport.d.ts +6 -0
- package/dist/core/runtime-launch-options.d.ts +84 -0
- package/dist/core/transport.d.ts +15 -0
- package/dist/core/worker-transport.d.ts +86 -0
- package/dist/direct-connect/direct-connect-transport.d.ts +3 -1
- package/dist/global/plugins.d.ts +14 -0
- package/dist/index.d.ts +14 -5
- package/dist/index.js +22 -20
- package/dist/protocol/common.d.ts +55 -0
- package/dist/protocol/control.d.ts +8 -1
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +1 -1
- package/dist/query/query-runner.d.ts +2 -0
- package/dist/query/query.d.ts +1 -1
- package/dist/runtime-manifest.json +8 -0
- package/dist/types/common.d.ts +1 -1
- package/dist/types/control.d.ts +1 -1
- package/dist/types/index.d.ts +6 -1
- package/dist/types/options.d.ts +15 -0
- package/dist/types/plugins.d.ts +41 -0
- package/package.json +5 -2
- package/scripts/postinstall.cjs +376 -19
package/scripts/postinstall.cjs
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* provide options.pathToQoderCLIExecutable or QODERCLI_PATH.
|
|
5
5
|
*
|
|
6
6
|
* Environment variables:
|
|
7
|
-
* - QODER_SKIP_DOWNLOAD=1|true: skip
|
|
7
|
+
* - QODER_SKIP_DOWNLOAD=1|true: skip postinstall runtime downloads
|
|
8
|
+
* - QODER_INSTALL_BUNDLED_CLI=1|true: download process fallback even when the packaged default runtime is Worker
|
|
8
9
|
* - QODER_CLI_MIRROR: CDN base URL. Accepts .../qodercli, .../qodercli/dev, or .../releases
|
|
10
|
+
* - QODER_WORKER_RUNTIME_URL: explicit worker runtime tgz URL override
|
|
9
11
|
* - QODER_CLI_VERSION: override package.json qoderCliVersion
|
|
10
12
|
* - QODER_CLI_SITE: download site. Supports global and cn
|
|
11
13
|
* - QODER_CLI_PLATFORM: override target artifact, e.g. darwin-arm64, linux-x64-musl
|
|
@@ -24,6 +26,10 @@ const GLOBAL_PROD_DOWNLOAD_BASE_URL =
|
|
|
24
26
|
'https://download.qoder.com/qodercli/releases';
|
|
25
27
|
const GLOBAL_DEV_DOWNLOAD_BASE_URL =
|
|
26
28
|
'https://qs-cli-dev.oss-cn-hangzhou.aliyuncs.com/qodercli/dev/releases';
|
|
29
|
+
const CN_PROD_DOWNLOAD_BASE_URL =
|
|
30
|
+
'https://static.qoder.com.cn/qoder-cli-cn/releases';
|
|
31
|
+
const CN_DEV_DOWNLOAD_BASE_URL =
|
|
32
|
+
'https://static.qoder.com.cn/qoder-cli-cn/dev/releases';
|
|
27
33
|
const LOG_PREFIX = '[@qoder-ai/qoder-agent-sdk]';
|
|
28
34
|
|
|
29
35
|
function isTruthy(value) {
|
|
@@ -38,7 +44,9 @@ function getCliVersion() {
|
|
|
38
44
|
const packageJson = require('../package.json');
|
|
39
45
|
const version = packageJson.qoderCliVersion ?? packageJson.version;
|
|
40
46
|
if (!version) {
|
|
41
|
-
throw new Error(
|
|
47
|
+
throw new Error(
|
|
48
|
+
'package.json must define "qoderCliVersion" or "version".',
|
|
49
|
+
);
|
|
42
50
|
}
|
|
43
51
|
return String(version).replace(/^v/, '');
|
|
44
52
|
} catch (error) {
|
|
@@ -83,6 +91,21 @@ function getDownloadBaseUrl(version = getCliVersion()) {
|
|
|
83
91
|
return GLOBAL_PROD_DOWNLOAD_BASE_URL;
|
|
84
92
|
}
|
|
85
93
|
|
|
94
|
+
function getWorkerRuntimeDownloadBaseUrl(version = getCliVersion()) {
|
|
95
|
+
if (process.env.QODER_CLI_MIRROR) {
|
|
96
|
+
return process.env.QODER_CLI_MIRROR;
|
|
97
|
+
}
|
|
98
|
+
const site = getCliSite();
|
|
99
|
+
if (site === 'cn') {
|
|
100
|
+
return isDevCliVersion(version)
|
|
101
|
+
? CN_DEV_DOWNLOAD_BASE_URL
|
|
102
|
+
: CN_PROD_DOWNLOAD_BASE_URL;
|
|
103
|
+
}
|
|
104
|
+
return isDevCliVersion(version)
|
|
105
|
+
? GLOBAL_DEV_DOWNLOAD_BASE_URL
|
|
106
|
+
: GLOBAL_PROD_DOWNLOAD_BASE_URL;
|
|
107
|
+
}
|
|
108
|
+
|
|
86
109
|
function normalizeDownloadBaseUrl(baseUrl, version = getCliVersion()) {
|
|
87
110
|
const trimmed = baseUrl.replace(/\/+$/, '');
|
|
88
111
|
if (trimmed.endsWith(`/${version}`)) return trimmed;
|
|
@@ -119,9 +142,7 @@ function linuxX64HasAvx2() {
|
|
|
119
142
|
}
|
|
120
143
|
|
|
121
144
|
function normalizePlatformOverride(value) {
|
|
122
|
-
const normalized = value
|
|
123
|
-
.replace(/_/g, '-')
|
|
124
|
-
.replace(/-amd64(?=-|$)/, '-x64');
|
|
145
|
+
const normalized = value.replace(/_/g, '-').replace(/-amd64(?=-|$)/, '-x64');
|
|
125
146
|
const supported = new Set([
|
|
126
147
|
'darwin-arm64',
|
|
127
148
|
'darwin-x64',
|
|
@@ -181,10 +202,89 @@ function getArtifactName(target = getPlatformTarget()) {
|
|
|
181
202
|
|
|
182
203
|
function getDownloadUrl() {
|
|
183
204
|
const version = getCliVersion();
|
|
184
|
-
const baseUrl = normalizeDownloadBaseUrl(
|
|
205
|
+
const baseUrl = normalizeDownloadBaseUrl(
|
|
206
|
+
getDownloadBaseUrl(version),
|
|
207
|
+
version,
|
|
208
|
+
);
|
|
185
209
|
return `${baseUrl}/${getArtifactName()}`;
|
|
186
210
|
}
|
|
187
211
|
|
|
212
|
+
function getWorkerRuntimeArtifactName(site = getCliSite()) {
|
|
213
|
+
return `${getCliArtifactPrefix(site)}-worker-runtime-universal.tgz`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function hasWorkerRuntimeDownloadSiteOverride() {
|
|
217
|
+
return Boolean(process.env.QODER_CLI_SITE || process.env.QODER_CLI_MIRROR);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function getManifestWorkerRuntime(manifest = readRuntimeManifest()) {
|
|
221
|
+
const workerRuntime = manifest?.workerRuntime;
|
|
222
|
+
return workerRuntime && typeof workerRuntime === 'object'
|
|
223
|
+
? workerRuntime
|
|
224
|
+
: null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function getManifestWorkerRuntimeDownloadUrl(manifest = readRuntimeManifest()) {
|
|
228
|
+
const workerRuntime = getManifestWorkerRuntime(manifest);
|
|
229
|
+
if (!workerRuntime || workerRuntime.packaged === true) return null;
|
|
230
|
+
|
|
231
|
+
const candidates = [
|
|
232
|
+
workerRuntime.url,
|
|
233
|
+
workerRuntime.artifact?.url,
|
|
234
|
+
workerRuntime.source?.url,
|
|
235
|
+
];
|
|
236
|
+
const url = candidates.find(
|
|
237
|
+
(candidate) => typeof candidate === 'string' && candidate.length > 0,
|
|
238
|
+
);
|
|
239
|
+
return url ?? null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function getManifestWorkerRuntimeSha256(manifest = readRuntimeManifest()) {
|
|
243
|
+
const workerRuntime = getManifestWorkerRuntime(manifest);
|
|
244
|
+
if (!workerRuntime || workerRuntime.packaged === true) return null;
|
|
245
|
+
|
|
246
|
+
const candidates = [
|
|
247
|
+
workerRuntime.sha256,
|
|
248
|
+
workerRuntime.artifact?.sha256,
|
|
249
|
+
workerRuntime.source?.sha256,
|
|
250
|
+
];
|
|
251
|
+
const checksum = candidates.find(
|
|
252
|
+
(candidate) =>
|
|
253
|
+
typeof candidate === 'string' &&
|
|
254
|
+
/^[a-fA-F0-9]{64}$/.test(candidate.trim()),
|
|
255
|
+
);
|
|
256
|
+
return checksum ? checksum.trim().toLowerCase() : null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function getWorkerRuntimeDownloadUrl() {
|
|
260
|
+
if (process.env.QODER_WORKER_RUNTIME_URL) {
|
|
261
|
+
return process.env.QODER_WORKER_RUNTIME_URL;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const manifestUrl = hasWorkerRuntimeDownloadSiteOverride()
|
|
265
|
+
? null
|
|
266
|
+
: getManifestWorkerRuntimeDownloadUrl();
|
|
267
|
+
if (manifestUrl) {
|
|
268
|
+
return manifestUrl;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const version = getCliVersion();
|
|
272
|
+
const baseUrl = normalizeDownloadBaseUrl(
|
|
273
|
+
getWorkerRuntimeDownloadBaseUrl(version),
|
|
274
|
+
version,
|
|
275
|
+
);
|
|
276
|
+
return `${baseUrl}/${getWorkerRuntimeArtifactName()}`;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function getWorkerRuntimeExpectedSha256(url = getWorkerRuntimeDownloadUrl()) {
|
|
280
|
+
const manifestUrl = getManifestWorkerRuntimeDownloadUrl();
|
|
281
|
+
if (manifestUrl && manifestUrl === url) {
|
|
282
|
+
return getManifestWorkerRuntimeSha256();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
|
|
188
288
|
function getBundledDir() {
|
|
189
289
|
return path.join(__dirname, '..', 'dist', '_bundled');
|
|
190
290
|
}
|
|
@@ -194,6 +294,105 @@ function getBundledCliPath() {
|
|
|
194
294
|
return path.join(getBundledDir(), cliName);
|
|
195
295
|
}
|
|
196
296
|
|
|
297
|
+
function getPackagedWorkerRuntimePath() {
|
|
298
|
+
return path.join(
|
|
299
|
+
__dirname,
|
|
300
|
+
'..',
|
|
301
|
+
'dist',
|
|
302
|
+
'_worker',
|
|
303
|
+
'qoder-worker-runtime.obf.mjs',
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function getPackagedWorkerRuntimeInfoPath() {
|
|
308
|
+
return path.join(path.dirname(getPackagedWorkerRuntimePath()), 'runtime-info.json');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function hasPackagedWorkerRuntime() {
|
|
312
|
+
return fs.existsSync(getPackagedWorkerRuntimePath());
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function readPackagedWorkerRuntimeInfo() {
|
|
316
|
+
const runtimeInfoPath = getPackagedWorkerRuntimeInfoPath();
|
|
317
|
+
if (!fs.existsSync(runtimeInfoPath)) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
const parsed = JSON.parse(fs.readFileSync(runtimeInfoPath, 'utf8'));
|
|
322
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
323
|
+
} catch {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function isPackagedWorkerRuntimeCompatibleWithSite(site = getCliSite()) {
|
|
329
|
+
if (!hasPackagedWorkerRuntime()) return false;
|
|
330
|
+
if (process.env.QODER_WORKER_RUNTIME_URL) return false;
|
|
331
|
+
|
|
332
|
+
const runtimeInfo = readPackagedWorkerRuntimeInfo();
|
|
333
|
+
if (!runtimeInfo) return false;
|
|
334
|
+
|
|
335
|
+
const expectedProductName = getCliArtifactPrefix(site);
|
|
336
|
+
const buildInfo =
|
|
337
|
+
runtimeInfo.build && typeof runtimeInfo.build === 'object'
|
|
338
|
+
? runtimeInfo.build
|
|
339
|
+
: {};
|
|
340
|
+
const actualProductName = buildInfo.productName;
|
|
341
|
+
const actualSite = buildInfo.site;
|
|
342
|
+
|
|
343
|
+
if (
|
|
344
|
+
typeof actualProductName === 'string' &&
|
|
345
|
+
actualProductName.length > 0 &&
|
|
346
|
+
actualProductName !== expectedProductName
|
|
347
|
+
) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (
|
|
352
|
+
typeof actualSite === 'string' &&
|
|
353
|
+
actualSite.length > 0 &&
|
|
354
|
+
actualSite !== site
|
|
355
|
+
) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function getRuntimeManifestPath() {
|
|
363
|
+
return path.join(__dirname, '..', 'dist', 'runtime-manifest.json');
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function readRuntimeManifest() {
|
|
367
|
+
const manifestPath = getRuntimeManifestPath();
|
|
368
|
+
if (!fs.existsSync(manifestPath)) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
373
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
374
|
+
} catch {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function getDefaultRuntimeTransport() {
|
|
380
|
+
const manifest = readRuntimeManifest();
|
|
381
|
+
return manifest?.defaultTransport === 'worker' ? 'worker' : 'process';
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function shouldInstallWorkerRuntimeForDefaultWorker() {
|
|
385
|
+
return (
|
|
386
|
+
getDefaultRuntimeTransport() === 'worker' &&
|
|
387
|
+
!isPackagedWorkerRuntimeCompatibleWithSite()
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function shouldSkipBundledCliDownloadForWorkerRuntime() {
|
|
392
|
+
if (getDefaultRuntimeTransport() !== 'worker') return false;
|
|
393
|
+
return !isTruthy(process.env.QODER_INSTALL_BUNDLED_CLI);
|
|
394
|
+
}
|
|
395
|
+
|
|
197
396
|
function requestUrl(url, redirectCount = 0) {
|
|
198
397
|
return new Promise((resolve, reject) => {
|
|
199
398
|
if (redirectCount > 5) {
|
|
@@ -241,7 +440,10 @@ async function downloadFile(url, destPath) {
|
|
|
241
440
|
}
|
|
242
441
|
|
|
243
442
|
await new Promise((resolve, reject) => {
|
|
244
|
-
const totalSize = Number.parseInt(
|
|
443
|
+
const totalSize = Number.parseInt(
|
|
444
|
+
response.headers['content-length'] || '0',
|
|
445
|
+
10,
|
|
446
|
+
);
|
|
245
447
|
let downloadedSize = 0;
|
|
246
448
|
let lastProgress = 0;
|
|
247
449
|
const file = fs.createWriteStream(destPath);
|
|
@@ -299,9 +501,26 @@ function sha256File(filePath) {
|
|
|
299
501
|
return hash.digest('hex');
|
|
300
502
|
}
|
|
301
503
|
|
|
302
|
-
async function verifyChecksum(archiveUrl, archivePath) {
|
|
504
|
+
async function verifyChecksum(archiveUrl, archivePath, expectedSha256) {
|
|
303
505
|
if (isTruthy(process.env.QODER_SKIP_CHECKSUM)) {
|
|
304
|
-
console.log(
|
|
506
|
+
console.log(
|
|
507
|
+
`${LOG_PREFIX} QODER_SKIP_CHECKSUM is set, skipping checksum verification.`,
|
|
508
|
+
);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (expectedSha256) {
|
|
513
|
+
const expected = String(expectedSha256).trim().toLowerCase();
|
|
514
|
+
if (!/^[a-fA-F0-9]{64}$/.test(expected)) {
|
|
515
|
+
throw new Error(`Invalid expected sha256: ${expectedSha256}`);
|
|
516
|
+
}
|
|
517
|
+
const actual = sha256File(archivePath);
|
|
518
|
+
if (actual !== expected) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
`Checksum verification failed. Expected ${expected}, actual ${actual}`,
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
console.log(`${LOG_PREFIX} Checksum verified.`);
|
|
305
524
|
return;
|
|
306
525
|
}
|
|
307
526
|
|
|
@@ -310,14 +529,16 @@ async function verifyChecksum(archiveUrl, archivePath) {
|
|
|
310
529
|
const expected = parseSha256(fs.readFileSync(checksumPath, 'utf8'));
|
|
311
530
|
const actual = sha256File(archivePath);
|
|
312
531
|
if (actual !== expected) {
|
|
313
|
-
throw new Error(
|
|
532
|
+
throw new Error(
|
|
533
|
+
`Checksum verification failed. Expected ${expected}, actual ${actual}`,
|
|
534
|
+
);
|
|
314
535
|
}
|
|
315
536
|
console.log(`${LOG_PREFIX} Checksum verified.`);
|
|
316
537
|
}
|
|
317
538
|
|
|
318
|
-
function execFilePromise(command, args) {
|
|
539
|
+
function execFilePromise(command, args, options = {}) {
|
|
319
540
|
return new Promise((resolve, reject) => {
|
|
320
|
-
execFile(command, args, (error, stdout, stderr) => {
|
|
541
|
+
execFile(command, args, options, (error, stdout, stderr) => {
|
|
321
542
|
if (error) {
|
|
322
543
|
reject(
|
|
323
544
|
new Error(
|
|
@@ -331,9 +552,28 @@ function execFilePromise(command, args) {
|
|
|
331
552
|
});
|
|
332
553
|
}
|
|
333
554
|
|
|
555
|
+
function getPathApi(filePath) {
|
|
556
|
+
return /^[a-zA-Z]:[\\/]/.test(filePath) ? path.win32 : path;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function getTarExtractInvocation(archivePath, destDir) {
|
|
560
|
+
const pathApi = getPathApi(archivePath);
|
|
561
|
+
const cwd = pathApi.dirname(archivePath);
|
|
562
|
+
return {
|
|
563
|
+
cwd,
|
|
564
|
+
args: [
|
|
565
|
+
'-xzf',
|
|
566
|
+
pathApi.basename(archivePath),
|
|
567
|
+
'-C',
|
|
568
|
+
pathApi.relative(cwd, destDir) || '.',
|
|
569
|
+
],
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
334
573
|
async function extractArchive(archivePath, destDir) {
|
|
335
|
-
if (archivePath.endsWith('.tar.gz')) {
|
|
336
|
-
|
|
574
|
+
if (archivePath.endsWith('.tar.gz') || archivePath.endsWith('.tgz')) {
|
|
575
|
+
const invocation = getTarExtractInvocation(archivePath, destDir);
|
|
576
|
+
await execFilePromise('tar', invocation.args, { cwd: invocation.cwd });
|
|
337
577
|
return;
|
|
338
578
|
}
|
|
339
579
|
|
|
@@ -423,13 +663,102 @@ function installExtractedContents(extractDir, bundledDir) {
|
|
|
423
663
|
}
|
|
424
664
|
|
|
425
665
|
const files = fs.readdirSync(bundledDir);
|
|
426
|
-
console.log(
|
|
666
|
+
console.log(
|
|
667
|
+
`${LOG_PREFIX} Copied ${files.length} file(s) to _bundled: ${files.join(', ')}`,
|
|
668
|
+
);
|
|
427
669
|
return target;
|
|
428
670
|
}
|
|
429
671
|
|
|
672
|
+
function findWorkerRuntimeRoot(dir) {
|
|
673
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
674
|
+
const hasWorkerRuntime = entries.some(
|
|
675
|
+
(entry) =>
|
|
676
|
+
entry.isFile() &&
|
|
677
|
+
(entry.name === 'qoder-worker-runtime.obf.mjs' ||
|
|
678
|
+
entry.name === 'qoder-worker-runtime.mjs'),
|
|
679
|
+
);
|
|
680
|
+
if (hasWorkerRuntime) return dir;
|
|
681
|
+
|
|
682
|
+
for (const entry of entries) {
|
|
683
|
+
if (!entry.isDirectory()) continue;
|
|
684
|
+
const nested = findWorkerRuntimeRoot(path.join(dir, entry.name));
|
|
685
|
+
if (nested) return nested;
|
|
686
|
+
}
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function installExtractedWorkerRuntime(extractDir, workerDir) {
|
|
691
|
+
const contentRoot = findWorkerRuntimeRoot(extractDir);
|
|
692
|
+
if (!contentRoot) {
|
|
693
|
+
throw new Error(
|
|
694
|
+
'Worker runtime not found in extracted archive. Expected qoder-worker-runtime.obf.mjs or qoder-worker-runtime.mjs.',
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
fs.rmSync(workerDir, { recursive: true, force: true });
|
|
699
|
+
copyDirContents(contentRoot, workerDir);
|
|
700
|
+
|
|
701
|
+
const obfuscatedRuntime = path.join(
|
|
702
|
+
workerDir,
|
|
703
|
+
'qoder-worker-runtime.obf.mjs',
|
|
704
|
+
);
|
|
705
|
+
const plainRuntime = path.join(workerDir, 'qoder-worker-runtime.mjs');
|
|
706
|
+
const runtimePath = fs.existsSync(obfuscatedRuntime)
|
|
707
|
+
? obfuscatedRuntime
|
|
708
|
+
: plainRuntime;
|
|
709
|
+
if (!fs.existsSync(runtimePath)) {
|
|
710
|
+
throw new Error(`Worker runtime copy failed: ${runtimePath}`);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const files = fs.readdirSync(workerDir);
|
|
714
|
+
console.log(
|
|
715
|
+
`${LOG_PREFIX} Copied ${files.length} file(s) to _worker: ${files.join(', ')}`,
|
|
716
|
+
);
|
|
717
|
+
return runtimePath;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
async function installWorkerRuntimeFromDownload() {
|
|
721
|
+
const url = getWorkerRuntimeDownloadUrl();
|
|
722
|
+
const expectedSha256 = getWorkerRuntimeExpectedSha256(url);
|
|
723
|
+
const tempDir = fs.mkdtempSync(
|
|
724
|
+
path.join(os.tmpdir(), 'qoder-worker-runtime-'),
|
|
725
|
+
);
|
|
726
|
+
const archivePath = path.join(tempDir, path.basename(new URL(url).pathname));
|
|
727
|
+
const extractDir = path.join(tempDir, 'extract');
|
|
728
|
+
|
|
729
|
+
try {
|
|
730
|
+
await downloadWithRetry(url, archivePath);
|
|
731
|
+
await verifyChecksum(url, archivePath, expectedSha256);
|
|
732
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
733
|
+
await extractArchive(archivePath, extractDir);
|
|
734
|
+
return installExtractedWorkerRuntime(
|
|
735
|
+
extractDir,
|
|
736
|
+
path.dirname(getPackagedWorkerRuntimePath()),
|
|
737
|
+
);
|
|
738
|
+
} finally {
|
|
739
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
430
743
|
async function main() {
|
|
431
744
|
if (isTruthy(process.env.QODER_SKIP_DOWNLOAD)) {
|
|
432
|
-
console.log(
|
|
745
|
+
console.log(
|
|
746
|
+
`${LOG_PREFIX} QODER_SKIP_DOWNLOAD is set, skipping runtime downloads.`,
|
|
747
|
+
);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
if (shouldInstallWorkerRuntimeForDefaultWorker()) {
|
|
752
|
+
console.log(
|
|
753
|
+
`${LOG_PREFIX} Package default runtime is Worker; downloading Worker runtime.`,
|
|
754
|
+
);
|
|
755
|
+
await installWorkerRuntimeFromDownload();
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (shouldSkipBundledCliDownloadForWorkerRuntime()) {
|
|
759
|
+
console.log(
|
|
760
|
+
`${LOG_PREFIX} Package default runtime is Worker; skipping bundled CLI binary download. Set QODER_INSTALL_BUNDLED_CLI=1 to install the process fallback as well.`,
|
|
761
|
+
);
|
|
433
762
|
return;
|
|
434
763
|
}
|
|
435
764
|
|
|
@@ -448,7 +777,9 @@ async function main() {
|
|
|
448
777
|
const archivePath = path.join(tempDir, archiveName);
|
|
449
778
|
const extractDir = path.join(tempDir, 'extract');
|
|
450
779
|
|
|
451
|
-
console.log(
|
|
780
|
+
console.log(
|
|
781
|
+
`${LOG_PREFIX} Installing ${bundleName} ${version} for ${target}.`,
|
|
782
|
+
);
|
|
452
783
|
|
|
453
784
|
try {
|
|
454
785
|
fs.mkdirSync(extractDir, { recursive: true });
|
|
@@ -461,8 +792,12 @@ async function main() {
|
|
|
461
792
|
`${LOG_PREFIX} CLI binary installed: ${installedPath} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`,
|
|
462
793
|
);
|
|
463
794
|
} catch (error) {
|
|
464
|
-
console.error(
|
|
465
|
-
|
|
795
|
+
console.error(
|
|
796
|
+
`${LOG_PREFIX} ERROR: Failed to install bundled CLI: ${error.message}`,
|
|
797
|
+
);
|
|
798
|
+
console.error(
|
|
799
|
+
`${LOG_PREFIX} Set QODER_SKIP_DOWNLOAD=1 to skip download and use a system qodercli.`,
|
|
800
|
+
);
|
|
466
801
|
process.exit(1);
|
|
467
802
|
} finally {
|
|
468
803
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
@@ -477,15 +812,37 @@ if (require.main === module) {
|
|
|
477
812
|
}
|
|
478
813
|
|
|
479
814
|
module.exports = {
|
|
815
|
+
downloadWithRetry,
|
|
816
|
+
extractArchive,
|
|
817
|
+
getTarExtractInvocation,
|
|
480
818
|
getArtifactName,
|
|
481
819
|
getArchiveExtension,
|
|
482
820
|
getCliSite,
|
|
483
821
|
getCliVersion,
|
|
484
822
|
getDownloadBaseUrl,
|
|
485
823
|
getDownloadUrl,
|
|
824
|
+
getManifestWorkerRuntimeDownloadUrl,
|
|
825
|
+
getManifestWorkerRuntimeSha256,
|
|
826
|
+
getPackagedWorkerRuntimeInfoPath,
|
|
827
|
+
getPackagedWorkerRuntimePath,
|
|
828
|
+
getRuntimeManifestPath,
|
|
486
829
|
getPlatformTarget,
|
|
830
|
+
getDefaultRuntimeTransport,
|
|
831
|
+
getWorkerRuntimeExpectedSha256,
|
|
832
|
+
getWorkerRuntimeArtifactName,
|
|
833
|
+
getWorkerRuntimeDownloadBaseUrl,
|
|
834
|
+
getWorkerRuntimeDownloadUrl,
|
|
835
|
+
hasPackagedWorkerRuntime,
|
|
487
836
|
installExtractedContents,
|
|
837
|
+
installExtractedWorkerRuntime,
|
|
838
|
+
installWorkerRuntimeFromDownload,
|
|
839
|
+
isPackagedWorkerRuntimeCompatibleWithSite,
|
|
488
840
|
isDevCliVersion,
|
|
489
841
|
normalizeDownloadBaseUrl,
|
|
490
842
|
normalizePlatformOverride,
|
|
843
|
+
readPackagedWorkerRuntimeInfo,
|
|
844
|
+
readRuntimeManifest,
|
|
845
|
+
shouldInstallWorkerRuntimeForDefaultWorker,
|
|
846
|
+
shouldSkipBundledCliDownloadForWorkerRuntime,
|
|
847
|
+
verifyChecksum,
|
|
491
848
|
};
|