openclaw-openviking-setup-helper 0.2.11 → 0.2.12

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 +289 -155
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Direct run:
13
13
  * node install.js [ -y | --yes ] [ --zh ] [ --workdir PATH ] [ --upgrade-plugin ]
14
- * [ --plugin-version=TAG ] [ --openviking-version=V ] [ --repo=PATH ]
14
+ * [ --plugin-version=TAG ] [ --openviking-version=V ] [ --version=V ] [ --repo=PATH ]
15
15
  *
16
16
  * Environment variables:
17
17
  * REPO, PLUGIN_VERSION (or BRANCH), OPENVIKING_INSTALL_YES, SKIP_OPENCLAW, SKIP_OPENVIKING
@@ -31,11 +31,11 @@ import { fileURLToPath } from "node:url";
31
31
 
32
32
  const __dirname = dirname(fileURLToPath(import.meta.url));
33
33
 
34
- let REPO = process.env.REPO || "volcengine/OpenViking";
35
- // PLUGIN_VERSION takes precedence over BRANCH (legacy). If omitted, resolve the latest tag from GitHub.
36
- const pluginVersionEnv = (process.env.PLUGIN_VERSION || process.env.BRANCH || "").trim();
37
- let PLUGIN_VERSION = pluginVersionEnv;
38
- let pluginVersionExplicit = Boolean(pluginVersionEnv);
34
+ let REPO = process.env.REPO || "volcengine/OpenViking";
35
+ // PLUGIN_VERSION takes precedence over BRANCH (legacy). If omitted, resolve the latest tag from GitHub.
36
+ const pluginVersionEnv = (process.env.PLUGIN_VERSION || process.env.BRANCH || "").trim();
37
+ let PLUGIN_VERSION = pluginVersionEnv;
38
+ let pluginVersionExplicit = Boolean(pluginVersionEnv);
39
39
  const NPM_REGISTRY = process.env.NPM_REGISTRY || "https://registry.npmmirror.com";
40
40
  const PIP_INDEX_URL = process.env.PIP_INDEX_URL || "https://mirrors.volces.com/pypi/simple/";
41
41
 
@@ -109,6 +109,11 @@ let openvikingRepo = process.env.OPENVIKING_REPO || "";
109
109
  let workdirExplicit = false;
110
110
  let upgradePluginOnly = false;
111
111
  let rollbackLastUpgrade = false;
112
+ let combinedVersion = "";
113
+ let combinedVersionExplicit = false;
114
+ let pluginVersionArgExplicit = false;
115
+ let openvikingVersionArgExplicit = false;
116
+ let showCurrentVersion = false;
112
117
 
113
118
  let selectedMode = "local";
114
119
  let selectedServerPort = DEFAULT_SERVER_PORT;
@@ -131,6 +136,10 @@ for (let i = 0; i < argv.length; i++) {
131
136
  langZh = true;
132
137
  continue;
133
138
  }
139
+ if (arg === "--current-version") {
140
+ showCurrentVersion = true;
141
+ continue;
142
+ }
134
143
  if (arg === "--upgrade-plugin" || arg === "--update" || arg === "--upgrade") {
135
144
  upgradePluginOnly = true;
136
145
  continue;
@@ -150,29 +159,32 @@ for (let i = 0; i < argv.length; i++) {
150
159
  i += 1;
151
160
  continue;
152
161
  }
153
- if (arg.startsWith("--plugin-version=")) {
154
- const version = arg.slice("--plugin-version=".length).trim();
155
- if (!version) {
156
- console.error("--plugin-version requires a value");
157
- process.exit(1);
158
- }
159
- PLUGIN_VERSION = version;
160
- pluginVersionExplicit = true;
161
- continue;
162
- }
162
+ if (arg.startsWith("--plugin-version=")) {
163
+ const version = arg.slice("--plugin-version=".length).trim();
164
+ if (!version) {
165
+ console.error("--plugin-version requires a value");
166
+ process.exit(1);
167
+ }
168
+ PLUGIN_VERSION = version;
169
+ pluginVersionExplicit = true;
170
+ pluginVersionArgExplicit = true;
171
+ continue;
172
+ }
163
173
  if (arg === "--plugin-version") {
164
174
  const version = argv[i + 1]?.trim();
165
175
  if (!version) {
166
176
  console.error("--plugin-version requires a value");
167
177
  process.exit(1);
168
- }
169
- PLUGIN_VERSION = version;
170
- pluginVersionExplicit = true;
171
- i += 1;
172
- continue;
173
- }
178
+ }
179
+ PLUGIN_VERSION = version;
180
+ pluginVersionExplicit = true;
181
+ pluginVersionArgExplicit = true;
182
+ i += 1;
183
+ continue;
184
+ }
174
185
  if (arg.startsWith("--openviking-version=")) {
175
186
  openvikingVersion = arg.slice("--openviking-version=".length).trim();
187
+ openvikingVersionArgExplicit = true;
176
188
  continue;
177
189
  }
178
190
  if (arg === "--openviking-version") {
@@ -182,6 +194,28 @@ for (let i = 0; i < argv.length; i++) {
182
194
  process.exit(1);
183
195
  }
184
196
  openvikingVersion = version;
197
+ openvikingVersionArgExplicit = true;
198
+ i += 1;
199
+ continue;
200
+ }
201
+ if (arg.startsWith("--version=")) {
202
+ const version = arg.slice("--version=".length).trim();
203
+ if (!version) {
204
+ console.error("--version requires a value");
205
+ process.exit(1);
206
+ }
207
+ combinedVersion = version;
208
+ combinedVersionExplicit = true;
209
+ continue;
210
+ }
211
+ if (arg === "--version") {
212
+ const version = argv[i + 1]?.trim();
213
+ if (!version) {
214
+ console.error("--version requires a value");
215
+ process.exit(1);
216
+ }
217
+ combinedVersion = version;
218
+ combinedVersionExplicit = true;
185
219
  i += 1;
186
220
  continue;
187
221
  }
@@ -209,18 +243,44 @@ for (let i = 0; i < argv.length; i++) {
209
243
  }
210
244
  }
211
245
 
246
+ if (combinedVersionExplicit) {
247
+ if (pluginVersionArgExplicit || openvikingVersionArgExplicit) {
248
+ console.error("--version cannot be used together with --plugin-version or --openviking-version");
249
+ process.exit(1);
250
+ }
251
+ const normalizedVersion = normalizeCombinedVersion(combinedVersion);
252
+ PLUGIN_VERSION = normalizedVersion.pluginVersion;
253
+ openvikingVersion = normalizedVersion.openvikingVersion;
254
+ pluginVersionExplicit = true;
255
+ }
256
+
212
257
  function setOpenClawDir(dir) {
213
258
  OPENCLAW_DIR = dir;
214
259
  }
215
260
 
261
+ function normalizeCombinedVersion(version) {
262
+ const value = (version || "").trim();
263
+ if (!/^(v)?\d+(\.\d+){1,2}$/.test(value)) {
264
+ console.error("--version requires a semantic version like 0.2.9 or v0.2.9");
265
+ process.exit(1);
266
+ }
267
+ const openvikingVersionValue = value.startsWith("v") ? value.slice(1) : value;
268
+ return {
269
+ pluginVersion: `v${openvikingVersionValue}`,
270
+ openvikingVersion: openvikingVersionValue,
271
+ };
272
+ }
273
+
216
274
  function printHelp() {
217
275
  console.log("Usage: node install.js [ OPTIONS ]");
218
276
  console.log("");
219
277
  console.log("Options:");
220
278
  console.log(" --github-repo=OWNER/REPO GitHub repository (default: volcengine/OpenViking)");
221
- console.log(" --plugin-version=TAG Plugin version (Git tag, e.g. v0.2.9, default: latest tag)");
279
+ console.log(" --version=V Shorthand for --plugin-version=vV and --openviking-version=V");
280
+ console.log(" --plugin-version=TAG Plugin version (Git tag, e.g. v0.2.9, default: latest tag)");
222
281
  console.log(" --openviking-version=V OpenViking PyPI version (e.g. 0.2.9, default: latest)");
223
282
  console.log(" --workdir PATH OpenClaw config directory (default: ~/.openclaw)");
283
+ console.log(" --current-version Print installed plugin/OpenViking versions and exit");
224
284
  console.log(" --repo=PATH Use local OpenViking repo at PATH (pip -e + local plugin)");
225
285
  console.log(" --update, --upgrade-plugin");
226
286
  console.log(" Upgrade only the plugin to the requested --plugin-version; keep ov.conf and do not change the OpenViking service");
@@ -234,13 +294,19 @@ function printHelp() {
234
294
  console.log(" # Install latest version");
235
295
  console.log(" node install.js");
236
296
  console.log("");
297
+ console.log(" # Show installed versions");
298
+ console.log(" node install.js --current-version");
299
+ console.log("");
300
+ console.log(" # Install a specific release version");
301
+ console.log(" node install.js --version=0.2.9");
302
+ console.log("");
237
303
  console.log(" # Install from a fork repository");
238
304
  console.log(" node install.js --github-repo=yourname/OpenViking --plugin-version=dev-branch");
239
305
  console.log("");
240
306
  console.log(" # Install specific plugin version");
241
307
  console.log(" node install.js --plugin-version=v0.2.8");
242
308
  console.log("");
243
- console.log(" # Upgrade only the plugin files from main branch");
309
+ console.log(" # Upgrade only the plugin files from main branch");
244
310
  console.log(" node install.js --update --plugin-version=main");
245
311
  console.log("");
246
312
  console.log(" # Roll back the last plugin upgrade");
@@ -442,6 +508,10 @@ async function selectWorkdir() {
442
508
 
443
509
  const instances = detectOpenClawInstances();
444
510
  if (instances.length <= 1) return;
511
+ if (showCurrentVersion) {
512
+ setOpenClawDir(instances[0]);
513
+ return;
514
+ }
445
515
  if (installYes) return;
446
516
 
447
517
  console.log("");
@@ -581,8 +651,8 @@ function ensurePluginOnlyOperationArgs() {
581
651
  if ((upgradePluginOnly || rollbackLastUpgrade) && openvikingVersion) {
582
652
  err(
583
653
  tr(
584
- "Plugin-only upgrade/rollback does not support --openviking-version. Use --plugin-version to choose the plugin release, and run a full install if you need to change the OpenViking service version.",
585
- "仅插件升级或回滚不支持 --openviking-version。请使用 --plugin-version 指定插件版本;如果需要调整 OpenViking 服务版本,请执行完整安装流程。",
654
+ "Plugin-only upgrade/rollback does not support --openviking-version or --version. Use --plugin-version to choose the plugin release, and run a full install if you need to change the OpenViking service version.",
655
+ "仅插件升级或回滚不支持 --openviking-version 或 --version。请使用 --plugin-version 指定插件版本;如果需要调整 OpenViking 服务版本,请执行完整安装流程。",
586
656
  ),
587
657
  );
588
658
  process.exit(1);
@@ -627,122 +697,122 @@ async function testRemoteFile(url) {
627
697
  return false;
628
698
  }
629
699
 
630
- function compareSemverDesc(a, b) {
631
- if (versionGte(a, b) && versionGte(b, a)) {
632
- return 0;
633
- }
634
- return versionGte(a, b) ? -1 : 1;
635
- }
636
-
637
- function pickLatestPluginTag(tagNames) {
638
- const normalized = tagNames
639
- .map((tag) => String(tag ?? "").trim())
640
- .filter(Boolean);
641
-
642
- const semverTags = normalized
643
- .filter((tag) => isSemverLike(tag))
644
- .sort(compareSemverDesc);
645
-
646
- if (semverTags.length > 0) {
647
- return semverTags[0];
648
- }
649
-
650
- return normalized[0] || "";
651
- }
652
-
653
- function parseGitLsRemoteTags(output) {
654
- return String(output ?? "")
655
- .split(/\r?\n/)
656
- .map((line) => {
657
- const match = line.match(/refs\/tags\/(.+)$/);
658
- return match?.[1]?.trim() || "";
659
- })
660
- .filter(Boolean);
661
- }
662
-
663
- async function resolveDefaultPluginVersion() {
664
- if (PLUGIN_VERSION) {
665
- return;
666
- }
667
-
668
- info(tr(
669
- `No plugin version specified; resolving latest tag from ${REPO}...`,
670
- `未指定插件版本,正在解析 ${REPO} 的最新 tag...`,
671
- ));
672
-
673
- const failures = [];
674
- const apiUrl = `https://api.github.com/repos/${REPO}/tags?per_page=100`;
675
-
676
- try {
677
- const controller = new AbortController();
678
- const timeoutId = setTimeout(() => controller.abort(), 10000);
679
- const response = await fetch(apiUrl, {
680
- headers: {
681
- Accept: "application/vnd.github+json",
682
- "User-Agent": "openviking-setup-helper",
683
- "X-GitHub-Api-Version": "2022-11-28",
684
- },
685
- signal: controller.signal,
686
- });
687
- clearTimeout(timeoutId);
688
-
689
- if (response.ok) {
690
- const payload = await response.json().catch(() => null);
691
- if (Array.isArray(payload)) {
692
- const latestTag = pickLatestPluginTag(payload.map((item) => item?.name || ""));
693
- if (latestTag) {
694
- PLUGIN_VERSION = latestTag;
695
- info(tr(
696
- `Resolved default plugin version to latest tag: ${PLUGIN_VERSION}`,
697
- `已将默认插件版本解析为最新 tag: ${PLUGIN_VERSION}`,
698
- ));
699
- return;
700
- }
701
- } else {
702
- failures.push("GitHub tags API returned an unexpected payload");
703
- }
704
- } else {
705
- failures.push(`GitHub tags API returned HTTP ${response.status}`);
706
- }
707
- } catch (error) {
708
- failures.push(`GitHub tags API failed: ${String(error)}`);
709
- }
710
-
711
- const gitRef = `https://github.com/${REPO}.git`;
712
- const gitResult = await runCapture("git", ["ls-remote", "--tags", "--refs", gitRef], {
713
- shell: IS_WIN,
714
- });
715
- if (gitResult.code === 0 && gitResult.out) {
716
- const latestTag = pickLatestPluginTag(parseGitLsRemoteTags(gitResult.out));
717
- if (latestTag) {
718
- PLUGIN_VERSION = latestTag;
719
- info(tr(
720
- `Resolved default plugin version via git tags: ${PLUGIN_VERSION}`,
721
- `已通过 git tag 解析默认插件版本: ${PLUGIN_VERSION}`,
722
- ));
723
- return;
724
- }
725
- failures.push("git ls-remote returned no usable tags");
726
- } else {
727
- failures.push(`git ls-remote failed${gitResult.err ? `: ${gitResult.err}` : ""}`);
728
- }
729
-
730
- err(tr(
731
- `Could not resolve the latest tag for ${REPO}.`,
732
- `无法解析 ${REPO} 的最新 tag。`,
733
- ));
734
- console.log(tr(
735
- "Please rerun with --plugin-version <tag>, or use --plugin-version main to track the branch head explicitly.",
736
- "请使用 --plugin-version <tag> 重新执行;如果需要显式跟踪分支头,请使用 --plugin-version main。",
737
- ));
738
- if (failures.length > 0) {
739
- warn(failures.join(" | "));
740
- }
741
- process.exit(1);
742
- }
743
-
744
- // Resolve plugin configuration from manifest or fallback
745
- async function resolvePluginConfig() {
700
+ function compareSemverDesc(a, b) {
701
+ if (versionGte(a, b) && versionGte(b, a)) {
702
+ return 0;
703
+ }
704
+ return versionGte(a, b) ? -1 : 1;
705
+ }
706
+
707
+ function pickLatestPluginTag(tagNames) {
708
+ const normalized = tagNames
709
+ .map((tag) => String(tag ?? "").trim())
710
+ .filter(Boolean);
711
+
712
+ const semverTags = normalized
713
+ .filter((tag) => isSemverLike(tag))
714
+ .sort(compareSemverDesc);
715
+
716
+ if (semverTags.length > 0) {
717
+ return semverTags[0];
718
+ }
719
+
720
+ return normalized[0] || "";
721
+ }
722
+
723
+ function parseGitLsRemoteTags(output) {
724
+ return String(output ?? "")
725
+ .split(/\r?\n/)
726
+ .map((line) => {
727
+ const match = line.match(/refs\/tags\/(.+)$/);
728
+ return match?.[1]?.trim() || "";
729
+ })
730
+ .filter(Boolean);
731
+ }
732
+
733
+ async function resolveDefaultPluginVersion() {
734
+ if (PLUGIN_VERSION) {
735
+ return;
736
+ }
737
+
738
+ info(tr(
739
+ `No plugin version specified; resolving latest tag from ${REPO}...`,
740
+ `未指定插件版本,正在解析 ${REPO} 的最新 tag...`,
741
+ ));
742
+
743
+ const failures = [];
744
+ const apiUrl = `https://api.github.com/repos/${REPO}/tags?per_page=100`;
745
+
746
+ try {
747
+ const controller = new AbortController();
748
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
749
+ const response = await fetch(apiUrl, {
750
+ headers: {
751
+ Accept: "application/vnd.github+json",
752
+ "User-Agent": "openviking-setup-helper",
753
+ "X-GitHub-Api-Version": "2022-11-28",
754
+ },
755
+ signal: controller.signal,
756
+ });
757
+ clearTimeout(timeoutId);
758
+
759
+ if (response.ok) {
760
+ const payload = await response.json().catch(() => null);
761
+ if (Array.isArray(payload)) {
762
+ const latestTag = pickLatestPluginTag(payload.map((item) => item?.name || ""));
763
+ if (latestTag) {
764
+ PLUGIN_VERSION = latestTag;
765
+ info(tr(
766
+ `Resolved default plugin version to latest tag: ${PLUGIN_VERSION}`,
767
+ `已将默认插件版本解析为最新 tag: ${PLUGIN_VERSION}`,
768
+ ));
769
+ return;
770
+ }
771
+ } else {
772
+ failures.push("GitHub tags API returned an unexpected payload");
773
+ }
774
+ } else {
775
+ failures.push(`GitHub tags API returned HTTP ${response.status}`);
776
+ }
777
+ } catch (error) {
778
+ failures.push(`GitHub tags API failed: ${String(error)}`);
779
+ }
780
+
781
+ const gitRef = `https://github.com/${REPO}.git`;
782
+ const gitResult = await runCapture("git", ["ls-remote", "--tags", "--refs", gitRef], {
783
+ shell: IS_WIN,
784
+ });
785
+ if (gitResult.code === 0 && gitResult.out) {
786
+ const latestTag = pickLatestPluginTag(parseGitLsRemoteTags(gitResult.out));
787
+ if (latestTag) {
788
+ PLUGIN_VERSION = latestTag;
789
+ info(tr(
790
+ `Resolved default plugin version via git tags: ${PLUGIN_VERSION}`,
791
+ `已通过 git tag 解析默认插件版本: ${PLUGIN_VERSION}`,
792
+ ));
793
+ return;
794
+ }
795
+ failures.push("git ls-remote returned no usable tags");
796
+ } else {
797
+ failures.push(`git ls-remote failed${gitResult.err ? `: ${gitResult.err}` : ""}`);
798
+ }
799
+
800
+ err(tr(
801
+ `Could not resolve the latest tag for ${REPO}.`,
802
+ `无法解析 ${REPO} 的最新 tag。`,
803
+ ));
804
+ console.log(tr(
805
+ "Please rerun with --plugin-version <tag>, or use --plugin-version main to track the branch head explicitly.",
806
+ "请使用 --plugin-version <tag> 重新执行;如果需要显式跟踪分支头,请使用 --plugin-version main。",
807
+ ));
808
+ if (failures.length > 0) {
809
+ warn(failures.join(" | "));
810
+ }
811
+ process.exit(1);
812
+ }
813
+
814
+ // Resolve plugin configuration from manifest or fallback
815
+ async function resolvePluginConfig() {
746
816
  const ghRaw = `https://raw.githubusercontent.com/${REPO}/${PLUGIN_VERSION}`;
747
817
 
748
818
  info(tr(`Resolving plugin configuration for version: ${PLUGIN_VERSION}`, `正在解析插件配置,版本: ${PLUGIN_VERSION}`));
@@ -864,9 +934,9 @@ async function checkOpenClawCompatibility() {
864
934
  }
865
935
 
866
936
  // If user explicitly requested an old version, pass
867
- if (isSemverLike(PLUGIN_VERSION) && !versionGte(PLUGIN_VERSION, "v0.2.8")) {
868
- return;
869
- }
937
+ if (isSemverLike(PLUGIN_VERSION) && !versionGte(PLUGIN_VERSION, "v0.2.8")) {
938
+ return;
939
+ }
870
940
 
871
941
  // Check compatibility
872
942
  if (!versionGte(ocVersion, resolvedMinOpenclawVersion)) {
@@ -935,9 +1005,9 @@ async function installOpenViking() {
935
1005
  // Determine package spec
936
1006
  const pkgSpec = openvikingVersion ? `openviking==${openvikingVersion}` : "openviking";
937
1007
  if (openvikingVersion) {
938
- info(tr(`Installing OpenViking ${openvikingVersion} from PyPI...`, `正在安装 OpenViking ${openvikingVersion} (PyPI)...`));
1008
+ info(tr(`Installing or upgrading OpenViking ${openvikingVersion} from PyPI...`, `正在安装或升级 OpenViking ${openvikingVersion} (PyPI)...`));
939
1009
  } else {
940
- info(tr("Installing OpenViking (latest) from PyPI...", "正在安装 OpenViking (最新版) (PyPI)..."));
1010
+ info(tr("Installing or upgrading OpenViking (latest) from PyPI...", "正在安装或升级 OpenViking (最新版) (PyPI)..."));
941
1011
  }
942
1012
  info(tr(`Using pip index: ${PIP_INDEX_URL}`, `使用 pip 镜像源: ${PIP_INDEX_URL}`));
943
1013
 
@@ -945,7 +1015,7 @@ async function installOpenViking() {
945
1015
  await runCapture(py, ["-m", "pip", "install", "--upgrade", "pip", "-q", "-i", PIP_INDEX_URL], { shell: false });
946
1016
  const installResult = await runLiveCapture(
947
1017
  py,
948
- ["-m", "pip", "install", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
1018
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
949
1019
  { shell: false },
950
1020
  );
951
1021
  if (installResult.code === 0) {
@@ -1001,7 +1071,7 @@ async function installOpenViking() {
1001
1071
  await runCapture(venvPy, ["-m", "pip", "install", "--upgrade", "pip", "-q", "-i", PIP_INDEX_URL], { shell: false });
1002
1072
  const venvInstall = await runLiveCapture(
1003
1073
  venvPy,
1004
- ["-m", "pip", "install", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
1074
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", pkgSpec, "-i", PIP_INDEX_URL],
1005
1075
  { shell: false },
1006
1076
  );
1007
1077
  if (venvInstall.code === 0) {
@@ -1018,7 +1088,7 @@ async function installOpenViking() {
1018
1088
  if (process.env.OPENVIKING_ALLOW_BREAK_SYSTEM_PACKAGES === "1") {
1019
1089
  const systemInstall = await runLiveCapture(
1020
1090
  py,
1021
- ["-m", "pip", "install", "--progress-bar", "on", "--break-system-packages", pkgSpec, "-i", PIP_INDEX_URL],
1091
+ ["-m", "pip", "install", "--upgrade", "--progress-bar", "on", "--break-system-packages", pkgSpec, "-i", PIP_INDEX_URL],
1022
1092
  { shell: false },
1023
1093
  );
1024
1094
  if (systemInstall.code === 0) {
@@ -1129,6 +1199,66 @@ function getInstallStatePathForPlugin(pluginId) {
1129
1199
  return join(OPENCLAW_DIR, "extensions", pluginId, ".ov-install-state.json");
1130
1200
  }
1131
1201
 
1202
+ async function detectInstalledOpenVikingVersion() {
1203
+ const pythonCandidates = [];
1204
+ const configuredPython = process.env.OPENVIKING_PYTHON?.trim();
1205
+ if (configuredPython) {
1206
+ pythonCandidates.push(configuredPython);
1207
+ }
1208
+
1209
+ const envCandidates = IS_WIN
1210
+ ? [join(OPENCLAW_DIR, "openviking.env.ps1"), join(OPENCLAW_DIR, "openviking.env.bat")]
1211
+ : [join(OPENCLAW_DIR, "openviking.env")];
1212
+
1213
+ for (const envPath of envCandidates) {
1214
+ if (!existsSync(envPath)) continue;
1215
+ const raw = await readFile(envPath, "utf8").catch(() => "");
1216
+ if (!raw) continue;
1217
+ const match = raw.match(/OPENVIKING_PYTHON(?:\s*=\s*|=)['"]?([^'"\r\n]+)['"]?/);
1218
+ const pythonPath = match?.[1]?.trim();
1219
+ if (pythonPath) {
1220
+ pythonCandidates.push(pythonPath);
1221
+ }
1222
+ }
1223
+
1224
+ for (const candidate of IS_WIN ? ["py", "python", "python3"] : ["python3", "python"]) {
1225
+ pythonCandidates.push(candidate);
1226
+ }
1227
+
1228
+ const seen = new Set();
1229
+ for (const candidate of pythonCandidates) {
1230
+ if (!candidate || seen.has(candidate)) continue;
1231
+ seen.add(candidate);
1232
+ const result = await runCapture(candidate, ["-c", "import openviking; print(openviking.__version__)"], { shell: IS_WIN });
1233
+ if (result.code === 0) {
1234
+ return result.out.trim();
1235
+ }
1236
+ }
1237
+
1238
+ return "";
1239
+ }
1240
+
1241
+ async function printCurrentVersionInfo() {
1242
+ const state = await readJsonFileIfExists(getInstallStatePathForPlugin("openviking"));
1243
+ const pluginRequestedRef = state?.requestedRef || "";
1244
+ const pluginReleaseId = state?.releaseId || "";
1245
+ const pluginInstalledAt = state?.installedAt || "";
1246
+ const openvikingInstalledVersion = await detectInstalledOpenVikingVersion();
1247
+
1248
+ console.log("");
1249
+ bold(tr("Installed versions", "当前已安装版本"));
1250
+ console.log("");
1251
+ console.log(`Target: ${OPENCLAW_DIR}`);
1252
+ console.log(`Plugin: ${pluginReleaseId || pluginRequestedRef || "not installed"}`);
1253
+ if (pluginRequestedRef && pluginReleaseId && pluginRequestedRef !== pluginReleaseId) {
1254
+ console.log(`Plugin requested ref: ${pluginRequestedRef}`);
1255
+ }
1256
+ console.log(`OpenViking: ${openvikingInstalledVersion || "unknown"}`);
1257
+ if (pluginInstalledAt) {
1258
+ console.log(`Installed at: ${pluginInstalledAt}`);
1259
+ }
1260
+ }
1261
+
1132
1262
  function getUpgradeAuditDir() {
1133
1263
  return join(OPENCLAW_DIR, ".openviking-upgrade-backup");
1134
1264
  }
@@ -2070,16 +2200,20 @@ async function main() {
2070
2200
 
2071
2201
  ensurePluginOnlyOperationArgs();
2072
2202
  await selectWorkdir();
2203
+ if (showCurrentVersion) {
2204
+ await printCurrentVersionInfo();
2205
+ return;
2206
+ }
2073
2207
  if (rollbackLastUpgrade) {
2074
2208
  info(tr("Mode: rollback last plugin upgrade", "模式: 回滚最近一次插件升级"));
2075
- if (pluginVersionExplicit) {
2076
- warn("--plugin-version is ignored in --rollback mode.");
2077
- }
2209
+ if (pluginVersionExplicit) {
2210
+ warn("--plugin-version is ignored in --rollback mode.");
2211
+ }
2078
2212
  await rollbackLastUpgradeOperation();
2079
2213
  return;
2080
2214
  }
2081
- await resolveDefaultPluginVersion();
2082
- validateRequestedPluginVersion();
2215
+ await resolveDefaultPluginVersion();
2216
+ validateRequestedPluginVersion();
2083
2217
  info(tr(`Target: ${OPENCLAW_DIR}`, `目标实例: ${OPENCLAW_DIR}`));
2084
2218
  info(tr(`Repository: ${REPO}`, `仓库: ${REPO}`));
2085
2219
  info(tr(`Plugin version: ${PLUGIN_VERSION}`, `插件版本: ${PLUGIN_VERSION}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-openviking-setup-helper",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Setup helper for installing OpenViking memory plugin into OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {