@vascend/talos 0.1.0 → 0.1.1

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.
Files changed (66) hide show
  1. package/README.md +7 -3
  2. package/dist/backend/asset-events.js +9 -9
  3. package/dist/core/agent.js +3 -3
  4. package/dist/core/cli-args.js +50 -50
  5. package/dist/core/cli-installation.d.ts +4 -0
  6. package/dist/core/cli-installation.js +55 -0
  7. package/dist/core/compaction.js +26 -26
  8. package/dist/core/config.js +101 -101
  9. package/dist/core/execution-guidance.js +21 -21
  10. package/dist/core/package-update.d.ts +3 -1
  11. package/dist/core/package-update.js +19 -6
  12. package/dist/core/self-update.d.ts +1 -1
  13. package/dist/core/signed-release.d.ts +33 -0
  14. package/dist/core/signed-release.js +121 -0
  15. package/dist/core/update-check.d.ts +1 -1
  16. package/dist/core/update-check.js +15 -14
  17. package/dist/core/vibe-modes.js +13 -13
  18. package/dist/distribution/install.d.ts +1 -0
  19. package/dist/distribution/install.js +31 -0
  20. package/dist/install.mjs +271 -0
  21. package/dist/node-runtime.json +13 -0
  22. package/dist/providers/oauth-callback-server.js +32 -32
  23. package/dist/tools/capabilities.js +30 -30
  24. package/dist/tools/computer-capture.js +50 -50
  25. package/dist/tools/program.js +82 -82
  26. package/dist/tui/i18n-catalog.js +16 -0
  27. package/dist/tui/quick-help.js +31 -31
  28. package/dist/tui/repl.js +5 -5
  29. package/dist/tui/update-prompt.js +1 -0
  30. package/dist/vascend/code-events.js +9 -9
  31. package/dist/vascend/completeness.js +31 -31
  32. package/dist/vascend/context-fabric.js +16 -16
  33. package/dist/vascend/contract-memory.js +30 -30
  34. package/dist/vascend/council.js +82 -82
  35. package/dist/vascend/decision-promotion.js +23 -23
  36. package/dist/vascend/granular-kingdom.js +17 -17
  37. package/dist/vascend/granular-launcher.js +2 -2
  38. package/dist/vascend/kingdom-kpi.js +19 -19
  39. package/dist/vascend/kingdom-run.js +6 -6
  40. package/dist/vascend/kingdom.js +56 -56
  41. package/dist/vascend/mandate.js +21 -21
  42. package/dist/vascend/objective-revision.js +34 -34
  43. package/dist/vascend/patch-plan.js +22 -22
  44. package/dist/vascend/requirements.js +29 -29
  45. package/dist/vascend/reviewer.js +26 -26
  46. package/dist/vascend/room-memory.js +25 -25
  47. package/dist/vascend/runtime.js +44 -44
  48. package/dist/vascend/self-improve.js +39 -39
  49. package/dist/vascend/test-failure-memory.js +9 -9
  50. package/dist/vascend/vision.js +18 -18
  51. package/dist/vendor/computer-use/README.md +7 -7
  52. package/dist/vendor/computer-use/computer-desktop.js +211 -211
  53. package/dist/vendor/computer-use/computer-observe.js +315 -315
  54. package/dist/vendor/computer-use/computer-scripts.js +1230 -1230
  55. package/dist/vendor/computer-use/computer-tools.js +2136 -2136
  56. package/dist/vendor/computer-use/package.json +1 -1
  57. package/dist/vendor/computer-use/rac/atomic-input.js +91 -91
  58. package/dist/vendor/computer-use/rac/grammatica.js +101 -101
  59. package/dist/vendor/computer-use/rac/parser.js +185 -185
  60. package/dist/vendor/computer-use/rac/protocol.js +136 -136
  61. package/install.ps1 +374 -30
  62. package/install.sh +356 -43
  63. package/package.json +2 -2
  64. package/dist/core/kingdoms-mode-state.d.ts +0 -24
  65. package/dist/core/kingdoms-mode-state.js +0 -139
  66. package/dist/text-sanitize.js +0 -28
package/install.ps1 CHANGED
@@ -1,30 +1,374 @@
1
- # Public entry point: https://cdn.jsdelivr.net/npm/@vascend/talos@latest/install.ps1
2
- & {
3
- $ErrorActionPreference = 'Stop'
4
- $node = Get-Command node.exe -ErrorAction SilentlyContinue
5
- $npm = Get-Command npm.cmd -ErrorAction SilentlyContinue
6
- if (-not $node -or -not $npm) {
7
- throw 'Talos requires Node.js 20 or newer (including npm). Install it from https://nodejs.org and run this command again.'
8
- }
9
- & $node.Source -e 'process.exit(Number(process.versions.node.split(String.fromCharCode(46))[0]) >= 20 ? 0 : 1)'
10
- if ($LASTEXITCODE -ne 0) { throw 'Please update Node.js to version 20 or newer.' }
11
- $talosVersion = if ($env:TALOS_VERSION) { $env:TALOS_VERSION } else { 'latest' }
12
- if ($talosVersion -notmatch '\A(?:latest|[0-9]+\.[0-9]+\.[0-9]+)\z') {
13
- throw 'TALOS_VERSION must be latest or a stable version such as 0.1.0.'
14
- }
15
- $talosPrefix = if ($env:TALOS_INSTALL_DIR) { $env:TALOS_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'Programs\Talos' }
16
- Write-Host "Installing Talos $talosVersion in $talosPrefix"
17
- & $npm.Source install --global --prefix $talosPrefix --registry=https://registry.npmjs.org "@vascend/talos@$talosVersion"
18
- if ($LASTEXITCODE -ne 0) { throw 'Talos installation failed. Check the npm output above.' }
19
- $talosEntry = Join-Path $talosPrefix 'node_modules\@vascend\talos\dist\index.js'
20
- & $node.Source $talosEntry --version
21
- if ($LASTEXITCODE -ne 0) { throw 'Talos was installed but the startup check failed.' }
22
- if ($env:TALOS_NO_MODIFY_PATH -ne '1') {
23
- $talosUserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
24
- if (($talosUserPath -split ';') -notcontains $talosPrefix) {
25
- [Environment]::SetEnvironmentVariable('Path', (([string]$talosUserPath).TrimEnd(';') + ';' + $talosPrefix).TrimStart(';'), 'User')
26
- }
27
- }
28
- if (($env:Path -split ';') -notcontains $talosPrefix) { $env:Path = "$talosPrefix;$env:Path" }
29
- Write-Host 'Talos is ready. Run talos to sign in.'
30
- }
1
+ # Generated by scripts/build-installers.mjs. Public entry: https://vascend.it/install.ps1
2
+ & {
3
+ $ErrorActionPreference = 'Stop'
4
+ $script:talosRuntimeBin = $null
5
+ function Initialize-TalosNode {
6
+ $existing = Get-Command node.exe -ErrorAction SilentlyContinue
7
+ $npm = Get-Command npm.cmd -ErrorAction SilentlyContinue
8
+ if ($env:TALOS_FORCE_BUNDLED_NODE -ne '1' -and $existing -and $npm) {
9
+ & $existing.Source -e 'process.exit(Number(process.versions.node.split(String.fromCharCode(46))[0]) >= 22 ? 0 : 1)' 2>$null
10
+ if ($LASTEXITCODE -eq 0) {
11
+ & $npm.Source --version *> $null
12
+ if ($LASTEXITCODE -eq 0) { return $existing.Source }
13
+ }
14
+ }
15
+ $architecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE }
16
+ switch ($architecture) {
17
+ 'ARM64' { $platform = 'win-arm64'; $digest = '8779b1bde1d39f8d420e3b57aa657b39891af434d3de44a919044cec06785921' }
18
+ 'AMD64' { $platform = 'win-x64'; $digest = '158f7685b44de51f6c0df1d153526cbcd3e1bc739a8dfc607721cef75de9e541' }
19
+ default { throw 'Talos requires 64-bit Windows (x64 or ARM64).' }
20
+ }
21
+ $runtimeBase = if ($env:TALOS_RUNTIME_DIR) { $env:TALOS_RUNTIME_DIR } else { Join-Path $env:LOCALAPPDATA 'Vascend\runtime' }
22
+ if ($runtimeBase -match '[;\x00-\x1f\x7f]') { throw 'Invalid Node runtime directory.' }
23
+ if (-not [IO.Path]::IsPathRooted($runtimeBase)) { $runtimeBase = Join-Path (Get-Location).Path $runtimeBase }
24
+ $runtimeBase = [IO.Path]::GetFullPath($runtimeBase)
25
+ $runtime = Join-Path $runtimeBase "node-v24.21.0-$platform"
26
+ if (-not (Test-Path -LiteralPath $runtime)) {
27
+ New-Item -ItemType Directory -Force -Path $runtimeBase | Out-Null
28
+ $stage = Join-Path $runtimeBase ('.node-download-' + [Guid]::NewGuid().ToString('N'))
29
+ New-Item -ItemType Directory -Path $stage | Out-Null
30
+ try {
31
+ Write-Host 'Installing Node.js 24.21.0 with npm for Talos...'
32
+ $archive = Join-Path $stage 'node.zip'
33
+ [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
34
+ Invoke-WebRequest -UseBasicParsing -MaximumRedirection 0 -TimeoutSec 300 -Uri "https://nodejs.org/dist/v24.21.0/node-v24.21.0-$platform.zip" -OutFile $archive
35
+ if ((Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant() -ne $digest) { throw 'Node checksum mismatch. Installation refused.' }
36
+ Expand-Archive -LiteralPath $archive -DestinationPath $stage
37
+ if (Test-Path -LiteralPath $runtime) { throw 'The Node runtime already exists. Run the installer again.' }
38
+ $expanded = Join-Path $stage "node-v24.21.0-$platform"
39
+ if (-not ([IO.Path]::GetFullPath($expanded)).StartsWith($stage + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { throw 'Invalid runtime source.' }
40
+ if (-not $runtime.StartsWith($runtimeBase + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { throw 'Invalid runtime destination.' }
41
+ Move-Item -LiteralPath $expanded -Destination $runtime
42
+ } finally {
43
+ $resolvedStage = [IO.Path]::GetFullPath($stage)
44
+ if (-not $resolvedStage.StartsWith($runtimeBase + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { throw 'Invalid temporary runtime directory.' }
45
+ Remove-Item -LiteralPath $resolvedStage -Recurse -Force
46
+ }
47
+ }
48
+ $script:talosRuntimeBin = $runtime
49
+ $env:Path = "$runtime;$env:Path"
50
+ $executable = Join-Path $runtime 'node.exe'
51
+ $reported = & $executable --version
52
+ if ($LASTEXITCODE -ne 0 -or $reported -ne 'v24.21.0' -or -not (Test-Path -LiteralPath (Join-Path $runtime 'node_modules\npm\bin\npm-cli.js'))) { throw 'The managed Node runtime is incomplete.' }
53
+ return $executable
54
+ }
55
+
56
+ function Merge-TalosPath([string]$ExistingPath, [string[]]$Directories) {
57
+ $paths = [Collections.Generic.List[string]]::new()
58
+ $seen = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
59
+ foreach ($directory in @($Directories) + @($ExistingPath -split ';')) {
60
+ if ($directory -and $seen.Add($directory.TrimEnd('\', '/'))) { $paths.Add($directory) }
61
+ }
62
+ return $paths -join ';'
63
+ }
64
+
65
+ function Update-TalosPath([string]$Prefix, [string]$RuntimeBin) {
66
+ $directories = @($Prefix, $RuntimeBin) | Where-Object { $_ }
67
+ $env:Path = Merge-TalosPath $env:Path $directories
68
+ if ($env:TALOS_NO_MODIFY_PATH -eq '1') { return }
69
+ $before = [Environment]::GetEnvironmentVariable('Path', 'User')
70
+ $after = Merge-TalosPath $before $directories
71
+ if ($after -eq $before) { return }
72
+ [Environment]::SetEnvironmentVariable('Path', $after, 'User')
73
+ # Inform Explorer so newly opened terminals can inherit the updated PATH.
74
+ try {
75
+ if (-not ('TalosInstaller.EnvironmentNotification' -as [type])) {
76
+ Add-Type -TypeDefinition @'
77
+ using System;
78
+ using System.Runtime.InteropServices;
79
+ namespace TalosInstaller {
80
+ public static class EnvironmentNotification {
81
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
82
+ public static extern IntPtr SendMessageTimeout(IntPtr window, uint message, IntPtr wParam,
83
+ string lParam, uint flags, uint timeout, out IntPtr result);
84
+ }
85
+ }
86
+ '@
87
+ }
88
+ $result = [IntPtr]::Zero
89
+ [void][TalosInstaller.EnvironmentNotification]::SendMessageTimeout([IntPtr]0xffff, 0x1a, [IntPtr]::Zero, 'Environment', 2, 1000, [ref]$result)
90
+ } catch { Write-Host 'PATH saved. Restart your terminal application if it still has the old environment.' }
91
+ }
92
+
93
+ $talosNode = Initialize-TalosNode
94
+ $env:TALOS_INSTALL_DIR = & $talosNode -p "require('node:path').resolve(process.env.TALOS_INSTALL_DIR || require('node:path').join(process.env.LOCALAPPDATA, 'Programs', 'Talos'))"
95
+ if ($LASTEXITCODE -ne 0) { throw 'Unable to resolve the Talos installation directory.' }
96
+ $talosInstaller = @'
97
+ // src/distribution/install.ts
98
+ import { join as join4 } from "node:path";
99
+ import { homedir } from "node:os";
100
+
101
+ // src/core/signed-release.ts
102
+ import { createHash, createPublicKey, verify } from "node:crypto";
103
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
104
+ import { tmpdir } from "node:os";
105
+ import { join } from "node:path";
106
+ var TALOS_DOWNLOAD_ORIGIN = "https://vascend.it";
107
+ var STABLE_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
108
+ function stableVersion(value) {
109
+ return typeof value === "string" && value.length <= 40 && STABLE_VERSION.exec(value)?.[0] === value;
110
+ }
111
+ function verifyRelease(bytes, registryKeys, options = {}) {
112
+ if (bytes.length > 64 * 1024)
113
+ throw new Error("Release metadata is too large.");
114
+ const data = JSON.parse(Buffer.from(bytes).toString("utf8"));
115
+ if (!data || data.name !== "@vascend/talos" || !stableVersion(data.version) || options.version !== undefined && data.version !== options.version)
116
+ throw new Error("Unexpected release version.");
117
+ if (typeof data.dist?.integrity !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(data.dist.integrity) || data.dist.integrity.length !== 95 || !Array.isArray(data.dist.signatures) || data.dist.signatures.length > 10)
118
+ throw new Error("Invalid npm release signature.");
119
+ const keys = registryKeys?.keys;
120
+ if (!Array.isArray(keys) || keys.length > 30)
121
+ throw new Error("Invalid npm signing keys.");
122
+ const payload = Buffer.from(`${data.name}@${data.version}:${data.dist.integrity}`);
123
+ for (const signature of data.dist.signatures) {
124
+ if (typeof signature?.sig !== "string" || signature.sig.length > 256 || typeof signature.keyid !== "string")
125
+ continue;
126
+ for (const trusted of keys) {
127
+ if (!trusted || trusted.keyid !== signature.keyid || trusted.keytype !== "ecdsa-sha2-nistp256" || trusted.scheme !== "ecdsa-sha2-nistp256" || typeof trusted.key !== "string" || trusted.key.length > 512 || trusted.expires !== null && !(Date.parse(trusted.expires) > (options.now ?? Date.now())))
128
+ continue;
129
+ try {
130
+ const key = createPublicKey({ key: Buffer.from(trusted.key, "base64"), format: "der", type: "spki" });
131
+ if (key.asymmetricKeyType === "ec" && key.asymmetricKeyDetails?.namedCurve === "prime256v1" && verify("sha256", payload, key, Buffer.from(signature.sig, "base64")))
132
+ return data;
133
+ } catch {}
134
+ }
135
+ }
136
+ throw new Error("The npm registry signature is invalid.");
137
+ }
138
+ function verifyPackage(bytes, release) {
139
+ if (`sha512-${createHash("sha512").update(bytes).digest("base64")}` !== release.dist.integrity) {
140
+ throw new Error("Release checksum does not match. Installation refused.");
141
+ }
142
+ }
143
+ async function fetchReleaseBytes(url, limit, options = {}) {
144
+ const controller = new AbortController;
145
+ const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 20000);
146
+ try {
147
+ const response = await (options.fetch ?? fetch)(url, { redirect: "error", signal: controller.signal, headers: { Accept: "application/octet-stream" } });
148
+ if (!response.ok || !response.body) {
149
+ await response.body?.cancel();
150
+ throw new Error("Release download is unavailable.");
151
+ }
152
+ if (Number(response.headers.get("content-length")) > limit) {
153
+ await response.body.cancel();
154
+ throw new Error("Release download is too large.");
155
+ }
156
+ const reader = response.body.getReader();
157
+ const chunks = [];
158
+ let length = 0;
159
+ try {
160
+ for (;; ) {
161
+ const { done, value } = await reader.read();
162
+ if (done)
163
+ break;
164
+ length += value.length;
165
+ if (length > limit)
166
+ throw new Error("Release download is too large.");
167
+ chunks.push(value);
168
+ }
169
+ } finally {
170
+ await reader.cancel();
171
+ }
172
+ return Buffer.concat(chunks);
173
+ } finally {
174
+ clearTimeout(timer);
175
+ }
176
+ }
177
+ async function fetchSignedRelease(version = "latest", options = {}) {
178
+ if (version !== "latest" && !stableVersion(version))
179
+ throw new Error("Invalid Talos version.");
180
+ const [metadata, keys] = await Promise.all([
181
+ fetchReleaseBytes(`https://registry.npmjs.org/@vascend%2ftalos/${version}`, 64 * 1024, options),
182
+ fetchReleaseBytes("https://registry.npmjs.org/-/npm/v1/keys", 64 * 1024, options)
183
+ ]);
184
+ return verifyRelease(metadata, JSON.parse(keys.toString("utf8")), version === "latest" ? {} : { version });
185
+ }
186
+ async function downloadVerifiedPackage(version, options = {}) {
187
+ const release = await fetchSignedRelease(version, options);
188
+ const filename = `vascend-talos-${release.version}.tgz`;
189
+ let bytes;
190
+ try {
191
+ bytes = await fetchReleaseBytes(`${TALOS_DOWNLOAD_ORIGIN}/talos/releases/${release.version}/${filename}`, 32 * 1024 * 1024, options);
192
+ verifyPackage(bytes, release);
193
+ } catch {
194
+ bytes = await fetchReleaseBytes(`https://registry.npmjs.org/@vascend/talos/-/talos-${release.version}.tgz`, 32 * 1024 * 1024, options);
195
+ verifyPackage(bytes, release);
196
+ }
197
+ const directory = await mkdtemp(join(tmpdir(), "talos-verified-"));
198
+ const dispose = () => rm(directory, { recursive: true, force: true });
199
+ try {
200
+ const path = join(directory, filename);
201
+ await writeFile(path, bytes, { flag: "wx", mode: 384 });
202
+ return { path, dispose };
203
+ } catch (error) {
204
+ await dispose();
205
+ throw error;
206
+ }
207
+ }
208
+
209
+ // src/core/package-update.ts
210
+ import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
211
+ import { delimiter, dirname as dirname2, join as join3 } from "node:path";
212
+
213
+ // src/core/update-process.ts
214
+ import { spawn } from "node:child_process";
215
+ var runUpdateCommand = (command) => new Promise((resolve, reject) => {
216
+ const child = spawn(command.command, [...command.args], {
217
+ cwd: command.cwd,
218
+ env: command.env,
219
+ shell: false,
220
+ windowsHide: true,
221
+ stdio: command.inherit ? "inherit" : ["ignore", "pipe", "pipe"],
222
+ timeout: command.timeoutMs
223
+ });
224
+ let output = "";
225
+ let failed = false;
226
+ const collect = (data) => {
227
+ output += data.toString();
228
+ if (output.length > 2000000) {
229
+ failed = true;
230
+ child.kill();
231
+ reject(new Error("Command output exceeded limit"));
232
+ }
233
+ };
234
+ child.stdout?.on("data", collect);
235
+ child.stderr?.resume();
236
+ child.on("error", reject);
237
+ child.on("close", (code, signal) => {
238
+ if (failed)
239
+ return;
240
+ if (code === 0 && !signal)
241
+ resolve(output.trim());
242
+ else
243
+ reject(new Error(`${command.command} exited with ${signal ?? code}`));
244
+ });
245
+ });
246
+
247
+ // src/core/cli-installation.ts
248
+ import { existsSync, lstatSync, readFileSync, realpathSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
249
+ import { dirname, join as join2, resolve } from "node:path";
250
+ function installationPrefix(value) {
251
+ const prefix = resolve(value);
252
+ if (/[\x00-\x1f\x7f]/.test(prefix) || prefix.includes(process.platform === "win32" ? ";" : ":")) {
253
+ throw new Error("The installation directory cannot be represented safely in PATH.");
254
+ }
255
+ return prefix;
256
+ }
257
+ function windowsCliShim() {
258
+ return `@echo off\r
259
+ "%~dp0.talos-runtime\\node.exe" "%~dp0node_modules\\@vascend\\talos\\dist\\index.js" %*\r
260
+ `;
261
+ }
262
+ function finalizeCliInstallation(root, version) {
263
+ const pkg = JSON.parse(readFileSync(join2(root, "package.json"), "utf8"));
264
+ if (pkg.name !== "@vascend/talos" || pkg.version !== version)
265
+ throw new Error("Installed Talos version differs from the requested release.");
266
+ if (process.platform !== "win32")
267
+ return;
268
+ const modules = dirname(dirname(root));
269
+ if (dirname(root).split(/[\\/]/).pop() !== "@vascend" || modules.split(/[\\/]/).pop() !== "node_modules")
270
+ return;
271
+ const prefix = dirname(modules);
272
+ const belongsToTalos = (file) => {
273
+ if (!existsSync(file))
274
+ return false;
275
+ const info = lstatSync(file);
276
+ return info.isFile() && !info.isSymbolicLink() && info.size < 16384 && /node_modules[\\/]@vascend[\\/]talos[\\/]dist[\\/]index\.js/i.test(readFileSync(file, "utf8"));
277
+ };
278
+ for (const alias of ["talos", "horizon"]) {
279
+ const cmd = join2(prefix, `${alias}.cmd`);
280
+ if (!belongsToTalos(cmd))
281
+ continue;
282
+ if (!process.versions.bun) {
283
+ const runtime = join2(prefix, ".talos-runtime");
284
+ if (existsSync(runtime)) {
285
+ if (!lstatSync(runtime).isSymbolicLink())
286
+ throw new Error("The Talos runtime link is occupied by a regular directory.");
287
+ if (realpathSync(runtime).toLowerCase() !== realpathSync(dirname(process.execPath)).toLowerCase())
288
+ unlinkSync(runtime);
289
+ }
290
+ if (!existsSync(runtime))
291
+ symlinkSync(dirname(process.execPath), runtime, "junction");
292
+ writeFileSync(cmd, windowsCliShim());
293
+ }
294
+ const ps1 = join2(prefix, `${alias}.ps1`);
295
+ if (belongsToTalos(ps1))
296
+ unlinkSync(ps1);
297
+ }
298
+ }
299
+
300
+ // src/core/package-update.ts
301
+ var REGISTRY = "https://registry.npmjs.org";
302
+ function managerCommand(manager, env) {
303
+ if (process.platform !== "win32")
304
+ return { command: manager, args: [] };
305
+ const path = Object.entries(env).find(([key]) => key.toLowerCase() === "path")?.[1] ?? "";
306
+ const directories = path.split(delimiter).filter(Boolean).map((directory) => directory.replace(/^"|"$/g, ""));
307
+ const node = process.versions.bun ? directories.map((directory) => join3(directory, "node.exe")).find((file) => existsSync2(file)) : process.execPath;
308
+ for (const directory of directories) {
309
+ const exe = join3(directory, `${manager}.exe`);
310
+ if (existsSync2(exe))
311
+ return { command: exe, args: [] };
312
+ const scripts = {
313
+ npm: ["npm/bin/npm-cli.js"],
314
+ pnpm: ["pnpm/bin/pnpm.cjs", "corepack/dist/pnpm.js"],
315
+ yarn: ["yarn/bin/yarn.js", "corepack/dist/yarn.js"]
316
+ };
317
+ if (manager !== "bun")
318
+ for (const script of scripts[manager]) {
319
+ const file = join3(directory, "node_modules", script);
320
+ if (node && existsSync2(file))
321
+ return { command: node, args: [file] };
322
+ }
323
+ }
324
+ return null;
325
+ }
326
+ function packageUpdateArgs(manager, target, prefix) {
327
+ const security = ["--ignore-scripts", `--registry=${REGISTRY}`];
328
+ if (manager === "npm")
329
+ return ["install", "--global", target, ...security, "--no-audit", "--no-fund", ...prefix ? ["--prefix", prefix] : []];
330
+ if (manager === "yarn")
331
+ return ["global", "add", target, ...security];
332
+ return ["add", "--global", target, ...security];
333
+ }
334
+
335
+ // src/distribution/install.ts
336
+ async function install() {
337
+ if (Number(process.versions.node.split(".")[0]) < 20)
338
+ throw new Error("Talos requires Node.js 20 or newer, including npm: https://nodejs.org");
339
+ const npm = managerCommand("npm", process.env);
340
+ if (!npm)
341
+ throw new Error("npm is missing. Install Node.js with npm from https://nodejs.org");
342
+ const version = process.env.TALOS_VERSION || "latest";
343
+ const release = await fetchSignedRelease(version);
344
+ const prefix = installationPrefix(process.env.TALOS_INSTALL_DIR || (process.platform === "win32" ? join4(process.env.LOCALAPPDATA || join4(homedir(), "AppData", "Local"), "Programs", "Talos") : join4(homedir(), ".local")));
345
+ console.log(`Installing Talos ${release.version} in ${prefix}`);
346
+ const artifact = await downloadVerifiedPackage(release.version);
347
+ try {
348
+ await runUpdateCommand({
349
+ ...npm,
350
+ args: [...npm.args, ...packageUpdateArgs("npm", artifact.path, prefix)],
351
+ cwd: homedir(),
352
+ env: process.env,
353
+ inherit: true,
354
+ timeoutMs: 300000
355
+ });
356
+ const entry = join4(prefix, ...process.platform === "win32" ? [] : ["lib"], "node_modules", "@vascend", "talos", "dist", "index.js");
357
+ finalizeCliInstallation(join4(prefix, ...process.platform === "win32" ? [] : ["lib"], "node_modules", "@vascend", "talos"), release.version);
358
+ await runUpdateCommand({ command: process.execPath, args: [entry, "--version"], cwd: homedir(), env: process.env, inherit: true, timeoutMs: 1e4 });
359
+ console.log("Talos installed. npm registry signature and SHA-512 verified.");
360
+ } finally {
361
+ await artifact.dispose();
362
+ }
363
+ }
364
+ install().catch((error) => {
365
+ console.error(error instanceof Error ? error.message : "Installation failed.");
366
+ process.exitCode = 1;
367
+ });
368
+
369
+ '@
370
+ $talosInstaller | & $talosNode --input-type=module -
371
+ if ($LASTEXITCODE -ne 0) { throw 'Talos installation failed. See the error above.' }
372
+ Update-TalosPath $env:TALOS_INSTALL_DIR $script:talosRuntimeBin
373
+ Write-Host 'Talos is ready. Run talos to sign in.'
374
+ }