@tedbrain/vlink 0.1.42 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,20 +5,29 @@ Codex 一样按当前平台下载对应的 vlink 二进制。推荐统一使用
5
5
  和 TedBrain 初始化:
6
6
 
7
7
  ```bash
8
- npx -y @tedbrain/vlink@latest install
8
+ npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
9
9
  ```
10
10
 
11
- 该命令会识别平台和架构、安装或更新 vlink、配置用户 PATH,并启动
12
- `vlink setup tedbrain`。安装完成后可直接运行:
11
+ 该命令会识别平台和架构,始终安装与当前 npm 包版本一致的 vlink,配置用户
12
+ PATH,并启动 `vlink setup tedbrain`。安装完成后可直接运行:
13
13
 
14
14
  ```bash
15
15
  vlink --version
16
16
  ```
17
17
 
18
+ Windows 会在 `vlink.exe` 旁同时生成 `vlink.cmd`。安装目录加入用户 PATH 后,
19
+ 可在 PowerShell 或 cmd 中直接运行 `vlink ...`,也可显式使用 `vlink.cmd ...`。
20
+
18
21
  也可以只把 npm 包作为临时 CLI 使用:
19
22
 
20
23
  ```bash
21
- npx -y @tedbrain/vlink@latest --version
24
+ npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest --version
25
+ ```
26
+
27
+ 手动配置 Agent 时可以只安装或更新 vlink,并跳过 TedBrain 配置向导:
28
+
29
+ ```bash
30
+ npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install --no-setup
22
31
  ```
23
32
 
24
33
  ## 下载地址
@@ -35,19 +44,19 @@ release 不存在或校验失败时,自动回退到 d01 下载服务器:
35
44
 
36
45
  ```bash
37
46
  # 跳过 Gitee,直接使用 d01/自定义下载源
38
- VLINK_SKIP_GITEE=1 npx -y @tedbrain/vlink@latest install
47
+ VLINK_SKIP_GITEE=1 npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
39
48
 
40
49
  # d01 回退源改用开发通道
41
- VLINK_DOWNLOAD_CHANNEL=oss-dev npx -y @tedbrain/vlink@latest install
50
+ VLINK_DOWNLOAD_CHANNEL=oss-dev npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
42
51
 
43
52
  # 自定义回退下载根路径(会自动拼接 <channel>/vlink/<version>/vlink-<platform>)
44
- VLINK_DOWNLOAD_BASE=https://internal.example/downloads npx -y @tedbrain/vlink@latest install
53
+ VLINK_DOWNLOAD_BASE=https://internal.example/downloads npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
45
54
 
46
55
  # 自定义回退下载目录(会自动拼接 vlink-<platform>)
47
- VLINK_DOWNLOAD_URL=https://internal.example/vlink npx -y @tedbrain/vlink@latest install
56
+ VLINK_DOWNLOAD_URL=https://internal.example/vlink npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
48
57
 
49
58
  # 指定不同版本(同时影响 Gitee release tag 与 d01 回退路径)
50
- VLINK_VERSION=0.1.21 npx -y @tedbrain/vlink@latest install
59
+ VLINK_VERSION=0.1.21 npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
51
60
  ```
52
61
 
53
62
  ## 平台映射
package/binaries.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "version": "0.1.42",
2
+ "version": "0.1.44",
3
3
  "binaries": {
4
- "linux-x86_64": "a5ea94730528e9781d6187a0a25fc3470bdf893288e196ee50b0d5b01da1f073",
5
- "linux-x86_64-glibc2.17": "9bf3d5e27bf22fb45764c1bf979ab9789db853eb293e69fe24177745546f037d",
6
- "linux-aarch64": "3baf4ffe4985203a518158d773a9893655954476c4637d73ddb55231196b2d50",
7
- "macos-x86_64": "1497f16bc14502be3669313170f9e11010cbefbffc7c4c42cae5236c5a175628",
8
- "macos-aarch64": "f71d44aa3bcf31d1968ce7b046adb5e7ec79ae125cfccb06a6ac29b93ec1ad77",
9
- "windows-x86_64.exe": "eb77aef209afa83916d1f728115a7468b8ddcdbf2e65755fdbf43c6ca19a501c",
10
- "windows-aarch64.exe": "de2f3bdb8514025e0473c88feb400acc6aa9d072f713713bd7a428a7dadcab8e"
4
+ "linux-x86_64": "935a98d64be6530c01d3e4c5a9ed24f672f8f3881889dc0970398978cdd8647c",
5
+ "linux-x86_64-glibc2.17": "eac985196bb3c31e2029b43a35e576b3fb02256b1a86fb2cdf40e2fd6cf80ffb",
6
+ "linux-aarch64": "45c11039633f881bdf889bef4da90d5f6275c9beaeb6066d0734e7eb0736845b",
7
+ "macos-x86_64": "ed1143ffa8bdce153f02a7a987d24033e31e604e0ef2653cf454fa470077c3cf",
8
+ "macos-aarch64": "d9c590290b1c383c60685feb7c9e88f6f6f52ba2c49bed5d0cf1f3e79b773cd8",
9
+ "windows-x86_64.exe": "b38582348385131acba91abec301f7249b65ef3eb880179185a976c2f9038ebc",
10
+ "windows-aarch64.exe": "815ef8fad0c2ab9ae83ca080e2f28109bb956ec4829bd3cae765d9097339f7e0"
11
11
  }
