@vantaloom/runtime-linux-x64 0.1.24 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/VERSION +1 -1
  2. package/bin/vantaloom-agent +0 -0
  3. package/bin/vantaloom-api +0 -0
  4. package/bin/vantaloomctl +0 -0
  5. package/cli/config.json +3 -2
  6. package/cli/package.json +1 -1
  7. package/cli/src/cli.mjs +357 -35
  8. package/manifest.json +2 -2
  9. package/package.json +1 -1
  10. package/web/404.html +1 -1
  11. package/web/__next.__PAGE__.txt +2 -2
  12. package/web/__next._full.txt +3 -3
  13. package/web/__next._head.txt +1 -1
  14. package/web/__next._index.txt +2 -2
  15. package/web/__next._tree.txt +2 -2
  16. package/web/_next/static/chunks/73d2c788f1076e9a.css +2 -0
  17. package/web/_next/static/chunks/7d5ab4ba8d474929.js +52 -0
  18. package/web/_not-found/__next._full.txt +2 -2
  19. package/web/_not-found/__next._head.txt +1 -1
  20. package/web/_not-found/__next._index.txt +2 -2
  21. package/web/_not-found/{__next._not-found.__PAGE__.txt → __next._not-found/__PAGE__.txt} +1 -1
  22. package/web/_not-found/__next._not-found.txt +1 -1
  23. package/web/_not-found/__next._tree.txt +2 -2
  24. package/web/_not-found.html +1 -1
  25. package/web/_not-found.txt +2 -2
  26. package/web/index.html +1 -31
  27. package/web/index.txt +3 -3
  28. package/web/_next/static/chunks/5922011684321db3.css +0 -2
  29. package/web/_next/static/chunks/bb819ea11a2befeb.js +0 -49
  30. /package/web/_next/static/{pPjXTcU0jyBCIxzhfecWl → 2kPL4gOT89qnDZSfX50Rn}/_buildManifest.js +0 -0
  31. /package/web/_next/static/{pPjXTcU0jyBCIxzhfecWl → 2kPL4gOT89qnDZSfX50Rn}/_clientMiddlewareManifest.json +0 -0
  32. /package/web/_next/static/{pPjXTcU0jyBCIxzhfecWl → 2kPL4gOT89qnDZSfX50Rn}/_ssgManifest.js +0 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5ce4bec
1
+ 532507a
Binary file
package/bin/vantaloom-api CHANGED
Binary file
package/bin/vantaloomctl CHANGED
Binary file
package/cli/config.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
- "remote": "https://github.com/Timefiles404/Vantaloom-next",
2
+ "sourceRoot": "D:\\Projects\\Vantaloom-ui",
3
+ "remote": "git@github-vantaloom:Timefiles404/Vantaloom-next.git",
3
4
  "repo": "Timefiles404/Vantaloom-next",
4
5
  "releaseTag": "runtime-latest",
5
- "runtimePackage": "@vantaloom/runtime-linux-x64",
6
+ "runtimePackage": "@vantaloom/runtime-win32-x64",
6
7
  "runtimeVersion": "latest",
7
8
  "npmRegistry": "https://registry.npmjs.org"
8
9
  }
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantaloom/cli",
3
- "version": "0.1.24",
3
+ "version": "0.3.6",
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,16 +140,19 @@ 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
 
