openclaw-openviking-setup-helper 0.2.13 → 0.2.14

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 (2) hide show
  1. package/install.js +75 -11
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * Environment variables:
17
17
  * REPO, PLUGIN_VERSION (or BRANCH), OPENVIKING_INSTALL_YES, SKIP_OPENCLAW, SKIP_OPENVIKING
18
- * OPENVIKING_VERSION Pip install openviking==VERSION (omit for latest)
18
+ * OPENVIKING_VERSION Pip install openviking==VERSION (omit to follow release plugin version when possible)
19
19
  * OPENVIKING_REPO Repo path: source install (pip -e) + local plugin (default: off)
20
20
  * NPM_REGISTRY, PIP_INDEX_URL
21
21
  * OPENVIKING_VLM_API_KEY, OPENVIKING_EMBEDDING_API_KEY, OPENVIKING_ARK_API_KEY
@@ -37,7 +37,9 @@ const pluginVersionEnv = (process.env.PLUGIN_VERSION || process.env.BRANCH || ""
37
37
  let PLUGIN_VERSION = pluginVersionEnv;
38
38
  let pluginVersionExplicit = Boolean(pluginVersionEnv);
39
39
  const NPM_REGISTRY = process.env.NPM_REGISTRY || "https://registry.npmmirror.com";
40
- const PIP_INDEX_URL = process.env.PIP_INDEX_URL || "https://mirrors.volces.com/pypi/simple/";
40
+ const DEFAULT_PIP_INDEX_URL = "https://mirrors.volces.com/pypi/simple/";
41
+ const OFFICIAL_PIP_INDEX_URL = "https://pypi.org/simple/";
42
+ const PIP_INDEX_URL = process.env.PIP_INDEX_URL || DEFAULT_PIP_INDEX_URL;
41
43
 
42
44
  const IS_WIN = process.platform === "win32";
43
45
  const HOME = process.env.HOME || process.env.USERPROFILE || "";
@@ -271,6 +273,33 @@ function normalizeCombinedVersion(version) {
271
273
  };
272
274
  }
273
275
 
276
+ function deriveOpenvikingVersionFromPluginVersion(version) {
277
+ const value = (version || "").trim();
278
+ if (!isSemverLike(value)) {
279
+ return "";
280
+ }
281
+ return value.startsWith("v") ? value.slice(1) : value;
282
+ }
283
+
284
+ function syncOpenvikingVersionWithPluginVersion(reason = "") {
285
+ if (openvikingVersion) {
286
+ return;
287
+ }
288
+
289
+ const derivedVersion = deriveOpenvikingVersionFromPluginVersion(PLUGIN_VERSION);
290
+ if (!derivedVersion) {
291
+ return;
292
+ }
293
+
294
+ openvikingVersion = derivedVersion;
295
+ info(tr(
296
+ `No OpenViking version specified; syncing runtime version to plugin version ${PLUGIN_VERSION}${reason ? ` (${reason})` : ""}.`,
297
+ `未指定 OpenViking 版本;已将运行时版本同步为插件版本 ${PLUGIN_VERSION}${reason ? `(${reason})` : ""}。`,
298
+ ));
299
+ }
300
+
301
+ syncOpenvikingVersionWithPluginVersion("requested plugin version");
302
+
274
303
  function printHelp() {
275
304
  console.log("Usage: node install.js [ OPTIONS ]");
276
305
  console.log("");
@@ -278,7 +307,7 @@ function printHelp() {
278
307
  console.log(" --github-repo=OWNER/REPO GitHub repository (default: volcengine/OpenViking)");
279
308
  console.log(" --version=V Shorthand for --plugin-version=vV and --openviking-version=V");
280
309
  console.log(" --plugin-version=TAG Plugin version (Git tag, e.g. v0.2.9, default: latest tag)");
281
- console.log(" --openviking-version=V OpenViking PyPI version (e.g. 0.2.9, default: latest)");
310
+ console.log(" --openviking-version=V OpenViking PyPI version (e.g. 0.2.9, default: match plugin release version)");
282
311
  console.log(" --workdir PATH OpenClaw config directory (default: ~/.openclaw)");
283
312
  console.log(" --current-version Print installed plugin/OpenViking versions and exit");
284
313
  console.log(" --repo=PATH Use local OpenViking repo at PATH (pip -e + local plugin)");
@@ -434,6 +463,34 @@ function runLiveCapture(cmd, args, opts = {}) {
434
463
  });
435
464
  }
436
465
 
