@pentoshi/clai 4.14.4 → 4.14.5
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/CONTRIBUTING.md +4 -0
- package/PROVIDERS.md +2 -0
- package/README.md +22 -0
- package/dist/agent/subagents/read-only-tools.js +2 -2
- package/dist/agent/subagents/read-only-tools.js.map +1 -1
- package/dist/app/adapters/current-updates-adapter.d.ts +1 -1
- package/dist/app/adapters/current-updates-adapter.js +4 -13
- package/dist/app/adapters/current-updates-adapter.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +5 -0
- package/dist/app/controllers/session-controller.js +54 -7
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/ports/updates-port.d.ts +1 -1
- package/dist/classic/app/action-handlers.js +7 -0
- package/dist/classic/app/action-handlers.js.map +1 -1
- package/dist/commands/update/detection.d.ts +20 -0
- package/dist/commands/update/detection.js +207 -0
- package/dist/commands/update/detection.js.map +1 -0
- package/dist/commands/update/download.d.ts +3 -0
- package/dist/commands/update/download.js +63 -0
- package/dist/commands/update/download.js.map +1 -0
- package/dist/commands/update/installers.d.ts +16 -5
- package/dist/commands/update/installers.js +12 -513
- package/dist/commands/update/installers.js.map +1 -1
- package/dist/commands/update/lock.d.ts +6 -0
- package/dist/commands/update/lock.js +86 -0
- package/dist/commands/update/lock.js.map +1 -0
- package/dist/commands/update/metadata.d.ts +6 -0
- package/dist/commands/update/metadata.js +36 -0
- package/dist/commands/update/metadata.js.map +1 -0
- package/dist/commands/update/native.d.ts +3 -0
- package/dist/commands/update/native.js +179 -0
- package/dist/commands/update/native.js.map +1 -0
- package/dist/commands/update/package-managers.d.ts +4 -0
- package/dist/commands/update/package-managers.js +158 -0
- package/dist/commands/update/package-managers.js.map +1 -0
- package/dist/commands/update/process.d.ts +17 -0
- package/dist/commands/update/process.js +114 -0
- package/dist/commands/update/process.js.map +1 -0
- package/dist/commands/update/source-worker.d.ts +2 -0
- package/dist/commands/update/source-worker.js +71 -0
- package/dist/commands/update/source-worker.js.map +1 -0
- package/dist/commands/update/source.d.ts +2 -0
- package/dist/commands/update/source.js +79 -0
- package/dist/commands/update/source.js.map +1 -0
- package/dist/commands/update/verification.d.ts +7 -0
- package/dist/commands/update/verification.js +73 -0
- package/dist/commands/update/verification.js.map +1 -0
- package/dist/commands/update/windows-stage.d.ts +21 -0
- package/dist/commands/update/windows-stage.js +186 -0
- package/dist/commands/update/windows-stage.js.map +1 -0
- package/dist/commands/update-install.d.ts +4 -13
- package/dist/commands/update-install.js +20 -152
- package/dist/commands/update-install.js.map +1 -1
- package/dist/commands/update.d.ts +4 -9
- package/dist/commands/update.js +51 -103
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/responses-error.d.ts +3 -0
- package/dist/llm/responses-error.js +37 -0
- package/dist/llm/responses-error.js.map +1 -0
- package/dist/llm/responses-http.js +5 -2
- package/dist/llm/responses-http.js.map +1 -1
- package/dist/llm/responses-replay.d.ts +2 -0
- package/dist/llm/responses-replay.js +37 -1
- package/dist/llm/responses-replay.js.map +1 -1
- package/dist/llm/responses-stream-events.js +3 -20
- package/dist/llm/responses-stream-events.js.map +1 -1
- package/dist/llm/responses-stream.js +2 -0
- package/dist/llm/responses-stream.js.map +1 -1
- package/dist/os/bun-runtime.js +2 -1
- package/dist/os/bun-runtime.js.map +1 -1
- package/dist/os/update-origin.d.ts +7 -0
- package/dist/os/update-origin.js +30 -0
- package/dist/os/update-origin.js.map +1 -0
- package/dist/prompts/embedded.js +2 -2
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.js +2 -2
- package/dist/prompts/system.agent.md +1 -1
- package/dist/prompts/system.ask.md +1 -1
- package/dist/session-runtime/client.js +2 -1
- package/dist/session-runtime/client.js.map +1 -1
- package/dist/store/history/jsonl-lock.js +10 -7
- package/dist/store/history/jsonl-lock.js.map +1 -1
- package/dist/store/history/recovery.js +2 -1
- package/dist/store/history/recovery.js.map +1 -1
- package/dist/store/history.js +4 -2
- package/dist/store/history.js.map +1 -1
- package/dist/tools/definitions/fs-read.js +1 -1
- package/dist/tools/definitions/fs-read.js.map +1 -1
- package/dist/tools/fs/read-input.d.ts +1 -1
- package/dist/tools/fs/read-input.js +2 -2
- package/dist/tools/fs/read-input.js.map +1 -1
- package/dist/tui-v2/app/App.js +13 -5
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/components/plan/plan-interaction.d.ts +11 -0
- package/dist/tui-v2/components/plan/plan-interaction.js +56 -0
- package/dist/tui-v2/components/plan/plan-interaction.js.map +1 -0
- package/dist/tui-v2/components/plan/plan-view.d.ts +7 -1
- package/dist/tui-v2/components/plan/plan-view.js +78 -175
- package/dist/tui-v2/components/plan/plan-view.js.map +1 -1
- package/dist/tui-v2/components/plan/task-title.d.ts +9 -0
- package/dist/tui-v2/components/plan/task-title.js +17 -0
- package/dist/tui-v2/components/plan/task-title.js.map +1 -0
- package/dist/tui-v2/components/plan/use-task-disclosure.d.ts +25 -0
- package/dist/tui-v2/components/plan/use-task-disclosure.js +125 -0
- package/dist/tui-v2/components/plan/use-task-disclosure.js.map +1 -0
- package/dist/tui-v2/composer/composer-editor.js +3 -0
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/ui-core/actions/action-id.d.ts +1 -1
- package/dist/ui-core/actions/action-id.js +7 -0
- package/dist/ui-core/actions/action-id.js.map +1 -1
- package/dist/ui-core/actions/format-shortcuts.js +7 -0
- package/dist/ui-core/actions/format-shortcuts.js.map +1 -1
- package/dist/ui-core/commands/config-commands.js +12 -6
- package/dist/ui-core/commands/config-commands.js.map +1 -1
- package/dist/ui-core/commands/prompt-commands.d.ts +1 -1
- package/dist/ui-core/commands/prompt-commands.js +12 -2
- package/dist/ui-core/commands/prompt-commands.js.map +1 -1
- package/dist/ui-core/controllers/toast-controller.js +4 -4
- package/dist/ui-core/controllers/toast-controller.js.map +1 -1
- package/dist/ui-core/rendering/plan-view.js +24 -12
- package/dist/ui-core/rendering/plan-view.js.map +1 -1
- package/dist/ui-core/rendering/task-disclosure.d.ts +19 -0
- package/dist/ui-core/rendering/task-disclosure.js +70 -0
- package/dist/ui-core/rendering/task-disclosure.js.map +1 -0
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export const sourceApplyWorker = String.raw `import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
const data = JSON.parse(readFileSync(process.argv[2], 'utf8'));
|
|
5
|
+
for (const key of ['root', 'stage', 'worktree', 'head', 'commit', 'runtime', 'version']) {
|
|
6
|
+
if (typeof data[key] !== 'string' || !data[key]) throw new Error('Invalid source-update task');
|
|
7
|
+
}
|
|
8
|
+
function command(file, args) {
|
|
9
|
+
const result = spawnSync(file, args, { cwd: data.root, encoding: 'utf8', timeout: 30000, maxBuffer: 16384, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
10
|
+
if (result.error || result.status !== 0) throw new Error((result.error?.message || result.stderr || 'Source update command failed').slice(-1024));
|
|
11
|
+
return result.stdout.trim();
|
|
12
|
+
}
|
|
13
|
+
const moved = [];
|
|
14
|
+
let merged = false;
|
|
15
|
+
let preserve = false;
|
|
16
|
+
try {
|
|
17
|
+
const changes = command('git', ['status', '--porcelain', '--', '.', ':(exclude)' + basename(data.stage)]);
|
|
18
|
+
if (changes || command('git', ['rev-parse', 'HEAD']) !== data.head) throw new Error('Checkout changed while the update was building; existing files were kept');
|
|
19
|
+
command('git', ['merge', '--ff-only', data.commit]);
|
|
20
|
+
merged = true;
|
|
21
|
+
for (const name of ['node_modules', 'dist']) {
|
|
22
|
+
const target = join(data.root, name);
|
|
23
|
+
const backup = join(data.stage, 'previous-' + name);
|
|
24
|
+
const entry = { target, backup, previous: existsSync(target), installed: false };
|
|
25
|
+
moved.push(entry);
|
|
26
|
+
if (entry.previous) renameSync(target, backup);
|
|
27
|
+
renameSync(join(data.worktree, name), target);
|
|
28
|
+
entry.installed = true;
|
|
29
|
+
}
|
|
30
|
+
const actual = command(data.runtime, [join(data.root, 'dist', 'index.js'), '--version']).replace(/^clai\s+|^v/g, '');
|
|
31
|
+
if (actual !== data.version) throw new Error('Source-update runtime verification failed: ' + actual);
|
|
32
|
+
process.stdout.write(actual + '\n');
|
|
33
|
+
} catch (error) {
|
|
34
|
+
try {
|
|
35
|
+
for (const entry of moved.reverse()) {
|
|
36
|
+
if (entry.installed) rmSync(entry.target, { recursive: true, force: true });
|
|
37
|
+
if (entry.previous && existsSync(entry.backup)) renameSync(entry.backup, entry.target);
|
|
38
|
+
}
|
|
39
|
+
if (merged) command('git', ['reset', '--keep', data.head]);
|
|
40
|
+
} catch (rollbackError) {
|
|
41
|
+
preserve = true;
|
|
42
|
+
writeFileSync(join(data.stage, 'recovery'), 'Previous files retained for recovery');
|
|
43
|
+
process.stderr.write('Rollback could not finish. Recovery files: ' + data.stage + '\n' + String(rollbackError) + '\n');
|
|
44
|
+
}
|
|
45
|
+
process.stderr.write(String(error) + '\n');
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
} finally {
|
|
48
|
+
if (!preserve) {
|
|
49
|
+
try { command('git', ['worktree', 'remove', '--force', data.worktree]); } catch {}
|
|
50
|
+
try { rmSync(data.stage, { recursive: true, force: true }); } catch {}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
export const sourceCleanupWorker = String.raw `import { spawnSync } from 'node:child_process';
|
|
55
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
56
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
57
|
+
const payload = process.argv.at(-1);
|
|
58
|
+
if (!payload || !existsSync(payload)) process.exit(0);
|
|
59
|
+
const data = JSON.parse(readFileSync(payload, 'utf8'));
|
|
60
|
+
for (const key of ['root', 'stage', 'worktree']) {
|
|
61
|
+
if (typeof data[key] !== 'string' || !data[key]) throw new Error('Invalid source-cleanup task');
|
|
62
|
+
}
|
|
63
|
+
if (dirname(resolve(data.stage)) !== resolve(data.root) || !basename(data.stage).startsWith('.clai-update-') || resolve(data.worktree) !== resolve(join(data.stage, 'worktree'))) throw new Error('Invalid source staging directory');
|
|
64
|
+
if (existsSync(join(data.stage, 'recovery'))) process.exit(0);
|
|
65
|
+
if (existsSync(data.worktree)) {
|
|
66
|
+
const result = spawnSync('git', ['worktree', 'remove', '--force', data.worktree], { cwd: data.root, timeout: 30000, encoding: 'utf8', windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
67
|
+
if (result.error || result.status !== 0) throw new Error((result.error?.message || result.stderr || 'Could not clean source worktree').slice(-1024));
|
|
68
|
+
}
|
|
69
|
+
rmSync(data.stage, { recursive: true, force: true });
|
|
70
|
+
`;
|
|
71
|
+
//# sourceMappingURL=source-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-worker.js","sourceRoot":"","sources":["../../../src/commands/update/source-worker.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD1C,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;CAgB5C,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PACKAGE_NAME } from "./installers.js";
|
|
4
|
+
import { runUpdateCommand, throwIfCancelled } from "./process.js";
|
|
5
|
+
import { sourceApplyWorker, sourceCleanupWorker } from "./source-worker.js";
|
|
6
|
+
import { compareVersions, releaseVersion, verifyCommand } from "./verification.js";
|
|
7
|
+
import { stageWindowsUpdate } from "./windows-stage.js";
|
|
8
|
+
export async function installSourceUpdate(options) {
|
|
9
|
+
const root = options.method.packageRoot;
|
|
10
|
+
const runtime = options.method.runtimePath;
|
|
11
|
+
if (!root || !runtime)
|
|
12
|
+
throw new Error("cannot identify the active source checkout and runtime");
|
|
13
|
+
const git = (args) => runUpdateCommand({ file: "git", args, cwd: root, env: { GIT_TERMINAL_PROMPT: "0", GIT_SSH_COMMAND: "ssh -o BatchMode=yes" } }, { signal: options.signal, timeoutMs: 120_000 });
|
|
14
|
+
throwIfCancelled(options.signal);
|
|
15
|
+
if (await git(["status", "--porcelain"]))
|
|
16
|
+
throw new Error("source checkout has local changes; commit or stash them before updating. Nothing was overwritten");
|
|
17
|
+
const head = await git(["rev-parse", "HEAD"]);
|
|
18
|
+
const branch = await git(["symbolic-ref", "--quiet", "--short", "HEAD"]);
|
|
19
|
+
const remote = await git(["config", "--get", `branch.${branch}.remote`]);
|
|
20
|
+
const ref = await git(["config", "--get", `branch.${branch}.merge`]);
|
|
21
|
+
const url = await git(["remote", "get-url", remote]);
|
|
22
|
+
if (!/^(?:https:\/\/github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)pentoshi007\/clai(?:\.git)?\/?$/i.test(url)) {
|
|
23
|
+
throw new Error("source checkout must track the official clai upstream; custom remotes are not changed automatically");
|
|
24
|
+
}
|
|
25
|
+
if (!ref.startsWith("refs/heads/"))
|
|
26
|
+
throw new Error("source checkout has no upstream branch; configure tracking before updating");
|
|
27
|
+
options.log?.("Fetching the tracked source upstream…");
|
|
28
|
+
await git(["fetch", "--no-tags", remote, ref]);
|
|
29
|
+
const commit = await git(["rev-parse", "FETCH_HEAD"]);
|
|
30
|
+
try {
|
|
31
|
+
await git(["merge-base", "--is-ancestor", head, commit]);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error("source checkout has local or divergent commits; update requires a safe fast-forward. Nothing was overwritten");
|
|
35
|
+
}
|
|
36
|
+
const stage = mkdtempSync(join(root, ".clai-update-"));
|
|
37
|
+
const worktree = join(stage, "worktree");
|
|
38
|
+
let pending = false;
|
|
39
|
+
try {
|
|
40
|
+
await git(["worktree", "add", "--detach", worktree, commit]);
|
|
41
|
+
const manifest = JSON.parse(readFileSync(join(worktree, "package.json"), "utf8"));
|
|
42
|
+
if (!manifest || typeof manifest !== "object" || !("name" in manifest) || manifest.name !== PACKAGE_NAME || !("version" in manifest))
|
|
43
|
+
throw new Error("upstream is not a clai source checkout");
|
|
44
|
+
const version = releaseVersion(manifest.version);
|
|
45
|
+
if (!version || compareVersions(version, options.version) < 0)
|
|
46
|
+
throw new Error(`tracked source upstream has not reached v${options.version}; existing checkout was kept`);
|
|
47
|
+
options.onProgress?.({ phase: "installing", detail: "building isolated source worktree" });
|
|
48
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
49
|
+
const runOptions = { signal: options.signal, log: options.log, timeoutMs: 600_000 };
|
|
50
|
+
await runUpdateCommand({ file: npm, args: ["ci", "--no-audit", "--no-fund"], cwd: worktree }, runOptions);
|
|
51
|
+
await runUpdateCommand({ file: npm, args: ["run", "build", "--silent"], cwd: worktree }, runOptions);
|
|
52
|
+
options.onProgress?.({ phase: "verifying" });
|
|
53
|
+
await verifyCommand({ file: runtime, args: [join(worktree, "dist", "index.js"), "--version"] }, version, { signal: options.signal });
|
|
54
|
+
const worker = join(stage, "apply-source.mjs");
|
|
55
|
+
const payload = join(stage, "task.json");
|
|
56
|
+
writeFileSync(worker, sourceApplyWorker);
|
|
57
|
+
writeFileSync(payload, JSON.stringify({ root, stage, worktree, head, commit, runtime, version }));
|
|
58
|
+
const application = { file: runtime, args: [worker, payload] };
|
|
59
|
+
const verification = { file: runtime, args: [join(root, "dist", "index.js"), "--version"] };
|
|
60
|
+
throwIfCancelled(options.signal);
|
|
61
|
+
if (process.platform === "win32") {
|
|
62
|
+
const cleanup = { file: runtime, args: ["--input-type=module", "-e", sourceCleanupWorker, payload] };
|
|
63
|
+
const statusFile = await stageWindowsUpdate({ kind: "commands", commands: [application], verification, version, allowNewer: false, cleanup }, { signal: options.signal, ...(options.lockFile ? { lockFile: options.lockFile, lockToken: options.lockToken } : {}) });
|
|
64
|
+
pending = true;
|
|
65
|
+
return { ok: true, method: "dev", outcome: "staged", needsRestart: true, statusFile, message: `source update built and staged; close clai to apply it. Result: ${statusFile}` };
|
|
66
|
+
}
|
|
67
|
+
await runUpdateCommand(application, { timeoutMs: 120_000, log: options.log });
|
|
68
|
+
const installedVersion = await verifyCommand(verification, version);
|
|
69
|
+
return { ok: true, method: "dev", outcome: "applied", installedVersion, needsRestart: true, message: `source checkout fast-forwarded, rebuilt and verified at v${installedVersion}` };
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (!pending && !existsSync(join(stage, "recovery"))) {
|
|
73
|
+
if (existsSync(worktree))
|
|
74
|
+
await runUpdateCommand({ file: "git", args: ["worktree", "remove", "--force", worktree], cwd: root }, { timeoutMs: 30_000 }).catch(() => { });
|
|
75
|
+
rmSync(stage, { recursive: true, force: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../../src/commands/update/source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InstallMethod } from "./installers.js";
|
|
2
|
+
import { type RunOptions, type UpdateCommand } from "./process.js";
|
|
3
|
+
export declare function releaseVersion(value: unknown): string | undefined;
|
|
4
|
+
export declare function compareVersions(left: string, right: string): number;
|
|
5
|
+
export declare function installedVersionCommand(method: InstallMethod): UpdateCommand;
|
|
6
|
+
export declare function verifyCommand(command: UpdateCommand, expected: string, options?: RunOptions, allowNewer?: boolean): Promise<string>;
|
|
7
|
+
export declare function verifyExecutable(path: string, expected: string, options?: RunOptions): Promise<string>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { runUpdateCommand } from "./process.js";
|
|
3
|
+
export function releaseVersion(value) {
|
|
4
|
+
if (typeof value !== "string")
|
|
5
|
+
return undefined;
|
|
6
|
+
const version = value.trim().replace(/^v/, "");
|
|
7
|
+
const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/.exec(version);
|
|
8
|
+
if (!match || match.slice(1, 4).some((part) => !Number.isSafeInteger(Number(part))))
|
|
9
|
+
return undefined;
|
|
10
|
+
if (match[4]?.split(".").some((part) => /^0\d+$/.test(part)))
|
|
11
|
+
return undefined;
|
|
12
|
+
return version;
|
|
13
|
+
}
|
|
14
|
+
function components(value) {
|
|
15
|
+
const version = value.split("+")[0];
|
|
16
|
+
const index = version.indexOf("-");
|
|
17
|
+
return { numbers: (index < 0 ? version : version.slice(0, index)).split(".").map(Number), pre: index < 0 ? [] : version.slice(index + 1).split(".") };
|
|
18
|
+
}
|
|
19
|
+
function compareIdentifier(left, right) {
|
|
20
|
+
if (left === right)
|
|
21
|
+
return 0;
|
|
22
|
+
const numericLeft = /^\d+$/.test(left);
|
|
23
|
+
const numericRight = /^\d+$/.test(right);
|
|
24
|
+
if (numericLeft !== numericRight)
|
|
25
|
+
return numericLeft ? -1 : 1;
|
|
26
|
+
if (numericLeft && left.length !== right.length)
|
|
27
|
+
return left.length - right.length;
|
|
28
|
+
return left < right ? -1 : 1;
|
|
29
|
+
}
|
|
30
|
+
export function compareVersions(left, right) {
|
|
31
|
+
if (!releaseVersion(left) || !releaseVersion(right))
|
|
32
|
+
throw new Error("invalid release version");
|
|
33
|
+
const a = components(left.replace(/^v/, ""));
|
|
34
|
+
const b = components(right.replace(/^v/, ""));
|
|
35
|
+
for (let i = 0; i < 3; i += 1) {
|
|
36
|
+
const difference = a.numbers[i] - b.numbers[i];
|
|
37
|
+
if (difference)
|
|
38
|
+
return difference;
|
|
39
|
+
}
|
|
40
|
+
if (a.pre.length === 0 || b.pre.length === 0)
|
|
41
|
+
return Number(b.pre.length > 0) - Number(a.pre.length > 0);
|
|
42
|
+
for (let i = 0; i < Math.min(a.pre.length, b.pre.length); i += 1) {
|
|
43
|
+
const difference = compareIdentifier(a.pre[i], b.pre[i]);
|
|
44
|
+
if (difference)
|
|
45
|
+
return difference;
|
|
46
|
+
}
|
|
47
|
+
return a.pre.length - b.pre.length;
|
|
48
|
+
}
|
|
49
|
+
export function installedVersionCommand(method) {
|
|
50
|
+
if (method.type === "pnpm" && method.scope === "global" && method.executablePath && !method.executablePath.endsWith(".mjs")) {
|
|
51
|
+
return { file: method.executablePath, args: ["--version"], env: { PNPM_SHIM_BYPASS: "1" } };
|
|
52
|
+
}
|
|
53
|
+
if (method.packageRoot && method.type !== "dev") {
|
|
54
|
+
if (!method.runtimePath)
|
|
55
|
+
throw new Error("cannot verify the installed package without its Node/Bun runtime");
|
|
56
|
+
return { file: method.runtimePath, args: [join(method.packageRoot, "bin", "clai.mjs"), "--version"] };
|
|
57
|
+
}
|
|
58
|
+
if (!method.executablePath)
|
|
59
|
+
throw new Error("cannot verify the active clai installation path");
|
|
60
|
+
return { file: method.executablePath, args: ["--version"] };
|
|
61
|
+
}
|
|
62
|
+
export async function verifyCommand(command, expected, options = {}, allowNewer = false) {
|
|
63
|
+
const output = await runUpdateCommand(command, { ...options, timeoutMs: 15_000, log: undefined });
|
|
64
|
+
const actual = releaseVersion(output.replace(/^clai\s+/i, ""));
|
|
65
|
+
if (!actual || (allowNewer ? compareVersions(actual, expected) < 0 : actual !== expected)) {
|
|
66
|
+
throw new Error(`update verification failed: expected ${allowNewer ? "at least " : ""}${expected}, installed command reports ${output.slice(0, 120) || "no version"}; restart or retry with the original installer`);
|
|
67
|
+
}
|
|
68
|
+
return actual;
|
|
69
|
+
}
|
|
70
|
+
export function verifyExecutable(path, expected, options = {}) {
|
|
71
|
+
return verifyCommand({ file: path, args: ["--version"] }, expected, options);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../../src/commands/update/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAuC,MAAM,cAAc,CAAC;AAErF,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,+HAA+H,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5J,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACtG,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AACxJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,KAAa;IACpD,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,CAAC,CAAC;IAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,WAAW,KAAK,YAAY;QAAE,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IACnF,OAAO,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAChG,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;QACjD,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,UAAU,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC;QAC3D,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;IACpC,CAAC;IACD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAqB;IAC3D,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5H,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,EAAE,CAAC;IAC9F,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAC7G,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;IACxG,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC/F,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAsB,EAAE,QAAgB,EAAE,UAAsB,EAAE,EAAE,UAAU,GAAG,KAAK;IACxH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAClG,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,wCAAwC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,+BAA+B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,YAAY,gDAAgD,CAAC,CAAC;IACvN,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAgB,EAAE,UAAsB,EAAE;IACvF,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RunOptions, type UpdateCommand } from "./process.js";
|
|
2
|
+
export type WindowsUpdateTask = {
|
|
3
|
+
readonly kind: "binary";
|
|
4
|
+
readonly source: string;
|
|
5
|
+
readonly destination: string;
|
|
6
|
+
readonly digest: string;
|
|
7
|
+
readonly previousDigest: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "commands";
|
|
11
|
+
readonly commands: readonly UpdateCommand[];
|
|
12
|
+
readonly verification: UpdateCommand;
|
|
13
|
+
readonly version: string;
|
|
14
|
+
readonly allowNewer: boolean;
|
|
15
|
+
readonly cleanup?: UpdateCommand;
|
|
16
|
+
};
|
|
17
|
+
export declare function windowsUpdateScript(encoded: string): string;
|
|
18
|
+
export declare function stageWindowsUpdate(task: WindowsUpdateTask, options?: RunOptions & {
|
|
19
|
+
readonly lockFile?: string;
|
|
20
|
+
readonly lockToken?: string | undefined;
|
|
21
|
+
}, elevated?: boolean): Promise<string>;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { copyFileSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { psQuote, runUpdateCommand, throwIfCancelled } from "./process.js";
|
|
7
|
+
export function windowsUpdateScript(encoded) {
|
|
8
|
+
return String.raw `$ErrorActionPreference = 'Stop'
|
|
9
|
+
$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encoded}')) | ConvertFrom-Json
|
|
10
|
+
$task = $data.task
|
|
11
|
+
$stage = $data.stage
|
|
12
|
+
$status = $data.status
|
|
13
|
+
$pending = $null
|
|
14
|
+
$backup = $null
|
|
15
|
+
$verified = $false
|
|
16
|
+
function Save-Status($state, $message) {
|
|
17
|
+
@{ state=$state; version=$task.version; message=$message; time=[DateTime]::UtcNow.ToString('o') } | ConvertTo-Json -Compress | Set-Content -LiteralPath $status -Encoding UTF8
|
|
18
|
+
}
|
|
19
|
+
function Quote-Argument($value) {
|
|
20
|
+
if ($value -notmatch '[\s"]' -and $value.Length -gt 0) { return $value }
|
|
21
|
+
$escaped = [regex]::Replace($value, '(\\*)"', '$1$1\"')
|
|
22
|
+
return '"' + [regex]::Replace($escaped, '(\\+)$', '$1$1') + '"'
|
|
23
|
+
}
|
|
24
|
+
function Get-ExecutableDigest($path) {
|
|
25
|
+
$hash = [Security.Cryptography.SHA256]::Create()
|
|
26
|
+
try {
|
|
27
|
+
$stream = [IO.File]::OpenRead($path)
|
|
28
|
+
try { return [BitConverter]::ToString($hash.ComputeHash($stream)).Replace('-', '').ToLowerInvariant() }
|
|
29
|
+
finally { $stream.Dispose() }
|
|
30
|
+
} finally { $hash.Dispose() }
|
|
31
|
+
}
|
|
32
|
+
function Invoke-CommandSpec($spec) {
|
|
33
|
+
if ($spec.env) { foreach ($property in $spec.env.PSObject.Properties) { [Environment]::SetEnvironmentVariable($property.Name, [string]$property.Value, 'Process') } }
|
|
34
|
+
$arguments = (@($spec.args | ForEach-Object { Quote-Argument ([string]$_) }) -join ' ')
|
|
35
|
+
$outFile = Join-Path $stage 'stdout.txt'
|
|
36
|
+
$errFile = Join-Path $stage 'stderr.txt'
|
|
37
|
+
$parameters = @{ FilePath=$spec.file; ArgumentList=$arguments; RedirectStandardOutput=$outFile; RedirectStandardError=$errFile; PassThru=$true; NoNewWindow=$true }
|
|
38
|
+
if ($spec.cwd) { $parameters.WorkingDirectory = $spec.cwd }
|
|
39
|
+
$child = Start-Process @parameters
|
|
40
|
+
$null = $child.Handle
|
|
41
|
+
$limit = 600000
|
|
42
|
+
if ($spec.args -contains '--version') { $limit = 15000 }
|
|
43
|
+
if (-not $child.WaitForExit($limit)) {
|
|
44
|
+
& taskkill.exe /PID $child.Id /T /F *> $null
|
|
45
|
+
throw "Update command timed out: $($spec.file)"
|
|
46
|
+
}
|
|
47
|
+
$output = (Get-Content -LiteralPath $outFile -Tail 64) -join [Environment]::NewLine
|
|
48
|
+
$exitCode = $child.ExitCode
|
|
49
|
+
if ($null -eq $exitCode) { throw "Cannot read update command exit status: $($spec.file)" }
|
|
50
|
+
if ($exitCode -ne 0) { throw "Update command exited with status $($exitCode): $($spec.file) $((Get-Content -LiteralPath $errFile -Tail 4) -join ' ') $output" }
|
|
51
|
+
return $output.Trim()
|
|
52
|
+
}
|
|
53
|
+
function Compare-Version($left, $right) {
|
|
54
|
+
$a = ($left -split '\+')[0] -split '-', 2
|
|
55
|
+
$b = ($right -split '\+')[0] -split '-', 2
|
|
56
|
+
$numbersA = $a[0].Split('.')
|
|
57
|
+
$numbersB = $b[0].Split('.')
|
|
58
|
+
for ($index = 0; $index -lt 3; $index++) {
|
|
59
|
+
$difference = ([long]$numbersA[$index]).CompareTo([long]$numbersB[$index])
|
|
60
|
+
if ($difference -ne 0) { return $difference }
|
|
61
|
+
}
|
|
62
|
+
if ($a.Count -eq 1 -or $b.Count -eq 1) { return [int]($b.Count -gt 1) - [int]($a.Count -gt 1) }
|
|
63
|
+
$preA = $a[1].Split('.')
|
|
64
|
+
$preB = $b[1].Split('.')
|
|
65
|
+
for ($index = 0; $index -lt [Math]::Min($preA.Count, $preB.Count); $index++) {
|
|
66
|
+
if ($preA[$index] -ceq $preB[$index]) { continue }
|
|
67
|
+
$numericA = $preA[$index] -match '^\d+$'
|
|
68
|
+
$numericB = $preB[$index] -match '^\d+$'
|
|
69
|
+
if ($numericA -ne $numericB) { return [int]$numericB - [int]$numericA }
|
|
70
|
+
if ($numericA -and $preA[$index].Length -ne $preB[$index].Length) { return $preA[$index].Length - $preB[$index].Length }
|
|
71
|
+
return [StringComparer]::Ordinal.Compare($preA[$index], $preB[$index])
|
|
72
|
+
}
|
|
73
|
+
return $preA.Count - $preB.Count
|
|
74
|
+
}
|
|
75
|
+
function Verify-Version($spec, $allowNewer) {
|
|
76
|
+
$value = (Invoke-CommandSpec $spec) -replace '^clai\s+', ''
|
|
77
|
+
if ($value -cnotmatch '^v?((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)$') { throw "Cannot verify installed version: $value" }
|
|
78
|
+
$actual = $Matches[1]
|
|
79
|
+
$parts = ($actual -split '\+')[0] -split '-', 2
|
|
80
|
+
if ($parts.Count -eq 2) { foreach ($part in $parts[1].Split('.')) { if ($part -match '^0\d+$') { throw "Invalid installed version: $value" } } }
|
|
81
|
+
if ($allowNewer) {
|
|
82
|
+
if ((Compare-Version $actual $task.version) -lt 0) { throw "Installer did not reach version $($task.version): $value" }
|
|
83
|
+
} elseif ($actual -cne $task.version) { throw "Installed version mismatch: $value" }
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
Save-Status 'waiting' 'Close this clai installation to apply the staged update.'
|
|
87
|
+
if (-not (Test-Path -LiteralPath $stage) -or (Test-Path -LiteralPath (Join-Path $stage 'cancel'))) { throw 'Update cancelled before staging.' }
|
|
88
|
+
if ($data.lockFile) {
|
|
89
|
+
$owner = Get-Content -LiteralPath $data.lockFile -Raw | ConvertFrom-Json
|
|
90
|
+
if ($owner.token -ne $data.lockToken) { throw 'Update lock changed before staging; existing installation was kept.' }
|
|
91
|
+
@{ pid=$PID; token=$data.lockToken } | ConvertTo-Json -Compress | Set-Content -LiteralPath $data.lockFile
|
|
92
|
+
}
|
|
93
|
+
Set-Content -LiteralPath (Join-Path $stage 'ready') -Value 'ready'
|
|
94
|
+
$deadline = [DateTime]::UtcNow.AddSeconds(120)
|
|
95
|
+
while ($true) {
|
|
96
|
+
if (-not (Test-Path -LiteralPath $stage) -or (Test-Path -LiteralPath (Join-Path $stage 'cancel'))) { throw 'Update cancelled before installation.' }
|
|
97
|
+
$owner = Get-Process -Id $data.pid -ErrorAction SilentlyContinue
|
|
98
|
+
$holders = @()
|
|
99
|
+
if ($task.kind -eq 'binary') { $holders = @(Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path -eq $task.destination }) }
|
|
100
|
+
if (-not $owner -and $holders.Count -eq 0) { break }
|
|
101
|
+
if ([DateTime]::UtcNow -ge $deadline) { throw 'Timed out waiting for clai to close; the previous installation was kept. Close all instances and retry.' }
|
|
102
|
+
Start-Sleep -Milliseconds 250
|
|
103
|
+
}
|
|
104
|
+
Save-Status 'installing' 'Applying staged update.'
|
|
105
|
+
if ($task.kind -eq 'binary') {
|
|
106
|
+
if ((Get-ExecutableDigest $task.source) -ne $task.digest) { throw 'Staged binary checksum mismatch.' }
|
|
107
|
+
Verify-Version @{ file=$task.source; args=@('--version') } $false
|
|
108
|
+
$pending = "$($task.destination).update-$([Guid]::NewGuid().ToString('N'))"
|
|
109
|
+
$backup = "$($task.destination).rollback-$([Guid]::NewGuid().ToString('N'))"
|
|
110
|
+
Copy-Item -LiteralPath $task.source -Destination $pending
|
|
111
|
+
if ((Get-ExecutableDigest $task.destination) -ne $task.previousDigest) { throw 'Installation changed while the update was staged; existing executable was kept.' }
|
|
112
|
+
[IO.File]::Replace($pending, $task.destination, $backup, $true)
|
|
113
|
+
try { Verify-Version @{ file=$task.destination; args=@('--version') } $false }
|
|
114
|
+
catch { [IO.File]::Replace($backup, $task.destination, $null, $true); throw }
|
|
115
|
+
} else {
|
|
116
|
+
foreach ($command in $task.commands) { $null = Invoke-CommandSpec $command }
|
|
117
|
+
Verify-Version $task.verification $task.allowNewer
|
|
118
|
+
}
|
|
119
|
+
$verified = $true
|
|
120
|
+
Save-Status 'applied' 'Update applied and verified.'
|
|
121
|
+
} catch {
|
|
122
|
+
$message = $_.Exception.Message
|
|
123
|
+
if ($backup -and (Test-Path -LiteralPath $backup)) { $message += "; recovery executable: $backup" }
|
|
124
|
+
Save-Status 'failed' $message
|
|
125
|
+
} finally {
|
|
126
|
+
if ($task.kind -eq 'commands' -and $task.cleanup) {
|
|
127
|
+
try { $null = [IO.Directory]::CreateDirectory($stage); $null = Invoke-CommandSpec $task.cleanup }
|
|
128
|
+
catch { Save-Status $(if ($verified) { 'applied' } else { 'failed' }) ("$message; staged source cleanup failed: " + $_.Exception.Message) }
|
|
129
|
+
}
|
|
130
|
+
if ($pending) { Remove-Item -LiteralPath $pending -Force -ErrorAction SilentlyContinue }
|
|
131
|
+
if ($verified -and $backup) { Remove-Item -LiteralPath $backup -Force -ErrorAction SilentlyContinue }
|
|
132
|
+
if ($data.lockFile -and (Test-Path -LiteralPath $data.lockFile)) {
|
|
133
|
+
try { if ((Get-Content -LiteralPath $data.lockFile -Raw | ConvertFrom-Json).token -eq $data.lockToken) { Remove-Item -LiteralPath $data.lockFile -Force } } catch {}
|
|
134
|
+
}
|
|
135
|
+
Remove-Item -LiteralPath $stage -Recurse -Force -ErrorAction SilentlyContinue
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
export async function stageWindowsUpdate(task, options = {}, elevated = false) {
|
|
140
|
+
throwIfCancelled(options.signal);
|
|
141
|
+
if (options.lockFile && !options.lockToken)
|
|
142
|
+
throw new Error("cannot stage an update without its installation lock token");
|
|
143
|
+
const stage = mkdtempSync(join(tmpdir(), "clai-update-stage-"));
|
|
144
|
+
const identity = task.kind === "binary" ? task.destination : task.verification.file + task.verification.args.join("|");
|
|
145
|
+
const status = join(tmpdir(), `clai-update-status-${createHash("sha256").update(identity).update(stage).digest("hex").slice(0, 20)}.json`);
|
|
146
|
+
let accepted = false;
|
|
147
|
+
try {
|
|
148
|
+
const stagedTask = task.kind === "binary" ? { ...task, source: join(stage, "clai.exe") } : task;
|
|
149
|
+
if (task.kind === "binary" && stagedTask.kind === "binary")
|
|
150
|
+
copyFileSync(task.source, stagedTask.source);
|
|
151
|
+
const encoded = Buffer.from(JSON.stringify({ task: stagedTask, stage, status, pid: process.pid, lockFile: options.lockFile, lockToken: options.lockToken })).toString("base64");
|
|
152
|
+
const script = join(stage, "apply-update.ps1");
|
|
153
|
+
writeFileSync(script, windowsUpdateScript(encoded));
|
|
154
|
+
if (elevated) {
|
|
155
|
+
const argumentsText = `-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${script}"`;
|
|
156
|
+
await runUpdateCommand({ file: "powershell.exe", args: ["-NoProfile", "-NonInteractive", "-Command", `Start-Process -Verb RunAs -WindowStyle Hidden -FilePath powershell.exe -ArgumentList ${psQuote(argumentsText)}`] }, { ...options, timeoutMs: 120_000 });
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
await new Promise((resolve, reject) => {
|
|
160
|
+
const child = spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script], { detached: true, stdio: "ignore", windowsHide: true });
|
|
161
|
+
child.once("error", reject);
|
|
162
|
+
child.once("spawn", () => { child.unref(); resolve(); });
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const deadline = Date.now() + 15_000;
|
|
166
|
+
while (!existsSync(join(stage, "ready"))) {
|
|
167
|
+
throwIfCancelled(options.signal);
|
|
168
|
+
if (Date.now() >= deadline || !existsSync(stage)) {
|
|
169
|
+
const failure = existsSync(status) ? readFileSync(status, "utf8") : "worker did not acknowledge the staged update";
|
|
170
|
+
throw new Error(`could not stage Windows update: ${failure.slice(0, 500)}`);
|
|
171
|
+
}
|
|
172
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
173
|
+
}
|
|
174
|
+
throwIfCancelled(options.signal);
|
|
175
|
+
accepted = true;
|
|
176
|
+
return status;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
if (!accepted) {
|
|
180
|
+
if (existsSync(stage))
|
|
181
|
+
writeFileSync(join(stage, "cancel"), "cancel");
|
|
182
|
+
rmSync(stage, { recursive: true, force: true });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=windows-stage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-stage.js","sourceRoot":"","sources":["../../../src/commands/update/windows-stage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PerformUpdateOptions, UpdateInstallResult } from "./update/installers.js";
|
|
2
|
+
import { installDirectBinary, installViaPackageManager } from "./update/installers.js";
|
|
3
|
+
export { detectInstallMethod, resolveInstallEnv } from "./update/detection.js";
|
|
4
|
+
export type { DetectEnv } from "./update/detection.js";
|
|
2
5
|
export { DEFAULT_MIRROR_BASE, ELEVATION_TIMEOUT_MS, PACKAGE_NAME, REPO, currentPlatformTarget, downloadBinary, mirrorBaseUrl } from "./update/installers.js";
|
|
3
6
|
export { installDirectBinary, installViaPackageManager };
|
|
4
7
|
export type { DownloadProgress, InstallMethod, InstallMethodType, PerformUpdateOptions, PlatformTarget, SecretRequester, UpdateElevation, UpdateInstallResult, UpdateProgress } from "./update/installers.js";
|
|
5
|
-
export interface DetectEnv {
|
|
6
|
-
readonly argv1: string;
|
|
7
|
-
readonly execPath: string;
|
|
8
|
-
readonly platform: NodeJS.Platform;
|
|
9
|
-
readonly home: string;
|
|
10
|
-
npmRoot?: string;
|
|
11
|
-
bunRoot?: string;
|
|
12
|
-
brewPrefix?: string;
|
|
13
|
-
scoopShimsDir?: string;
|
|
14
|
-
}
|
|
15
|
-
export declare function detectInstallMethod(env: DetectEnv): InstallMethod;
|
|
16
|
-
export declare function resolveInstallEnv(): Promise<DetectEnv>;
|
|
17
8
|
export declare function performUpdate(options: PerformUpdateOptions): Promise<UpdateInstallResult>;
|