@qoder-ai/qoder-agent-sdk 1.0.25 → 1.0.26
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 +28 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/diagnostic-args.d.ts +2 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +28 -29
- package/dist/protocol/control.d.ts +37 -3
- package/dist/protocol/index.d.ts +3 -2
- package/dist/protocol/index.js +1 -1
- package/dist/protocol/messages.d.ts +21 -2
- package/dist/protocol/skill-evolution.d.ts +67 -0
- package/dist/protocol/version.d.ts +1 -1
- package/dist/query/query-runner.d.ts +26 -5
- package/dist/runtime-manifest.json +5 -5
- package/dist/session/session-manager.d.ts +42 -4
- package/dist/skill-evolution/skill-evolution-options.d.ts +2 -0
- package/dist/types/control.d.ts +1 -1
- package/dist/types/hooks.d.ts +4 -4
- package/dist/types/index.d.ts +1 -1
- package/dist/types/messages.d.ts +1 -1
- package/dist/types/model-policy-provider.d.ts +8 -2
- package/dist/types/options.d.ts +29 -5
- package/dist/types/session.d.ts +8 -0
- package/dist/types/skill-evolution.d.ts +41 -0
- package/dist/types/tools.d.ts +26 -8
- package/package.json +2 -2
- package/scripts/postinstall.cjs +52 -39
package/dist/types/options.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ import type { PluginDetails } from './plugins.js';
|
|
|
18
18
|
import type { SessionStore, SessionStoreFlush } from '../session/session-store.js';
|
|
19
19
|
import type { ModelPromptPatches } from '../protocol/model-prompt-patches.js';
|
|
20
20
|
import type { MemoryOptions } from './memory.js';
|
|
21
|
-
import type {
|
|
21
|
+
import type { EvolutionOptions } from './skill-evolution.js';
|
|
22
|
+
import type { SDKGoalSnapshot, SDKGoalStatus, SDKPlanModeSnapshot } from '../protocol/control.js';
|
|
22
23
|
export type { CanUseTool };
|
|
23
24
|
export type { AuthOptions };
|
|
24
25
|
export type ElicitationRequest = {
|
|
@@ -147,12 +148,15 @@ export type Options = {
|
|
|
147
148
|
skills?: string[] | 'all';
|
|
148
149
|
extensions?: string[];
|
|
149
150
|
/**
|
|
150
|
-
* Proxy URL used by
|
|
151
|
+
* Proxy URL used by qodercli for its own outbound network traffic.
|
|
151
152
|
*
|
|
152
153
|
* Supports the same schemes as qodercli: `http://`, `https://`,
|
|
153
|
-
* `socks5://`, and `socks://`.
|
|
154
|
-
*
|
|
155
|
-
*
|
|
154
|
+
* `socks5://`, and `socks://`. The SDK passes this value through qodercli's
|
|
155
|
+
* startup interface without rewriting proxy environment variables.
|
|
156
|
+
*
|
|
157
|
+
* When omitted, SDK-integrated qodercli connects directly and does not
|
|
158
|
+
* discover a proxy from the inherited environment. Environment variables are
|
|
159
|
+
* still preserved for tools and subprocesses launched by the agent.
|
|
156
160
|
*/
|
|
157
161
|
proxy?: string;
|
|
158
162
|
/**
|
|
@@ -176,6 +180,7 @@ export type Options = {
|
|
|
176
180
|
};
|
|
177
181
|
executable?: 'bun' | 'deno' | 'node';
|
|
178
182
|
executableArgs?: string[];
|
|
183
|
+
/** Additional qodercli flags. `proxy` is reserved; use `proxy` instead. */
|
|
179
184
|
extraArgs?: Record<string, string | null>;
|
|
180
185
|
enableFileCheckpointing?: boolean;
|
|
181
186
|
toolConfig?: ToolConfig;
|
|
@@ -205,6 +210,8 @@ export type Options = {
|
|
|
205
210
|
* Functions stay in the SDK process and are bridged through control requests.
|
|
206
211
|
*/
|
|
207
212
|
memory?: MemoryOptions;
|
|
213
|
+
/** Configure component evolution capabilities for this query. */
|
|
214
|
+
evolution?: EvolutionOptions;
|
|
208
215
|
onElicitation?: OnElicitation;
|
|
209
216
|
/**
|
|
210
217
|
* Called when the SDK detects that authentication has expired or
|
|
@@ -245,6 +252,13 @@ export type Options = {
|
|
|
245
252
|
*/
|
|
246
253
|
pathToQoderCLIExecutable?: string;
|
|
247
254
|
permissionMode?: PermissionMode;
|
|
255
|
+
/**
|
|
256
|
+
* Initial Plan Mode state for the main session. Applied after the CLI
|
|
257
|
+
* initialize handshake and before the first user message, without changing
|
|
258
|
+
* the underlying `permissionMode`. Requires the CLI `plan_mode_v1`
|
|
259
|
+
* capability.
|
|
260
|
+
*/
|
|
261
|
+
planMode?: boolean;
|
|
248
262
|
allowDangerouslySkipPermissions?: boolean;
|
|
249
263
|
/**
|
|
250
264
|
* MCP tool name to use for permission prompts. Mutually exclusive with
|
|
@@ -403,6 +417,14 @@ export interface Query extends AsyncGenerator<SDKMessage, void> {
|
|
|
403
417
|
getGoal?(): Promise<SDKGoalSnapshot | null>;
|
|
404
418
|
/** Clear the session goal; returns whether a goal was cleared. */
|
|
405
419
|
clearGoal?(): Promise<boolean>;
|
|
420
|
+
/**
|
|
421
|
+
* Enter or leave the main session's independent Plan Mode. The current tool
|
|
422
|
+
* permission mode is preserved. Requires the CLI `plan_mode_v1` capability.
|
|
423
|
+
* Only present on the local CLI transport; absent on cloud-agent queries.
|
|
424
|
+
*/
|
|
425
|
+
setPlanMode?(active: boolean): Promise<SDKPlanModeSnapshot>;
|
|
426
|
+
/** Read the authoritative Plan Mode state from the running CLI session. */
|
|
427
|
+
getPlanMode?(): Promise<SDKPlanModeSnapshot>;
|
|
406
428
|
setPermissionMode(mode: PermissionMode): Promise<void>;
|
|
407
429
|
setModel(model?: string): Promise<void>;
|
|
408
430
|
/**
|
|
@@ -489,6 +511,8 @@ export interface Query extends AsyncGenerator<SDKMessage, void> {
|
|
|
489
511
|
seedReadState(path: string, mtime: number): Promise<void>;
|
|
490
512
|
/** Wait until pending TurnComplete memory generation has finished. */
|
|
491
513
|
flushMemory(): Promise<void>;
|
|
514
|
+
/** Wait until pending TurnComplete skill evolution review has finished. */
|
|
515
|
+
flushSkillEvolution(): Promise<void>;
|
|
492
516
|
/** Reload configured memory consumption files without changing config. */
|
|
493
517
|
refreshMemory(): Promise<void>;
|
|
494
518
|
/**
|
package/dist/types/session.d.ts
CHANGED
|
@@ -89,10 +89,18 @@ export type ListSessionsOptions = SessionStoreOptions & {
|
|
|
89
89
|
export type GetSessionInfoOptions = SessionStoreOptions & {
|
|
90
90
|
dir?: string;
|
|
91
91
|
};
|
|
92
|
+
/** Message projection returned by {@link getSessionMessages}. */
|
|
93
|
+
export type SessionMessageView = 'runtime' | 'historical';
|
|
92
94
|
export type GetSessionMessagesOptions = SessionStoreOptions & {
|
|
93
95
|
dir?: string;
|
|
94
96
|
limit?: number;
|
|
95
97
|
offset?: number;
|
|
98
|
+
/**
|
|
99
|
+
* `runtime` returns the latest compact summary and post-compact messages.
|
|
100
|
+
* `historical` returns real messages across compact boundaries while hiding
|
|
101
|
+
* compact boundary and summary implementation records. Defaults to `runtime`.
|
|
102
|
+
*/
|
|
103
|
+
view?: SessionMessageView;
|
|
96
104
|
/**
|
|
97
105
|
* Include `system` entries in the result (compact boundaries, informational
|
|
98
106
|
* notices). Defaults to false — only user/assistant are returned.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SkillEvolutionGateInput, SkillEvolutionGateResult, SkillEvolutionResult, SerializableSkillEvolutionConfig } from '../protocol/skill-evolution.js';
|
|
2
|
+
export type { SkillEvolutionMode } from '../protocol/skill-evolution.js';
|
|
3
|
+
export declare const MAX_SKILL_EVOLUTION_REVIEW_THRESHOLD = 10;
|
|
4
|
+
export type { EffectiveEvolutionConfig, EffectiveSkillEvolutionConfig, SkillEvolutionGateInput, SkillEvolutionGateResult, SkillEvolutionResult, SerializableEvolutionConfig, SerializableSkillEvolutionConfig, SkillEvolutionSuggestion, } from '../protocol/skill-evolution.js';
|
|
5
|
+
export type SkillEvolutionShouldReview = (input: SkillEvolutionGateInput, options: {
|
|
6
|
+
signal: AbortSignal;
|
|
7
|
+
}) => Promise<SkillEvolutionGateResult>;
|
|
8
|
+
export type SkillEvolutionGenerationOptions = {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
prompt?: string;
|
|
11
|
+
maxSuggestions?: number;
|
|
12
|
+
turnComplete?: {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
/** Integer from 1 to 10. Defaults to 5. */
|
|
15
|
+
reviewThreshold?: number;
|
|
16
|
+
shouldReview?: SkillEvolutionShouldReview;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
onGateError?: 'skip' | 'report_failed';
|
|
19
|
+
};
|
|
20
|
+
onResult?: (result: SkillEvolutionResult) => void | Promise<void>;
|
|
21
|
+
};
|
|
22
|
+
export type SkillEvolutionOptions = {
|
|
23
|
+
mode: 'native';
|
|
24
|
+
generation?: Pick<SkillEvolutionGenerationOptions, 'enabled' | 'onResult'> & {
|
|
25
|
+
turnComplete?: Pick<NonNullable<SkillEvolutionGenerationOptions['turnComplete']>, 'reviewThreshold'>;
|
|
26
|
+
};
|
|
27
|
+
} | {
|
|
28
|
+
mode: 'custom';
|
|
29
|
+
generation?: SkillEvolutionGenerationOptions;
|
|
30
|
+
};
|
|
31
|
+
export type EvolutionOptions = {
|
|
32
|
+
skill?: SkillEvolutionOptions;
|
|
33
|
+
};
|
|
34
|
+
export type SkillEvolutionRuntimeCallbacks = {
|
|
35
|
+
shouldReviewCallbacks: ReadonlyMap<string, SkillEvolutionShouldReview>;
|
|
36
|
+
onResult?: SkillEvolutionGenerationOptions['onResult'];
|
|
37
|
+
};
|
|
38
|
+
export type PreparedSkillEvolutionOptions = {
|
|
39
|
+
config?: SerializableSkillEvolutionConfig;
|
|
40
|
+
callbacks?: SkillEvolutionRuntimeCallbacks;
|
|
41
|
+
};
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export type AgentToolCompletionResult = {
|
|
|
26
26
|
outputPath?: string;
|
|
27
27
|
transcriptPath?: string;
|
|
28
28
|
worktreePath?: string;
|
|
29
|
+
worktreeBranch?: string;
|
|
29
30
|
remoteContextId?: string;
|
|
30
31
|
remoteTaskId?: string;
|
|
31
32
|
};
|
|
@@ -324,23 +325,40 @@ export type ConfigOutput = {
|
|
|
324
325
|
error?: string;
|
|
325
326
|
};
|
|
326
327
|
export type EnterWorktreeInput = {
|
|
328
|
+
/** Create (or resume) a managed worktree with this name. */
|
|
327
329
|
name?: string;
|
|
330
|
+
/** Enter an existing registered Git worktree instead of creating one. */
|
|
331
|
+
path?: string;
|
|
328
332
|
};
|
|
333
|
+
/**
|
|
334
|
+
* Successful EnterWorktree result. Failures use ToolResultBlock.is_error/content.
|
|
335
|
+
*
|
|
336
|
+
* SDK 1.0.25 and earlier declared a snake_case success/error object that was
|
|
337
|
+
* never the qodercli wire shape. This type intentionally follows the actual
|
|
338
|
+
* structured result available with the paired qodercli 1.1.27 or newer.
|
|
339
|
+
*/
|
|
329
340
|
export type EnterWorktreeOutput = {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
error?: string;
|
|
341
|
+
worktreePath: string;
|
|
342
|
+
worktreeBranch?: string;
|
|
343
|
+
message: string;
|
|
334
344
|
};
|
|
335
345
|
export type ExitWorktreeInput = {
|
|
336
346
|
action: 'keep' | 'remove';
|
|
337
347
|
discard_changes?: boolean;
|
|
338
348
|
};
|
|
349
|
+
/** Successful ExitWorktree result. Failures use ToolResultBlock.is_error/content. */
|
|
339
350
|
export type ExitWorktreeOutput = {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
351
|
+
action: 'keep' | 'remove';
|
|
352
|
+
originalCwd: string;
|
|
353
|
+
worktreePath: string;
|
|
354
|
+
worktreeBranch?: string;
|
|
355
|
+
/** Reserved for forward compatibility; current qodercli does not populate it. */
|
|
356
|
+
tmuxSessionName?: string;
|
|
357
|
+
/** Reserved for forward compatibility; current qodercli does not populate it. */
|
|
358
|
+
discardedFiles?: number;
|
|
359
|
+
/** Reserved for forward compatibility; current qodercli does not populate it. */
|
|
360
|
+
discardedCommits?: number;
|
|
361
|
+
message: string;
|
|
344
362
|
};
|
|
345
363
|
export type TodoWriteInput = {
|
|
346
364
|
todos: Array<{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qoder-ai/qoder-agent-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "TypeScript SDK for building Qoder-powered coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"zod": "^3.25.0 || ^4.0.0"
|
|
52
52
|
},
|
|
53
|
-
"qoderCliVersion": "1.1.
|
|
53
|
+
"qoderCliVersion": "1.1.31",
|
|
54
54
|
"qoderSdkBrand": "global",
|
|
55
55
|
"license": "SEE LICENSE IN LICENSE"
|
|
56
56
|
}
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
* - QODER_CLI_MIRROR: CDN base URL. Accepts .../qodercli, .../qodercli/dev, or .../releases
|
|
10
10
|
* - QODER_WORKER_RUNTIME_URL: explicit worker runtime tgz URL override
|
|
11
11
|
* - QODER_CLI_VERSION: override package.json qoderCliVersion
|
|
12
|
-
* - QODER_CLI_SITE: download site. Supports global and cn
|
|
13
12
|
* - QODER_CLI_PLATFORM: override target artifact, e.g. darwin-arm64, linux-x64-musl
|
|
14
13
|
* - QODER_SKIP_CHECKSUM=1|true: skip .sha256 verification
|
|
15
14
|
*/
|
|
@@ -30,6 +29,18 @@ const CN_DEV_DOWNLOAD_BASE_URL = 'https://static.qoder.com.cn/qoder-cli-cn/dev/r
|
|
|
30
29
|
const PACKAGE_JSON = require('../package.json');
|
|
31
30
|
const LOG_PREFIX = `[${PACKAGE_JSON.name ?? '@qoder-ai/qoder-agent-sdk'}]`;
|
|
32
31
|
const WORKER_RUNTIME_ENTRY_NAMES = ['qoder-worker-runtime.obf.mjs', 'qoder-worker-runtime.mjs'];
|
|
32
|
+
const SUPPORTED_CLI_PLATFORM_TARGETS = Object.freeze([
|
|
33
|
+
'darwin-arm64',
|
|
34
|
+
'darwin-x64',
|
|
35
|
+
'linux-arm64',
|
|
36
|
+
'linux-arm64-musl',
|
|
37
|
+
'linux-x64',
|
|
38
|
+
'linux-x64-baseline',
|
|
39
|
+
'linux-x64-musl',
|
|
40
|
+
'openharmony-arm64',
|
|
41
|
+
'windows-arm64',
|
|
42
|
+
'windows-x64',
|
|
43
|
+
]);
|
|
33
44
|
|
|
34
45
|
function isTruthy(value) {
|
|
35
46
|
return value === '1' || value === 'true';
|
|
@@ -61,11 +72,11 @@ function normalizeCliSite(value) {
|
|
|
61
72
|
const normalized = String(value).trim().toLowerCase();
|
|
62
73
|
if (normalized === 'global') return 'global';
|
|
63
74
|
if (normalized === 'cn') return 'cn';
|
|
64
|
-
throw new Error(`Unsupported
|
|
75
|
+
throw new Error(`Unsupported package.json qoderSdkBrand "${value}". Supported: global, cn`);
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
function getCliSite() {
|
|
68
|
-
return normalizeCliSite(
|
|
79
|
+
return normalizeCliSite(PACKAGE_JSON.qoderSdkBrand ?? 'global');
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
function getCliArtifactPrefix(site = getCliSite()) {
|
|
@@ -86,11 +97,10 @@ function getDownloadBaseUrl(version = getCliVersion()) {
|
|
|
86
97
|
return GLOBAL_PROD_DOWNLOAD_BASE_URL;
|
|
87
98
|
}
|
|
88
99
|
|
|
89
|
-
function getWorkerRuntimeDownloadBaseUrl(version = getCliVersion()) {
|
|
100
|
+
function getWorkerRuntimeDownloadBaseUrl(version = getCliVersion(), site = getCliSite()) {
|
|
90
101
|
if (process.env.QODER_CLI_MIRROR) {
|
|
91
102
|
return process.env.QODER_CLI_MIRROR;
|
|
92
103
|
}
|
|
93
|
-
const site = getCliSite();
|
|
94
104
|
if (site === 'cn') {
|
|
95
105
|
return isDevCliVersion(version) ? CN_DEV_DOWNLOAD_BASE_URL : CN_PROD_DOWNLOAD_BASE_URL;
|
|
96
106
|
}
|
|
@@ -134,22 +144,9 @@ function linuxX64HasAvx2() {
|
|
|
134
144
|
|
|
135
145
|
function normalizePlatformOverride(value) {
|
|
136
146
|
const normalized = value.replace(/_/g, '-').replace(/-amd64(?=-|$)/, '-x64');
|
|
137
|
-
|
|
138
|
-
'darwin-arm64',
|
|
139
|
-
'darwin-x64',
|
|
140
|
-
'linux-arm64',
|
|
141
|
-
'linux-arm64-musl',
|
|
142
|
-
'linux-x64',
|
|
143
|
-
'linux-x64-baseline',
|
|
144
|
-
'linux-x64-musl',
|
|
145
|
-
'openharmony-arm64',
|
|
146
|
-
'windows-arm64',
|
|
147
|
-
'windows-x64',
|
|
148
|
-
]);
|
|
149
|
-
|
|
150
|
-
if (!supported.has(normalized)) {
|
|
147
|
+
if (!SUPPORTED_CLI_PLATFORM_TARGETS.includes(normalized)) {
|
|
151
148
|
throw new Error(
|
|
152
|
-
`Unsupported QODER_CLI_PLATFORM "${value}". Supported: ${
|
|
149
|
+
`Unsupported QODER_CLI_PLATFORM "${value}". Supported: ${SUPPORTED_CLI_PLATFORM_TARGETS.join(', ')}`,
|
|
153
150
|
);
|
|
154
151
|
}
|
|
155
152
|
return normalized;
|
|
@@ -213,11 +210,19 @@ function getWorkerRuntimeTarget(target = getPlatformTarget()) {
|
|
|
213
210
|
if (platform === 'darwin') return `darwin-${arch}`;
|
|
214
211
|
if (platform === 'linux') return `linux-${arch}`;
|
|
215
212
|
if (platform === 'windows') return `win32-${arch}`;
|
|
213
|
+
if (platform === 'openharmony') return `openharmony-${arch}`;
|
|
216
214
|
throw new Error(
|
|
217
|
-
`Worker runtime platform artifacts do not support ${target}. Supported: darwin-arm64, darwin-x64, linux-arm64, linux-x64, windows-arm64, windows-x64`,
|
|
215
|
+
`Worker runtime platform artifacts do not support ${target}. Supported: darwin-arm64, darwin-x64, linux-arm64, linux-x64, openharmony-arm64, windows-arm64, windows-x64`,
|
|
218
216
|
);
|
|
219
217
|
}
|
|
220
218
|
|
|
219
|
+
function getWorkerRuntimeArtifactTargets() {
|
|
220
|
+
return [
|
|
221
|
+
'universal',
|
|
222
|
+
...new Set(SUPPORTED_CLI_PLATFORM_TARGETS.map((target) => getWorkerRuntimeTarget(target))),
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
|
|
221
226
|
function getWorkerRuntimeArtifactName(site = getCliSite(), target = getPlatformTarget()) {
|
|
222
227
|
const workerTarget = getWorkerRuntimeTarget(target);
|
|
223
228
|
return `${getCliArtifactPrefix(site)}-worker-runtime-${workerTarget}.tgz`;
|
|
@@ -230,6 +235,10 @@ function getWorkerRuntimeArtifactNameTemplate(site = getCliSite()) {
|
|
|
230
235
|
function getWorkerRuntimeRequiredAssets(target = getPlatformTarget()) {
|
|
231
236
|
const workerTarget = getWorkerRuntimeTarget(target);
|
|
232
237
|
const [platform, arch] = workerTarget.split('-');
|
|
238
|
+
// ripgrep has no HarmonyOS build, so its worker archive ships without one and
|
|
239
|
+
// search falls back to a system rg. Demanding the asset would make every
|
|
240
|
+
// HarmonyOS install fail the completeness check.
|
|
241
|
+
if (platform === 'openharmony') return [];
|
|
233
242
|
return [
|
|
234
243
|
path.join(
|
|
235
244
|
'vendor',
|
|
@@ -240,10 +249,6 @@ function getWorkerRuntimeRequiredAssets(target = getPlatformTarget()) {
|
|
|
240
249
|
];
|
|
241
250
|
}
|
|
242
251
|
|
|
243
|
-
function hasWorkerRuntimeDownloadSiteOverride() {
|
|
244
|
-
return Boolean(process.env.QODER_CLI_SITE || process.env.QODER_CLI_MIRROR);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
252
|
function getManifestWorkerRuntime(manifest = readRuntimeManifest()) {
|
|
248
253
|
const workerRuntime = manifest?.workerRuntime;
|
|
249
254
|
return workerRuntime && typeof workerRuntime === 'object' ? workerRuntime : null;
|
|
@@ -281,14 +286,17 @@ function getManifestWorkerRuntimeSha256(manifest = readRuntimeManifest()) {
|
|
|
281
286
|
return checksum ? checksum.trim().toLowerCase() : null;
|
|
282
287
|
}
|
|
283
288
|
|
|
284
|
-
function getWorkerRuntimeDownloadUrlTemplate() {
|
|
289
|
+
function getWorkerRuntimeDownloadUrlTemplate(site = getCliSite()) {
|
|
285
290
|
const version = getCliVersion();
|
|
286
|
-
const baseUrl = normalizeDownloadBaseUrl(
|
|
287
|
-
|
|
291
|
+
const baseUrl = normalizeDownloadBaseUrl(
|
|
292
|
+
getWorkerRuntimeDownloadBaseUrl(version, site),
|
|
293
|
+
version,
|
|
294
|
+
);
|
|
295
|
+
return `${baseUrl}/${getWorkerRuntimeArtifactNameTemplate(site)}`;
|
|
288
296
|
}
|
|
289
297
|
|
|
290
|
-
function getWorkerRuntimeDefaultDownloadUrl() {
|
|
291
|
-
return getWorkerRuntimeDownloadUrlTemplate().replace(
|
|
298
|
+
function getWorkerRuntimeDefaultDownloadUrl(site = getCliSite()) {
|
|
299
|
+
return getWorkerRuntimeDownloadUrlTemplate(site).replace(
|
|
292
300
|
'{target}',
|
|
293
301
|
getWorkerRuntimeTarget(),
|
|
294
302
|
);
|
|
@@ -299,7 +307,7 @@ function getWorkerRuntimeDownloadUrl() {
|
|
|
299
307
|
return process.env.QODER_WORKER_RUNTIME_URL;
|
|
300
308
|
}
|
|
301
309
|
|
|
302
|
-
if (!
|
|
310
|
+
if (!process.env.QODER_CLI_MIRROR) {
|
|
303
311
|
const template = getManifestWorkerRuntimeDownloadUrlTemplate();
|
|
304
312
|
if (template) {
|
|
305
313
|
return template.replace('{target}', getWorkerRuntimeTarget());
|
|
@@ -781,7 +789,7 @@ function assertWorkerRuntimeComplete(runtimeDir, sourceDescription) {
|
|
|
781
789
|
return runtimePath;
|
|
782
790
|
}
|
|
783
791
|
|
|
784
|
-
function assertWorkerRuntimeIdentity(runtimeDir) {
|
|
792
|
+
function assertWorkerRuntimeIdentity(runtimeDir, brand = getCliSite()) {
|
|
785
793
|
const runtimeInfoPath = path.join(runtimeDir, 'runtime-info.json');
|
|
786
794
|
if (!fs.existsSync(runtimeInfoPath)) {
|
|
787
795
|
throw new Error(`Downloaded Worker runtime is missing identity metadata: ${runtimeInfoPath}`);
|
|
@@ -795,8 +803,7 @@ function assertWorkerRuntimeIdentity(runtimeDir) {
|
|
|
795
803
|
}
|
|
796
804
|
|
|
797
805
|
const expectedTarget = getWorkerRuntimeTarget();
|
|
798
|
-
const
|
|
799
|
-
const expectedProductName = getCliArtifactPrefix(expectedSite);
|
|
806
|
+
const expectedProductName = getCliArtifactPrefix(brand);
|
|
800
807
|
const expectedVersion = getCliVersion();
|
|
801
808
|
const mismatches = [];
|
|
802
809
|
|
|
@@ -809,8 +816,8 @@ function assertWorkerRuntimeIdentity(runtimeDir) {
|
|
|
809
816
|
if (runtimeInfo.version !== expectedVersion) {
|
|
810
817
|
mismatches.push(`version=${String(runtimeInfo.version)} (expected ${expectedVersion})`);
|
|
811
818
|
}
|
|
812
|
-
if (runtimeInfo.build?.site !==
|
|
813
|
-
mismatches.push(`site=${String(runtimeInfo.build?.site)} (expected ${
|
|
819
|
+
if (runtimeInfo.build?.site !== brand) {
|
|
820
|
+
mismatches.push(`site=${String(runtimeInfo.build?.site)} (expected ${brand})`);
|
|
814
821
|
}
|
|
815
822
|
if (runtimeInfo.build?.productName !== expectedProductName) {
|
|
816
823
|
mismatches.push(
|
|
@@ -832,7 +839,7 @@ function installExtractedWorkerRuntime(extractDir, workerDir, options = {}) {
|
|
|
832
839
|
}
|
|
833
840
|
assertWorkerRuntimeComplete(contentRoot, contentRoot);
|
|
834
841
|
if (options.validateIdentity === true) {
|
|
835
|
-
assertWorkerRuntimeIdentity(contentRoot);
|
|
842
|
+
assertWorkerRuntimeIdentity(contentRoot, options.brand);
|
|
836
843
|
}
|
|
837
844
|
|
|
838
845
|
fs.rmSync(workerDir, { recursive: true, force: true });
|
|
@@ -846,8 +853,12 @@ function installExtractedWorkerRuntime(extractDir, workerDir, options = {}) {
|
|
|
846
853
|
}
|
|
847
854
|
|
|
848
855
|
async function downloadAndInstallWorkerRuntime(workerDir, options = {}) {
|
|
849
|
-
const
|
|
850
|
-
const
|
|
856
|
+
const brand = options.brand ?? getCliSite();
|
|
857
|
+
const url =
|
|
858
|
+
options.urlOverride ??
|
|
859
|
+
(options.brand ? getWorkerRuntimeDefaultDownloadUrl(brand) : getWorkerRuntimeDownloadUrl());
|
|
860
|
+
const expectedSha256 =
|
|
861
|
+
options.urlOverride || options.brand ? null : getWorkerRuntimeExpectedSha256(url);
|
|
851
862
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'qoder-worker-runtime-'));
|
|
852
863
|
const archivePath = path.join(tempDir, path.basename(new URL(url).pathname));
|
|
853
864
|
const extractDir = path.join(tempDir, 'extract');
|
|
@@ -860,6 +871,7 @@ async function downloadAndInstallWorkerRuntime(workerDir, options = {}) {
|
|
|
860
871
|
return {
|
|
861
872
|
runtimePath: installExtractedWorkerRuntime(extractDir, workerDir, {
|
|
862
873
|
validateIdentity: true,
|
|
874
|
+
brand,
|
|
863
875
|
}),
|
|
864
876
|
url,
|
|
865
877
|
};
|
|
@@ -986,6 +998,7 @@ module.exports = {
|
|
|
986
998
|
getWorkerRuntimeExpectedSha256,
|
|
987
999
|
getWorkerRuntimeArtifactName,
|
|
988
1000
|
getWorkerRuntimeArtifactNameTemplate,
|
|
1001
|
+
getWorkerRuntimeArtifactTargets,
|
|
989
1002
|
getWorkerRuntimeDownloadBaseUrl,
|
|
990
1003
|
getWorkerRuntimeDownloadUrl,
|
|
991
1004
|
getWorkerRuntimeDownloadUrlTemplate,
|