12
12
  }
package/installer.js CHANGED
@@ -318,6 +318,45 @@ function installBinary(sourcePath, targetPath, options = {}) {
318
318
  return targetPath;
319
319
  }
320
320
 
321
+ function windowsCommandShimPath(vlinkPath) {
322
+ return path.join(path.dirname(vlinkPath), 'vlink.cmd');
323
+ }
324
+
325
+ function windowsCommandShimContents() {
326
+ return [
327
+ '@echo off',
328
+ '"%~dp0vlink.exe" %*',
329
+ 'exit /b %ERRORLEVEL%',
330
+ ''
331
+ ].join('\r\n');
332
+ }
333
+
334
+ function installWindowsCommandShim(vlinkPath, options = {}) {
335
+ const platform = options.platform || process.platform;
336
+ if (platform !== 'win32') return null;
337
+
338
+ const fsImpl = options.fs || fs;
339
+ const output = options.output || process.stderr;
340
+ const commandPath = windowsCommandShimPath(vlinkPath);
341
+ const temporary = `${commandPath}.install-${process.pid}-${Date.now()}`;
342
+
343
+ try {
344
+ fsImpl.writeFileSync(temporary, windowsCommandShimContents(), 'utf8');
345
+ if (fsImpl.existsSync(commandPath)) {
346
+ fsImpl.rmSync(commandPath, { force: true });
347
+ }
348
+ fsImpl.renameSync(temporary, commandPath);
349
+ } catch (error) {
350
+ fsImpl.rmSync(temporary, { force: true });
351
+ throw new VlinkSetupError(
352
+ `failed to install Windows command shim at ${commandPath}: ${error.message}`
353
+ );
354
+ }
355
+
356
+ log(`installed Windows command shim at ${commandPath}`, output);
357
+ return commandPath;
358
+ }
359
+
321
360
  function binaryIsStaticElf(binaryPath, options = {}) {
322
361
  if ((options.platform || process.platform) !== 'linux') return false;
323
362
  const spawnSyncImpl = options.spawnSync || spawnSync;
@@ -346,6 +385,7 @@ async function runInstaller(options = {}) {
346
385
  const env = options.env || process.env;
347
386
  const platform = options.platform || env.VLINK_PLATFORM || process.platform;
348
387
  const arch = options.arch || env.VLINK_ARCH || process.arch;
388
+ const skipSetup = Boolean(options.skipSetup);
349
389
  const home = options.home || os.homedir();
350
390
  const fsImpl = options.fs || fs;
351
391
  const output = options.output || process.stderr;
@@ -381,71 +421,64 @@ async function runInstaller(options = {}) {
381
421
  });
382
422
 
383
423
  if (vlinkPath) {
384
- log(`found vlink at ${vlinkPath}`, output);
424
+ log(
425
+ `found vlink at ${vlinkPath}; installing vlink ${installModule.VERSION}`,
426
+ output
427
+ );
385
428
  } else if (isExecutableFile(targetPath, platform, fsImpl)) {
386
429
  vlinkPath = targetPath;
387
430
  ensureUserPath(installDir, sharedOptions);
388
- log(`found vlink at ${vlinkPath}`, output);
431
+ log(
432
+ `found vlink at ${vlinkPath}; installing vlink ${installModule.VERSION}`,
433
+ output
434
+ );
389
435
  } else {
390
436
  log(`installing vlink ${installModule.VERSION}`, output);
391
- const sourcePath = await ensureBinary({});
392
- installBinary(sourcePath, targetPath, {
393
- ...sharedOptions,
394
- stopDaemon: false
395
- });
396
- ensureUserPath(installDir, sharedOptions);
397
- vlinkPath = targetPath;
398
437
  }
399
438
 
400
- const update = runVlinkUpdate(vlinkPath, { spawnSync: spawnSyncImpl });
401
- if (update.supported) {
402
- if (update.updateRequired) {
403
- log('a newer vlink release is available; applying it', output);
404
- if (
405
- update.installedPath &&
406
- isExecutableFile(update.installedPath, platform, fsImpl)
407
- ) {
408
- vlinkPath = update.installedPath;
409
- if (samePath(path.dirname(vlinkPath), installDir, platform)) {
410
- ensureUserPath(installDir, sharedOptions);
411
- }
412
- }
413
- } else {
414
- log('vlink is up to date', output);
415
- }
416
- } else {
417
- log('installed vlink does not support update checks; installing the latest release', output);
418
- const sourcePath = await ensureBinary({});
419
- installBinary(sourcePath, targetPath, {
420
- ...sharedOptions,
421
- stopDaemon: true
422
- });
439
+ const replacingExisting = Boolean(vlinkPath);
440
+ const installTarget = vlinkPath || targetPath;
441
+ const sourcePath = await ensureBinary({});
442
+ installBinary(sourcePath, installTarget, {
443
+ ...sharedOptions,
444
+ stopDaemon: replacingExisting
445
+ });
446
+ if (
447
+ !replacingExisting ||
448
+ samePath(path.dirname(installTarget), installDir, platform)
449
+ ) {
423
450
  ensureUserPath(installDir, sharedOptions);
424
- vlinkPath = targetPath;
425
451
  }
452
+ vlinkPath = installTarget;
426
453
 
427
454
  vlinkPath = await migrateStaticVlink(vlinkPath, spec, {
428
455
  ...sharedOptions,
429
456
  ensureBinary
430
457
  });
458
+ const commandShimPath = installWindowsCommandShim(vlinkPath, sharedOptions);
431
459
 
432
- log('starting TedBrain Agent setup', output);
433
- const setup = spawnSyncImpl(vlinkPath, ['setup', 'tedbrain'], {
434
- stdio: 'inherit'
435
- });
436
- const failure = commandFailure(setup, 'vlink setup tedbrain');
437
- if (failure) throw new VlinkSetupError(failure);
460
+ if (skipSetup) {
461
+ log('skipping TedBrain Agent setup', output);
462
+ } else {
463
+ log('starting TedBrain Agent setup', output);
464
+ const setup = spawnSyncImpl(vlinkPath, ['setup', 'tedbrain'], {
465
+ stdio: 'inherit'
466
+ });
467
+ const failure = commandFailure(setup, 'vlink setup tedbrain');
468
+ if (failure) throw new VlinkSetupError(failure);
469
+ }
438
470
 
439
- return { installDir, vlinkPath };
471
+ return { installDir, vlinkPath, commandShimPath, setupSkipped: skipSetup };
440
472
  }
441
473
 
442
474
  function printInstallHelp(output = process.stdout) {
443
475
  output.write(
444
476
  [
445
- 'Usage: npx -y @tedbrain/vlink@latest install',
477
+ 'Usage: npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install [--no-setup]',
478
+ '',
479
+ 'Installs or updates vlink and adds it to the user PATH.',
446
480
  '',
447
- 'Installs or updates vlink, adds it to the user PATH, and starts',
448
- 'the TedBrain setup wizard.'
481
+ ' --no-setup Install without starting the TedBrain setup wizard.'
449
482
  ].join('\n') + '\n'
450
483
  );
451
484
  }
@@ -455,10 +488,16 @@ async function runInstallerFromArgs(args, options = {}) {
455
488
  printInstallHelp(options.output || process.stdout);
456
489
  return null;
457
490
  }
458
- if (args.length > 0) {
459
- throw new VlinkSetupError(`unknown install option: ${args[0]}`);
491
+
492
+ let skipSetup = false;
493
+ for (const arg of args) {
494
+ if (arg === '--no-setup') {
495
+ skipSetup = true;
496
+ } else {
497
+ throw new VlinkSetupError(`unknown install option: ${arg}`);
498
+ }
460
499
  }
461
- return runInstaller(options);
500
+ return runInstaller({ ...options, skipSetup });
462
501
  }
463
502
 
464
503
  module.exports = {
@@ -472,6 +511,8 @@ module.exports = {
472
511
  ensureUserPath,
473
512
  runVlinkUpdate,
474
513
  installBinary,
514
+ windowsCommandShimPath,
515
+ installWindowsCommandShim,
475
516
  binaryIsStaticElf,
476
517
  runInstaller,
477
518
  runInstallerFromArgs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tedbrain/vlink",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "vlink Virtuoso bridge CLI installer. Installs the matching platform binary at npm install time, like Claude Code / Codex.",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {