@honor-claw/yoyo 1.6.1-alpha.2 → 1.6.1-beta.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.
- package/dist/apis/http-client.mjs +0 -2
- package/dist/cloud-channel/authorization-refresh-manager.mjs +21 -6
- package/dist/cloud-channel/message-handler.mjs +2 -39
- package/dist/gateway-client/admin-client.mjs +8 -19
- package/dist/gateway-client/protocol-client.mjs +2 -2
- package/dist/modules/configs/config-manager.mjs +2 -11
- package/dist/modules/configs/identity-persist.mjs +30 -28
- package/dist/modules/device/providers/windows.mjs +1 -1
- package/openclaw.plugin.json +0 -4
- package/package.json +1 -7
- package/skills/yoyo-control/configs/sub-skills.json +10 -1
- package/skills/yoyo-update/SKILL.md +5 -11
|
@@ -3,8 +3,6 @@ import { getProxyUrl as t, shouldUseProxy as n } from "../utils/proxy.mjs";
|
|
|
3
3
|
import { ProxyAgent as r, request as i } from "undici";
|
|
4
4
|
//#region src/apis/http-client.ts
|
|
5
5
|
var a = class extends Error {
|
|
6
|
-
status;
|
|
7
|
-
data;
|
|
8
6
|
constructor(e, t, n) {
|
|
9
7
|
super(n), this.status = e, this.data = t, this.name = "HttpError";
|
|
10
8
|
}
|
|
@@ -9,6 +9,7 @@ var a = "[yoyoclaw-auth-refresh]", o = .3, s = .1, c = 1e3, l = 6e4, u = class {
|
|
|
9
9
|
scheduleVersion = 0;
|
|
10
10
|
destroyed = !1;
|
|
11
11
|
pausedForExpiredToken = !1;
|
|
12
|
+
pendingConfigTokenRefresh = !1;
|
|
12
13
|
constructor(e) {
|
|
13
14
|
this.config = e;
|
|
14
15
|
}
|
|
@@ -29,15 +30,29 @@ var a = "[yoyoclaw-auth-refresh]", o = .3, s = .1, c = 1e3, l = 6e4, u = class {
|
|
|
29
30
|
}
|
|
30
31
|
this.sendUpdateAuthorizationRequest(), this.scheduleTimer(n.expireMs * s);
|
|
31
32
|
}
|
|
32
|
-
async handleAuthorizationUpdate(
|
|
33
|
-
let
|
|
34
|
-
if (typeof
|
|
33
|
+
async handleAuthorizationUpdate(r) {
|
|
34
|
+
let i = r.bizExtInfo, o = i?.jwtToken;
|
|
35
|
+
if (typeof o != "string" || !o.trim()) {
|
|
35
36
|
e().warn(`${a} updateAuthorization missing valid jwtToken`);
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
try {
|
|
39
|
-
let
|
|
40
|
-
e().info(`${a} cached new token, expireMs: ${
|
|
40
|
+
let s = Date.now(), c = o.trim(), l = (await n(c, i?.expire, s))?.authorizationCache?.expireMs ?? 0;
|
|
41
|
+
if (e().info(`${a} cached new token, expireMs: ${l}, receivedAtMs: ${s}, sourceDeviceId: ${r.sourceDeviceId || "unknown"}, sourceRole: ${r.sourceRole || "unknown"}`), this.pendingConfigTokenRefresh) {
|
|
42
|
+
this.pendingConfigTokenRefresh = !1;
|
|
43
|
+
try {
|
|
44
|
+
let n = t(), r = n.getUserConfig();
|
|
45
|
+
await n.updateUserConfig({
|
|
46
|
+
...r,
|
|
47
|
+
token: c,
|
|
48
|
+
userId: void 0,
|
|
49
|
+
expired: void 0
|
|
50
|
+
}), e().info(`${a} persisted upgraded token to plugin config, expireMs: ${l}`);
|
|
51
|
+
} catch (t) {
|
|
52
|
+
e().error(`${a} failed to persist upgraded token to plugin config: ${String(t)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
this.pausedForExpiredToken = !1, await this.schedule();
|
|
41
56
|
} catch (t) {
|
|
42
57
|
e().error(`${a} failed to cache new token: ${String(t)}`);
|
|
43
58
|
}
|
|
@@ -54,7 +69,7 @@ var a = "[yoyoclaw-auth-refresh]", o = .3, s = .1, c = 1e3, l = 6e4, u = class {
|
|
|
54
69
|
let s = (await r())?.authorizationCache, c = i(s?.expireMs), u = s?.receivedAtMs ?? 0;
|
|
55
70
|
if (!c || !Number.isFinite(u) || u <= 0) {
|
|
56
71
|
let t = Date.now();
|
|
57
|
-
return await n(o, l, t), e().warn(`${a} missing cached authorization timing, persisted legacy token timing and refreshing immediately`), {
|
|
72
|
+
return this.pendingConfigTokenRefresh = !0, await n(o, l, t), e().warn(`${a} missing cached authorization timing, persisted legacy token timing and refreshing immediately`), {
|
|
58
73
|
receivedAtMs: t,
|
|
59
74
|
expireMs: l,
|
|
60
75
|
refreshImmediately: !0
|
|
@@ -9,7 +9,6 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
|
|
|
9
9
|
config;
|
|
10
10
|
pendingFirstMessages = /* @__PURE__ */ new Map();
|
|
11
11
|
initializedDeviceIds = /* @__PURE__ */ new Set();
|
|
12
|
-
pendingNodeConnects = /* @__PURE__ */ new Map();
|
|
13
12
|
contextUpdateHandlers = {
|
|
14
13
|
style: this.updateStyleContext.bind(this),
|
|
15
14
|
"model.primary": this.updatePrimaryModel.bind(this),
|
|
@@ -117,43 +116,7 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
forwardToNodeGateway(t, n, r, a) {
|
|
120
|
-
e().info(`${i} forwarding user message to node gateway from ${n}, session: ${t}`);
|
|
121
|
-
let o = this.readNodeConnectRequest(a);
|
|
122
|
-
o && this.pendingNodeConnects.set(o.requestId, o.nodeId);
|
|
123
|
-
try {
|
|
124
|
-
r.send(a);
|
|
125
|
-
} catch (e) {
|
|
126
|
-
throw o && this.pendingNodeConnects.delete(o.requestId), e;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
readNodeConnectRequest(e) {
|
|
130
|
-
let t;
|
|
131
|
-
try {
|
|
132
|
-
t = JSON.parse(e);
|
|
133
|
-
} catch {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (t.type !== "req" || t.method !== "connect" || typeof t.id != "string" || !t.params || typeof t.params != "object") return;
|
|
137
|
-
let n = t.params;
|
|
138
|
-
if (n.role !== "node" || !n.device || typeof n.device != "object") return;
|
|
139
|
-
let r = n.device;
|
|
140
|
-
if (!(typeof r.id != "string" || !r.id.trim())) return {
|
|
141
|
-
requestId: t.id,
|
|
142
|
-
nodeId: r.id
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
handleNodeConnectResponse(e) {
|
|
146
|
-
let t = e;
|
|
147
|
-
if (t.type !== "res" || typeof t.id != "string") return;
|
|
148
|
-
let n = this.pendingNodeConnects.get(t.id);
|
|
149
|
-
n && (this.pendingNodeConnects.delete(t.id), !(t.ok !== !0 || !t.payload || typeof t.payload != "object") && t.payload.type === "hello-ok" && this.armNodePairingAutoApproval(n));
|
|
150
|
-
}
|
|
151
|
-
async armNodePairingAutoApproval(t) {
|
|
152
|
-
if (!await this.adminClientManager.waitForReady()) {
|
|
153
|
-
e().warn(`${i} admin client not available for node pairing auto approval, nodeId: ${t}`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
await this.adminClientManager.getClient()?.approvePendingNodePairing(t);
|
|
119
|
+
e().info(`${i} forwarding user message to node gateway from ${n}, session: ${t}`), r.send(a);
|
|
157
120
|
}
|
|
158
121
|
processMessageBuffer(e, t, n, r) {
|
|
159
122
|
let i = this.pendingFirstMessages.get(t);
|
|
@@ -193,7 +156,7 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
|
|
|
193
156
|
e().warn(`${i} gateway message is not valid JSON`);
|
|
194
157
|
return;
|
|
195
158
|
}
|
|
196
|
-
if (
|
|
159
|
+
if (!a.ok && a.error?.code === "NOT_PAIRED") {
|
|
197
160
|
let r = a.error?.details?.requestId;
|
|
198
161
|
if (!r) {
|
|
199
162
|
e().warn(`${i} NOT_PAIRED without requestId, ignoring...`);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ProtocolGatewayClient as r } from "./protocol-client.mjs";
|
|
1
|
+
import { GATEWAY_CLIENT_IDS as e, GATEWAY_CLIENT_MODES as t } from "./types/client.mjs";
|
|
2
|
+
import { ProtocolGatewayClient as n } from "./protocol-client.mjs";
|
|
4
3
|
//#region src/gateway-client/admin-client.ts
|
|
5
|
-
var
|
|
4
|
+
var r = {
|
|
6
5
|
role: "operator",
|
|
7
6
|
scopes: [
|
|
8
7
|
"operator.admin",
|
|
@@ -12,12 +11,12 @@ var i = {
|
|
|
12
11
|
"operator.approvals",
|
|
13
12
|
"operator.pairing"
|
|
14
13
|
],
|
|
15
|
-
clientId:
|
|
14
|
+
clientId: e.CLI,
|
|
16
15
|
displayName: "YOYO-Control",
|
|
17
|
-
clientMode:
|
|
18
|
-
},
|
|
16
|
+
clientMode: t.BACKEND
|
|
17
|
+
}, i = class extends n {
|
|
19
18
|
constructor(e = {}) {
|
|
20
|
-
super(e,
|
|
19
|
+
super(e, r);
|
|
21
20
|
}
|
|
22
21
|
async setAgentFile(e, t, n = "main") {
|
|
23
22
|
return this.sendRequest("agents.files.set", {
|
|
@@ -50,16 +49,6 @@ var i = {
|
|
|
50
49
|
async devicePairApprove(e) {
|
|
51
50
|
return this.sendRequest("device.pair.approve", { requestId: e });
|
|
52
51
|
}
|
|
53
|
-
async approvePendingNodePairing(t) {
|
|
54
|
-
let n = t.trim();
|
|
55
|
-
if (!n) return !1;
|
|
56
|
-
try {
|
|
57
|
-
let t = (await this.sendRequest("node.pair.list", {})).pending?.find((e) => e.nodeId === n);
|
|
58
|
-
return t ? (e().info(`${a} auto approving node pairing, nodeId: ${n}, requestId: ${t.requestId}`), await this.sendRequest("node.pair.approve", { requestId: t.requestId }), !0) : !1;
|
|
59
|
-
} catch (t) {
|
|
60
|
-
return e().error(`${a} node pairing auto approve failed, nodeId: ${n}, error: ${String(t)}`), !1;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
52
|
};
|
|
64
53
|
//#endregion
|
|
65
|
-
export {
|
|
54
|
+
export { i as default };
|
|
@@ -10,23 +10,14 @@ import { STATE_FLAG as c, hasPersistedStateFlag as l, markPersistedStateFlag as
|
|
|
10
10
|
var d = "yoyo", f = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,alarm.enable,alarm.query,alarm.update,app.close,app.open,call.phone,call.search,capture-screenshot,contact.search,file-upload,hotspot,local-search,message.search,message.send,mobile-data,no-disturb,quiet-mode,ringing-mode,schedule.create,schedule.delete,schedule.search,schedule.update,screen-record,vibration-mode,volume.operate,wlan,bluetooth,location-service,nfc,usb-shared-network,eyecomfort,status-bar-show,brightness,autoscreen-onnotice,dark-mode,device-operation,camera,app.uninstall,audio-record,battery,gui.create,gui.pause,gui.terminate,mcp.tool.call,task_result_query".split(","), p = class {
|
|
11
11
|
loadConfig() {
|
|
12
12
|
try {
|
|
13
|
-
|
|
14
|
-
return typeof n == "function" ? structuredClone(n()) : structuredClone(e.loadConfig());
|
|
13
|
+
return t().config.loadConfig();
|
|
15
14
|
} catch (e) {
|
|
16
15
|
throw i(e, "Failed to load config");
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
async saveConfig(e) {
|
|
20
19
|
try {
|
|
21
|
-
|
|
22
|
-
if (typeof r == "function") {
|
|
23
|
-
await r({
|
|
24
|
-
nextConfig: e,
|
|
25
|
-
afterWrite: { mode: "auto" }
|
|
26
|
-
});
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
await n.writeConfigFile(e);
|
|
20
|
+
await t().config.writeConfigFile(e);
|
|
30
21
|
} catch (e) {
|
|
31
22
|
throw i(e, "Failed to save config");
|
|
32
23
|
}
|
|
@@ -4,68 +4,70 @@ import { safeReadFile as n, safeWriteFile as r } from "../../utils/fs-safe.mjs";
|
|
|
4
4
|
import { resolveEffectiveHomeDir as i } from "../../utils/home-dir.mjs";
|
|
5
5
|
import a from "node:path";
|
|
6
6
|
//#region src/modules/configs/identity-persist.ts
|
|
7
|
-
var o =
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
var o = /* @__PURE__ */ function(e) {
|
|
8
|
+
return e[e.LEGACY = 1] = "LEGACY", e[e.NEW = 2] = "NEW", e;
|
|
9
|
+
}({}), s = ".openclaw", c = "yoyo", l = "identity.json", u = 6e4;
|
|
10
|
+
function d() {
|
|
11
|
+
return a.join(s, c, l);
|
|
10
12
|
}
|
|
11
|
-
async function
|
|
12
|
-
let r =
|
|
13
|
+
async function f(t) {
|
|
14
|
+
let r = d();
|
|
13
15
|
try {
|
|
14
16
|
let e = (await n({
|
|
15
17
|
rootDir: t,
|
|
16
18
|
relativePath: r,
|
|
17
19
|
maxBytes: 10 * 1024
|
|
18
20
|
})).buffer.toString("utf8"), i = JSON.parse(e);
|
|
19
|
-
return typeof i != "object" || !i ?
|
|
20
|
-
...
|
|
21
|
+
return typeof i != "object" || !i ? v() : {
|
|
22
|
+
...v(),
|
|
21
23
|
...i
|
|
22
24
|
};
|
|
23
25
|
} catch (t) {
|
|
24
26
|
return e(t, "[yoyo-identity] failed to read identity"), null;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
async function
|
|
29
|
+
async function p() {
|
|
28
30
|
let e = i();
|
|
29
|
-
return e ? await
|
|
31
|
+
return e ? await f(e) || null : (t().warn("[yoyo-identity] failed to find home dir"), null);
|
|
30
32
|
}
|
|
31
|
-
async function
|
|
33
|
+
async function m(e) {
|
|
32
34
|
let n = i();
|
|
33
35
|
if (!n) return t().warn("[yoyo-identity] failed to find home dir"), null;
|
|
34
|
-
let a = await
|
|
36
|
+
let a = await f(n), s = {
|
|
35
37
|
...a,
|
|
36
|
-
version: a?.version ||
|
|
38
|
+
version: a?.version || o.NEW
|
|
37
39
|
};
|
|
38
|
-
return e.legacyDeviceId && (
|
|
40
|
+
return e.legacyDeviceId && (s.legacyDeviceId = e.legacyDeviceId), e.deviceId && (s.deviceId = e.deviceId, s.publicKeyPem = e.publicKeyPem, s.privateKeyPem = e.privateKeyPem, s.createdAtMs = e.createdAtMs), e.version && (s.version = e.version), "gatewayAuthMd5" in e && (s.gatewayAuthMd5 = e.gatewayAuthMd5), "pluginVersionCode" in e && (s.pluginVersionCode = e.pluginVersionCode), "authorizationCache" in e && (s.authorizationCache = e.authorizationCache), await r({
|
|
39
41
|
rootDir: n,
|
|
40
|
-
relativePath:
|
|
41
|
-
data: JSON.stringify(
|
|
42
|
+
relativePath: d(),
|
|
43
|
+
data: JSON.stringify(s, null, 2),
|
|
42
44
|
encoding: "utf8",
|
|
43
45
|
mkdir: !0
|
|
44
|
-
}),
|
|
46
|
+
}), s;
|
|
45
47
|
}
|
|
46
|
-
function
|
|
48
|
+
function h(e) {
|
|
47
49
|
let t = typeof e == "number" ? e : typeof e == "string" && e.trim() ? Number(e) : 0;
|
|
48
|
-
return !Number.isFinite(t) || t <
|
|
50
|
+
return !Number.isFinite(t) || t < u ? 0 : Math.floor(t);
|
|
49
51
|
}
|
|
50
|
-
async function
|
|
51
|
-
let r = await
|
|
52
|
+
async function g(e, t, n = Date.now()) {
|
|
53
|
+
let r = await m({ authorizationCache: {
|
|
52
54
|
jwtToken: e,
|
|
53
55
|
receivedAtMs: n,
|
|
54
|
-
expireMs:
|
|
56
|
+
expireMs: h(t)
|
|
55
57
|
} });
|
|
56
58
|
if (!r) throw Error("failed to write authorization cache");
|
|
57
59
|
return r;
|
|
58
60
|
}
|
|
59
|
-
async function
|
|
60
|
-
let e = await
|
|
61
|
-
return t?.jwtToken ?
|
|
61
|
+
async function _() {
|
|
62
|
+
let e = await p(), t = e?.authorizationCache;
|
|
63
|
+
return t?.jwtToken ? m({ authorizationCache: {
|
|
62
64
|
jwtToken: void 0,
|
|
63
65
|
receivedAtMs: t.receivedAtMs,
|
|
64
|
-
expireMs:
|
|
66
|
+
expireMs: h(t.expireMs)
|
|
65
67
|
} }) : e;
|
|
66
68
|
}
|
|
67
|
-
function
|
|
68
|
-
return { version:
|
|
69
|
+
function v() {
|
|
70
|
+
return { version: o.NEW };
|
|
69
71
|
}
|
|
70
72
|
//#endregion
|
|
71
|
-
export {
|
|
73
|
+
export { o as IdentityVersion, g as cacheAuthorizationToken, _ as clearCachedAuthorizationToken, p as getPersistedIdentity, h as parseAuthorizationExpireMs, m as updatePersistedIdentity };
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@honor-claw/yoyo",
|
|
3
|
-
"version": "1.6.1-
|
|
3
|
+
"version": "1.6.1-beta.1",
|
|
4
4
|
"description": "OpenClaw Honor Yoyo connection plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -26,10 +26,6 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "vite build",
|
|
28
28
|
"ci:check": "npx tsc --noEmit && npm run test:coverage",
|
|
29
|
-
"format": "oxfmt",
|
|
30
|
-
"format:fix": "oxfmt --write",
|
|
31
|
-
"lint": "oxlint src/",
|
|
32
|
-
"lint:fix": "oxlint --fix src/",
|
|
33
29
|
"publish:alpha": "npm run build && node scripts/publish.js --alpha",
|
|
34
30
|
"publish:beta": "npm run build && node scripts/publish.js",
|
|
35
31
|
"publish:latest": "npm run build && node scripts/publish.js --release",
|
|
@@ -53,8 +49,6 @@
|
|
|
53
49
|
"@types/node": "^25.0.10",
|
|
54
50
|
"@types/ws": "^8.5.13",
|
|
55
51
|
"@vitest/coverage-v8": "^2.1.8",
|
|
56
|
-
"oxfmt": "^0.55.0",
|
|
57
|
-
"oxlint": "^1.70.0",
|
|
58
52
|
"typescript": "^6.0.2",
|
|
59
53
|
"vite": "^8.0.10",
|
|
60
54
|
"vitest": "^2.1.8"
|
|
@@ -58,5 +58,14 @@
|
|
|
58
58
|
"resumeTimer",
|
|
59
59
|
"restartTimer",
|
|
60
60
|
"cancelTimer",
|
|
61
|
-
"task_result_query"
|
|
61
|
+
"task_result_query",
|
|
62
|
+
"cancel_countdown_timer",
|
|
63
|
+
"check_countdown_timer",
|
|
64
|
+
"close_countdown_timer",
|
|
65
|
+
"create_countdown_timer",
|
|
66
|
+
"express_logistics_query",
|
|
67
|
+
"open_countdown_timer",
|
|
68
|
+
"pause_countdown_timer",
|
|
69
|
+
"restart_countdown_timer",
|
|
70
|
+
"resume_countdown_timer"
|
|
62
71
|
]
|
|
@@ -9,6 +9,8 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
9
9
|
|
|
10
10
|
严格按下面顺序执行。不要输出步骤名、命令、判断过程或额外解释;只输出本文写明的用户可见文案。所有输出使用中文。
|
|
11
11
|
|
|
12
|
+
注意:所有用户可见文案以纯文本形式输出,不要用代码块(` ```markdown ` 等)包裹同一份内容两次。
|
|
13
|
+
|
|
12
14
|
## 禁止事项
|
|
13
15
|
|
|
14
16
|
- 不得执行 `openclaw plugins uninstall`。
|
|
@@ -24,11 +26,9 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
24
26
|
- 记录 `Version` 和 `Spec`。
|
|
25
27
|
- 若 `Spec` 是精确版本号(如 `@honor-claw/yoyo@1.3.0-beta.8`),输出以下文案并停止:
|
|
26
28
|
|
|
27
|
-
```markdown
|
|
28
29
|
当前 YOYO 插件使用精确版本号安装,自动升级流程已停止。
|
|
29
30
|
|
|
30
31
|
请修改 OpenClaw 配置文件,将 `plugins.installs.yoyo.spec` 从当前精确版本改为非精确版本规格(例如 `@honor-claw/yoyo@beta`、`@honor-claw/yoyo@alpha` 或 `@honor-claw/yoyo`),然后再重新发起升级。
|
|
31
|
-
```
|
|
32
32
|
|
|
33
33
|
## 步骤 2:确定目标版本
|
|
34
34
|
|
|
@@ -45,7 +45,8 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
45
45
|
|
|
46
46
|
## 步骤 3:输出更新摘要和更新阶段文案
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
输出以下文案:
|
|
49
|
+
|
|
49
50
|
🔄 YOYO 插件更新可用
|
|
50
51
|
|
|
51
52
|
当前版本:v{当前版本}
|
|
@@ -59,7 +60,6 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
59
60
|
|
|
60
61
|
2. 正在更新插件
|
|
61
62
|
状态:正在安装并配置新版本插件,请勿中断操作
|
|
62
|
-
```
|
|
63
63
|
|
|
64
64
|
## 步骤 4:执行更新
|
|
65
65
|
|
|
@@ -67,13 +67,11 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
67
67
|
|
|
68
68
|
## 步骤 5:校验并输出结果
|
|
69
69
|
|
|
70
|
-
若步骤 4
|
|
70
|
+
若步骤 4 失败,输出以下文案:
|
|
71
71
|
|
|
72
|
-
```markdown
|
|
73
72
|
❌ 插件更新失败
|
|
74
73
|
|
|
75
74
|
失败原因:{简要描述错误}
|
|
76
|
-
```
|
|
77
75
|
|
|
78
76
|
网络错误补充 `请检查网络连接后重试`;权限错误补充 `请检查 OpenClaw 安装目录的读写权限`;其他错误补充 `请将错误信息反馈给开发团队,或稍后重试`。停止。
|
|
79
77
|
|
|
@@ -90,16 +88,12 @@ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
|
|
|
90
88
|
|
|
91
89
|
若实际版本高于步骤 2 获取的目标版本,在步骤 6 成功文案后追加:
|
|
92
90
|
|
|
93
|
-
```markdown
|
|
94
91
|
说明:本次实际升级到 v{实际版本},高于预检查获取的目标版本 v{目标版本}。
|
|
95
|
-
```
|
|
96
92
|
|
|
97
93
|
## 步骤 6:输出完成结果
|
|
98
94
|
|
|
99
95
|
输出阶段 3 文案:
|
|
100
96
|
|
|
101
|
-
```markdown
|
|
102
97
|
3. 插件更新完成
|
|
103
98
|
Claw 插件更新已完成
|
|
104
99
|
网关即将重启,请稍候...
|
|
105
|
-
```
|