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.
- package/install.js +289 -155
- 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
|
-
|
|
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
|
-
|
|
172
|
-
|
|
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=
|
|
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...`,
|
|
1008
|
+
info(tr(`Installing or upgrading OpenViking ${openvikingVersion} from PyPI...`, `正在安装或升级 OpenViking ${openvikingVersion} (PyPI)...`));
|
|
939
1009
|
} else {
|
|
940
|
-
info(tr("Installing OpenViking (latest) from 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}`));
|