466
+ function shouldFallbackToOfficialPypi(output) {
467
+ if (process.env.PIP_INDEX_URL?.trim()) return false;
468
+ if (PIP_INDEX_URL !== DEFAULT_PIP_INDEX_URL) return false;
469
+
470
+ return /Could not find a version that satisfies the requirement|No matching distribution found|HTTP error 404|too many 502 error responses|Temporary failure in name resolution|Failed to establish a new connection|Connection (?:timed out|reset by peer)|Read timed out|ProxyError|SSLError|TLSV1_ALERT|Remote end closed connection/i.test(output);
471
+ }
472
+
473
+ async function runPipInstallWithFallback(py, pipArgs, opts = {}) {
474
+ const shell = opts.shell ?? false;
475
+ const primaryResult = await runLiveCapture(py, [...pipArgs, "-i", PIP_INDEX_URL], { shell });
476
+ if (primaryResult.code === 0) {
477
+ return { result: primaryResult, usedFallback: false };
478
+ }
479
+
480
+ const primaryOutput = `${primaryResult.out}\n${primaryResult.err}`;
481
+ if (!shouldFallbackToOfficialPypi(primaryOutput)) {
482
+ return { result: primaryResult, usedFallback: false };
483
+ }
484
+
485
+ warn(tr(
486
+ `Install from mirror failed. Retrying with official PyPI: ${OFFICIAL_PIP_INDEX_URL}`,
487
+ `镜像源安装失败,正在回退到官方 PyPI: ${OFFICIAL_PIP_INDEX_URL}`,
488
+ ));
489
+
490
+ const fallbackResult = await runLiveCapture(py, [...pipArgs, "-i", OFFICIAL_PIP_INDEX_URL], { shell });
491
+ return { result: fallbackResult, usedFallback: true, primaryResult, fallbackResult };
492
+ }
493
+
437
494
  function question(prompt, defaultValue = "") {
438
495
  const rl = createInterface({ input: process.stdin, output: process.stdout });
439
496
  const suffix = defaultValue ? ` [${defaultValue}]` : "";
@@ -762,6 +819,7 @@ async function resolveDefaultPluginVersion() {
762
819
  const latestTag = pickLatestPluginTag(payload.map((item) => item?.name || ""));
763
820
  if (latestTag) {
764
821
  PLUGIN_VERSION = latestTag;
822
+ syncOpenvikingVersionWithPluginVersion("latest plugin tag");
765
823
  info(tr(
766
824
  `Resolved default plugin version to latest tag: ${PLUGIN_VERSION}`,
767
825
  `已将默认插件版本解析为最新 tag: ${PLUGIN_VERSION}`,
@@ -786,6 +844,7 @@ async function resolveDefaultPluginVersion() {
786
844
  const latestTag = pickLatestPluginTag(parseGitLsRemoteTags(gitResult.out));
787
845
  if (latestTag) {
788
846
  PLUGIN_VERSION = latestTag;
847
+ syncOpenvikingVersionWithPluginVersion("latest plugin tag");
789
848
  info(tr(
790
849
  `Resolved default plugin version via git tags: ${PLUGIN_VERSION}`,
791
850
  `已通过 git tag 解析默认插件版本: ${PLUGIN_VERSION}`,
@@ -1013,9 +1072,9 @@ async function installOpenViking() {
1013
1072
 
1014
1073
  info(`Package: ${pkgSpec}`);
1015
1074
  await runCapture(py, ["-m", "pip", "install", "--upgrade", "pip", "-q", "-i", PIP_INDEX_URL], { shell: false });
1016
- const installResult = await runLiveCapture(
1075
+ const { result: installResult } = await runPipInstallWithFallback(
1017
1076
  py,
1018
- ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
1077
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec],
1019
1078
  { shell: false },
1020
1079
  );
1021
1080
  if (installResult.code === 0) {
@@ -1033,11 +1092,16 @@ async function installOpenViking() {
1033
1092
  if (existsSync(venvPy)) {
1034
1093
  const reuseCheck = await runCapture(venvPy, ["-c", "import openviking"], { shell: false });
1035
1094
  if (reuseCheck.code === 0) {
1036
- await runLiveCapture(
1095
+ const { result: venvReuseInstall } = await runPipInstallWithFallback(
1037
1096
  venvPy,
1038
- ["-m", "pip", "install", "--progress-bar", "on", "-U", pkgSpec, "-i", PIP_INDEX_URL],
1097
+ ["-m", "pip", "install", "--progress-bar", "on", "-U", pkgSpec],
1039
1098
  { shell: false },
1040
1099
  );
1100
+ if (venvReuseInstall.code !== 0) {
1101
+ err(tr("OpenViking install failed in venv.", "在虚拟环境中安装 OpenViking 失败。"));
1102
+ console.log(venvReuseInstall.err || venvReuseInstall.out);
1103
+ process.exit(1);
1104
+ }
1041
1105
  openvikingPythonPath = venvPy;
1042
1106
  info(tr("OpenViking installed ✓ (venv)", "OpenViking 安装完成 ✓(虚拟环境)"));
1043
1107
  return;
@@ -1069,9 +1133,9 @@ async function installOpenViking() {
1069
1133
  }
1070
1134
 
1071
1135
  await runCapture(venvPy, ["-m", "pip", "install", "--upgrade", "pip", "-q", "-i", PIP_INDEX_URL], { shell: false });
1072
- const venvInstall = await runLiveCapture(
1136
+ const { result: venvInstall } = await runPipInstallWithFallback(
1073
1137
  venvPy,
1074
- ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
1138
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec],
1075
1139
  { shell: false },
1076
1140
  );
1077
1141
  if (venvInstall.code === 0) {
@@ -1086,9 +1150,9 @@ async function installOpenViking() {
1086
1150
  }
1087
1151
 
1088
1152
  if (process.env.OPENVIKING_ALLOW_BREAK_SYSTEM_PACKAGES === "1") {
1089
- const systemInstall = await runLiveCapture(
1153
+ const { result: systemInstall } = await runPipInstallWithFallback(
1090
1154
  py,
1091
- ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", "--break-system-packages", pkgSpec, "-i", PIP_INDEX_URL],
1155
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", "--break-system-packages", pkgSpec],
1092
1156
  { shell: false },
1093
1157
  );
1094
1158
  if (systemInstall.code === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-openviking-setup-helper",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "description": "Setup helper for installing OpenViking memory plugin into OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {