openclaw-openviking-setup-helper 0.2.9-dev.0 → 0.2.9-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/install.js +219 -127
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -23,9 +23,9 @@
23
23
  */
24
24
 
25
25
  import { spawn } from "node:child_process";
26
- import { cp, mkdir, rm, writeFile } from "node:fs/promises";
27
- import { existsSync, readdirSync } from "node:fs";
28
- import { dirname, join, relative } from "node:path";
26
+ import { cp, mkdir, rm, writeFile } from "node:fs/promises";
27
+ import { existsSync, readdirSync } from "node:fs";
28
+ import { dirname, join, relative } from "node:path";
29
29
  import { createInterface } from "node:readline";
30
30
  import { fileURLToPath } from "node:url";
31
31
 
@@ -35,7 +35,7 @@ let REPO = process.env.REPO || "volcengine/OpenViking";
35
35
  // PLUGIN_VERSION takes precedence over BRANCH (legacy)
36
36
  let PLUGIN_VERSION = process.env.PLUGIN_VERSION || process.env.BRANCH || "main";
37
37
  const NPM_REGISTRY = process.env.NPM_REGISTRY || "https://registry.npmmirror.com";
38
- const PIP_INDEX_URL = process.env.PIP_INDEX_URL || "https://mirrors.volces.com/pypi/simple/";
38
+ const PIP_INDEX_URL = process.env.PIP_INDEX_URL || "https://mirrors.volces.com/pypi/simple/";
39
39
 
40
40
  const IS_WIN = process.platform === "win32";
41
41
  const HOME = process.env.HOME || process.env.USERPROFILE || "";
@@ -66,8 +66,8 @@ const FALLBACK_CURRENT = {
66
66
  id: "openviking",
67
67
  kind: "context-engine",
68
68
  slot: "contextEngine",
69
- required: ["index.ts", "context-engine.ts", "config.ts", "client.ts", "process-manager.ts", "memory-ranking.ts", "text-utils.ts", "session-transcript-repair.ts", "tool-call-id.ts", "openclaw.plugin.json", "package.json", "tsconfig.json"],
70
- optional: ["package-lock.json", ".gitignore"],
69
+ required: ["index.ts", "config.ts", "openclaw.plugin.json", "package.json"],
70
+ optional: ["context-engine.ts", "client.ts", "process-manager.ts", "memory-ranking.ts", "text-utils.ts", "session-transcript-repair.ts", "tool-call-id.ts", "tsconfig.json", "package-lock.json", ".gitignore"],
71
71
  };
72
72
 
73
73
  // Resolved plugin config (set by resolvePluginConfig)
@@ -75,11 +75,11 @@ let resolvedPluginDir = "";
75
75
  let resolvedPluginId = "";
76
76
  let resolvedPluginKind = "";
77
77
  let resolvedPluginSlot = "";
78
- let resolvedFilesRequired = [];
79
- let resolvedFilesOptional = [];
80
- let resolvedNpmOmitDev = true;
81
- let resolvedMinOpenclawVersion = "";
82
- let resolvedMinOpenvikingVersion = "";
78
+ let resolvedFilesRequired = [];
79
+ let resolvedFilesOptional = [];
80
+ let resolvedNpmOmitDev = true;
81
+ let resolvedMinOpenclawVersion = "";
82
+ let resolvedMinOpenvikingVersion = "";
83
83
 
84
84
  let installYes = process.env.OPENVIKING_INSTALL_YES === "1";
85
85
  let langZh = false;
@@ -296,8 +296,19 @@ function question(prompt, defaultValue = "") {
296
296
  });
297
297
  }
298
298
 
299
+ async function resolveAbsoluteCommand(cmd) {
300
+ if (cmd.startsWith("/") || (IS_WIN && /^[A-Za-z]:[/\\]/.test(cmd))) return cmd;
301
+ if (IS_WIN) {
302
+ const r = await runCapture("where", [cmd], { shell: true });
303
+ return r.out.split(/\r?\n/)[0]?.trim() || cmd;
304
+ }
305
+ const r = await runCapture("which", [cmd], { shell: false });
306
+ return r.out.trim() || cmd;
307
+ }
308
+
299
309
  async function checkPython() {
300
- const py = process.env.OPENVIKING_PYTHON || (IS_WIN ? "python" : "python3");
310
+ const raw = process.env.OPENVIKING_PYTHON || (IS_WIN ? "python" : "python3");
311
+ const py = await resolveAbsoluteCommand(raw);
301
312
  const result = await runCapture(py, ["-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"]);
302
313
  if (result.code !== 0 || !result.out) {
303
314
  return {
@@ -452,7 +463,7 @@ async function checkOpenClaw() {
452
463
  }
453
464
 
454
465
  // Compare versions: returns true if v1 >= v2
455
- function versionGte(v1, v2) {
466
+ function versionGte(v1, v2) {
456
467
  const parseVersion = (v) => {
457
468
  const cleaned = v.replace(/^v/, "").replace(/-.*$/, "");
458
469
  const parts = cleaned.split(".").map((p) => Number.parseInt(p, 10) || 0);
@@ -463,12 +474,12 @@ function versionGte(v1, v2) {
463
474
  const [b1, b2, b3] = parseVersion(v2);
464
475
  if (a1 !== b1) return a1 > b1;
465
476
  if (a2 !== b2) return a2 > b2;
466
- return a3 >= b3;
467
- }
468
-
469
- function isSemverLike(value) {
470
- return /^v?\d+(\.\d+){1,2}$/.test(value);
471
- }
477
+ return a3 >= b3;
478
+ }
479
+
480
+ function isSemverLike(value) {
481
+ return /^v?\d+(\.\d+){1,2}$/.test(value);
482
+ }
472
483
 
473
484
  // Detect OpenClaw version
474
485
  async function detectOpenClawVersion() {
@@ -547,19 +558,40 @@ async function resolvePluginConfig() {
547
558
 
548
559
  resolvedPluginDir = pluginDir;
549
560
 
550
- if (manifestData) {
551
- resolvedPluginId = manifestData.plugin?.id || "";
552
- resolvedPluginKind = manifestData.plugin?.kind || "";
553
- resolvedPluginSlot = manifestData.plugin?.slot || "";
554
- resolvedMinOpenclawVersion = manifestData.compatibility?.minOpenclawVersion || "";
555
- resolvedMinOpenvikingVersion = manifestData.compatibility?.minOpenvikingVersion || "";
556
- resolvedNpmOmitDev = manifestData.npm?.omitDev !== false;
557
- resolvedFilesRequired = manifestData.files?.required || [];
558
- resolvedFilesOptional = manifestData.files?.optional || [];
559
- } else {
560
- // Use fallback config
561
- const fallback = pluginDir === "openclaw-memory-plugin" ? FALLBACK_LEGACY : FALLBACK_CURRENT;
562
- resolvedPluginDir = fallback.dir;
561
+ if (manifestData) {
562
+ resolvedPluginId = manifestData.plugin?.id || "";
563
+ resolvedPluginKind = manifestData.plugin?.kind || "";
564
+ resolvedPluginSlot = manifestData.plugin?.slot || "";
565
+ resolvedMinOpenclawVersion = manifestData.compatibility?.minOpenclawVersion || "";
566
+ resolvedMinOpenvikingVersion = manifestData.compatibility?.minOpenvikingVersion || "";
567
+ resolvedNpmOmitDev = manifestData.npm?.omitDev !== false;
568
+ resolvedFilesRequired = manifestData.files?.required || [];
569
+ resolvedFilesOptional = manifestData.files?.optional || [];
570
+ } else {
571
+ // No manifest — determine plugin identity by package.json name
572
+ let fallbackKey = pluginDir === "openclaw-memory-plugin" ? "legacy" : "current";
573
+ let compatVer = "";
574
+
575
+ const pkgJson = await tryFetch(`${ghRaw}/examples/${pluginDir}/package.json`);
576
+ if (pkgJson) {
577
+ try {
578
+ const pkg = JSON.parse(pkgJson);
579
+ const pkgName = pkg.name || "";
580
+ if (pkgName && pkgName !== "@openclaw/openviking") {
581
+ fallbackKey = "legacy";
582
+ info(tr(`Detected legacy plugin by package name: ${pkgName}`, `通过 package.json 名称检测到旧版插件: ${pkgName}`));
583
+ } else if (pkgName) {
584
+ fallbackKey = "current";
585
+ }
586
+ compatVer = (pkg.engines?.openclaw || "").replace(/^>=?\s*/, "").trim();
587
+ if (compatVer) {
588
+ info(tr(`Read minOpenclawVersion from package.json engines.openclaw: >=${compatVer}`, `从 package.json engines.openclaw 读取到最低版本: >=${compatVer}`));
589
+ }
590
+ } catch {}
591
+ }
592
+
593
+ const fallback = fallbackKey === "legacy" ? FALLBACK_LEGACY : FALLBACK_CURRENT;
594
+ resolvedPluginDir = pluginDir;
563
595
  resolvedPluginId = fallback.id;
564
596
  resolvedPluginKind = fallback.kind;
565
597
  resolvedPluginSlot = fallback.slot;
@@ -567,13 +599,24 @@ async function resolvePluginConfig() {
567
599
  resolvedFilesOptional = fallback.optional;
568
600
  resolvedNpmOmitDev = true;
569
601
 
570
- if (pluginDir === "openclaw-plugin") {
571
- resolvedMinOpenclawVersion = "3.7";
572
- } else {
573
- resolvedMinOpenclawVersion = "";
574
- }
575
- resolvedMinOpenvikingVersion = "";
576
- }
602
+ // If no compatVer from package.json, try main branch manifest
603
+ if (!compatVer && PLUGIN_VERSION !== "main") {
604
+ const mainRaw = `https://raw.githubusercontent.com/${REPO}/main`;
605
+ const mainManifest = await tryFetch(`${mainRaw}/examples/openclaw-plugin/install-manifest.json`);
606
+ if (mainManifest) {
607
+ try {
608
+ const m = JSON.parse(mainManifest);
609
+ compatVer = m.compatibility?.minOpenclawVersion || "";
610
+ if (compatVer) {
611
+ info(tr(`Read minOpenclawVersion from main branch manifest: >=${compatVer}`, `从 main 分支 manifest 读取到最低版本: >=${compatVer}`));
612
+ }
613
+ } catch {}
614
+ }
615
+ }
616
+
617
+ resolvedMinOpenclawVersion = compatVer || "2026.3.7";
618
+ resolvedMinOpenvikingVersion = "";
619
+ }
577
620
 
578
621
  // Set plugin destination
579
622
  PLUGIN_DEST = join(OPENCLAW_DIR, "extensions", resolvedPluginId);
@@ -596,9 +639,9 @@ async function checkOpenClawCompatibility() {
596
639
  }
597
640
 
598
641
  // If user explicitly requested an old version, pass
599
- if (PLUGIN_VERSION !== "main" && isSemverLike(PLUGIN_VERSION) && !versionGte(PLUGIN_VERSION, "v0.2.9")) {
600
- return;
601
- }
642
+ if (PLUGIN_VERSION !== "main" && isSemverLike(PLUGIN_VERSION) && !versionGte(PLUGIN_VERSION, "v0.2.9")) {
643
+ return;
644
+ }
602
645
 
603
646
  // Check compatibility
604
647
  if (!versionGte(ocVersion, resolvedMinOpenclawVersion)) {
@@ -610,32 +653,32 @@ async function checkOpenClawCompatibility() {
610
653
  bold(tr("Please choose one of the following options:", "请选择以下方案之一:"));
611
654
  console.log("");
612
655
  console.log(` ${tr("Option 1: Upgrade OpenClaw", "方案 1:升级 OpenClaw")}`);
613
- console.log(` npm update -g openclaw --registry ${NPM_REGISTRY}`);
656
+ console.log(` npm update -g openclaw --registry ${NPM_REGISTRY}`);
614
657
  console.log("");
615
658
  console.log(` ${tr("Option 2: Install legacy plugin (v0.2.8)", "方案 2:安装旧版插件 (v0.2.8)")}`);
616
659
  console.log(` node install.js --plugin-version=v0.2.8${langZh ? " --zh" : ""}`);
617
660
  console.log("");
618
661
  process.exit(1);
619
662
  }
620
- }
621
-
622
- function checkRequestedOpenVikingCompatibility() {
623
- if (!resolvedMinOpenvikingVersion || !openvikingVersion) return;
624
- if (versionGte(openvikingVersion, resolvedMinOpenvikingVersion)) return;
625
-
626
- err(tr(
627
- `OpenViking ${openvikingVersion} does not support this plugin (requires >= ${resolvedMinOpenvikingVersion})`,
628
- `OpenViking ${openvikingVersion} 不支持此插件(需要 >= ${resolvedMinOpenvikingVersion})`,
629
- ));
630
- console.log("");
631
- console.log(tr(
632
- "Use a newer OpenViking version, or omit --openviking-version to install the latest release.",
633
- "请使用更新版本的 OpenViking,或省略 --openviking-version 以安装最新版本。",
634
- ));
635
- process.exit(1);
636
- }
637
-
638
- async function installOpenViking() {
663
+ }
664
+
665
+ function checkRequestedOpenVikingCompatibility() {
666
+ if (!resolvedMinOpenvikingVersion || !openvikingVersion) return;
667
+ if (versionGte(openvikingVersion, resolvedMinOpenvikingVersion)) return;
668
+
669
+ err(tr(
670
+ `OpenViking ${openvikingVersion} does not support this plugin (requires >= ${resolvedMinOpenvikingVersion})`,
671
+ `OpenViking ${openvikingVersion} 不支持此插件(需要 >= ${resolvedMinOpenvikingVersion})`,
672
+ ));
673
+ console.log("");
674
+ console.log(tr(
675
+ "Use a newer OpenViking version, or omit --openviking-version to install the latest release.",
676
+ "请使用更新版本的 OpenViking,或省略 --openviking-version 以安装最新版本。",
677
+ ));
678
+ process.exit(1);
679
+ }
680
+
681
+ async function installOpenViking() {
639
682
  if (process.env.SKIP_OPENVIKING === "1") {
640
683
  info(tr("Skipping OpenViking install (SKIP_OPENVIKING=1)", "跳过 OpenViking 安装 (SKIP_OPENVIKING=1)"));
641
684
  return;
@@ -646,6 +689,12 @@ async function installOpenViking() {
646
689
  err(tr("Python check failed.", "Python 校验失败"));
647
690
  process.exit(1);
648
691
  }
692
+ if (!python.ok) {
693
+ warn(tr(
694
+ `${python.detail}. Will attempt to find a suitable Python for pip install.`,
695
+ `${python.detail}。将尝试查找合适的 Python 进行 pip 安装。`,
696
+ ));
697
+ }
649
698
 
650
699
  const py = python.cmd;
651
700
 
@@ -809,20 +858,20 @@ async function configureOvConf() {
809
858
  rotation_days: 3,
810
859
  rotation_interval: "midnight",
811
860
  },
812
- embedding: {
813
- dense: {
814
- provider: "volcengine",
815
- api_key: embeddingApiKey || null,
816
- model: embeddingModel,
817
- api_base: "https://ark.cn-beijing.volces.com/api/v3",
861
+ embedding: {
862
+ dense: {
863
+ provider: "volcengine",
864
+ api_key: embeddingApiKey || null,
865
+ model: embeddingModel,
866
+ api_base: "https://ark.cn-beijing.volces.com/api/v3",
818
867
  dimension: 1024,
819
868
  input: "multimodal",
820
869
  },
821
- },
822
- vlm: {
823
- provider: "volcengine",
824
- api_key: vlmApiKey || null,
825
- model: vlmModel,
870
+ },
871
+ vlm: {
872
+ provider: "volcengine",
873
+ api_key: vlmApiKey || null,
874
+ model: vlmModel,
826
875
  api_base: "https://ark.cn-beijing.volces.com/api/v3",
827
876
  temperature: 0.1,
828
877
  max_retries: 3,
@@ -903,29 +952,29 @@ async function downloadPlugin() {
903
952
 
904
953
  // npm install
905
954
  info(tr("Installing plugin npm dependencies...", "正在安装插件 npm 依赖..."));
906
- const npmArgs = resolvedNpmOmitDev
907
- ? ["install", "--omit=dev", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY]
908
- : ["install", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY];
909
- await run("npm", npmArgs, { cwd: PLUGIN_DEST, silent: false });
955
+ const npmArgs = resolvedNpmOmitDev
956
+ ? ["install", "--omit=dev", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY]
957
+ : ["install", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY];
958
+ await run("npm", npmArgs, { cwd: PLUGIN_DEST, silent: false });
910
959
  info(tr(`Plugin deployed: ${PLUGIN_DEST}`, `插件部署完成: ${PLUGIN_DEST}`));
911
960
  }
912
961
 
913
- async function deployLocalPlugin(localPluginDir) {
914
- await rm(PLUGIN_DEST, { recursive: true, force: true });
915
- await mkdir(PLUGIN_DEST, { recursive: true });
916
- await cp(localPluginDir, PLUGIN_DEST, {
917
- recursive: true,
918
- force: true,
919
- filter: (sourcePath) => {
920
- const rel = relative(localPluginDir, sourcePath);
921
- if (!rel) return true;
922
- const firstSegment = rel.split(/[\\/]/)[0];
923
- return firstSegment !== "node_modules" && firstSegment !== ".git";
924
- },
925
- });
926
- }
927
-
928
- async function configureOpenClawPlugin() {
962
+ async function deployLocalPlugin(localPluginDir) {
963
+ await rm(PLUGIN_DEST, { recursive: true, force: true });
964
+ await mkdir(PLUGIN_DEST, { recursive: true });
965
+ await cp(localPluginDir, PLUGIN_DEST, {
966
+ recursive: true,
967
+ force: true,
968
+ filter: (sourcePath) => {
969
+ const rel = relative(localPluginDir, sourcePath);
970
+ if (!rel) return true;
971
+ const firstSegment = rel.split(/[\\/]/)[0];
972
+ return firstSegment !== "node_modules" && firstSegment !== ".git";
973
+ },
974
+ });
975
+ }
976
+
977
+ async function configureOpenClawPlugin() {
929
978
  info(tr("Configuring OpenClaw plugin...", "正在配置 OpenClaw 插件..."));
930
979
 
931
980
  const pluginId = resolvedPluginId;
@@ -936,18 +985,18 @@ async function configureOpenClawPlugin() {
936
985
  ocEnv.OPENCLAW_STATE_DIR = OPENCLAW_DIR;
937
986
  }
938
987
 
939
- const oc = async (args) => {
940
- const result = await runCapture("openclaw", args, { env: ocEnv, shell: IS_WIN });
941
- if (result.code !== 0) {
942
- const detail = result.err || result.out;
943
- throw new Error(`openclaw ${args.join(" ")} failed (exit code ${result.code})${detail ? `: ${detail}` : ""}`);
944
- }
945
- return result;
946
- };
947
-
948
- // Enable plugin (files already deployed to extensions dir by deployPlugin)
949
- await oc(["plugins", "enable", pluginId]);
950
- await oc(["config", "set", `plugins.slots.${pluginSlot}`, pluginId]);
988
+ const oc = async (args) => {
989
+ const result = await runCapture("openclaw", args, { env: ocEnv, shell: IS_WIN });
990
+ if (result.code !== 0) {
991
+ const detail = result.err || result.out;
992
+ throw new Error(`openclaw ${args.join(" ")} failed (exit code ${result.code})${detail ? `: ${detail}` : ""}`);
993
+ }
994
+ return result;
995
+ };
996
+
997
+ // Enable plugin (files already deployed to extensions dir by deployPlugin)
998
+ await oc(["plugins", "enable", pluginId]);
999
+ await oc(["config", "set", `plugins.slots.${pluginSlot}`, pluginId]);
951
1000
 
952
1001
  // Set gateway mode
953
1002
  await oc(["config", "set", "gateway.mode", "local"]);
@@ -969,22 +1018,34 @@ async function configureOpenClawPlugin() {
969
1018
  }
970
1019
  }
971
1020
 
1021
+ // Legacy (memory) plugins need explicit targetUri/autoRecall/autoCapture (new version has defaults in config.ts)
1022
+ if (resolvedPluginKind === "memory") {
1023
+ await oc(["config", "set", `plugins.entries.${pluginId}.config.targetUri`, "viking://user/memories"]);
1024
+ await oc(["config", "set", `plugins.entries.${pluginId}.config.autoRecall`, "true", "--json"]);
1025
+ await oc(["config", "set", `plugins.entries.${pluginId}.config.autoCapture`, "true", "--json"]);
1026
+ }
1027
+
972
1028
  info(tr("OpenClaw plugin configured", "OpenClaw 插件配置完成"));
973
1029
  }
974
1030
 
1031
+ async function discoverOpenvikingPython(failedPy) {
1032
+ const candidates = IS_WIN
1033
+ ? ["python3", "python", "py -3"]
1034
+ : ["python3.13", "python3.12", "python3.11", "python3.10", "python3", "python"];
1035
+ for (const candidate of candidates) {
1036
+ if (candidate === failedPy) continue;
1037
+ const resolved = await resolveAbsoluteCommand(candidate);
1038
+ if (!resolved || resolved === candidate || resolved === failedPy) continue;
1039
+ const check = await runCapture(resolved, ["-c", "import openviking"], { shell: false });
1040
+ if (check.code === 0) return resolved;
1041
+ }
1042
+ return "";
1043
+ }
1044
+
975
1045
  async function resolvePythonPath() {
976
1046
  if (openvikingPythonPath) return openvikingPythonPath;
977
1047
  const python = await checkPython();
978
- const py = python.cmd;
979
- if (!py) return "";
980
-
981
- if (IS_WIN) {
982
- const result = await runCapture("where", [py], { shell: true });
983
- return result.out.split(/\r?\n/)[0]?.trim() || py;
984
- }
985
-
986
- const result = await runCapture("which", [py], { shell: false });
987
- return result.out.trim() || py;
1048
+ return python.cmd || "";
988
1049
  }
989
1050
 
990
1051
  async function writeOpenvikingEnv({ includePython }) {
@@ -1001,6 +1062,37 @@ async function writeOpenvikingEnv({ includePython }) {
1001
1062
  ),
1002
1063
  );
1003
1064
  }
1065
+
1066
+ // Verify the resolved Python can actually import openviking
1067
+ if (pythonPath) {
1068
+ const verify = await runCapture(pythonPath, ["-c", "import openviking"], { shell: false });
1069
+ if (verify.code !== 0) {
1070
+ warn(
1071
+ tr(
1072
+ `Resolved Python (${pythonPath}) cannot import openviking. The pip install target may differ from the runtime python3.`,
1073
+ `解析到的 Python(${pythonPath})无法 import openviking。pip 安装目标可能与运行时的 python3 不一致。`,
1074
+ ),
1075
+ );
1076
+ // Try to discover the correct Python via pip show
1077
+ const corrected = await discoverOpenvikingPython(pythonPath);
1078
+ if (corrected) {
1079
+ info(
1080
+ tr(
1081
+ `Auto-corrected OPENVIKING_PYTHON to ${corrected}`,
1082
+ `已自动修正 OPENVIKING_PYTHON 为 ${corrected}`,
1083
+ ),
1084
+ );
1085
+ pythonPath = corrected;
1086
+ } else {
1087
+ warn(
1088
+ tr(
1089
+ `Could not auto-detect the correct Python. Edit OPENVIKING_PYTHON in the env file manually.`,
1090
+ `无法自动检测正确的 Python。请手动修改 env 文件中的 OPENVIKING_PYTHON。`,
1091
+ ),
1092
+ );
1093
+ }
1094
+ }
1095
+ }
1004
1096
  }
1005
1097
 
1006
1098
  // Remote mode + default state dir + no python line → nothing to persist
@@ -1069,11 +1161,11 @@ async function main() {
1069
1161
  if (selectedMode === "local") {
1070
1162
  await validateEnvironment();
1071
1163
  await checkOpenClaw();
1072
- // Resolve plugin config after OpenClaw is available (for version detection)
1073
- await resolvePluginConfig();
1074
- await checkOpenClawCompatibility();
1075
- checkRequestedOpenVikingCompatibility();
1076
- await installOpenViking();
1164
+ // Resolve plugin config after OpenClaw is available (for version detection)
1165
+ await resolvePluginConfig();
1166
+ await checkOpenClawCompatibility();
1167
+ checkRequestedOpenVikingCompatibility();
1168
+ await installOpenViking();
1077
1169
  await configureOvConf();
1078
1170
  } else {
1079
1171
  await checkOpenClaw();
@@ -1088,19 +1180,19 @@ async function main() {
1088
1180
  pluginPath = localPluginDir;
1089
1181
  PLUGIN_DEST = join(OPENCLAW_DIR, "extensions", resolvedPluginId || "openviking");
1090
1182
  info(tr(`Using local plugin from repo: ${pluginPath}`, `使用仓库内插件: ${pluginPath}`));
1091
- await deployLocalPlugin(pluginPath);
1183
+ await deployLocalPlugin(pluginPath);
1092
1184
  info(tr("Installing plugin npm dependencies...", "正在安装插件 npm 依赖..."));
1093
- const npmArgs = resolvedNpmOmitDev
1094
- ? ["install", "--omit=dev", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY]
1095
- : ["install", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY];
1096
- await run("npm", npmArgs, { cwd: PLUGIN_DEST, silent: false });
1097
- pluginPath = PLUGIN_DEST;
1185
+ const npmArgs = resolvedNpmOmitDev
1186
+ ? ["install", "--omit=dev", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY]
1187
+ : ["install", "--no-audit", "--no-fund", "--registry", NPM_REGISTRY];
1188
+ await run("npm", npmArgs, { cwd: PLUGIN_DEST, silent: false });
1189
+ pluginPath = PLUGIN_DEST;
1098
1190
  } else {
1099
1191
  await downloadPlugin();
1100
1192
  pluginPath = PLUGIN_DEST;
1101
1193
  }
1102
1194
 
1103
- await configureOpenClawPlugin();
1195
+ await configureOpenClawPlugin();
1104
1196
  const envFiles = await writeOpenvikingEnv({
1105
1197
  includePython: selectedMode === "local",
1106
1198
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-openviking-setup-helper",
3
- "version": "0.2.9-dev.0",
3
+ "version": "0.2.9-dev.1",
4
4
  "description": "Setup helper for installing OpenViking memory plugin into OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {