@vantaloom/runtime-win32-x64 0.2.0 → 0.4.0

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 (35) hide show
  1. package/VERSION +1 -1
  2. package/bin/easytier-cli.exe +0 -0
  3. package/bin/easytier-core.exe +0 -0
  4. package/bin/vantaloom-agent.exe +0 -0
  5. package/bin/vantaloom-api.exe +0 -0
  6. package/bin/vantaloom-tray.exe +0 -0
  7. package/bin/vantaloomctl.exe +0 -0
  8. package/bin/wintun.dll +0 -0
  9. package/cli/package.json +1 -1
  10. package/cli/src/cli.mjs +344 -23
  11. package/manifest.json +2 -2
  12. package/package.json +1 -1
  13. package/web/404.html +1 -1
  14. package/web/__next.__PAGE__.txt +2 -2
  15. package/web/__next._full.txt +3 -3
  16. package/web/__next._head.txt +1 -1
  17. package/web/__next._index.txt +2 -2
  18. package/web/__next._tree.txt +2 -2
  19. package/web/_next/static/chunks/73d2c788f1076e9a.css +2 -0
  20. package/web/_next/static/chunks/80b4a364458ec11d.js +52 -0
  21. package/web/_not-found/__next._full.txt +2 -2
  22. package/web/_not-found/__next._head.txt +1 -1
  23. package/web/_not-found/__next._index.txt +2 -2
  24. package/web/_not-found/__next._not-found/__PAGE__.txt +1 -1
  25. package/web/_not-found/__next._not-found.txt +1 -1
  26. package/web/_not-found/__next._tree.txt +2 -2
  27. package/web/_not-found.html +1 -1
  28. package/web/_not-found.txt +2 -2
  29. package/web/index.html +1 -31
  30. package/web/index.txt +3 -3
  31. package/web/_next/static/chunks/1da7f8d27cd96c86.js +0 -52
  32. package/web/_next/static/chunks/c0c4db6d45c7ff65.css +0 -2
  33. /package/web/_next/static/{qDb937Fsr8zR_VHDxrNf_ → E6VnJNHPIVhiQoKxBWUU2}/_buildManifest.js +0 -0
  34. /package/web/_next/static/{qDb937Fsr8zR_VHDxrNf_ → E6VnJNHPIVhiQoKxBWUU2}/_clientMiddlewareManifest.json +0 -0
  35. /package/web/_next/static/{qDb937Fsr8zR_VHDxrNf_ → E6VnJNHPIVhiQoKxBWUU2}/_ssgManifest.js +0 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9bcdf40
1
+ 532507a
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/bin/wintun.dll ADDED
Binary file
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantaloom/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Vantaloom local runtime manager.",
package/cli/src/cli.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { execFileSync, spawnSync } from "node:child_process"
2
2
  import {
3
+ appendFileSync,
3
4
  chmodSync,
4
5
  existsSync,
5
6
  mkdirSync,
@@ -20,11 +21,45 @@ const installedConfigPath = path.join(cliRoot, "config.json")
20
21
  const defaultReleaseTag = "runtime-latest"
21
22
  const defaultRepo = "Timefiles404/Vantaloom-next"
22
23
  const defaultNpmRegistry = "https://registry.npmjs.org"
24
+ const fallbackNpmRegistries = [
25
+ "https://registry.npmmirror.com",
26
+ ]
27
+
28
+ // Inherit strict-ssl=false from npm/npx config, or respect NODE_TLS_REJECT_UNAUTHORIZED.
29
+ // When npm runs us via npx with strict-ssl disabled, it sets npm_config_strict_ssl="false".
30
+ // Also check user .npmrc for strict-ssl=false (common in China behind proxies).
31
+ function shouldDisableTLS() {
32
+ if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === "0") return true
33
+ if (process.env.npm_config_strict_ssl === "false") return true
34
+ if (process.env.npm_config_strict_ssl === "") return true
35
+ try {
36
+ const npmrcPath = path.join(os.homedir(), ".npmrc")
37
+ if (existsSync(npmrcPath)) {
38
+ const content = readFileSync(npmrcPath, "utf8")
39
+ if (/^\s*strict-ssl\s*=\s*false/m.test(content)) return true
40
+ }
41
+ } catch {}
42
+ return false
43
+ }
44
+ if (shouldDisableTLS()) {
45
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
46
+ }
47
+
48
+ const cliVersion = readJSONIfExists(path.join(cliRoot, "package.json")).version ?? "unknown"
23
49
 
24
50
  export async function main(argv) {
25
51
  const command = argv[0] ?? "help"
26
52
  const options = parseOptions(argv.slice(1))
27
53
 
54
+ // --no-strict-ssl flag disables TLS certificate verification for fetch calls
55
+ if (options.noStrictSsl) {
56
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
57
+ }
58
+
59
+ if (command === "install" || command === "update") {
60
+ console.log(`vantaloom-cli v${cliVersion} (${platformId()})`)
61
+ }
62
+
28
63
  switch (command) {
29
64
  case "install":
30
65
  if (options.package) {
@@ -91,6 +126,7 @@ async function installFromSource(options) {
91
126
 
92
127
  console.log(`${options.update ? "updated" : "installed"} Vantaloom: ${prefix}`)
93
128
  console.log(`version: ${version}`)
129
+ ensureInPath(prefix)
94
130
  console.log(`run: ${displayCommand(prefix)} status`)
95
131
  }
96
132
 
@@ -104,6 +140,7 @@ async function installFromPackage(options) {
104
140
 
105
141
  console.log(`${options.update ? "updated" : "installed"} Vantaloom: ${prefix}`)
106
142
  console.log(`version: ${version}`)
143
+ ensureInPath(prefix)
107
144
  console.log(`run: ${displayCommand(prefix)} status`)
108
145
  }
109
146
 
@@ -159,6 +196,9 @@ async function buildRuntimePackage(sourceRoot, packageRoot, options) {
159
196
  } catch { /* optional: skip if systray build fails */ }
160
197
  }
161
198
 
199
+ // Bundle the EasyTier mesh binaries (P2P virtual network) for the target platform.
200
+ await copyEasyTier(sourceRoot, buildBin, platform)
201
+
162
202
  if (options.buildWeb) {
163
203
  runPnpm(["--filter", "vantaloom-app", "build"], { cwd: sourceRoot })
164
204
  }
@@ -170,6 +210,41 @@ async function buildRuntimePackage(sourceRoot, packageRoot, options) {
170
210
  return { platform, version }
171
211
  }
172
212
 
213
+ // copyEasyTier bundles the vendored EasyTier binaries (easytier-core/easytier-cli,
214
+ // plus wintun.dll on Windows) for the target platform into the package bin/ dir.
215
+ async function copyEasyTier(sourceRoot, buildBin, platform) {
216
+ const vendorMap = {
217
+ "win32-x64": "windows-x86_64",
218
+ "darwin-arm64": "macos-aarch64",
219
+ "linux-x64": "linux-x86_64",
220
+ }
221
+ const vendorName = vendorMap[platform]
222
+ if (!vendorName) {
223
+ console.warn(` warning: no EasyTier mapping for ${platform}; mesh disabled for this platform`)
224
+ return
225
+ }
226
+ const srcDir = path.join(sourceRoot, "vendor", "easytier", vendorName, `easytier-${vendorName}`)
227
+ if (!existsSync(srcDir)) {
228
+ console.warn(` warning: EasyTier binaries not found at ${srcDir}; run vendor download first`)
229
+ return
230
+ }
231
+ const isWin = platform.startsWith("win32")
232
+ const files = isWin
233
+ ? ["easytier-core.exe", "easytier-cli.exe", "wintun.dll"]
234
+ : ["easytier-core", "easytier-cli"]
235
+ let copied = 0
236
+ for (const f of files) {
237
+ const src = path.join(srcDir, f)
238
+ if (!existsSync(src)) {
239
+ console.warn(` warning: EasyTier file missing: ${f}`)
240
+ continue
241
+ }
242
+ await cp(src, path.join(buildBin, f), { force: true })
243
+ copied++
244
+ }
245
+ console.log(` bundled EasyTier ${vendorName} (${copied} files)`)
246
+ }
247
+
173
248
  async function applyPackage(packageRoot, prefix, options) {
174
249
  assertRuntimePackage(packageRoot)
175
250
 
@@ -186,15 +261,49 @@ async function applyPackage(packageRoot, prefix, options) {
186
261
  spawnSync(existingCtl, ["stop", "--prefix", prefix], { stdio: "inherit" })
187
262
  }
188
263
 
264
+ // Kill lingering tray process that may hold locks on bin/ (older versions
265
+ // don't write tray.pid, so vantaloomctl stop won't find them).
266
+ killTrayProcess(prefix)
267
+
268
+ // Copy package contents to install prefix
189
269
  for (const name of ["bin", "web", "cli"]) {
190
- removeKnownPath(path.join(prefix, name), prefix)
191
- await cp(path.join(packageRoot, name), path.join(prefix, name), {
270
+ const src = path.join(packageRoot, name)
271
+ const dst = path.join(prefix, name)
272
+ if (!existsSync(src)) {
273
+ console.error(` warning: package missing ${name}/ directory`)
274
+ continue
275
+ }
276
+ removeKnownPath(dst, prefix)
277
+ await cp(src, dst, {
192
278
  recursive: true,
193
279
  force: true,
194
280
  dereference: false,
195
281
  })
196
282
  }
197
283
 
284
+ // Ensure binaries are executable on Unix (cross-compiled from Windows they lose +x)
285
+ const binDir = path.join(prefix, "bin")
286
+ if (process.platform !== "win32" && existsSync(binDir)) {
287
+ for (const entry of readdirSync(binDir)) {
288
+ const binPath = path.join(binDir, entry)
289
+ try { chmodSync(binPath, 0o755) } catch {}
290
+ }
291
+ }
292
+
293
+ // Verify vantaloomctl binary exists before trying to run it
294
+ const ctlBin = path.join(prefix, "bin", binaryName("vantaloomctl"))
295
+ if (!existsSync(ctlBin)) {
296
+ const binContents = existsSync(binDir) ? readdirSync(binDir) : []
297
+ const srcBinContents = existsSync(path.join(packageRoot, "bin")) ? readdirSync(path.join(packageRoot, "bin")) : []
298
+ throw new Error(
299
+ `vantaloomctl binary not found at ${ctlBin}\n` +
300
+ ` installed bin/: [${binContents.join(", ")}]\n` +
301
+ ` package bin/: [${srcBinContents.join(", ")}]\n` +
302
+ ` platform: ${platformId()}\n` +
303
+ ` This may indicate a corrupt download. Try again or install from source.`
304
+ )
305
+ }
306
+
198
307
  await writeLauncher(prefix)
199
308
  await writeText(path.join(prefix, "cli", "config.json"), `${JSON.stringify(mergedConfig, null, 2)}\n`)
200
309
  await writeText(path.join(prefix, "VERSION"), `${version}\n`)
@@ -202,7 +311,7 @@ async function applyPackage(packageRoot, prefix, options) {
202
311
  force: true,
203
312
  })
204
313
 
205
- run(path.join(prefix, "bin", binaryName("vantaloomctl")), [
314
+ run(ctlBin, [
206
315
  "install",
207
316
  "--prefix",
208
317
  prefix,
@@ -211,7 +320,7 @@ async function applyPackage(packageRoot, prefix, options) {
211
320
  ])
212
321
 
213
322
  if (!options.noStart) {
214
- run(path.join(prefix, "bin", binaryName("vantaloomctl")), [
323
+ run(ctlBin, [
215
324
  "start",
216
325
  "--prefix",
217
326
  prefix,
@@ -224,9 +333,13 @@ async function applyPackage(packageRoot, prefix, options) {
224
333
  async function syncFromNpmRegistry(options, action) {
225
334
  const prefix = safeDirectory(options.prefix ?? defaultPrefix())
226
335
  const installedConfig = readInstalledConfig(prefix)
227
- const runtimePackage = options.runtimePackage || installedConfig.runtimePackage || runtimePackageName(platformId())
336
+ // Always derive runtimePackage from current platform — never trust stale config
337
+ // from a different platform (e.g. win32 config baked into a darwin package).
338
+ // Only explicit --runtime-package flag can override.
339
+ const runtimePackage = options.runtimePackage || runtimePackageName(platformId())
228
340
  const runtimeVersion = options.runtimeVersion || installedConfig.runtimeVersion || "latest"
229
- const registry = normalizeRegistry(options.npmRegistry || installedConfig.npmRegistry || defaultNpmRegistry)
341
+ const explicitRegistry = options.npmRegistry || installedConfig.npmRegistry
342
+ const registry = normalizeRegistry(explicitRegistry || detectNpmRegistry() || defaultNpmRegistry)
230
343
  const tempRoot = mkdtempSync(path.join(os.tmpdir(), "vantaloom-npm-"))
231
344
 
232
345
  try {
@@ -234,7 +347,11 @@ async function syncFromNpmRegistry(options, action) {
234
347
  const archive = path.join(tempRoot, `${packageBasename(runtimePackage)}-${runtimeVersion}.tgz`)
235
348
  mkdirSync(extractRoot, { recursive: true })
236
349
 
237
- const resolved = await resolveNpmPackage({ registry, name: runtimePackage, version: runtimeVersion })
350
+ const resolved = await resolveNpmPackageWithFallback({
351
+ registries: explicitRegistry ? [registry] : [registry, ...fallbackNpmRegistries.map(normalizeRegistry)],
352
+ name: runtimePackage,
353
+ version: runtimeVersion,
354
+ })
238
355
  await downloadNpmTarball({
239
356
  tarballUrl: resolved.tarball,
240
357
  target: archive,
@@ -248,13 +365,15 @@ async function syncFromNpmRegistry(options, action) {
248
365
  noStart: options.noStart,
249
366
  runtimePackage,
250
367
  runtimeVersion: options.runtimeVersion ? resolved.version : "latest",
251
- npmRegistry: registry,
368
+ npmRegistry: resolved.registry,
252
369
  update: action === "update",
253
370
  })
254
371
 
255
372
  console.log(`${action === "update" ? "updated" : "installed"} Vantaloom: ${prefix}`)
256
373
  console.log(`version: ${version}`)
257
374
  console.log(`source: ${runtimePackage}@${resolved.version}`)
375
+ console.log(`registry: ${resolved.registry}`)
376
+ ensureInPath(prefix)
258
377
  console.log(`run: ${displayCommand(prefix)} status`)
259
378
  } finally {
260
379
  removeKnownPath(tempRoot, os.tmpdir())
@@ -296,6 +415,7 @@ async function syncFromRelease(options, action) {
296
415
  console.log(`${action === "update" ? "updated" : "installed"} Vantaloom: ${prefix}`)
297
416
  console.log(`version: ${version}`)
298
417
  console.log(`source: ${repo}@${releaseTag}`)
418
+ ensureInPath(prefix)
299
419
  console.log(`run: ${displayCommand(prefix)} status`)
300
420
  } finally {
301
421
  removeKnownPath(tempRoot, os.tmpdir())
@@ -346,14 +466,114 @@ async function downloadReleaseAsset({ repo, releaseTag, assetName, target, token
346
466
  await writeFile(target, buffer)
347
467
  }
348
468
 
469
+ function detectNpmRegistry() {
470
+ // 1. NPM_CONFIG_REGISTRY env var (highest priority, set by npm/npx when running)
471
+ if (process.env.NPM_CONFIG_REGISTRY) {
472
+ return process.env.npm_config_registry || process.env.NPM_CONFIG_REGISTRY
473
+ }
474
+ // npm also sets the lowercase variant
475
+ if (process.env.npm_config_registry) {
476
+ return process.env.npm_config_registry
477
+ }
478
+
479
+ // 2. Read user .npmrc
480
+ try {
481
+ const npmrcPaths = [
482
+ path.join(os.homedir(), ".npmrc"),
483
+ ]
484
+ // Also check project-level .npmrc
485
+ const localNpmrc = path.resolve(".npmrc")
486
+ if (localNpmrc !== npmrcPaths[0]) {
487
+ npmrcPaths.unshift(localNpmrc)
488
+ }
489
+ for (const npmrcPath of npmrcPaths) {
490
+ if (existsSync(npmrcPath)) {
491
+ const content = readFileSync(npmrcPath, "utf8")
492
+ const match = content.match(/^\s*registry\s*=\s*(.+)/m)
493
+ if (match) {
494
+ return match[1].trim()
495
+ }
496
+ }
497
+ }
498
+ } catch {
499
+ // Ignore .npmrc read errors
500
+ }
501
+
502
+ return ""
503
+ }
504
+
505
+ async function resolveNpmPackageWithFallback({ registries, name, version }) {
506
+ const errors = []
507
+ for (const registry of registries) {
508
+ try {
509
+ const result = await resolveNpmPackage({ registry, name, version })
510
+ return { ...result, registry }
511
+ } catch (error) {
512
+ const causeCode = error?.cause?.code || ""
513
+ const isNetworkError = causeCode === "ECONNREFUSED"
514
+ || causeCode === "ENOTFOUND"
515
+ || causeCode === "ETIMEDOUT"
516
+ || causeCode === "ECONNRESET"
517
+ || causeCode === "UND_ERR_CONNECT_TIMEOUT"
518
+ || (error instanceof TypeError && error.message === "fetch failed")
519
+ const isSslError = causeCode === "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
520
+ || causeCode === "CERT_HAS_EXPIRED"
521
+ || causeCode === "DEPTH_ZERO_SELF_SIGNED_CERT"
522
+ || causeCode === "SELF_SIGNED_CERT_IN_CHAIN"
523
+ || causeCode === "ERR_TLS_CERT_ALTNAME_INVALID"
524
+ const isRetryable = isNetworkError || isSslError
525
+ errors.push({ registry, error, isRetryable, isSslError })
526
+
527
+ if (isRetryable && registries.length > 1) {
528
+ const hint = isSslError ? " (SSL certificate error)" : ""
529
+ console.error(`vantaloom: ${registry} unreachable${hint}, trying next registry...`)
530
+ continue
531
+ }
532
+ if (isSslError) {
533
+ throw new Error(
534
+ `SSL certificate error connecting to ${registry}: ${causeCode}\n` +
535
+ ` Fix: run with --no-strict-ssl, or set npm config: npm config set strict-ssl false`
536
+ )
537
+ }
538
+ // Non-network error (404, parse error, etc.) — don't try fallbacks
539
+ throw error
540
+ }
541
+ }
542
+
543
+ // All registries failed
544
+ const hasSslError = errors.some((e) => e.isSslError)
545
+ const tried = errors.map((e) => e.registry).join(", ")
546
+ const sslHint = hasSslError
547
+ ? `\n SSL fix: run with --no-strict-ssl, or set npm config: npm config set strict-ssl false`
548
+ : ""
549
+ throw new Error(
550
+ `all registries unreachable (tried: ${tried}). ` +
551
+ `Check your network or specify --npm-registry <url>${sslHint}`
552
+ )
553
+ }
554
+
349
555
  async function resolveNpmPackage({ registry, name, version }) {
350
556
  const metadataUrl = `${registry}/${encodeURIComponent(name).replace("%2F", "%2f")}`
351
- const response = await fetch(metadataUrl, {
352
- headers: {
353
- Accept: "application/vnd.npm.install-v1+json",
354
- "User-Agent": "vantaloom-cli",
355
- },
356
- })
557
+ let response
558
+ try {
559
+ response = await fetch(metadataUrl, {
560
+ headers: {
561
+ Accept: "application/vnd.npm.install-v1+json",
562
+ "User-Agent": "vantaloom-cli",
563
+ },
564
+ signal: AbortSignal.timeout(15000),
565
+ })
566
+ } catch (error) {
567
+ if (error instanceof TypeError && error.message === "fetch failed") {
568
+ const causeCode = error.cause?.code || ""
569
+ const causeMsg = causeCode || error.cause?.message || String(error.cause || "")
570
+ throw Object.assign(
571
+ new Error(`cannot reach registry ${registry} (${causeMsg})`),
572
+ { cause: error.cause }
573
+ )
574
+ }
575
+ throw error
576
+ }
357
577
  if (!response.ok) {
358
578
  const detail = await response.text().catch(() => "")
359
579
  throw new Error(`failed to inspect npm package ${name}: HTTP ${response.status}${detail ? ` ${detail.slice(0, 200)}` : ""}`)
@@ -373,11 +593,22 @@ async function resolveNpmPackage({ registry, name, version }) {
373
593
  }
374
594
 
375
595
  async function downloadNpmTarball({ tarballUrl, target, packageName, version }) {
376
- const response = await fetch(tarballUrl, {
377
- headers: {
378
- "User-Agent": "vantaloom-cli",
379
- },
380
- })
596
+ console.log(` downloading ${packageName}@${version}...`)
597
+ let response
598
+ try {
599
+ response = await fetch(tarballUrl, {
600
+ headers: {
601
+ "User-Agent": "vantaloom-cli",
602
+ },
603
+ signal: AbortSignal.timeout(120000),
604
+ })
605
+ } catch (error) {
606
+ const causeCode = error?.cause?.code || ""
607
+ const causeMsg = causeCode || error?.cause?.message || error.message || ""
608
+ const isSsl = causeCode.includes("CERT") || causeCode === "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
609
+ const hint = isSsl ? `\n Fix: run with --no-strict-ssl` : ""
610
+ throw new Error(`failed to download ${packageName}@${version} from ${tarballUrl}: ${causeMsg}${hint}`)
611
+ }
381
612
  if (!response.ok) {
382
613
  const detail = await response.text().catch(() => "")
383
614
  throw new Error(`failed to download ${packageName}@${version}: HTTP ${response.status}${detail ? ` ${detail.slice(0, 200)}` : ""}`)
@@ -385,6 +616,7 @@ async function downloadNpmTarball({ tarballUrl, target, packageName, version })
385
616
 
386
617
  const buffer = Buffer.from(await response.arrayBuffer())
387
618
  await writeFile(target, buffer)
619
+ console.log(` downloaded ${(buffer.length / 1024 / 1024).toFixed(1)} MB`)
388
620
  }
389
621
 
390
622
  function shouldUseSourceInstall(options) {
@@ -448,9 +680,9 @@ function mergeRuntimeConfig(packageConfig, existingConfig, overrides) {
448
680
  if (!merged.releaseTag) {
449
681
  merged.releaseTag = defaultReleaseTag
450
682
  }
451
- if (!merged.runtimePackage) {
452
- merged.runtimePackage = runtimePackageName(platformId())
453
- }
683
+ // Always force runtimePackage to match the running platform — a cross-compiled
684
+ // package may carry a config for a different platform (e.g. win32 inside darwin).
685
+ merged.runtimePackage = runtimePackageName(platformId())
454
686
  if (!merged.runtimeVersion) {
455
687
  merged.runtimeVersion = "latest"
456
688
  }
@@ -470,7 +702,7 @@ function runtimeConfigFromSource(sourceRoot) {
470
702
  releaseTag: defaultReleaseTag,
471
703
  runtimePackage: runtimePackageName(platformId()),
472
704
  runtimeVersion: "latest",
473
- npmRegistry: defaultNpmRegistry,
705
+ npmRegistry: detectNpmRegistry() || defaultNpmRegistry,
474
706
  }
475
707
  }
476
708
 
@@ -776,6 +1008,9 @@ function parseOptions(args) {
776
1008
  case "local":
777
1009
  options.local = true
778
1010
  break
1011
+ case "no-strict-ssl":
1012
+ options.noStrictSsl = true
1013
+ break
779
1014
  default:
780
1015
  throw new Error(`unknown option --${key}`)
781
1016
  }
@@ -897,6 +1132,92 @@ async function writeText(filePath, content) {
897
1132
  await writeFile(filePath, content)
898
1133
  }
899
1134
 
1135
+ // ensureInPath adds the Vantaloom install directory to the user's shell PATH
1136
+ // on macOS and Linux, so `vantaloom` can be run directly after install.
1137
+ // On Windows this is not needed (vantaloom.cmd is run by full path or added via installer).
1138
+ function ensureInPath(prefix) {
1139
+ if (process.platform === "win32") return
1140
+
1141
+ // Check if already in PATH
1142
+ const pathDirs = (process.env.PATH || "").split(":")
1143
+ if (pathDirs.includes(prefix)) return
1144
+
1145
+ // Determine shell profile file
1146
+ const home = os.homedir()
1147
+ const shell = process.env.SHELL || ""
1148
+ let profilePath
1149
+ if (shell.endsWith("/zsh") || existsSync(path.join(home, ".zshrc"))) {
1150
+ profilePath = path.join(home, ".zshrc")
1151
+ } else if (shell.endsWith("/bash")) {
1152
+ // On macOS, bash uses .bash_profile; on Linux, .bashrc
1153
+ profilePath = process.platform === "darwin"
1154
+ ? path.join(home, ".bash_profile")
1155
+ : path.join(home, ".bashrc")
1156
+ } else if (existsSync(path.join(home, ".profile"))) {
1157
+ profilePath = path.join(home, ".profile")
1158
+ } else {
1159
+ profilePath = path.join(home, ".profile")
1160
+ }
1161
+
1162
+ // Use $HOME-relative path for portability
1163
+ const homeRelative = prefix.startsWith(home)
1164
+ ? `$HOME${prefix.slice(home.length)}`
1165
+ : prefix
1166
+ const exportLine = `export PATH="${homeRelative}:$PATH"`
1167
+ const marker = "# vantaloom"
1168
+
1169
+ // Check if already added to profile
1170
+ try {
1171
+ if (existsSync(profilePath)) {
1172
+ const content = readFileSync(profilePath, "utf8")
1173
+ if (content.includes("vantaloom") && content.includes("PATH")) return
1174
+ }
1175
+ } catch {}
1176
+
1177
+ // Append to profile
1178
+ try {
1179
+ const entry = `\n${marker}\n${exportLine}\n`
1180
+ appendFileSync(profilePath, entry)
1181
+ console.log(`PATH: added ${prefix} to ${profilePath}`)
1182
+ console.log(` run: source ${profilePath} (or open a new terminal)`)
1183
+ } catch (error) {
1184
+ console.log(`PATH: could not update ${profilePath}: ${error.message}`)
1185
+ console.log(` add manually: ${exportLine}`)
1186
+ }
1187
+ }
1188
+
1189
+ function killTrayProcess(prefix) {
1190
+ if (process.platform === "win32") {
1191
+ // Try PID file first (new tray versions write runtime/tray.pid).
1192
+ const pidFile = path.join(prefix, "runtime", "tray.pid")
1193
+ if (existsSync(pidFile)) {
1194
+ const pid = readFileSync(pidFile, "utf8").trim()
1195
+ if (pid) {
1196
+ spawnSync("taskkill", ["/PID", pid, "/F"], { stdio: "ignore" })
1197
+ try { rmSync(pidFile, { force: true }) } catch {}
1198
+ }
1199
+ }
1200
+ // Fallback: kill by image name if the binary is inside our prefix.
1201
+ const result = spawnSync("tasklist", ["/FI", "IMAGENAME eq vantaloom-tray.exe", "/FO", "CSV", "/NH"], {
1202
+ encoding: "utf8",
1203
+ windowsHide: true,
1204
+ })
1205
+ if (result.stdout) {
1206
+ for (const line of result.stdout.split("\n")) {
1207
+ const match = line.match(/"vantaloom-tray\.exe","(\d+)"/)
1208
+ if (match) {
1209
+ spawnSync("taskkill", ["/PID", match[1], "/F"], { stdio: "ignore" })
1210
+ }
1211
+ }
1212
+ }
1213
+ // Brief pause to let file handles release.
1214
+ spawnSync("timeout", ["/t", "1", "/nobreak"], { stdio: "ignore", windowsHide: true })
1215
+ } else {
1216
+ // Unix: pkill by name (best-effort).
1217
+ spawnSync("pkill", ["-f", "vantaloom-tray"], { stdio: "ignore" })
1218
+ }
1219
+ }
1220
+
900
1221
  function printHelp() {
901
1222
  console.log(`Vantaloom CLI
902
1223
 
package/manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "Vantaloom Local Runtime",
3
- "version": "9bcdf40",
3
+ "version": "532507a",
4
4
  "platform": "win32-x64",
5
- "updatedAt": "2026-05-29T18:52:26.307Z",
5
+ "updatedAt": "2026-05-31T17:14:42.106Z",
6
6
  "components": [
7
7
  "api",
8
8
  "agent",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantaloom/runtime-win32-x64",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Vantaloom local runtime for win32-x64.",
6
6
  "type": "module",
package/web/404.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><!--qDb937Fsr8zR_VHDxrNf_--><html lang="zh-CN" class="font-sans antialiased" data-vtl-theme="default" data-vtl-density="default" data-vtl-motion="default"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/c0c4db6d45c7ff65.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/a678910d6e3629e7.js"/><script src="/_next/static/chunks/b9cfbaaba1fd82be.js" async=""></script><script src="/_next/static/chunks/757e2e1b77b5bacc.js" async=""></script><script src="/_next/static/chunks/turbopack-d8677f40582561e6.js" async=""></script><script src="/_next/static/chunks/eca64d281474b631.js" async=""></script><script src="/_next/static/chunks/7dfeab42587bcc0e.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Vantaloom</title><meta name="description" content="Vantaloom local agent operations console."/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","system",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/a678910d6e3629e7.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[22332,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"ThemeProvider\"]\n3:I[45121,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n4:I[60512,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n5:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"OutletBoundary\"]\n6:\"$Sreact.suspense\"\n8:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"ViewportBoundary\"]\na:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"MetadataBoundary\"]\nc:I[50025,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n:HL[\"/_next/static/chunks/c0c4db6d45c7ff65.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"qDb937Fsr8zR_VHDxrNf_\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/c0c4db6d45c7ff65.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/eca64d281474b631.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/7dfeab42587bcc0e.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"zh-CN\",\"suppressHydrationWarning\":true,\"className\":\"font-sans antialiased\",\"data-vtl-theme\":\"default\",\"data-vtl-density\":\"default\",\"data-vtl-motion\":\"default\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L5\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@7\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"7:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"Vantaloom\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Vantaloom local agent operations console.\"}]]\n"])</script></body></html>
1
+ <!DOCTYPE html><!--E6VnJNHPIVhiQoKxBWUU2--><html lang="zh-CN" class="font-sans antialiased" data-vtl-theme="default" data-vtl-density="default" data-vtl-motion="default"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/73d2c788f1076e9a.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/a678910d6e3629e7.js"/><script src="/_next/static/chunks/b9cfbaaba1fd82be.js" async=""></script><script src="/_next/static/chunks/757e2e1b77b5bacc.js" async=""></script><script src="/_next/static/chunks/turbopack-d8677f40582561e6.js" async=""></script><script src="/_next/static/chunks/eca64d281474b631.js" async=""></script><script src="/_next/static/chunks/7dfeab42587bcc0e.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Vantaloom</title><meta name="description" content="Vantaloom local agent operations console."/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","system",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/a678910d6e3629e7.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[22332,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"ThemeProvider\"]\n3:I[45121,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n4:I[60512,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n5:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"OutletBoundary\"]\n6:\"$Sreact.suspense\"\n8:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"ViewportBoundary\"]\na:I[35417,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"MetadataBoundary\"]\nc:I[50025,[\"/_next/static/chunks/eca64d281474b631.js\",\"/_next/static/chunks/7dfeab42587bcc0e.js\"],\"default\"]\n:HL[\"/_next/static/chunks/73d2c788f1076e9a.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"E6VnJNHPIVhiQoKxBWUU2\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/73d2c788f1076e9a.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/eca64d281474b631.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/7dfeab42587bcc0e.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"zh-CN\",\"suppressHydrationWarning\":true,\"className\":\"font-sans antialiased\",\"data-vtl-theme\":\"default\",\"data-vtl-density\":\"default\",\"data-vtl-motion\":\"default\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L5\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@7\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"7:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"Vantaloom\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Vantaloom local agent operations console.\"}]]\n"])</script></body></html>
@@ -1,9 +1,9 @@
1
1
  1:"$Sreact.fragment"
2
2
  2:I[66863,["/_next/static/chunks/7dfeab42587bcc0e.js"],"ClientPageRoot"]
3
- 3:I[66204,["/_next/static/chunks/eca64d281474b631.js","/_next/static/chunks/17e0384154325960.js","/_next/static/chunks/c990601c49cb69a5.js","/_next/static/chunks/1da7f8d27cd96c86.js","/_next/static/chunks/742d3900ca49db0a.js"],"default"]
3
+ 3:I[66204,["/_next/static/chunks/eca64d281474b631.js","/_next/static/chunks/17e0384154325960.js","/_next/static/chunks/c990601c49cb69a5.js","/_next/static/chunks/80b4a364458ec11d.js","/_next/static/chunks/742d3900ca49db0a.js"],"default"]
4
4
  6:I[35417,["/_next/static/chunks/7dfeab42587bcc0e.js"],"OutletBoundary"]
5
5
  7:"$Sreact.suspense"
6
- 0:{"buildId":"qDb937Fsr8zR_VHDxrNf_","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/17e0384154325960.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/c990601c49cb69a5.js","async":true}],["$","script","script-2",{"src":"/_next/static/chunks/1da7f8d27cd96c86.js","async":true}],["$","script","script-3",{"src":"/_next/static/chunks/742d3900ca49db0a.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
6
+ 0:{"buildId":"E6VnJNHPIVhiQoKxBWUU2","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/17e0384154325960.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/c990601c49cb69a5.js","async":true}],["$","script","script-2",{"src":"/_next/static/chunks/80b4a364458ec11d.js","async":true}],["$","script","script-3",{"src":"/_next/static/chunks/742d3900ca49db0a.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
7
7
  4:{}
8
8
  5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
9
9
  8:null