110
147
  async function packageRuntime(options) {
111
148
  const sourceRoot = findSourceRoot(options.source)
149
+ const targetPlatform = options.target ?? platformId()
112
150
  const packageRoot = safeDirectory(
113
- options.output ?? path.join(sourceRoot, "artifacts", "packages", `vantaloom-${platformId()}`)
151
+ options.output ?? path.join(sourceRoot, "artifacts", "packages", `vantaloom-${targetPlatform}`)
114
152
  )
115
153
  const { platform: builtPlatform, version } = await buildRuntimePackage(sourceRoot, packageRoot, {
116
154
  buildWeb: options.buildWeb,
155
+ target: targetPlatform,
117
156
  })
118
157
 
119
158
  if (options.npmPackage) {
@@ -140,16 +179,22 @@ async function packageRuntime(options) {
140
179
 
141
180
  async function buildRuntimePackage(sourceRoot, packageRoot, options) {
142
181
  const version = gitVersion(sourceRoot)
143
- const platform = platformId()
182
+ const platform = options.target ?? platformId()
144
183
  const buildBin = path.join(packageRoot, "bin")
145
184
  const buildWeb = path.join(packageRoot, "web")
146
185
 
147
186
  removeKnownPath(packageRoot, path.dirname(packageRoot))
148
187
  mkdirSync(buildBin, { recursive: true })
149
188
 
150
- buildGo(sourceRoot, buildBin, "vantaloom-api")
151
- buildGo(sourceRoot, buildBin, "vantaloom-agent")
152
- buildGo(sourceRoot, buildBin, "vantaloomctl")
189
+ buildGo(sourceRoot, buildBin, "vantaloom-api", platform)
190
+ buildGo(sourceRoot, buildBin, "vantaloom-agent", platform)
191
+ buildGo(sourceRoot, buildBin, "vantaloomctl", platform)
192
+ // Tray app requires CGO (systray), only buildable natively on Windows.
193
+ if (platform.startsWith("win32") && process.platform === "win32") {
194
+ try {
195
+ buildGo(sourceRoot, buildBin, "vantaloom-tray", platform)
196
+ } catch { /* optional: skip if systray build fails */ }
197
+ }
153
198
 
154
199
  if (options.buildWeb) {
155
200
  runPnpm(["--filter", "vantaloom-app", "build"], { cwd: sourceRoot })
@@ -178,15 +223,49 @@ async function applyPackage(packageRoot, prefix, options) {
178
223
  spawnSync(existingCtl, ["stop", "--prefix", prefix], { stdio: "inherit" })
179
224
  }
180
225
 
226
+ // Kill lingering tray process that may hold locks on bin/ (older versions
227
+ // don't write tray.pid, so vantaloomctl stop won't find them).
228
+ killTrayProcess(prefix)
229
+
230
+ // Copy package contents to install prefix
181
231
  for (const name of ["bin", "web", "cli"]) {
182
- removeKnownPath(path.join(prefix, name), prefix)
183
- await cp(path.join(packageRoot, name), path.join(prefix, name), {
232
+ const src = path.join(packageRoot, name)
233
+ const dst = path.join(prefix, name)
234
+ if (!existsSync(src)) {
235
+ console.error(` warning: package missing ${name}/ directory`)
236
+ continue
237
+ }
238
+ removeKnownPath(dst, prefix)
239
+ await cp(src, dst, {
184
240
  recursive: true,
185
241
  force: true,
186
242
  dereference: false,
187
243
  })
188
244
  }
189
245
 
246
+ // Ensure binaries are executable on Unix (cross-compiled from Windows they lose +x)
247
+ const binDir = path.join(prefix, "bin")
248
+ if (process.platform !== "win32" && existsSync(binDir)) {
249
+ for (const entry of readdirSync(binDir)) {
250
+ const binPath = path.join(binDir, entry)
251
+ try { chmodSync(binPath, 0o755) } catch {}
252
+ }
253
+ }
254
+
255
+ // Verify vantaloomctl binary exists before trying to run it
256
+ const ctlBin = path.join(prefix, "bin", binaryName("vantaloomctl"))
257
+ if (!existsSync(ctlBin)) {
258
+ const binContents = existsSync(binDir) ? readdirSync(binDir) : []
259
+ const srcBinContents = existsSync(path.join(packageRoot, "bin")) ? readdirSync(path.join(packageRoot, "bin")) : []
260
+ throw new Error(
261
+ `vantaloomctl binary not found at ${ctlBin}\n` +
262
+ ` installed bin/: [${binContents.join(", ")}]\n` +
263
+ ` package bin/: [${srcBinContents.join(", ")}]\n` +
264
+ ` platform: ${platformId()}\n` +
265
+ ` This may indicate a corrupt download. Try again or install from source.`
266
+ )
267
+ }
268
+
190
269
  await writeLauncher(prefix)
191
270
  await writeText(path.join(prefix, "cli", "config.json"), `${JSON.stringify(mergedConfig, null, 2)}\n`)
192
271
  await writeText(path.join(prefix, "VERSION"), `${version}\n`)
@@ -194,7 +273,7 @@ async function applyPackage(packageRoot, prefix, options) {
194
273
  force: true,
195
274
  })
196
275
 
197
- run(path.join(prefix, "bin", binaryName("vantaloomctl")), [
276
+ run(ctlBin, [
198
277
  "install",
199
278
  "--prefix",
200
279
  prefix,
@@ -203,7 +282,7 @@ async function applyPackage(packageRoot, prefix, options) {
203
282
  ])
204
283
 
205
284
  if (!options.noStart) {
206
- run(path.join(prefix, "bin", binaryName("vantaloomctl")), [
285
+ run(ctlBin, [
207
286
  "start",
208
287
  "--prefix",
209
288
  prefix,
@@ -216,9 +295,13 @@ async function applyPackage(packageRoot, prefix, options) {
216
295
  async function syncFromNpmRegistry(options, action) {
217
296
  const prefix = safeDirectory(options.prefix ?? defaultPrefix())
218
297
  const installedConfig = readInstalledConfig(prefix)
219
- const runtimePackage = options.runtimePackage || installedConfig.runtimePackage || runtimePackageName(platformId())
298
+ // Always derive runtimePackage from current platform — never trust stale config
299
+ // from a different platform (e.g. win32 config baked into a darwin package).
300
+ // Only explicit --runtime-package flag can override.
301
+ const runtimePackage = options.runtimePackage || runtimePackageName(platformId())
220
302
  const runtimeVersion = options.runtimeVersion || installedConfig.runtimeVersion || "latest"
221
- const registry = normalizeRegistry(options.npmRegistry || installedConfig.npmRegistry || defaultNpmRegistry)
303
+ const explicitRegistry = options.npmRegistry || installedConfig.npmRegistry
304
+ const registry = normalizeRegistry(explicitRegistry || detectNpmRegistry() || defaultNpmRegistry)
222
305
  const tempRoot = mkdtempSync(path.join(os.tmpdir(), "vantaloom-npm-"))
223
306
 
224
307
  try {
@@ -226,7 +309,11 @@ async function syncFromNpmRegistry(options, action) {
226
309
  const archive = path.join(tempRoot, `${packageBasename(runtimePackage)}-${runtimeVersion}.tgz`)
227
310
  mkdirSync(extractRoot, { recursive: true })
228
311
 
229
- const resolved = await resolveNpmPackage({ registry, name: runtimePackage, version: runtimeVersion })
312
+ const resolved = await resolveNpmPackageWithFallback({
313
+ registries: explicitRegistry ? [registry] : [registry, ...fallbackNpmRegistries.map(normalizeRegistry)],
314
+ name: runtimePackage,
315
+ version: runtimeVersion,
316
+ })
230
317
  await downloadNpmTarball({
231
318
  tarballUrl: resolved.tarball,
232
319
  target: archive,
@@ -240,13 +327,15 @@ async function syncFromNpmRegistry(options, action) {
240
327
  noStart: options.noStart,
241
328
  runtimePackage,
242
329
  runtimeVersion: options.runtimeVersion ? resolved.version : "latest",
243
- npmRegistry: registry,
330
+ npmRegistry: resolved.registry,
244
331
  update: action === "update",
245
332
  })
246
333
 
247
334
  console.log(`${action === "update" ? "updated" : "installed"} Vantaloom: ${prefix}`)
248
335
  console.log(`version: ${version}`)
249
336
  console.log(`source: ${runtimePackage}@${resolved.version}`)
337
+ console.log(`registry: ${resolved.registry}`)
338
+ ensureInPath(prefix)
250
339
  console.log(`run: ${displayCommand(prefix)} status`)
251
340
  } finally {
252
341
  removeKnownPath(tempRoot, os.tmpdir())
@@ -288,6 +377,7 @@ async function syncFromRelease(options, action) {
288
377
  console.log(`${action === "update" ? "updated" : "installed"} Vantaloom: ${prefix}`)
289
378
  console.log(`version: ${version}`)
290
379
  console.log(`source: ${repo}@${releaseTag}`)
380
+ ensureInPath(prefix)
291
381
  console.log(`run: ${displayCommand(prefix)} status`)
292
382
  } finally {
293
383
  removeKnownPath(tempRoot, os.tmpdir())
@@ -338,14 +428,114 @@ async function downloadReleaseAsset({ repo, releaseTag, assetName, target, token
338
428
  await writeFile(target, buffer)
339
429
  }
340
430
 
431
+ function detectNpmRegistry() {
432
+ // 1. NPM_CONFIG_REGISTRY env var (highest priority, set by npm/npx when running)
433
+ if (process.env.NPM_CONFIG_REGISTRY) {
434
+ return process.env.npm_config_registry || process.env.NPM_CONFIG_REGISTRY
435
+ }
436
+ // npm also sets the lowercase variant
437
+ if (process.env.npm_config_registry) {
438
+ return process.env.npm_config_registry
439
+ }
440
+
441
+ // 2. Read user .npmrc
442
+ try {
443
+ const npmrcPaths = [
444
+ path.join(os.homedir(), ".npmrc"),
445
+ ]
446
+ // Also check project-level .npmrc
447
+ const localNpmrc = path.resolve(".npmrc")
448
+ if (localNpmrc !== npmrcPaths[0]) {
449
+ npmrcPaths.unshift(localNpmrc)
450
+ }
451
+ for (const npmrcPath of npmrcPaths) {
452
+ if (existsSync(npmrcPath)) {
453
+ const content = readFileSync(npmrcPath, "utf8")
454
+ const match = content.match(/^\s*registry\s*=\s*(.+)/m)
455
+ if (match) {
456
+ return match[1].trim()
457
+ }
458
+ }
459
+ }
460
+ } catch {
461
+ // Ignore .npmrc read errors
462
+ }
463
+
464
+ return ""
465
+ }
466
+
467
+ async function resolveNpmPackageWithFallback({ registries, name, version }) {
468
+ const errors = []
469
+ for (const registry of registries) {
470
+ try {
471
+ const result = await resolveNpmPackage({ registry, name, version })
472
+ return { ...result, registry }
473
+ } catch (error) {
474
+ const causeCode = error?.cause?.code || ""
475
+ const isNetworkError = causeCode === "ECONNREFUSED"
476
+ || causeCode === "ENOTFOUND"
477
+ || causeCode === "ETIMEDOUT"
478
+ || causeCode === "ECONNRESET"
479
+ || causeCode === "UND_ERR_CONNECT_TIMEOUT"
480
+ || (error instanceof TypeError && error.message === "fetch failed")
481
+ const isSslError = causeCode === "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
482
+ || causeCode === "CERT_HAS_EXPIRED"
483
+ || causeCode === "DEPTH_ZERO_SELF_SIGNED_CERT"
484
+ || causeCode === "SELF_SIGNED_CERT_IN_CHAIN"
485
+ || causeCode === "ERR_TLS_CERT_ALTNAME_INVALID"
486
+ const isRetryable = isNetworkError || isSslError
487
+ errors.push({ registry, error, isRetryable, isSslError })
488
+
489
+ if (isRetryable && registries.length > 1) {
490
+ const hint = isSslError ? " (SSL certificate error)" : ""
491
+ console.error(`vantaloom: ${registry} unreachable${hint}, trying next registry...`)
492
+ continue
493
+ }
494
+ if (isSslError) {
495
+ throw new Error(
496
+ `SSL certificate error connecting to ${registry}: ${causeCode}\n` +
497
+ ` Fix: run with --no-strict-ssl, or set npm config: npm config set strict-ssl false`
498
+ )
499
+ }
500
+ // Non-network error (404, parse error, etc.) — don't try fallbacks
501
+ throw error
502
+ }
503
+ }
504
+
505
+ // All registries failed
506
+ const hasSslError = errors.some((e) => e.isSslError)
507
+ const tried = errors.map((e) => e.registry).join(", ")
508
+ const sslHint = hasSslError
509
+ ? `\n SSL fix: run with --no-strict-ssl, or set npm config: npm config set strict-ssl false`
510
+ : ""
511
+ throw new Error(
512
+ `all registries unreachable (tried: ${tried}). ` +
513
+ `Check your network or specify --npm-registry <url>${sslHint}`
514
+ )
515
+ }
516
+
341
517
  async function resolveNpmPackage({ registry, name, version }) {
342
518
  const metadataUrl = `${registry}/${encodeURIComponent(name).replace("%2F", "%2f")}`
343
- const response = await fetch(metadataUrl, {
344
- headers: {
345
- Accept: "application/vnd.npm.install-v1+json",
346
- "User-Agent": "vantaloom-cli",
347
- },
348
- })
519
+ let response
520
+ try {
521
+ response = await fetch(metadataUrl, {
522
+ headers: {
523
+ Accept: "application/vnd.npm.install-v1+json",
524
+ "User-Agent": "vantaloom-cli",
525
+ },
526
+ signal: AbortSignal.timeout(15000),
527
+ })
528
+ } catch (error) {
529
+ if (error instanceof TypeError && error.message === "fetch failed") {
530
+ const causeCode = error.cause?.code || ""
531
+ const causeMsg = causeCode || error.cause?.message || String(error.cause || "")
532
+ throw Object.assign(
533
+ new Error(`cannot reach registry ${registry} (${causeMsg})`),
534
+ { cause: error.cause }
535
+ )
536
+ }
537
+ throw error
538
+ }
349
539
  if (!response.ok) {
350
540
  const detail = await response.text().catch(() => "")
351
541
  throw new Error(`failed to inspect npm package ${name}: HTTP ${response.status}${detail ? ` ${detail.slice(0, 200)}` : ""}`)
@@ -365,11 +555,22 @@ async function resolveNpmPackage({ registry, name, version }) {
365
555
  }
366
556
 
367
557
  async function downloadNpmTarball({ tarballUrl, target, packageName, version }) {
368
- const response = await fetch(tarballUrl, {
369
- headers: {
370
- "User-Agent": "vantaloom-cli",
371
- },
372
- })
558
+ console.log(` downloading ${packageName}@${version}...`)
559
+ let response
560
+ try {
561
+ response = await fetch(tarballUrl, {
562
+ headers: {
563
+ "User-Agent": "vantaloom-cli",
564
+ },
565
+ signal: AbortSignal.timeout(120000),
566
+ })
567
+ } catch (error) {
568
+ const causeCode = error?.cause?.code || ""
569
+ const causeMsg = causeCode || error?.cause?.message || error.message || ""
570
+ const isSsl = causeCode.includes("CERT") || causeCode === "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
571
+ const hint = isSsl ? `\n Fix: run with --no-strict-ssl` : ""
572
+ throw new Error(`failed to download ${packageName}@${version} from ${tarballUrl}: ${causeMsg}${hint}`)
573
+ }
373
574
  if (!response.ok) {
374
575
  const detail = await response.text().catch(() => "")
375
576
  throw new Error(`failed to download ${packageName}@${version}: HTTP ${response.status}${detail ? ` ${detail.slice(0, 200)}` : ""}`)
@@ -377,6 +578,7 @@ async function downloadNpmTarball({ tarballUrl, target, packageName, version })
377
578
 
378
579
  const buffer = Buffer.from(await response.arrayBuffer())
379
580
  await writeFile(target, buffer)
581
+ console.log(` downloaded ${(buffer.length / 1024 / 1024).toFixed(1)} MB`)
380
582
  }
381
583
 
382
584
  function shouldUseSourceInstall(options) {
@@ -440,9 +642,9 @@ function mergeRuntimeConfig(packageConfig, existingConfig, overrides) {
440
642
  if (!merged.releaseTag) {
441
643
  merged.releaseTag = defaultReleaseTag
442
644
  }
443
- if (!merged.runtimePackage) {
444
- merged.runtimePackage = runtimePackageName(platformId())
445
- }
645
+ // Always force runtimePackage to match the running platform — a cross-compiled
646
+ // package may carry a config for a different platform (e.g. win32 inside darwin).
647
+ merged.runtimePackage = runtimePackageName(platformId())
446
648
  if (!merged.runtimeVersion) {
447
649
  merged.runtimeVersion = "latest"
448
650
  }
@@ -462,7 +664,7 @@ function runtimeConfigFromSource(sourceRoot) {
462
664
  releaseTag: defaultReleaseTag,
463
665
  runtimePackage: runtimePackageName(platformId()),
464
666
  runtimeVersion: "latest",
465
- npmRegistry: defaultNpmRegistry,
667
+ npmRegistry: detectNpmRegistry() || defaultNpmRegistry,
466
668
  }
467
669
  }
468
670
 
@@ -598,13 +800,20 @@ function printPaths(options) {
598
800
  console.log(JSON.stringify({ sourceRoot, prefix }, null, 2))
599
801
  }
600
802
 
601
- function buildGo(sourceRoot, buildBin, name) {
803
+ function buildGo(sourceRoot, buildBin, name, targetPlatform) {
804
+ const goEnv = targetPlatform ? platformToGoEnv(targetPlatform) : {}
805
+ const isWindowsTarget = targetPlatform
806
+ ? targetPlatform.startsWith("win32")
807
+ : process.platform === "win32"
808
+ const ext = isWindowsTarget ? ".exe" : ""
809
+ const ldflags = name === "vantaloom-tray" ? "-s -w -H windowsgui" : "-s -w"
602
810
  run("go", [
603
811
  "build",
812
+ "-ldflags", ldflags,
604
813
  "-o",
605
- path.join(buildBin, binaryName(name)),
814
+ path.join(buildBin, `${name}${ext}`),
606
815
  `./apps/api/cmd/${name}`,
607
- ], { cwd: sourceRoot })
816
+ ], { cwd: sourceRoot, env: { ...process.env, ...goEnv } })
608
817
  }
609
818
 
610
819
  async function copyDir(source, destination, options = {}) {
@@ -621,6 +830,10 @@ async function copyDir(source, destination, options = {}) {
621
830
  }
622
831
 
623
832
  function writeBuildManifest(buildRoot, version, platform) {
833
+ const components = ["api", "agent", "web", "ctl"]
834
+ if (platform.startsWith("win32")) {
835
+ components.push("tray")
836
+ }
624
837
  writeFileSync(path.join(buildRoot, "VERSION"), `${version}\n`)
625
838
  writeFileSync(
626
839
  path.join(buildRoot, "manifest.json"),
@@ -630,7 +843,7 @@ function writeBuildManifest(buildRoot, version, platform) {
630
843
  version,
631
844
  platform,
632
845
  updatedAt: new Date().toISOString(),
633
- components: ["api", "agent", "web", "ctl"],
846
+ components,
634
847
  },
635
848
  null,
636
849
  2
@@ -748,9 +961,18 @@ function parseOptions(args) {
748
961
  case "npm-package":
749
962
  options.npmPackage = true
750
963
  break
964
+ case "target":
965
+ options.target = inlineValue ?? args[++index]
966
+ if (!options.target) {
967
+ throw new Error("missing value for --target")
968
+ }
969
+ break
751
970
  case "local":
752
971
  options.local = true
753
972
  break
973
+ case "no-strict-ssl":
974
+ options.noStrictSsl = true
975
+ break
754
976
  default:
755
977
  throw new Error(`unknown option --${key}`)
756
978
  }
@@ -799,8 +1021,22 @@ function runPnpm(args, options = {}) {
799
1021
  run("pnpm", args, options)
800
1022
  }
801
1023
 
802
- function binaryName(name) {
803
- return process.platform === "win32" ? `${name}.exe` : name
1024
+ function binaryName(name, targetPlatform) {
1025
+ const isWindows = targetPlatform
1026
+ ? targetPlatform.startsWith("win32")
1027
+ : process.platform === "win32"
1028
+ return isWindows ? `${name}.exe` : name
1029
+ }
1030
+
1031
+ function platformToGoEnv(platform) {
1032
+ const { os: runtimeOS, cpu } = parsePlatformId(platform)
1033
+ const goosMap = { win32: "windows", linux: "linux", darwin: "darwin" }
1034
+ const goarchMap = { x64: "amd64", arm64: "arm64" }
1035
+ return {
1036
+ GOOS: goosMap[runtimeOS] ?? runtimeOS,
1037
+ GOARCH: goarchMap[cpu] ?? cpu,
1038
+ CGO_ENABLED: "0",
1039
+ }
804
1040
  }
805
1041
 
806
1042
  function platformId() {
@@ -858,6 +1094,92 @@ async function writeText(filePath, content) {
858
1094
  await writeFile(filePath, content)
859
1095
  }
860
1096
 
1097
+ // ensureInPath adds the Vantaloom install directory to the user's shell PATH
1098
+ // on macOS and Linux, so `vantaloom` can be run directly after install.
1099
+ // On Windows this is not needed (vantaloom.cmd is run by full path or added via installer).
1100
+ function ensureInPath(prefix) {
1101
+ if (process.platform === "win32") return
1102
+
1103
+ // Check if already in PATH
1104
+ const pathDirs = (process.env.PATH || "").split(":")
1105
+ if (pathDirs.includes(prefix)) return
1106
+
1107
+ // Determine shell profile file
1108
+ const home = os.homedir()
1109
+ const shell = process.env.SHELL || ""
1110
+ let profilePath
1111
+ if (shell.endsWith("/zsh") || existsSync(path.join(home, ".zshrc"))) {
1112
+ profilePath = path.join(home, ".zshrc")
1113
+ } else if (shell.endsWith("/bash")) {
1114
+ // On macOS, bash uses .bash_profile; on Linux, .bashrc
1115
+ profilePath = process.platform === "darwin"
1116
+ ? path.join(home, ".bash_profile")
1117
+ : path.join(home, ".bashrc")
1118
+ } else if (existsSync(path.join(home, ".profile"))) {
1119
+ profilePath = path.join(home, ".profile")
1120
+ } else {
1121
+ profilePath = path.join(home, ".profile")
1122
+ }
1123
+
1124
+ // Use $HOME-relative path for portability
1125
+ const homeRelative = prefix.startsWith(home)
1126
+ ? `$HOME${prefix.slice(home.length)}`
1127
+ : prefix
1128
+ const exportLine = `export PATH="${homeRelative}:$PATH"`
1129
+ const marker = "# vantaloom"
1130
+
1131
+ // Check if already added to profile
1132
+ try {
1133
+ if (existsSync(profilePath)) {
1134
+ const content = readFileSync(profilePath, "utf8")
1135
+ if (content.includes("vantaloom") && content.includes("PATH")) return
1136
+ }
1137
+ } catch {}
1138
+
1139
+ // Append to profile
1140
+ try {
1141
+ const entry = `\n${marker}\n${exportLine}\n`
1142
+ appendFileSync(profilePath, entry)
1143
+ console.log(`PATH: added ${prefix} to ${profilePath}`)
1144
+ console.log(` run: source ${profilePath} (or open a new terminal)`)
1145
+ } catch (error) {
1146
+ console.log(`PATH: could not update ${profilePath}: ${error.message}`)
1147
+ console.log(` add manually: ${exportLine}`)
1148
+ }
1149
+ }
1150
+
1151
+ function killTrayProcess(prefix) {
1152
+ if (process.platform === "win32") {
1153
+ // Try PID file first (new tray versions write runtime/tray.pid).
1154
+ const pidFile = path.join(prefix, "runtime", "tray.pid")
1155
+ if (existsSync(pidFile)) {
1156
+ const pid = readFileSync(pidFile, "utf8").trim()
1157
+ if (pid) {
1158
+ spawnSync("taskkill", ["/PID", pid, "/F"], { stdio: "ignore" })
1159
+ try { rmSync(pidFile, { force: true }) } catch {}
1160
+ }
1161
+ }
1162
+ // Fallback: kill by image name if the binary is inside our prefix.
1163
+ const result = spawnSync("tasklist", ["/FI", "IMAGENAME eq vantaloom-tray.exe", "/FO", "CSV", "/NH"], {
1164
+ encoding: "utf8",
1165
+ windowsHide: true,
1166
+ })
1167
+ if (result.stdout) {
1168
+ for (const line of result.stdout.split("\n")) {
1169
+ const match = line.match(/"vantaloom-tray\.exe","(\d+)"/)
1170
+ if (match) {
1171
+ spawnSync("taskkill", ["/PID", match[1], "/F"], { stdio: "ignore" })
1172
+ }
1173
+ }
1174
+ }
1175
+ // Brief pause to let file handles release.
1176
+ spawnSync("timeout", ["/t", "1", "/nobreak"], { stdio: "ignore", windowsHide: true })
1177
+ } else {
1178
+ // Unix: pkill by name (best-effort).
1179
+ spawnSync("pkill", ["-f", "vantaloom-tray"], { stdio: "ignore" })
1180
+ }
1181
+ }
1182
+
861
1183
  function printHelp() {
862
1184
  console.log(`Vantaloom CLI
863
1185
 
@@ -866,7 +1188,7 @@ Usage:
866
1188
  vantaloom install --local [--prefix <dir>] [--source <repo>] [--build-web] [--no-start]
867
1189
  vantaloom update [--prefix <dir>] [--runtime-version <version>] [--npm-registry <url>] [--no-start]
868
1190
  vantaloom update --local [--prefix <dir>] [--source <repo>] [--build-web] [--no-start]
869
- vantaloom package [--source <repo>] [--output <dir>] [--build-web] [--archive] [--npm-package]
1191
+ vantaloom package [--source <repo>] [--output <dir>] [--build-web] [--archive] [--npm-package] [--target <platform>]
870
1192
  vantaloom start [--prefix <dir>] [--component all|api|agent|web]
871
1193
  vantaloom stop [--prefix <dir>] [--component all|api|agent|web]
872
1194
  vantaloom restart [--prefix <dir>] [--component all|api|agent|web]
package/manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "Vantaloom Local Runtime",
3
- "version": "5ce4bec",
3
+ "version": "532507a",
4
4
  "platform": "linux-x64",
5
- "updatedAt": "2026-05-28T16:04:31.021Z",
5
+ "updatedAt": "2026-05-30T15:43:12.245Z",
6
6
  "components": [
7
7
  "api",
8
8
  "agent",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantaloom/runtime-linux-x64",
3
- "version": "0.1.24",
3
+ "version": "0.3.6",
4
4
  "private": false,
5
5
  "description": "Vantaloom local runtime for linux-x64.",
6
6
  "type": "module",