@honor-claw/yoyo 1.3.0-alpha.1 → 1.3.0-alpha.3
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/index.mjs
CHANGED
|
@@ -1,52 +1,43 @@
|
|
|
1
|
-
import e, {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { createServer as g } from "http";
|
|
13
|
-
import { URL as te, fileURLToPath as ne } from "node:url";
|
|
14
|
-
import { createHash as re, randomBytes as ie } from "crypto";
|
|
15
|
-
import _, { createHash as ae, randomUUID as oe } from "node:crypto";
|
|
1
|
+
import e, { constants as t, existsSync as n } from "node:fs";
|
|
2
|
+
import r from "node:path";
|
|
3
|
+
import i from "open";
|
|
4
|
+
import { customAlphabet as a } from "nanoid";
|
|
5
|
+
import { ProxyAgent as o, request as s } from "undici";
|
|
6
|
+
import { HttpProxyAgent as c } from "http-proxy-agent";
|
|
7
|
+
import { HttpsProxyAgent as l } from "https-proxy-agent";
|
|
8
|
+
import { createServer as u } from "http";
|
|
9
|
+
import { URL as d, fileURLToPath as f } from "node:url";
|
|
10
|
+
import { createHash as p, randomBytes as m } from "crypto";
|
|
11
|
+
import h, { createHash as g, randomUUID as _ } from "node:crypto";
|
|
16
12
|
import v from "node:fs/promises";
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import {
|
|
13
|
+
import y from "node:os";
|
|
14
|
+
import b, { promises as x } from "fs";
|
|
15
|
+
import S from "os";
|
|
16
|
+
import { execFile as ee } from "child_process";
|
|
17
|
+
import { promisify as te } from "util";
|
|
18
|
+
import * as C from "winreg";
|
|
19
|
+
import * as ne from "path";
|
|
20
|
+
import { z as w } from "zod";
|
|
21
|
+
import T, { WebSocket as re } from "ws";
|
|
22
|
+
import { Buffer as ie } from "node:buffer";
|
|
25
23
|
//#region src/utils/version.ts
|
|
26
|
-
var
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
let e = n(a(i(o(import.meta.url)), "../../package.json"), "utf-8");
|
|
31
|
-
w = (JSON.parse(e).version || "").includes("beta");
|
|
32
|
-
} catch (e) {
|
|
33
|
-
console.error(`Failed to check version: ${e}`);
|
|
34
|
-
}
|
|
35
|
-
return !!w;
|
|
24
|
+
var ae = null;
|
|
25
|
+
function oe() {
|
|
26
|
+
return ae === null && (ae = "1.3.0-alpha.3".includes("beta") || "1.3.0-alpha.3".includes("alpha")), !!ae;
|
|
36
27
|
}
|
|
37
28
|
//#endregion
|
|
38
29
|
//#region src/runtime.ts
|
|
39
|
-
var
|
|
40
|
-
function
|
|
41
|
-
|
|
30
|
+
var se = null;
|
|
31
|
+
function ce(e) {
|
|
32
|
+
se = e;
|
|
42
33
|
}
|
|
43
|
-
function
|
|
44
|
-
if (!
|
|
45
|
-
return
|
|
34
|
+
function le() {
|
|
35
|
+
if (!se) throw Error("Yoyo runtime not initialized");
|
|
36
|
+
return se;
|
|
46
37
|
}
|
|
47
|
-
function
|
|
38
|
+
function ue() {
|
|
48
39
|
try {
|
|
49
|
-
let e =
|
|
40
|
+
let e = M();
|
|
50
41
|
return {
|
|
51
42
|
env: e.getEnvInfo().env,
|
|
52
43
|
grayTag: e.getGrayTag()
|
|
@@ -57,46 +48,49 @@ function he() {
|
|
|
57
48
|
}
|
|
58
49
|
//#endregion
|
|
59
50
|
//#region src/utils/env.ts
|
|
60
|
-
|
|
51
|
+
function E() {
|
|
52
|
+
return (typeof process < "u" ? process : {}).env || {};
|
|
53
|
+
}
|
|
54
|
+
var D = {
|
|
61
55
|
brand: "YOYO_CLAW_BRAND",
|
|
62
56
|
manufacture: "YOYO_CLAW_MANUFACTURER",
|
|
63
57
|
deviceType: "YOYO_CLAW_DEVICE_TYPE",
|
|
64
58
|
userId: "YOYO_CLAW_USER_ID"
|
|
65
|
-
},
|
|
59
|
+
}, de = "YOYO_CLAW_ENV", fe = {
|
|
66
60
|
dev: "dev",
|
|
67
61
|
pre: "test",
|
|
68
62
|
test: "test",
|
|
69
63
|
prd: "production",
|
|
70
64
|
production: "production"
|
|
71
65
|
};
|
|
72
|
-
function
|
|
66
|
+
function pe() {
|
|
73
67
|
return {
|
|
74
|
-
brand:
|
|
75
|
-
manufacture:
|
|
76
|
-
deviceType:
|
|
68
|
+
brand: E()[D.brand],
|
|
69
|
+
manufacture: E()[D.manufacture],
|
|
70
|
+
deviceType: E()[D.deviceType]
|
|
77
71
|
};
|
|
78
72
|
}
|
|
79
|
-
function
|
|
80
|
-
return
|
|
73
|
+
function me() {
|
|
74
|
+
return E()[D.userId];
|
|
81
75
|
}
|
|
82
|
-
function
|
|
83
|
-
let e =
|
|
84
|
-
if (e) return
|
|
76
|
+
function he() {
|
|
77
|
+
let e = E()[de];
|
|
78
|
+
if (e) return fe[e.toLowerCase()];
|
|
85
79
|
}
|
|
86
80
|
//#endregion
|
|
87
81
|
//#region src/utils/error.ts
|
|
88
|
-
function
|
|
82
|
+
function O(e, t) {
|
|
89
83
|
let n = e instanceof Error ? e.message : String(e);
|
|
90
84
|
return Error(`${t}: ${n}`, { cause: e });
|
|
91
85
|
}
|
|
92
86
|
//#endregion
|
|
93
87
|
//#region src/utils/logger.ts
|
|
94
|
-
var
|
|
95
|
-
function
|
|
96
|
-
|
|
88
|
+
var ge = null;
|
|
89
|
+
function _e(e) {
|
|
90
|
+
ge = e;
|
|
97
91
|
}
|
|
98
|
-
function
|
|
99
|
-
return
|
|
92
|
+
function k() {
|
|
93
|
+
return ge || {
|
|
100
94
|
debug: console.debug,
|
|
101
95
|
info: console.log,
|
|
102
96
|
warn: console.warn,
|
|
@@ -105,7 +99,7 @@ function D() {
|
|
|
105
99
|
}
|
|
106
100
|
//#endregion
|
|
107
101
|
//#region src/modules/configs/provider.ts
|
|
108
|
-
function
|
|
102
|
+
function ve(e) {
|
|
109
103
|
let t = {};
|
|
110
104
|
if (!e.models?.providers) return t;
|
|
111
105
|
let n = Object.keys(e.models.providers);
|
|
@@ -115,7 +109,7 @@ function Ce(e) {
|
|
|
115
109
|
}
|
|
116
110
|
return t;
|
|
117
111
|
}
|
|
118
|
-
function
|
|
112
|
+
function ye(e, t) {
|
|
119
113
|
let n = { ...e };
|
|
120
114
|
if (n.models?.providers) {
|
|
121
115
|
let e = {};
|
|
@@ -128,46 +122,46 @@ function we(e, t) {
|
|
|
128
122
|
providers: e
|
|
129
123
|
};
|
|
130
124
|
}
|
|
131
|
-
return n.agents &&=
|
|
125
|
+
return n.agents &&= be(n.agents, t), n.auth?.profiles && (n.auth = {
|
|
132
126
|
...n.auth,
|
|
133
|
-
profiles:
|
|
134
|
-
},
|
|
127
|
+
profiles: we(n.auth.profiles, t)
|
|
128
|
+
}, De(t)), n;
|
|
135
129
|
}
|
|
136
|
-
function
|
|
130
|
+
function be(e, t) {
|
|
137
131
|
let n = { ...e };
|
|
138
|
-
return n.defaults &&=
|
|
132
|
+
return n.defaults &&= xe(n.defaults, t), n.list &&= n.list.map((e) => Se(e, t)), n;
|
|
139
133
|
}
|
|
140
|
-
function
|
|
134
|
+
function xe(e, t) {
|
|
141
135
|
let n = { ...e };
|
|
142
|
-
if (n.model &&=
|
|
136
|
+
if (n.model &&= A(n.model, t), n.imageModel &&= A(n.imageModel, t), n.pdfModel &&= A(n.pdfModel, t), n.models) {
|
|
143
137
|
let e = {};
|
|
144
138
|
for (let [r, i] of Object.entries(n.models)) {
|
|
145
|
-
let n =
|
|
139
|
+
let n = Ce(r, t);
|
|
146
140
|
e[n] = i;
|
|
147
141
|
}
|
|
148
142
|
n.models = e;
|
|
149
143
|
}
|
|
150
144
|
return n.subagents?.model && (n.subagents = {
|
|
151
145
|
...n.subagents,
|
|
152
|
-
model:
|
|
146
|
+
model: A(n.subagents.model, t)
|
|
153
147
|
}), n;
|
|
154
148
|
}
|
|
155
|
-
function
|
|
149
|
+
function Se(e, t) {
|
|
156
150
|
let n = { ...e };
|
|
157
|
-
return n.model &&=
|
|
151
|
+
return n.model &&= A(n.model, t), n.subagents?.model && (n.subagents = {
|
|
158
152
|
...n.subagents,
|
|
159
|
-
model:
|
|
153
|
+
model: A(n.subagents.model, t)
|
|
160
154
|
}), n;
|
|
161
155
|
}
|
|
162
|
-
function
|
|
163
|
-
if (typeof e == "string") return
|
|
156
|
+
function A(e, t) {
|
|
157
|
+
if (typeof e == "string") return Ce(e, t);
|
|
164
158
|
if (typeof e == "object" && e) {
|
|
165
159
|
let n = { ...e };
|
|
166
|
-
return n.primary &&=
|
|
160
|
+
return n.primary &&= Ce(n.primary, t), n.fallbacks && Array.isArray(n.fallbacks) && (n.fallbacks = n.fallbacks.map((e) => Ce(e, t))), n;
|
|
167
161
|
}
|
|
168
162
|
return e;
|
|
169
163
|
}
|
|
170
|
-
function
|
|
164
|
+
function Ce(e, t) {
|
|
171
165
|
let n = e.split("/");
|
|
172
166
|
if (n.length > 0) {
|
|
173
167
|
let e = t[n[0]];
|
|
@@ -175,7 +169,7 @@ function k(e, t) {
|
|
|
175
169
|
}
|
|
176
170
|
return e;
|
|
177
171
|
}
|
|
178
|
-
function
|
|
172
|
+
function we(e, t) {
|
|
179
173
|
let n = {};
|
|
180
174
|
for (let [r, i] of Object.entries(e)) {
|
|
181
175
|
let e = { ...i }, a = t[e.provider];
|
|
@@ -183,85 +177,85 @@ function Oe(e, t) {
|
|
|
183
177
|
}
|
|
184
178
|
return n;
|
|
185
179
|
}
|
|
186
|
-
function
|
|
187
|
-
return process.platform === "win32" ?
|
|
180
|
+
function Te() {
|
|
181
|
+
return process.platform === "win32" ? E().USERPROFILE || "" : E().HOME || "";
|
|
188
182
|
}
|
|
189
|
-
function
|
|
190
|
-
let
|
|
191
|
-
|
|
192
|
-
let
|
|
193
|
-
if (
|
|
194
|
-
let
|
|
195
|
-
for (let
|
|
196
|
-
let
|
|
197
|
-
|
|
183
|
+
function Ee(t) {
|
|
184
|
+
let n = [], i = Te(), a = t || r.join(i, ".openclaw"), o = r.join(a, "agents", "main", "agent", "auth-profiles.json");
|
|
185
|
+
e.existsSync(o) && n.push(o);
|
|
186
|
+
let s = r.join(a, "agents");
|
|
187
|
+
if (e.existsSync(s)) {
|
|
188
|
+
let t = e.readdirSync(s, { withFileTypes: !0 });
|
|
189
|
+
for (let i of t) if (i.isDirectory()) {
|
|
190
|
+
let t = r.join(s, i.name, "agent", "auth-profiles.json");
|
|
191
|
+
e.existsSync(t) && !n.includes(t) && n.push(t);
|
|
198
192
|
}
|
|
199
193
|
}
|
|
200
|
-
return
|
|
194
|
+
return n;
|
|
201
195
|
}
|
|
202
|
-
function
|
|
203
|
-
let
|
|
204
|
-
for (let
|
|
205
|
-
let
|
|
206
|
-
if (!
|
|
207
|
-
let
|
|
208
|
-
for (let [
|
|
209
|
-
let
|
|
210
|
-
i && r !== i && (
|
|
211
|
-
}
|
|
212
|
-
if (
|
|
213
|
-
let
|
|
214
|
-
for (let [n, r] of Object.entries(
|
|
215
|
-
let i =
|
|
216
|
-
|
|
196
|
+
function De(t, n) {
|
|
197
|
+
let r = Ee(n), i = [], a = [], o = !1;
|
|
198
|
+
for (let n of r) try {
|
|
199
|
+
let r = e.readFileSync(n, "utf-8"), a = JSON.parse(r);
|
|
200
|
+
if (!a.profiles || typeof a.profiles != "object") continue;
|
|
201
|
+
let s = !1;
|
|
202
|
+
for (let [e, n] of Object.entries(a.profiles)) {
|
|
203
|
+
let e = n, r = e.provider, i = t[r];
|
|
204
|
+
i && r !== i && (e.provider = i, s = !0);
|
|
205
|
+
}
|
|
206
|
+
if (a.order && typeof a.order == "object") {
|
|
207
|
+
let e = {};
|
|
208
|
+
for (let [n, r] of Object.entries(a.order)) {
|
|
209
|
+
let i = t[n], a = i || n;
|
|
210
|
+
e[a] = r, i && n !== i && (s = !0);
|
|
217
211
|
}
|
|
218
|
-
|
|
212
|
+
s && (a.order = e);
|
|
219
213
|
}
|
|
220
|
-
if (
|
|
221
|
-
let
|
|
222
|
-
for (let [n, r] of Object.entries(
|
|
223
|
-
let i =
|
|
224
|
-
|
|
214
|
+
if (a.lastGood && typeof a.lastGood == "object") {
|
|
215
|
+
let e = {};
|
|
216
|
+
for (let [n, r] of Object.entries(a.lastGood)) {
|
|
217
|
+
let i = t[n], a = i || n;
|
|
218
|
+
e[a] = r, i && n !== i && (s = !0);
|
|
225
219
|
}
|
|
226
|
-
|
|
220
|
+
s && (a.lastGood = e);
|
|
227
221
|
}
|
|
228
|
-
|
|
222
|
+
s && (e.writeFileSync(n, JSON.stringify(a, null, 2) + "\n", "utf-8"), i.push(n), o = !0);
|
|
229
223
|
} catch (e) {
|
|
230
|
-
let
|
|
231
|
-
|
|
224
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
225
|
+
a.push(`${n}: ${t}`);
|
|
232
226
|
}
|
|
233
227
|
return {
|
|
234
|
-
updated:
|
|
235
|
-
files:
|
|
236
|
-
errors:
|
|
228
|
+
updated: o,
|
|
229
|
+
files: i,
|
|
230
|
+
errors: a
|
|
237
231
|
};
|
|
238
232
|
}
|
|
239
233
|
//#endregion
|
|
240
234
|
//#region src/modules/configs/config-manager.ts
|
|
241
|
-
var
|
|
235
|
+
var j = "yoyo", Oe = { watch: !0 }, ke = 250, Ae = /* @__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".split(","), je = class {
|
|
242
236
|
loadConfig() {
|
|
243
237
|
try {
|
|
244
|
-
return
|
|
238
|
+
return le().config.loadConfig();
|
|
245
239
|
} catch (e) {
|
|
246
|
-
throw
|
|
240
|
+
throw O(e, "Failed to load config");
|
|
247
241
|
}
|
|
248
242
|
}
|
|
249
243
|
async saveConfig(e) {
|
|
250
244
|
try {
|
|
251
|
-
await
|
|
245
|
+
await le().config.writeConfigFile(e);
|
|
252
246
|
} catch (e) {
|
|
253
|
-
throw
|
|
247
|
+
throw O(e, "Failed to save config");
|
|
254
248
|
}
|
|
255
249
|
}
|
|
256
250
|
getGatewayAuthConfig() {
|
|
257
251
|
try {
|
|
258
252
|
let e = this.loadConfig().gateway?.auth;
|
|
259
253
|
if (!e) return;
|
|
260
|
-
let t =
|
|
261
|
-
|
|
262
|
-
|
|
254
|
+
let t = e.token ?? "", n = e.password ?? "";
|
|
255
|
+
return !t && !n ? void 0 : {
|
|
256
|
+
token: t,
|
|
257
|
+
password: n
|
|
263
258
|
};
|
|
264
|
-
return e.token && (t.token = e.token), e.password && (t.password = e.password), Object.keys(t).length === 0 ? void 0 : t;
|
|
265
259
|
} catch (e) {
|
|
266
260
|
console.error(`[claw-configs] Failed to read gateway auth config: ${e}`);
|
|
267
261
|
return;
|
|
@@ -276,7 +270,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
276
270
|
}
|
|
277
271
|
getUserConfig() {
|
|
278
272
|
try {
|
|
279
|
-
return this.loadConfig().plugins?.entries?.[
|
|
273
|
+
return this.loadConfig().plugins?.entries?.[j]?.config?.user;
|
|
280
274
|
} catch (e) {
|
|
281
275
|
console.error(`[claw-configs] Failed to read user config: ${e}`);
|
|
282
276
|
return;
|
|
@@ -284,14 +278,14 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
284
278
|
}
|
|
285
279
|
getEnvInfo() {
|
|
286
280
|
try {
|
|
287
|
-
let e = this.loadConfig().plugins?.entries?.[
|
|
281
|
+
let e = this.loadConfig().plugins?.entries?.[j]?.config, t = e?.envInfo;
|
|
288
282
|
if (t?.env) return t;
|
|
289
283
|
let n = e?.env;
|
|
290
284
|
if (n) return {
|
|
291
285
|
env: n,
|
|
292
286
|
source: "manual"
|
|
293
287
|
};
|
|
294
|
-
let r =
|
|
288
|
+
let r = he();
|
|
295
289
|
return r ? {
|
|
296
290
|
env: r,
|
|
297
291
|
source: "env"
|
|
@@ -308,7 +302,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
308
302
|
}
|
|
309
303
|
getGrayTag() {
|
|
310
304
|
try {
|
|
311
|
-
return this.loadConfig().plugins?.entries?.[
|
|
305
|
+
return this.loadConfig().plugins?.entries?.[j]?.config?.gray;
|
|
312
306
|
} catch (e) {
|
|
313
307
|
console.error(`[claw-configs] Failed to read gray tag config: ${e}`);
|
|
314
308
|
return;
|
|
@@ -316,7 +310,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
316
310
|
}
|
|
317
311
|
getDeviceConfig() {
|
|
318
312
|
try {
|
|
319
|
-
return this.loadConfig().plugins?.entries?.[
|
|
313
|
+
return this.loadConfig().plugins?.entries?.[j]?.config?.device;
|
|
320
314
|
} catch (e) {
|
|
321
315
|
console.error(`[claw-configs] Failed to read device config: ${e}`);
|
|
322
316
|
return;
|
|
@@ -324,17 +318,17 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
324
318
|
}
|
|
325
319
|
async updateDeviceConfig(e) {
|
|
326
320
|
try {
|
|
327
|
-
let t = this.loadConfig(), n = t.plugins?.entries?.[
|
|
321
|
+
let t = this.loadConfig(), n = t.plugins?.entries?.[j]?.config?.device || {}, r = {
|
|
328
322
|
...t,
|
|
329
323
|
plugins: {
|
|
330
324
|
...t.plugins,
|
|
331
325
|
entries: {
|
|
332
326
|
...t.plugins?.entries,
|
|
333
|
-
[
|
|
334
|
-
...t.plugins?.entries?.[
|
|
327
|
+
[j]: {
|
|
328
|
+
...t.plugins?.entries?.[j],
|
|
335
329
|
enabled: !0,
|
|
336
330
|
config: {
|
|
337
|
-
...t.plugins?.entries?.[
|
|
331
|
+
...t.plugins?.entries?.[j]?.config,
|
|
338
332
|
device: {
|
|
339
333
|
...n,
|
|
340
334
|
...e
|
|
@@ -346,7 +340,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
346
340
|
};
|
|
347
341
|
await this.saveConfig(r);
|
|
348
342
|
} catch (e) {
|
|
349
|
-
throw
|
|
343
|
+
throw O(e, "Failed to update device config");
|
|
350
344
|
}
|
|
351
345
|
}
|
|
352
346
|
async updateEnv(e) {
|
|
@@ -357,11 +351,11 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
357
351
|
...t.plugins,
|
|
358
352
|
entries: {
|
|
359
353
|
...t.plugins?.entries,
|
|
360
|
-
[
|
|
361
|
-
...t.plugins?.entries?.[
|
|
354
|
+
[j]: {
|
|
355
|
+
...t.plugins?.entries?.[j],
|
|
362
356
|
enabled: !0,
|
|
363
357
|
config: {
|
|
364
|
-
...t.plugins?.entries?.[
|
|
358
|
+
...t.plugins?.entries?.[j]?.config,
|
|
365
359
|
envInfo: {
|
|
366
360
|
env: e,
|
|
367
361
|
source: "manual"
|
|
@@ -374,12 +368,12 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
374
368
|
};
|
|
375
369
|
await this.saveConfig(n);
|
|
376
370
|
} catch (e) {
|
|
377
|
-
throw
|
|
371
|
+
throw O(e, "Failed to update env config");
|
|
378
372
|
}
|
|
379
373
|
}
|
|
380
374
|
async resetEnv() {
|
|
381
375
|
try {
|
|
382
|
-
let e = this.loadConfig(), t = e.plugins?.entries?.[
|
|
376
|
+
let e = this.loadConfig(), t = e.plugins?.entries?.[j]?.config?.envInfo;
|
|
383
377
|
if (!t?.env) return;
|
|
384
378
|
let n = {
|
|
385
379
|
...e,
|
|
@@ -387,11 +381,11 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
387
381
|
...e.plugins,
|
|
388
382
|
entries: {
|
|
389
383
|
...e.plugins?.entries,
|
|
390
|
-
[
|
|
391
|
-
...e.plugins?.entries?.[
|
|
384
|
+
[j]: {
|
|
385
|
+
...e.plugins?.entries?.[j],
|
|
392
386
|
enabled: !0,
|
|
393
387
|
config: {
|
|
394
|
-
...e.plugins?.entries?.[
|
|
388
|
+
...e.plugins?.entries?.[j]?.config,
|
|
395
389
|
envInfo: {
|
|
396
390
|
env: t.env,
|
|
397
391
|
source: "env"
|
|
@@ -403,7 +397,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
403
397
|
};
|
|
404
398
|
await this.saveConfig(n);
|
|
405
399
|
} catch (e) {
|
|
406
|
-
throw
|
|
400
|
+
throw O(e, "Failed to reset env config");
|
|
407
401
|
}
|
|
408
402
|
}
|
|
409
403
|
async updateGrayTag(e) {
|
|
@@ -414,11 +408,11 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
414
408
|
...t.plugins,
|
|
415
409
|
entries: {
|
|
416
410
|
...t.plugins?.entries,
|
|
417
|
-
[
|
|
418
|
-
...t.plugins?.entries?.[
|
|
411
|
+
[j]: {
|
|
412
|
+
...t.plugins?.entries?.[j],
|
|
419
413
|
enabled: !0,
|
|
420
414
|
config: {
|
|
421
|
-
...t.plugins?.entries?.[
|
|
415
|
+
...t.plugins?.entries?.[j]?.config,
|
|
422
416
|
...e && { gray: e }
|
|
423
417
|
}
|
|
424
418
|
}
|
|
@@ -427,7 +421,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
427
421
|
};
|
|
428
422
|
await this.saveConfig(n);
|
|
429
423
|
} catch (e) {
|
|
430
|
-
throw
|
|
424
|
+
throw O(e, "Failed to update gray tag config");
|
|
431
425
|
}
|
|
432
426
|
}
|
|
433
427
|
async updateUserConfig(e) {
|
|
@@ -438,11 +432,11 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
438
432
|
...t.plugins,
|
|
439
433
|
entries: {
|
|
440
434
|
...t.plugins?.entries,
|
|
441
|
-
[
|
|
442
|
-
...t.plugins?.entries?.[
|
|
435
|
+
[j]: {
|
|
436
|
+
...t.plugins?.entries?.[j],
|
|
443
437
|
enabled: !0,
|
|
444
438
|
config: {
|
|
445
|
-
...t.plugins?.entries?.[
|
|
439
|
+
...t.plugins?.entries?.[j]?.config,
|
|
446
440
|
user: e
|
|
447
441
|
}
|
|
448
442
|
}
|
|
@@ -451,7 +445,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
451
445
|
};
|
|
452
446
|
await this.saveConfig(n);
|
|
453
447
|
} catch (e) {
|
|
454
|
-
throw
|
|
448
|
+
throw O(e, "Failed to update user config");
|
|
455
449
|
}
|
|
456
450
|
}
|
|
457
451
|
async clearUserConfig() {
|
|
@@ -462,10 +456,10 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
462
456
|
...e.plugins,
|
|
463
457
|
entries: {
|
|
464
458
|
...e.plugins?.entries,
|
|
465
|
-
[
|
|
466
|
-
...e.plugins?.entries?.[
|
|
459
|
+
[j]: {
|
|
460
|
+
...e.plugins?.entries?.[j],
|
|
467
461
|
config: {
|
|
468
|
-
...e.plugins?.entries?.[
|
|
462
|
+
...e.plugins?.entries?.[j]?.config,
|
|
469
463
|
user: void 0
|
|
470
464
|
}
|
|
471
465
|
}
|
|
@@ -474,21 +468,25 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
474
468
|
};
|
|
475
469
|
await this.saveConfig(t);
|
|
476
470
|
} catch (e) {
|
|
477
|
-
throw
|
|
471
|
+
throw O(e, "Failed to clear user config");
|
|
478
472
|
}
|
|
479
473
|
}
|
|
480
474
|
async initializePluginConfig(e) {
|
|
481
475
|
try {
|
|
482
|
-
let t = this.loadConfig(), n = t.plugins?.allow || [], r = n.includes(e) ? n : [...n, e], i = t.gateway?.nodes?.allowCommands || [], a = Array.from(new Set([...i, ...
|
|
483
|
-
|
|
476
|
+
let t = this.loadConfig(), n = t.plugins?.allow || [], r = n.includes(e) ? n : [...n, e], i = t.gateway?.nodes?.allowCommands || [], a = Array.from(new Set([...i, ...Ae])), o = t.skills || {}, s = o.load || {}, c = s.watch === Oe.watch && s.watchDebounceMs !== void 0 ? s : {
|
|
477
|
+
...s,
|
|
478
|
+
...Oe,
|
|
479
|
+
watchDebounceMs: s.watchDebounceMs ?? ke
|
|
480
|
+
}, l = t.plugins?.entries?.[e]?.config?.envInfo, u = t.plugins?.entries?.[e]?.config?.env, d = !!(l?.env || u), f = he(), p = !!l?.env && l.source === "env", m = !l?.env && !!u || p && f && l.env !== f, h = !d || m, g = {
|
|
481
|
+
env: f || u || (oe() ? "test" : "production"),
|
|
484
482
|
source: "env"
|
|
485
|
-
},
|
|
486
|
-
...
|
|
487
|
-
envInfo:
|
|
483
|
+
}, _ = t.plugins?.entries?.[e]?.config || {}, v = h ? {
|
|
484
|
+
..._,
|
|
485
|
+
envInfo: g,
|
|
488
486
|
env: void 0
|
|
489
|
-
} :
|
|
490
|
-
Object.keys(
|
|
491
|
-
let
|
|
487
|
+
} : _, y = ve(t);
|
|
488
|
+
Object.keys(y).length > 0 && k().info(`[claw-configs] Found ${Object.keys(y).length} providers to rename: ${Object.entries(y).map(([e, t]) => `${e} -> ${t}`).join(", ")}`);
|
|
489
|
+
let b = {
|
|
492
490
|
...t,
|
|
493
491
|
plugins: {
|
|
494
492
|
...t.plugins,
|
|
@@ -498,7 +496,7 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
498
496
|
[e]: {
|
|
499
497
|
...t.plugins?.entries?.[e],
|
|
500
498
|
enabled: !0,
|
|
501
|
-
config:
|
|
499
|
+
config: v
|
|
502
500
|
}
|
|
503
501
|
}
|
|
504
502
|
},
|
|
@@ -508,28 +506,32 @@ var A = "yoyo", Me = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,al
|
|
|
508
506
|
...t.gateway?.nodes,
|
|
509
507
|
allowCommands: a
|
|
510
508
|
}
|
|
509
|
+
},
|
|
510
|
+
skills: {
|
|
511
|
+
...o,
|
|
512
|
+
load: c
|
|
511
513
|
}
|
|
512
514
|
};
|
|
513
|
-
Object.keys(
|
|
515
|
+
Object.keys(y).length > 0 && (b = ye(b, y), k().info("[claw-configs] Provider renaming completed")), await this.saveConfig(b);
|
|
514
516
|
} catch (e) {
|
|
515
|
-
throw
|
|
517
|
+
throw O(e, "failed to initialize plugin config");
|
|
516
518
|
}
|
|
517
519
|
}
|
|
518
|
-
},
|
|
519
|
-
function
|
|
520
|
-
return
|
|
520
|
+
}, Me = null;
|
|
521
|
+
function M() {
|
|
522
|
+
return Me ||= new je(), Me;
|
|
521
523
|
}
|
|
522
524
|
//#endregion
|
|
523
525
|
//#region src/commands/env/impl.ts
|
|
524
|
-
var
|
|
526
|
+
var Ne = {
|
|
525
527
|
env: "environment variable",
|
|
526
528
|
manual: "manual config"
|
|
527
529
|
};
|
|
528
|
-
function
|
|
530
|
+
function Pe(e, t) {
|
|
529
531
|
return t.command("env").description("Manage runtime environment (dev/test/production)").option("--set <env>", "Set environment: dev, test or production").option("--gray <tag>", "Set gray header").option("--reset", "Reset env source to environment variable").action(async (e) => {
|
|
530
|
-
let { set: t, gray: n, reset: r } = e, i =
|
|
532
|
+
let { set: t, gray: n, reset: r } = e, i = k();
|
|
531
533
|
try {
|
|
532
|
-
let e =
|
|
534
|
+
let e = M();
|
|
533
535
|
if (r && (await e.resetEnv(), i.info("✅ Environment source reset to environment variable")), t) {
|
|
534
536
|
if (t !== "test" && t !== "dev" && t !== "production") {
|
|
535
537
|
i.error("❌ Invalid environment. Use 'test' or 'production'.");
|
|
@@ -539,7 +541,7 @@ function Ie(e, t) {
|
|
|
539
541
|
}
|
|
540
542
|
if (n ? (await e.updateGrayTag(n), i.info(`✅ Gray tag set to: ${n}`)) : n === "" && (await e.updateGrayTag(void 0), i.info("✅ Gray tag cleared")), !t && n === void 0) {
|
|
541
543
|
let t = e.getEnvInfo(), n = e.getGrayTag();
|
|
542
|
-
i.info(`📋 Current environment: ${t.env} (source: ${
|
|
544
|
+
i.info(`📋 Current environment: ${t.env} (source: ${Ne[t.source]})`), n ? i.info(`📋 Current gray tag: ${n}`) : i.info("📋 Gray tag: not set");
|
|
543
545
|
}
|
|
544
546
|
} catch (e) {
|
|
545
547
|
let t = e instanceof Error ? e.message : String(e);
|
|
@@ -549,19 +551,19 @@ function Ie(e, t) {
|
|
|
549
551
|
}
|
|
550
552
|
//#endregion
|
|
551
553
|
//#region src/utils/id.ts
|
|
552
|
-
var
|
|
553
|
-
function
|
|
554
|
-
return
|
|
554
|
+
var Fe = a("0123456789abcdefghijklmnopqrstuvwxyz", 32);
|
|
555
|
+
function Ie(e) {
|
|
556
|
+
return Fe(e);
|
|
555
557
|
}
|
|
556
558
|
//#endregion
|
|
557
559
|
//#region src/apis/helpers.ts
|
|
558
|
-
function
|
|
560
|
+
function Le(e) {
|
|
559
561
|
return e.status >= 200 && e.status < 300 && e.data.code === "1";
|
|
560
562
|
}
|
|
561
563
|
//#endregion
|
|
562
564
|
//#region src/apis/hosts.ts
|
|
563
|
-
function
|
|
564
|
-
let e =
|
|
565
|
+
function Re() {
|
|
566
|
+
let e = ue(), t;
|
|
565
567
|
switch (e.env) {
|
|
566
568
|
case "dev":
|
|
567
569
|
t = {
|
|
@@ -586,34 +588,34 @@ function ze() {
|
|
|
586
588
|
}
|
|
587
589
|
//#endregion
|
|
588
590
|
//#region src/utils/proxy.ts
|
|
589
|
-
function
|
|
590
|
-
return e ||
|
|
591
|
+
function ze(e) {
|
|
592
|
+
return e || E().HTTP_PROXY || E().http_proxy || E().HTTPS_PROXY || E().https_proxy;
|
|
591
593
|
}
|
|
592
|
-
function
|
|
594
|
+
function Be(e, t) {
|
|
593
595
|
return !t && !!e;
|
|
594
596
|
}
|
|
595
|
-
function
|
|
596
|
-
let n =
|
|
597
|
+
function Ve(e, t) {
|
|
598
|
+
let n = ze(t);
|
|
597
599
|
if (n) {
|
|
598
|
-
if (e.startsWith("wss://")) return new
|
|
599
|
-
if (e.startsWith("ws://")) return new
|
|
600
|
+
if (e.startsWith("wss://")) return new l(n);
|
|
601
|
+
if (e.startsWith("ws://")) return new c(n);
|
|
600
602
|
}
|
|
601
603
|
}
|
|
602
604
|
//#endregion
|
|
603
605
|
//#region src/apis/http-client.ts
|
|
604
|
-
var
|
|
606
|
+
var He = class extends Error {
|
|
605
607
|
constructor(e, t, n) {
|
|
606
608
|
super(n), this.status = e, this.data = t, this.name = "HttpError";
|
|
607
609
|
}
|
|
608
|
-
},
|
|
610
|
+
}, Ue = class {
|
|
609
611
|
baseUrl;
|
|
610
612
|
defaultHeaders;
|
|
611
613
|
defaultTimeout;
|
|
612
614
|
proxyAgent;
|
|
613
615
|
constructor(e, t) {
|
|
614
616
|
this.baseUrl = e.replace(/\/$/, ""), this.defaultHeaders = t?.defaultHeaders || {}, this.defaultTimeout = t?.defaultTimeout || 3e4;
|
|
615
|
-
let n =
|
|
616
|
-
n && (this.proxyAgent = new
|
|
617
|
+
let n = ze(t?.proxy);
|
|
618
|
+
n && (this.proxyAgent = new o(n));
|
|
617
619
|
}
|
|
618
620
|
async request(e) {
|
|
619
621
|
let { method: t = "GET", headers: n = {}, body: r, timeout: i = this.defaultTimeout, query: a } = e, o = e.url;
|
|
@@ -625,35 +627,35 @@ var Ue = class extends Error {
|
|
|
625
627
|
let t = e.toString();
|
|
626
628
|
t && (o += (o.includes("?") ? "&" : "?") + t);
|
|
627
629
|
}
|
|
628
|
-
let
|
|
630
|
+
let c = {
|
|
629
631
|
...this.defaultHeaders,
|
|
630
632
|
...n
|
|
631
633
|
};
|
|
632
|
-
r && !
|
|
633
|
-
let
|
|
634
|
-
r != null && (
|
|
634
|
+
r && !c["Content-Type"] && (c["Content-Type"] = "application/json");
|
|
635
|
+
let l;
|
|
636
|
+
r != null && (l = typeof r == "string" ? r : JSON.stringify(r));
|
|
635
637
|
try {
|
|
636
|
-
let n =
|
|
638
|
+
let n = Be(ze(), e.disableProxy) && this.proxyAgent ? this.proxyAgent : void 0, r = await s(o, {
|
|
637
639
|
method: t,
|
|
638
|
-
headers:
|
|
639
|
-
body:
|
|
640
|
+
headers: c,
|
|
641
|
+
body: l,
|
|
640
642
|
headersTimeout: i,
|
|
641
643
|
bodyTimeout: i,
|
|
642
644
|
dispatcher: n
|
|
643
|
-
}), a = await r.body.text(),
|
|
645
|
+
}), a = await r.body.text(), u;
|
|
644
646
|
try {
|
|
645
|
-
|
|
647
|
+
u = a ? JSON.parse(a) : {};
|
|
646
648
|
} catch {
|
|
647
|
-
|
|
649
|
+
u = a;
|
|
648
650
|
}
|
|
649
651
|
if (r.statusCode >= 200 && r.statusCode < 300) return {
|
|
650
|
-
data:
|
|
652
|
+
data: u,
|
|
651
653
|
status: r.statusCode,
|
|
652
654
|
headers: r.headers
|
|
653
655
|
};
|
|
654
|
-
throw new
|
|
656
|
+
throw new He(r.statusCode, u, `HTTP request failed with status ${r.statusCode}`);
|
|
655
657
|
} catch (e) {
|
|
656
|
-
throw e instanceof
|
|
658
|
+
throw e instanceof He ? e : O(e, "HTTP request failed");
|
|
657
659
|
}
|
|
658
660
|
}
|
|
659
661
|
async get(e, t) {
|
|
@@ -691,14 +693,14 @@ var Ue = class extends Error {
|
|
|
691
693
|
method: "PATCH"
|
|
692
694
|
});
|
|
693
695
|
}
|
|
694
|
-
},
|
|
696
|
+
}, We = class {
|
|
695
697
|
httpClient;
|
|
696
698
|
constructor(e, t) {
|
|
697
|
-
this.httpClient = new
|
|
699
|
+
this.httpClient = new Ue(e, t);
|
|
698
700
|
}
|
|
699
701
|
async registerDevice(e, t, n) {
|
|
700
702
|
let r = {
|
|
701
|
-
"x-trace-id":
|
|
703
|
+
"x-trace-id": Ie(),
|
|
702
704
|
"x-jwt-token": t.token,
|
|
703
705
|
"x-device-id": e.deviceId
|
|
704
706
|
}, i = {
|
|
@@ -718,7 +720,7 @@ var Ue = class extends Error {
|
|
|
718
720
|
}
|
|
719
721
|
async logoutDevice(e, t) {
|
|
720
722
|
let n = {
|
|
721
|
-
"x-trace-id":
|
|
723
|
+
"x-trace-id": Ie(),
|
|
722
724
|
"x-jwt-token": t.token,
|
|
723
725
|
"x-device-id": e.deviceId
|
|
724
726
|
}, r = {
|
|
@@ -735,7 +737,7 @@ var Ue = class extends Error {
|
|
|
735
737
|
});
|
|
736
738
|
}
|
|
737
739
|
async exchangeToken(e, t) {
|
|
738
|
-
let n =
|
|
740
|
+
let n = Ie(), r = {
|
|
739
741
|
"Content-Type": "application/json",
|
|
740
742
|
"x-device-id": e.deviceId,
|
|
741
743
|
"x-trace-id": n
|
|
@@ -750,28 +752,25 @@ var Ue = class extends Error {
|
|
|
750
752
|
headers: r,
|
|
751
753
|
timeout: 15e3
|
|
752
754
|
});
|
|
753
|
-
if (
|
|
755
|
+
if (Le(a) && a.data.data) return a.data.data;
|
|
754
756
|
throw Error(`failed to get token: ${JSON.stringify(a.data)}, traceId: ${n}`);
|
|
755
757
|
}
|
|
756
758
|
};
|
|
757
759
|
function N() {
|
|
758
|
-
let e =
|
|
759
|
-
return new
|
|
760
|
+
let e = Re();
|
|
761
|
+
return new We(`https://${e.clawCloud}/aicloud/yoyo-claw-service`, e.grayTag ? { defaultHeaders: { "x-gray": e.grayTag } } : void 0);
|
|
760
762
|
}
|
|
761
763
|
//#endregion
|
|
762
764
|
//#region src/honor-auth/assets/favicon.png
|
|
763
|
-
var Ke = "data:image/png;base64,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", qe = "data:image/png;base64,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", Je = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M22.5 32.5L29 39L42.5 25.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>", Ye = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M24.5 24.5L39.5 39.5M39.5 24.5L24.5 39.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\"/></svg>", Xe = {
|
|
764
|
-
favicon: "/favicon.png",
|
|
765
|
-
yoyoLogo: "/yoyo-logo.png"
|
|
766
|
-
};
|
|
765
|
+
var Ge = "data:image/png;base64,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", Ke = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M22.5 32.5L29 39L42.5 25.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>", qe = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M24.5 24.5L39.5 39.5M39.5 24.5L24.5 39.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\"/></svg>", Je = { favicon: "/favicon.png" };
|
|
767
766
|
function P(e) {
|
|
768
767
|
return e.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
769
768
|
}
|
|
770
|
-
function
|
|
769
|
+
function Ye(e) {
|
|
771
770
|
return !e || e.length === 0 ? "" : `<div class="details">${e.map((e) => `<div class="detail-item"><span class="detail-key">${P(e.key)}</span><span class="detail-value">${P(e.value)}</span></div>`).join("")}</div>`;
|
|
772
771
|
}
|
|
773
772
|
function F(e) {
|
|
774
|
-
let t = e.statusClass === "success" ?
|
|
773
|
+
let t = e.statusClass === "success" ? Ke : qe;
|
|
775
774
|
return `<!doctype html>
|
|
776
775
|
<html lang="zh-CN">
|
|
777
776
|
<head>
|
|
@@ -959,12 +958,11 @@ function F(e) {
|
|
|
959
958
|
<body>
|
|
960
959
|
<main class="card">
|
|
961
960
|
<div class="brand">
|
|
962
|
-
<img class="brand-logo" src="data:image/png;base64,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" alt="" />
|
|
963
961
|
<span>YOYOClaw</span>
|
|
964
962
|
</div>
|
|
965
963
|
<div class="icon-wrap ${e.statusClass}">${t}</div>
|
|
966
964
|
<h1>${P(e.title)}</h1>
|
|
967
|
-
${
|
|
965
|
+
${Ye(e.details)}
|
|
968
966
|
<div class="footer">
|
|
969
967
|
<p class="hint">${P(e.hintText)}</p>
|
|
970
968
|
<p class="caption">浏览器不会自动关闭当前页面,保留或稍后关闭都不影响登录结果。</p>
|
|
@@ -975,12 +973,9 @@ function F(e) {
|
|
|
975
973
|
}
|
|
976
974
|
//#endregion
|
|
977
975
|
//#region src/honor-auth/callback-server.ts
|
|
978
|
-
var
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
};
|
|
982
|
-
function $e(e, t) {
|
|
983
|
-
let n = Qe[t];
|
|
976
|
+
var Xe = { "favicon.png": Ge };
|
|
977
|
+
function Ze(e, t) {
|
|
978
|
+
let n = Xe[t];
|
|
984
979
|
if (!n) {
|
|
985
980
|
e.writeHead(404), e.end();
|
|
986
981
|
return;
|
|
@@ -991,19 +986,19 @@ function $e(e, t) {
|
|
|
991
986
|
"Cache-Control": "public, max-age=3600"
|
|
992
987
|
}), e.end(i);
|
|
993
988
|
}
|
|
994
|
-
function
|
|
989
|
+
function Qe(e) {
|
|
995
990
|
return new Promise((t, n) => {
|
|
996
|
-
let { port: r, timeout: i = 6e5, onCodeReceived: a, onError: o } = e, s = null, c = !1, l = !1,
|
|
997
|
-
c || (c = !0, s && clearTimeout(s),
|
|
998
|
-
},
|
|
999
|
-
|
|
1000
|
-
},
|
|
991
|
+
let { port: r, timeout: i = 6e5, onCodeReceived: a, onError: o } = e, s = null, c = !1, l = !1, f = !1, p = () => {
|
|
992
|
+
c || (c = !0, s && clearTimeout(s), g.close());
|
|
993
|
+
}, m = (e) => {
|
|
994
|
+
p(), o?.(e), f || (f = !0, n(e));
|
|
995
|
+
}, h = (e = 120) => {
|
|
1001
996
|
setTimeout(() => {
|
|
1002
|
-
|
|
997
|
+
p();
|
|
1003
998
|
}, e);
|
|
1004
|
-
},
|
|
999
|
+
}, g = u((e, t) => {
|
|
1005
1000
|
try {
|
|
1006
|
-
let n = new
|
|
1001
|
+
let n = new d(e.url || "", `http://localhost:${r}`);
|
|
1007
1002
|
if (e.method !== "GET") {
|
|
1008
1003
|
t.writeHead(405, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
|
|
1009
1004
|
pageTitle: "请求方式不支持",
|
|
@@ -1013,12 +1008,8 @@ function et(e) {
|
|
|
1013
1008
|
}));
|
|
1014
1009
|
return;
|
|
1015
1010
|
}
|
|
1016
|
-
if (n.pathname === "/favicon.ico" || n.pathname ===
|
|
1017
|
-
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
if (n.pathname === Xe.yoyoLogo) {
|
|
1021
|
-
$e(t, "yoyo-logo.png");
|
|
1011
|
+
if (n.pathname === "/favicon.ico" || n.pathname === Je.favicon) {
|
|
1012
|
+
Ze(t, "favicon.png");
|
|
1022
1013
|
return;
|
|
1023
1014
|
}
|
|
1024
1015
|
let i = n.searchParams.get("code") || "", o = n.searchParams.get("error") || "", s = n.searchParams.get("error_description") || n.searchParams.get("error_message") || "";
|
|
@@ -1027,7 +1018,7 @@ function et(e) {
|
|
|
1027
1018
|
statusClass: "success",
|
|
1028
1019
|
title: "登录已完成",
|
|
1029
1020
|
hintText: "请返回 OpenClaw,登录流程会继续完成。"
|
|
1030
|
-
})),
|
|
1021
|
+
})), h(), a(i)) : o && !l ? (t.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
|
|
1031
1022
|
pageTitle: "授权失败",
|
|
1032
1023
|
statusClass: "error",
|
|
1033
1024
|
title: "未能完成授权",
|
|
@@ -1040,7 +1031,7 @@ function et(e) {
|
|
|
1040
1031
|
value: s
|
|
1041
1032
|
}] : []]
|
|
1042
1033
|
})), setTimeout(() => {
|
|
1043
|
-
|
|
1034
|
+
m(/* @__PURE__ */ Error(s ? `authorization failed: ${o} (${s})` : `authorization failed: ${o}`));
|
|
1044
1035
|
}, 120)) : l ? (t.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
|
|
1045
1036
|
pageTitle: "登录已完成",
|
|
1046
1037
|
statusClass: "success",
|
|
@@ -1052,7 +1043,7 @@ function et(e) {
|
|
|
1052
1043
|
title: "回调参数不完整",
|
|
1053
1044
|
hintText: "请返回 OpenClaw 重新发起登录。"
|
|
1054
1045
|
})), setTimeout(() => {
|
|
1055
|
-
|
|
1046
|
+
m(/* @__PURE__ */ Error("authorization failed: no code in callback"));
|
|
1056
1047
|
}, 120));
|
|
1057
1048
|
} catch (e) {
|
|
1058
1049
|
console.error("authorize callback error:", e), t.writeHead(500, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
|
|
@@ -1061,24 +1052,24 @@ function et(e) {
|
|
|
1061
1052
|
title: "回调服务出现异常",
|
|
1062
1053
|
hintText: "请返回 OpenClaw 后重新发起登录。"
|
|
1063
1054
|
})), setTimeout(() => {
|
|
1064
|
-
|
|
1055
|
+
m(/* @__PURE__ */ Error("authorization failed: callback server internal error"));
|
|
1065
1056
|
}, 120);
|
|
1066
1057
|
}
|
|
1067
1058
|
});
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
}),
|
|
1059
|
+
g.on("error", (e) => {
|
|
1060
|
+
m(e);
|
|
1061
|
+
}), g.listen(r, () => {
|
|
1071
1062
|
s = setTimeout(() => {
|
|
1072
|
-
|
|
1063
|
+
m(/* @__PURE__ */ Error("authorize timeout"));
|
|
1073
1064
|
}, i);
|
|
1074
|
-
}),
|
|
1075
|
-
s && clearTimeout(s),
|
|
1065
|
+
}), g.on("close", () => {
|
|
1066
|
+
s && clearTimeout(s), f || (f = !0, t());
|
|
1076
1067
|
});
|
|
1077
1068
|
});
|
|
1078
1069
|
}
|
|
1079
1070
|
//#endregion
|
|
1080
1071
|
//#region src/honor-auth/config.ts
|
|
1081
|
-
var
|
|
1072
|
+
var $e = {
|
|
1082
1073
|
authHost: "https://hnoauth-login-test-drcn.cloud.honor.com",
|
|
1083
1074
|
clientId: "221641491",
|
|
1084
1075
|
redirectUri: "http://127.0.0.1:8081/deepLink",
|
|
@@ -1086,7 +1077,7 @@ var tt = {
|
|
|
1086
1077
|
scope: "openid profile",
|
|
1087
1078
|
reqClientType: "110",
|
|
1088
1079
|
loginChannel: "99011000"
|
|
1089
|
-
},
|
|
1080
|
+
}, et = {
|
|
1090
1081
|
authHost: "https://hnoauth-login-drcn.cloud.honor.com",
|
|
1091
1082
|
clientId: "221000597",
|
|
1092
1083
|
redirectUri: "http://127.0.0.1:8081/deepLink",
|
|
@@ -1095,31 +1086,31 @@ var tt = {
|
|
|
1095
1086
|
reqClientType: "110",
|
|
1096
1087
|
loginChannel: "99011000"
|
|
1097
1088
|
};
|
|
1098
|
-
function
|
|
1089
|
+
function tt(e) {
|
|
1099
1090
|
return {
|
|
1100
|
-
...
|
|
1091
|
+
...ue()?.env === "production" ? et : $e,
|
|
1101
1092
|
...e
|
|
1102
1093
|
};
|
|
1103
1094
|
}
|
|
1104
1095
|
//#endregion
|
|
1105
1096
|
//#region src/honor-auth/honor-auth-client.ts
|
|
1106
|
-
var
|
|
1097
|
+
var nt = class {
|
|
1107
1098
|
config;
|
|
1108
1099
|
constructor(e) {
|
|
1109
1100
|
this.config = e;
|
|
1110
1101
|
}
|
|
1111
1102
|
generateRandomString(e) {
|
|
1112
|
-
let t =
|
|
1103
|
+
let t = m(e), n = "";
|
|
1113
1104
|
for (let r = 0; r < e; r++) n += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[t[r] % 62];
|
|
1114
1105
|
return n;
|
|
1115
1106
|
}
|
|
1116
1107
|
generateCodeVerifier(e = 128) {
|
|
1117
|
-
let t =
|
|
1108
|
+
let t = m(e), n = "";
|
|
1118
1109
|
for (let r = 0; r < e; r++) n += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"[t[r] % 66];
|
|
1119
1110
|
return n;
|
|
1120
1111
|
}
|
|
1121
1112
|
generateCodeChallenge(e) {
|
|
1122
|
-
return
|
|
1113
|
+
return p("sha256").update(e).digest().toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1123
1114
|
}
|
|
1124
1115
|
generatePKCEParams() {
|
|
1125
1116
|
let e = this.generateCodeVerifier();
|
|
@@ -1147,8 +1138,8 @@ var it = class {
|
|
|
1147
1138
|
return { ...this.config };
|
|
1148
1139
|
}
|
|
1149
1140
|
};
|
|
1150
|
-
function
|
|
1151
|
-
return new
|
|
1141
|
+
function rt(e) {
|
|
1142
|
+
return new nt(e);
|
|
1152
1143
|
}
|
|
1153
1144
|
//#endregion
|
|
1154
1145
|
//#region src/utils/fs-safe.ts
|
|
@@ -1157,61 +1148,61 @@ var I = class extends Error {
|
|
|
1157
1148
|
constructor(e, t, n) {
|
|
1158
1149
|
super(t, n), this.code = e, this.name = "SafeFsError";
|
|
1159
1150
|
}
|
|
1160
|
-
},
|
|
1151
|
+
}, it = new Set(["ENOENT", "ENOTDIR"]), at = new Set([
|
|
1161
1152
|
"ELOOP",
|
|
1162
1153
|
"EINVAL",
|
|
1163
1154
|
"ENOTSUP"
|
|
1164
1155
|
]);
|
|
1165
|
-
function
|
|
1156
|
+
function ot(e) {
|
|
1166
1157
|
return !!(e && typeof e == "object" && "code" in e);
|
|
1167
1158
|
}
|
|
1168
1159
|
function L(e) {
|
|
1169
|
-
return
|
|
1160
|
+
return ot(e) && typeof e.code == "string" && it.has(e.code);
|
|
1170
1161
|
}
|
|
1171
|
-
function
|
|
1172
|
-
return
|
|
1162
|
+
function st(e) {
|
|
1163
|
+
return ot(e) && typeof e.code == "string" && at.has(e.code);
|
|
1173
1164
|
}
|
|
1174
|
-
function
|
|
1175
|
-
let t =
|
|
1165
|
+
function ct(e) {
|
|
1166
|
+
let t = r.win32.normalize(e);
|
|
1176
1167
|
return t.startsWith("\\\\?\\") && (t = t.slice(4), t.toUpperCase().startsWith("UNC\\") && (t = `\\\\${t.slice(4)}`)), t.replaceAll("/", "\\").toLowerCase();
|
|
1177
1168
|
}
|
|
1178
1169
|
function R(e, t) {
|
|
1179
|
-
let n =
|
|
1170
|
+
let n = r.resolve(e), i = r.resolve(t);
|
|
1180
1171
|
if (process.platform === "win32") {
|
|
1181
|
-
let e =
|
|
1182
|
-
return
|
|
1172
|
+
let e = ct(n), t = ct(i), a = r.win32.relative(e, t);
|
|
1173
|
+
return a === "" || !a.startsWith("..") && !r.win32.isAbsolute(a);
|
|
1183
1174
|
}
|
|
1184
|
-
let
|
|
1185
|
-
return
|
|
1175
|
+
let a = r.relative(n, i);
|
|
1176
|
+
return a === "" || !a.startsWith("..") && !r.isAbsolute(a);
|
|
1186
1177
|
}
|
|
1187
|
-
function
|
|
1178
|
+
function lt(e) {
|
|
1188
1179
|
return e === 0 || e === 0n;
|
|
1189
1180
|
}
|
|
1190
1181
|
function z(e, t, n = process.platform) {
|
|
1191
|
-
return e.ino === t.ino ? e.dev === t.dev ? !0 : n === "win32" && (
|
|
1182
|
+
return e.ino === t.ino ? e.dev === t.dev ? !0 : n === "win32" && (lt(e.dev) || lt(t.dev)) : !1;
|
|
1192
1183
|
}
|
|
1193
|
-
var
|
|
1194
|
-
function
|
|
1184
|
+
var ut = process.platform !== "win32" && "O_NOFOLLOW" in t, dt = t.O_RDONLY | (ut ? t.O_NOFOLLOW : 0), ft = t.O_WRONLY | t.O_CREAT | t.O_EXCL | (ut ? t.O_NOFOLLOW : 0), pt = t.O_WRONLY | t.O_APPEND | (ut ? t.O_NOFOLLOW : 0), mt = (e) => e.endsWith(r.sep) ? e : e + r.sep;
|
|
1185
|
+
function ht(e, t) {
|
|
1195
1186
|
if (!e.startsWith("~")) return e;
|
|
1196
|
-
let n = t ??
|
|
1187
|
+
let n = t ?? E().HOME ?? E().USERPROFILE ?? y.homedir();
|
|
1197
1188
|
return n ? e.replace(/^~(?=$|[\\/])/, n) : e;
|
|
1198
1189
|
}
|
|
1199
|
-
async function
|
|
1190
|
+
async function gt(e) {
|
|
1200
1191
|
let t;
|
|
1201
1192
|
try {
|
|
1202
1193
|
t = await v.realpath(e.rootDir);
|
|
1203
1194
|
} catch (e) {
|
|
1204
1195
|
throw L(e) ? new I("not-found", "root dir not found") : e;
|
|
1205
1196
|
}
|
|
1206
|
-
let n =
|
|
1207
|
-
if (!R(n,
|
|
1197
|
+
let n = mt(t), i = ht(e.relativePath), a = r.resolve(n, i);
|
|
1198
|
+
if (!R(n, a)) throw new I("outside-root", "file is outside workspace root");
|
|
1208
1199
|
return {
|
|
1209
1200
|
rootReal: t,
|
|
1210
1201
|
rootWithSep: n,
|
|
1211
|
-
resolved:
|
|
1202
|
+
resolved: a
|
|
1212
1203
|
};
|
|
1213
1204
|
}
|
|
1214
|
-
async function
|
|
1205
|
+
async function _t(e, t) {
|
|
1215
1206
|
try {
|
|
1216
1207
|
if ((await v.lstat(e)).isDirectory()) throw new I("not-file", "not a file");
|
|
1217
1208
|
} catch (e) {
|
|
@@ -1219,19 +1210,19 @@ async function yt(e, t) {
|
|
|
1219
1210
|
}
|
|
1220
1211
|
let n;
|
|
1221
1212
|
try {
|
|
1222
|
-
n = await v.open(e,
|
|
1213
|
+
n = await v.open(e, dt);
|
|
1223
1214
|
} catch (e) {
|
|
1224
|
-
throw L(e) ? new I("not-found", "file not found") :
|
|
1215
|
+
throw L(e) ? new I("not-found", "file not found") : st(e) ? new I("symlink", "symlink open blocked", { cause: e }) : ot(e) && e.code === "EISDIR" ? new I("not-file", "not a file") : e;
|
|
1225
1216
|
}
|
|
1226
1217
|
try {
|
|
1227
1218
|
let [r, i] = await Promise.all([n.stat(), v.lstat(e)]);
|
|
1228
1219
|
if (i.isSymbolicLink()) throw new I("symlink", "symlink not allowed");
|
|
1229
1220
|
if (!r.isFile()) throw new I("not-file", "not a file");
|
|
1230
1221
|
if (t?.rejectHardlinks && r.nlink > 1) throw new I("invalid-path", "hardlinked path not allowed");
|
|
1231
|
-
if (!z(r, i)) throw new I("path-mismatch", "path changed during read");
|
|
1222
|
+
if (process.platform !== "win32" && !z(r, i)) throw new I("path-mismatch", "path changed during read");
|
|
1232
1223
|
let a = await v.realpath(e), o = await v.stat(a);
|
|
1233
1224
|
if (t?.rejectHardlinks && o.nlink > 1) throw new I("invalid-path", "hardlinked path not allowed");
|
|
1234
|
-
if (!z(r, o)) throw new I("path-mismatch", "path mismatch");
|
|
1225
|
+
if (process.platform !== "win32" && !z(r, o)) throw new I("path-mismatch", "path mismatch");
|
|
1235
1226
|
return {
|
|
1236
1227
|
handle: n,
|
|
1237
1228
|
realPath: a,
|
|
@@ -1241,8 +1232,8 @@ async function yt(e, t) {
|
|
|
1241
1232
|
throw await n.close().catch(() => {}), e instanceof I ? e : L(e) ? new I("not-found", "file not found") : e;
|
|
1242
1233
|
}
|
|
1243
1234
|
}
|
|
1244
|
-
async function
|
|
1245
|
-
let { rootWithSep: t, resolved: n } = await
|
|
1235
|
+
async function vt(e) {
|
|
1236
|
+
let { rootWithSep: t, resolved: n } = await gt(e), r = await _t(n);
|
|
1246
1237
|
if (!R(t, r.realPath)) throw await r.handle.close().catch(() => {}), new I("outside-root", "file is outside workspace root");
|
|
1247
1238
|
try {
|
|
1248
1239
|
if (e.maxBytes !== void 0 && r.stat.size > e.maxBytes) throw new I("too-large", `file exceeds limit of ${e.maxBytes} bytes (got ${r.stat.size})`);
|
|
@@ -1255,62 +1246,62 @@ async function bt(e) {
|
|
|
1255
1246
|
await r.handle.close().catch(() => {});
|
|
1256
1247
|
}
|
|
1257
1248
|
}
|
|
1258
|
-
function
|
|
1259
|
-
let t =
|
|
1260
|
-
return
|
|
1249
|
+
function yt(e) {
|
|
1250
|
+
let t = r.dirname(e), n = r.basename(e);
|
|
1251
|
+
return r.join(t, `.${n}.${process.pid}.${_()}.tmp`);
|
|
1261
1252
|
}
|
|
1262
|
-
async function
|
|
1263
|
-
let t = await v.open(e.tempPath,
|
|
1253
|
+
async function bt(e) {
|
|
1254
|
+
let t = await v.open(e.tempPath, ft, e.mode);
|
|
1264
1255
|
try {
|
|
1265
1256
|
return typeof e.data == "string" ? await t.writeFile(e.data, e.encoding ?? "utf8") : await t.writeFile(e.data), await t.stat();
|
|
1266
1257
|
} finally {
|
|
1267
1258
|
await t.close().catch(() => {});
|
|
1268
1259
|
}
|
|
1269
1260
|
}
|
|
1270
|
-
async function
|
|
1271
|
-
let t =
|
|
1261
|
+
async function xt(e) {
|
|
1262
|
+
let t = mt(await v.realpath(e.rootDir)), n = await _t(e.targetPath, { rejectHardlinks: !0 });
|
|
1272
1263
|
try {
|
|
1273
|
-
if (!z(n.stat, e.expectedStat)) throw new I("path-mismatch", "path changed during write");
|
|
1264
|
+
if (process.platform !== "win32" && !z(n.stat, e.expectedStat)) throw new I("path-mismatch", "path changed during write");
|
|
1274
1265
|
if (!R(t, n.realPath)) throw new I("outside-root", "file is outside workspace root");
|
|
1275
1266
|
} finally {
|
|
1276
1267
|
await n.handle.close().catch(() => {});
|
|
1277
1268
|
}
|
|
1278
1269
|
}
|
|
1279
1270
|
async function B(e) {
|
|
1280
|
-
let { rootWithSep: t, resolved: n } = await
|
|
1281
|
-
e.mkdir !== !1 && await v.mkdir(
|
|
1282
|
-
let
|
|
1271
|
+
let { rootWithSep: t, resolved: n } = await gt(e);
|
|
1272
|
+
e.mkdir !== !1 && await v.mkdir(r.dirname(n), { recursive: !0 });
|
|
1273
|
+
let i = n, a = !1;
|
|
1283
1274
|
try {
|
|
1284
1275
|
let e = await v.realpath(n);
|
|
1285
1276
|
if (!R(t, e)) throw new I("outside-root", "file is outside workspace root");
|
|
1286
|
-
|
|
1277
|
+
i = e, a = !0;
|
|
1287
1278
|
} catch (e) {
|
|
1288
1279
|
if (e instanceof I || !L(e)) throw e;
|
|
1289
1280
|
}
|
|
1290
|
-
let
|
|
1291
|
-
if (
|
|
1292
|
-
return
|
|
1293
|
-
ioPath:
|
|
1281
|
+
let o = e.mode === "append";
|
|
1282
|
+
if (o && !a) throw new I("not-found", "cannot append to non-existent file");
|
|
1283
|
+
return o ? await St({
|
|
1284
|
+
ioPath: i,
|
|
1294
1285
|
rootWithSep: t,
|
|
1295
1286
|
data: e.data,
|
|
1296
1287
|
encoding: e.encoding,
|
|
1297
1288
|
maxBytes: e.maxBytes
|
|
1298
|
-
}) : await
|
|
1299
|
-
ioPath:
|
|
1289
|
+
}) : await Ct({
|
|
1290
|
+
ioPath: i,
|
|
1300
1291
|
rootWithSep: t,
|
|
1301
1292
|
rootDir: e.rootDir,
|
|
1302
1293
|
data: e.data,
|
|
1303
1294
|
encoding: e.encoding,
|
|
1304
|
-
existingFile:
|
|
1295
|
+
existingFile: a,
|
|
1305
1296
|
fileMode: 384
|
|
1306
1297
|
});
|
|
1307
1298
|
}
|
|
1308
|
-
async function
|
|
1299
|
+
async function St(e) {
|
|
1309
1300
|
let t;
|
|
1310
1301
|
try {
|
|
1311
|
-
t = await v.open(e.ioPath,
|
|
1302
|
+
t = await v.open(e.ioPath, pt);
|
|
1312
1303
|
} catch (e) {
|
|
1313
|
-
throw L(e) ? new I("not-found", "file not found") :
|
|
1304
|
+
throw L(e) ? new I("not-found", "file not found") : st(e) ? new I("symlink", "symlink open blocked", { cause: e }) : e;
|
|
1314
1305
|
}
|
|
1315
1306
|
try {
|
|
1316
1307
|
let n = await t.stat();
|
|
@@ -1331,11 +1322,11 @@ async function wt(e) {
|
|
|
1331
1322
|
await t.close().catch(() => {});
|
|
1332
1323
|
}
|
|
1333
1324
|
}
|
|
1334
|
-
async function
|
|
1325
|
+
async function Ct(e) {
|
|
1335
1326
|
let t = null, n = e.ioPath;
|
|
1336
1327
|
try {
|
|
1337
|
-
t =
|
|
1338
|
-
let r = await
|
|
1328
|
+
t = yt(n);
|
|
1329
|
+
let r = await bt({
|
|
1339
1330
|
tempPath: t,
|
|
1340
1331
|
data: e.data,
|
|
1341
1332
|
encoding: e.encoding,
|
|
@@ -1343,13 +1334,13 @@ async function Tt(e) {
|
|
|
1343
1334
|
});
|
|
1344
1335
|
await v.rename(t, n), t = null;
|
|
1345
1336
|
try {
|
|
1346
|
-
await
|
|
1337
|
+
await xt({
|
|
1347
1338
|
rootDir: e.rootDir,
|
|
1348
1339
|
targetPath: n,
|
|
1349
1340
|
expectedStat: r
|
|
1350
1341
|
});
|
|
1351
1342
|
} catch (e) {
|
|
1352
|
-
throw new I("write-failed",
|
|
1343
|
+
throw e instanceof I ? e : new I("write-failed", "atomic write verification failed", { cause: e });
|
|
1353
1344
|
}
|
|
1354
1345
|
return {
|
|
1355
1346
|
realPath: n,
|
|
@@ -1365,30 +1356,30 @@ async function Tt(e) {
|
|
|
1365
1356
|
function V(e) {
|
|
1366
1357
|
return e?.trim() || void 0;
|
|
1367
1358
|
}
|
|
1368
|
-
function
|
|
1369
|
-
let t =
|
|
1370
|
-
for (; t !==
|
|
1371
|
-
if (
|
|
1372
|
-
t =
|
|
1359
|
+
function wt(e = import.meta.url) {
|
|
1360
|
+
let t = r.dirname(f(e));
|
|
1361
|
+
for (; t !== r.dirname(t);) {
|
|
1362
|
+
if (n(r.join(t, "package.json"))) return t;
|
|
1363
|
+
t = r.dirname(t);
|
|
1373
1364
|
}
|
|
1374
1365
|
return t;
|
|
1375
1366
|
}
|
|
1376
|
-
function
|
|
1377
|
-
let n =
|
|
1378
|
-
return n ?
|
|
1367
|
+
function H(e = E(), t = y.homedir) {
|
|
1368
|
+
let n = Tt(e, t);
|
|
1369
|
+
return n ? r.resolve(n) : void 0;
|
|
1379
1370
|
}
|
|
1380
|
-
function
|
|
1371
|
+
function Tt(e, t) {
|
|
1381
1372
|
let n = V(e.OPENCLAW_HOME);
|
|
1382
1373
|
if (n) {
|
|
1383
1374
|
if (n === "~" || n.startsWith("~/") || n.startsWith("~\\")) {
|
|
1384
|
-
let r = V(e.HOME) ?? V(e.USERPROFILE) ??
|
|
1375
|
+
let r = V(e.HOME) ?? V(e.USERPROFILE) ?? Et(t);
|
|
1385
1376
|
return r ? n.replace(/^~(?=$|[\\/])/, r) : void 0;
|
|
1386
1377
|
}
|
|
1387
1378
|
return n;
|
|
1388
1379
|
}
|
|
1389
|
-
return V(e.HOME) || V(e.USERPROFILE) ||
|
|
1380
|
+
return V(e.HOME) || V(e.USERPROFILE) || Et(t);
|
|
1390
1381
|
}
|
|
1391
|
-
function
|
|
1382
|
+
function Et(e) {
|
|
1392
1383
|
try {
|
|
1393
1384
|
return V(e());
|
|
1394
1385
|
} catch {
|
|
@@ -1397,76 +1388,91 @@ function kt(e) {
|
|
|
1397
1388
|
}
|
|
1398
1389
|
//#endregion
|
|
1399
1390
|
//#region src/modules/configs/identity-persist.ts
|
|
1400
|
-
var
|
|
1391
|
+
var Dt = /* @__PURE__ */ function(e) {
|
|
1401
1392
|
return e[e.LEGACY = 1] = "LEGACY", e[e.NEW = 2] = "NEW", e;
|
|
1402
|
-
}({}),
|
|
1403
|
-
function
|
|
1404
|
-
return
|
|
1393
|
+
}({}), Ot = ".openclaw", kt = "yoyo", At = "identity.json";
|
|
1394
|
+
function jt() {
|
|
1395
|
+
return r.join(Ot, kt, At);
|
|
1405
1396
|
}
|
|
1406
|
-
async function
|
|
1407
|
-
let t =
|
|
1397
|
+
async function Mt(e) {
|
|
1398
|
+
let t = jt();
|
|
1408
1399
|
try {
|
|
1409
|
-
let n = (await
|
|
1400
|
+
let n = (await vt({
|
|
1410
1401
|
rootDir: e,
|
|
1411
1402
|
relativePath: t,
|
|
1412
1403
|
maxBytes: 10 * 1024
|
|
1413
1404
|
})).buffer.toString("utf8"), r = JSON.parse(n);
|
|
1414
|
-
return typeof r != "object" || !r ?
|
|
1415
|
-
...
|
|
1405
|
+
return typeof r != "object" || !r ? Ft() : {
|
|
1406
|
+
...Ft(),
|
|
1416
1407
|
...r
|
|
1417
1408
|
};
|
|
1418
1409
|
} catch (e) {
|
|
1419
|
-
return
|
|
1410
|
+
return k().warn(`[yoyo-identity] failed to read identity: ${e.message}`), null;
|
|
1420
1411
|
}
|
|
1421
1412
|
}
|
|
1422
|
-
async function
|
|
1423
|
-
let e =
|
|
1424
|
-
return e ? await
|
|
1413
|
+
async function Nt() {
|
|
1414
|
+
let e = H();
|
|
1415
|
+
return e ? await Mt(e) || null : (k().warn("[yoyo-identity] failed to find home dir"), null);
|
|
1425
1416
|
}
|
|
1426
|
-
async function
|
|
1427
|
-
let t =
|
|
1428
|
-
if (!t) return
|
|
1429
|
-
let n = await
|
|
1417
|
+
async function Pt(e) {
|
|
1418
|
+
let t = H();
|
|
1419
|
+
if (!t) return k().warn("[yoyo-identity] failed to find home dir"), null;
|
|
1420
|
+
let n = await Mt(t), r = {
|
|
1430
1421
|
...n,
|
|
1431
|
-
version: n?.version ||
|
|
1422
|
+
version: n?.version || Dt.NEW
|
|
1432
1423
|
};
|
|
1433
|
-
return e.legacyDeviceId && (r.legacyDeviceId = e.legacyDeviceId), e.deviceId && (r.deviceId = e.deviceId, r.publicKeyPem = e.publicKeyPem, r.privateKeyPem = e.privateKeyPem, r.createdAtMs = e.createdAtMs), e.version && (r.version = e.version), await B({
|
|
1424
|
+
return e.legacyDeviceId && (r.legacyDeviceId = e.legacyDeviceId), e.deviceId && (r.deviceId = e.deviceId, r.publicKeyPem = e.publicKeyPem, r.privateKeyPem = e.privateKeyPem, r.createdAtMs = e.createdAtMs), e.version && (r.version = e.version), "gatewayAuthMd5" in e && (r.gatewayAuthMd5 = e.gatewayAuthMd5), await B({
|
|
1434
1425
|
rootDir: t,
|
|
1435
|
-
relativePath:
|
|
1426
|
+
relativePath: jt(),
|
|
1436
1427
|
data: JSON.stringify(r, null, 2),
|
|
1437
1428
|
encoding: "utf8",
|
|
1438
1429
|
mkdir: !0
|
|
1439
1430
|
}), r;
|
|
1440
1431
|
}
|
|
1441
|
-
function
|
|
1442
|
-
return { version:
|
|
1432
|
+
function Ft() {
|
|
1433
|
+
return { version: Dt.NEW };
|
|
1443
1434
|
}
|
|
1444
1435
|
//#endregion
|
|
1445
|
-
//#region src/
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1436
|
+
//#region src/utils/hash.ts
|
|
1437
|
+
function It(e) {
|
|
1438
|
+
return h.createHash("md5").update(e).digest("hex");
|
|
1439
|
+
}
|
|
1440
|
+
function Lt(e) {
|
|
1441
|
+
return e ? `${e.slice(0, 8)}...` : "none";
|
|
1442
|
+
}
|
|
1443
|
+
//#endregion
|
|
1444
|
+
//#region src/modules/device/gateway-auth.ts
|
|
1445
|
+
function Rt(e) {
|
|
1446
|
+
return typeof e == "string" ? e : e == null ? "" : JSON.stringify(e);
|
|
1447
|
+
}
|
|
1448
|
+
function zt(e) {
|
|
1449
|
+
return It(JSON.stringify({
|
|
1450
|
+
token: Rt(e?.token),
|
|
1451
|
+
password: Rt(e?.password)
|
|
1452
|
+
}));
|
|
1453
|
+
}
|
|
1454
|
+
function Bt(e, t) {
|
|
1455
|
+
return (e ?? "") === t;
|
|
1450
1456
|
}
|
|
1451
1457
|
//#endregion
|
|
1452
1458
|
//#region src/modules/device/identity.ts
|
|
1453
|
-
var
|
|
1454
|
-
function
|
|
1459
|
+
var U = Buffer.from("302a300506032b6570032100", "hex");
|
|
1460
|
+
function Vt(e) {
|
|
1455
1461
|
return e.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
|
|
1456
1462
|
}
|
|
1457
|
-
function
|
|
1458
|
-
let t =
|
|
1463
|
+
function Ht(e) {
|
|
1464
|
+
let t = h.createPublicKey(e).export({
|
|
1459
1465
|
type: "spki",
|
|
1460
1466
|
format: "der"
|
|
1461
1467
|
});
|
|
1462
|
-
return t.length ===
|
|
1468
|
+
return t.length === U.length + 32 && t.subarray(0, U.length).equals(U) ? t.subarray(U.length) : t;
|
|
1463
1469
|
}
|
|
1464
|
-
function
|
|
1465
|
-
let t =
|
|
1466
|
-
return
|
|
1470
|
+
function Ut(e) {
|
|
1471
|
+
let t = Ht(e);
|
|
1472
|
+
return h.createHash("sha256").update(t).digest("hex");
|
|
1467
1473
|
}
|
|
1468
|
-
async function
|
|
1469
|
-
let { publicKey: e, privateKey: t } =
|
|
1474
|
+
async function Wt() {
|
|
1475
|
+
let { publicKey: e, privateKey: t } = h.generateKeyPairSync("ed25519"), n = e.export({
|
|
1470
1476
|
type: "spki",
|
|
1471
1477
|
format: "pem"
|
|
1472
1478
|
}).toString(), r = t.export({
|
|
@@ -1474,17 +1480,17 @@ async function Ut() {
|
|
|
1474
1480
|
format: "pem"
|
|
1475
1481
|
}).toString();
|
|
1476
1482
|
return {
|
|
1477
|
-
deviceId:
|
|
1483
|
+
deviceId: Ut(n),
|
|
1478
1484
|
publicKeyPem: n,
|
|
1479
1485
|
privateKeyPem: r,
|
|
1480
1486
|
createdAtMs: Date.now()
|
|
1481
1487
|
};
|
|
1482
1488
|
}
|
|
1483
|
-
async function
|
|
1484
|
-
let e = await
|
|
1489
|
+
async function Gt() {
|
|
1490
|
+
let e = await Nt();
|
|
1485
1491
|
if (e && e.deviceId && e.publicKeyPem && e.privateKeyPem && e.createdAtMs) {
|
|
1486
|
-
let t = e.deviceId, n =
|
|
1487
|
-
return n && n !== e.deviceId && (await
|
|
1492
|
+
let t = e.deviceId, n = Ut(e.publicKeyPem);
|
|
1493
|
+
return n && n !== e.deviceId && (await Pt({
|
|
1488
1494
|
...e,
|
|
1489
1495
|
deviceId: n
|
|
1490
1496
|
}), t = n), {
|
|
@@ -1495,32 +1501,50 @@ async function Wt() {
|
|
|
1495
1501
|
createdAtMs: e.createdAtMs
|
|
1496
1502
|
};
|
|
1497
1503
|
}
|
|
1498
|
-
let t = await
|
|
1499
|
-
return await
|
|
1504
|
+
let t = await Wt();
|
|
1505
|
+
return await Pt(t), t;
|
|
1500
1506
|
}
|
|
1501
|
-
function
|
|
1502
|
-
|
|
1503
|
-
return Bt(_.sign(null, Buffer.from(t, "utf8"), n));
|
|
1507
|
+
async function Kt() {
|
|
1508
|
+
return (await Nt())?.gatewayAuthMd5;
|
|
1504
1509
|
}
|
|
1505
|
-
function
|
|
1506
|
-
|
|
1510
|
+
function qt(e, t) {
|
|
1511
|
+
let n = h.createPrivateKey(e);
|
|
1512
|
+
return Vt(h.sign(null, Buffer.from(t, "utf8"), n));
|
|
1513
|
+
}
|
|
1514
|
+
function Jt(e) {
|
|
1515
|
+
return Vt(Ht(e));
|
|
1516
|
+
}
|
|
1517
|
+
//#endregion
|
|
1518
|
+
//#region src/modules/device/registry.ts
|
|
1519
|
+
async function Yt(e, t) {
|
|
1520
|
+
if (!e || !t) throw Error("设备信息或用户信息缺失");
|
|
1521
|
+
let n = M().getGatewayAuthConfig(), r = await N().registerDevice(e, t, n);
|
|
1522
|
+
if (!Le(r)) throw Error(`注册失败:${r.data?.cnMessage}`);
|
|
1523
|
+
}
|
|
1524
|
+
async function Xt(e, t) {
|
|
1525
|
+
let n = zt(M().getGatewayAuthConfig()), r = await Kt(), i = k();
|
|
1526
|
+
if (i.info(`[yoyoclaw-registry] checking gateway auth md5: current=${Lt(n)}, persisted=${Lt(r)}`), Bt(r, n)) {
|
|
1527
|
+
i.info("[yoyoclaw-registry] gateway auth unchanged, skipping device registration");
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
i.info("[yoyoclaw-registry] gateway auth changed, registering device"), await Yt(e, t), await Pt({ gatewayAuthMd5: n }), i.info("[yoyoclaw-registry] gateway auth md5 persisted after device registration");
|
|
1507
1531
|
}
|
|
1508
1532
|
//#endregion
|
|
1509
1533
|
//#region src/modules/device/providers/linux.ts
|
|
1510
|
-
function
|
|
1534
|
+
function Zt(e) {
|
|
1511
1535
|
try {
|
|
1512
|
-
return
|
|
1536
|
+
return b.existsSync(e) ? b.readFileSync(e, "utf-8").trim() : "";
|
|
1513
1537
|
} catch {
|
|
1514
1538
|
return "";
|
|
1515
1539
|
}
|
|
1516
1540
|
}
|
|
1517
|
-
var
|
|
1541
|
+
var Qt = class {
|
|
1518
1542
|
async ensureInitialized() {}
|
|
1519
1543
|
getLinuxDeviceModel() {
|
|
1520
|
-
return
|
|
1544
|
+
return Zt("/sys/class/dmi/id/product_name") || Zt("/sys/class/dmi/id/board_name") || `${S.cpus()[0]?.model || "Linux PC"} (${S.arch()})`;
|
|
1521
1545
|
}
|
|
1522
1546
|
getLinuxDeviceName() {
|
|
1523
|
-
return `${
|
|
1547
|
+
return `${S.hostname()} (${this.getLinuxDeviceModel()})`;
|
|
1524
1548
|
}
|
|
1525
1549
|
getDeviceName() {
|
|
1526
1550
|
return this.getLinuxDeviceName();
|
|
@@ -1534,13 +1558,13 @@ var Jt = class {
|
|
|
1534
1558
|
getDeviceType() {
|
|
1535
1559
|
return "pc";
|
|
1536
1560
|
}
|
|
1537
|
-
},
|
|
1561
|
+
}, $t = class {
|
|
1538
1562
|
async ensureInitialized() {}
|
|
1539
1563
|
getMacOSDeviceModel() {
|
|
1540
|
-
return `${
|
|
1564
|
+
return `${S.cpus()[0]?.model || "Mac"} (${S.machine?.() || S.arch()})`;
|
|
1541
1565
|
}
|
|
1542
1566
|
getMacOSDeviceName() {
|
|
1543
|
-
return `${
|
|
1567
|
+
return `${S.hostname()} (${this.getMacOSDeviceModel()})`;
|
|
1544
1568
|
}
|
|
1545
1569
|
getDeviceName() {
|
|
1546
1570
|
return this.getMacOSDeviceName();
|
|
@@ -1554,7 +1578,7 @@ var Jt = class {
|
|
|
1554
1578
|
getDeviceType() {
|
|
1555
1579
|
return "pc";
|
|
1556
1580
|
}
|
|
1557
|
-
},
|
|
1581
|
+
}, en = te(ee), tn = class {
|
|
1558
1582
|
cache = {
|
|
1559
1583
|
brand: "",
|
|
1560
1584
|
model: "",
|
|
@@ -1569,7 +1593,7 @@ var Jt = class {
|
|
|
1569
1593
|
}
|
|
1570
1594
|
async execAndroidCmd(e, t = 5e3) {
|
|
1571
1595
|
try {
|
|
1572
|
-
let { stdout: n } = await
|
|
1596
|
+
let { stdout: n } = await en("/system/bin/sh", ["-c", e], {
|
|
1573
1597
|
timeout: t,
|
|
1574
1598
|
encoding: "utf-8"
|
|
1575
1599
|
});
|
|
@@ -1591,13 +1615,13 @@ var Jt = class {
|
|
|
1591
1615
|
getAndroidDeviceModel() {
|
|
1592
1616
|
if (this.cache.model) return this.cache.model;
|
|
1593
1617
|
try {
|
|
1594
|
-
let
|
|
1595
|
-
if (
|
|
1596
|
-
let
|
|
1597
|
-
if (
|
|
1618
|
+
let e = "/system/build.prop";
|
|
1619
|
+
if (b.existsSync(e)) {
|
|
1620
|
+
let t = b.readFileSync(e, "utf8").match(/ro\.product\.model=(.*)/);
|
|
1621
|
+
if (t && t[1]) return t[1].trim();
|
|
1598
1622
|
}
|
|
1599
1623
|
} catch {}
|
|
1600
|
-
return `Android(${
|
|
1624
|
+
return `Android(${S.arch()})`;
|
|
1601
1625
|
}
|
|
1602
1626
|
getAndroidDeviceName() {
|
|
1603
1627
|
return this.getAndroidDeviceModel();
|
|
@@ -1617,10 +1641,10 @@ var Jt = class {
|
|
|
1617
1641
|
};
|
|
1618
1642
|
//#endregion
|
|
1619
1643
|
//#region src/modules/device/providers/windows.ts
|
|
1620
|
-
function
|
|
1644
|
+
function W(e, t, n) {
|
|
1621
1645
|
return new Promise((r) => {
|
|
1622
1646
|
try {
|
|
1623
|
-
new
|
|
1647
|
+
new C({
|
|
1624
1648
|
hive: e,
|
|
1625
1649
|
key: t
|
|
1626
1650
|
}).get(n, (e, t) => {
|
|
@@ -1631,10 +1655,10 @@ function U(e, t, n) {
|
|
|
1631
1655
|
}
|
|
1632
1656
|
});
|
|
1633
1657
|
}
|
|
1634
|
-
function
|
|
1658
|
+
function nn(e, t) {
|
|
1635
1659
|
return new Promise((n) => {
|
|
1636
1660
|
try {
|
|
1637
|
-
new
|
|
1661
|
+
new C({
|
|
1638
1662
|
hive: e,
|
|
1639
1663
|
key: t
|
|
1640
1664
|
}).values((e) => {
|
|
@@ -1645,7 +1669,7 @@ function Qt(e, t) {
|
|
|
1645
1669
|
}
|
|
1646
1670
|
});
|
|
1647
1671
|
}
|
|
1648
|
-
var
|
|
1672
|
+
var rn = class {
|
|
1649
1673
|
cache = { deviceBrand: "" };
|
|
1650
1674
|
initPromise;
|
|
1651
1675
|
constructor() {
|
|
@@ -1657,26 +1681,26 @@ var $t = class {
|
|
|
1657
1681
|
async _initializeCache() {
|
|
1658
1682
|
try {
|
|
1659
1683
|
let [e, t, n, r] = await Promise.all([
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1684
|
+
W(C.HKLM, "\\HARDWARE\\DESCRIPTION\\System", "SystemManufacturer"),
|
|
1685
|
+
W(C.HKLM, "\\HARDWARE\\DESCRIPTION\\System", "SystemBiosVendor"),
|
|
1686
|
+
W(C.HKLM, "\\HARDWARE\\DESCRIPTION\\System\\BIOS", "Vendor"),
|
|
1687
|
+
W(C.HKLM, "\\HARDWARE\\DESCRIPTION\\System\\BIOS", "SystemManufacturer")
|
|
1664
1688
|
]);
|
|
1665
1689
|
[
|
|
1666
1690
|
e,
|
|
1667
1691
|
t,
|
|
1668
1692
|
n,
|
|
1669
1693
|
r
|
|
1670
|
-
].find((e) => e && e.toLowerCase().includes("honor")) || await
|
|
1694
|
+
].find((e) => e && e.toLowerCase().includes("honor")) || await nn(C.HKLM, "\\SOFTWARE\\HONOR\\PCManager") ? this.cache.deviceBrand = "HONOR" : this.cache.deviceBrand = "";
|
|
1671
1695
|
} catch {
|
|
1672
1696
|
this.cache.deviceBrand = "";
|
|
1673
1697
|
}
|
|
1674
1698
|
}
|
|
1675
1699
|
getWindowsDeviceModel() {
|
|
1676
|
-
return `Windows ${
|
|
1700
|
+
return `Windows ${S.release()}`;
|
|
1677
1701
|
}
|
|
1678
1702
|
getWindowsDeviceName() {
|
|
1679
|
-
return `${
|
|
1703
|
+
return `${S.hostname()} (${this.getWindowsDeviceModel()})`;
|
|
1680
1704
|
}
|
|
1681
1705
|
getDeviceName() {
|
|
1682
1706
|
return this.getWindowsDeviceName();
|
|
@@ -1693,33 +1717,33 @@ var $t = class {
|
|
|
1693
1717
|
};
|
|
1694
1718
|
//#endregion
|
|
1695
1719
|
//#region src/modules/device/providers/index.ts
|
|
1696
|
-
function
|
|
1697
|
-
let
|
|
1698
|
-
if (
|
|
1699
|
-
if (
|
|
1720
|
+
function an() {
|
|
1721
|
+
let t = process.platform;
|
|
1722
|
+
if (t === "win32") return "windows";
|
|
1723
|
+
if (t === "linux") {
|
|
1700
1724
|
try {
|
|
1701
|
-
if (
|
|
1725
|
+
if (e.existsSync("/system/bin/getprop")) return "pad";
|
|
1702
1726
|
} catch {}
|
|
1703
1727
|
return "linux";
|
|
1704
1728
|
}
|
|
1705
|
-
return
|
|
1729
|
+
return t === "darwin" ? "macos" : "linux";
|
|
1706
1730
|
}
|
|
1707
|
-
function
|
|
1708
|
-
switch (
|
|
1709
|
-
case "pad": return new
|
|
1710
|
-
case "windows": return new
|
|
1711
|
-
case "linux": return new
|
|
1712
|
-
case "macos": return new
|
|
1713
|
-
default: return new
|
|
1731
|
+
function on() {
|
|
1732
|
+
switch (an()) {
|
|
1733
|
+
case "pad": return new tn();
|
|
1734
|
+
case "windows": return new rn();
|
|
1735
|
+
case "linux": return new Qt();
|
|
1736
|
+
case "macos": return new $t();
|
|
1737
|
+
default: return new Qt();
|
|
1714
1738
|
}
|
|
1715
1739
|
}
|
|
1716
1740
|
//#endregion
|
|
1717
1741
|
//#region src/modules/device/device-info.ts
|
|
1718
|
-
async function
|
|
1719
|
-
let e =
|
|
1742
|
+
async function G() {
|
|
1743
|
+
let e = on(), t = M();
|
|
1720
1744
|
await e.ensureInitialized();
|
|
1721
|
-
let n = await
|
|
1722
|
-
|
|
1745
|
+
let n = await Gt(), r = n.legacyDeviceId ?? n.deviceId, i = pe(), a = t.getDeviceConfig();
|
|
1746
|
+
k().debug?.(`[yoyoclaw-device] env: ${JSON.stringify(i)}, config: ${JSON.stringify(a)}`);
|
|
1723
1747
|
let o = i.brand || a?.brand || e.getDeviceBrand() || "unknown", s = i.deviceType || a?.type || e.getDeviceType(), c = (i.manufacture || a?.manufacture || o).slice(0, 128), l = (a?.name || e.getDeviceName()).slice(0, 128), u = (a?.model || e.getDeviceModel()).slice(0, 128), d = {
|
|
1724
1748
|
deviceId: r,
|
|
1725
1749
|
deviceName: l,
|
|
@@ -1729,7 +1753,7 @@ async function W() {
|
|
|
1729
1753
|
manufacture: c,
|
|
1730
1754
|
port: t.getGatewayPort()
|
|
1731
1755
|
}, f = i.brand || i.deviceType || i.manufacture ? "env" : "config";
|
|
1732
|
-
|
|
1756
|
+
k().info(`[yoyoclaw-device] device info: ${JSON.stringify(d)} (source: ${f})`);
|
|
1733
1757
|
let p = !!(i.brand && i.brand !== a?.brand || i.manufacture && i.manufacture !== a?.manufacture || i.deviceType && i.deviceType !== a?.type);
|
|
1734
1758
|
if (!a || p) {
|
|
1735
1759
|
let e = {
|
|
@@ -1740,27 +1764,27 @@ async function W() {
|
|
|
1740
1764
|
model: u
|
|
1741
1765
|
};
|
|
1742
1766
|
t.updateDeviceConfig(e).catch((e) => {
|
|
1743
|
-
|
|
1767
|
+
k().warn(`[yoyoclaw-device] failed to persist device config: ${String(e)}`);
|
|
1744
1768
|
});
|
|
1745
1769
|
}
|
|
1746
1770
|
return d;
|
|
1747
1771
|
}
|
|
1748
1772
|
//#endregion
|
|
1749
1773
|
//#region src/modules/device/helpers.ts
|
|
1750
|
-
function
|
|
1774
|
+
function sn(e) {
|
|
1751
1775
|
return typeof e == "string" && e.trim() || "";
|
|
1752
1776
|
}
|
|
1753
|
-
function
|
|
1777
|
+
function cn(e) {
|
|
1754
1778
|
return e.replace(/[A-Z]/g, (e) => String.fromCharCode(e.charCodeAt(0) + 32));
|
|
1755
1779
|
}
|
|
1756
|
-
function
|
|
1757
|
-
let t =
|
|
1758
|
-
return t ?
|
|
1780
|
+
function ln(e) {
|
|
1781
|
+
let t = sn(e);
|
|
1782
|
+
return t ? cn(t) : "";
|
|
1759
1783
|
}
|
|
1760
1784
|
//#endregion
|
|
1761
1785
|
//#region src/modules/device/auth.ts
|
|
1762
|
-
function
|
|
1763
|
-
let t = e.scopes.join(","), n = e.token ?? "", r =
|
|
1786
|
+
function un(e) {
|
|
1787
|
+
let t = e.scopes.join(","), n = e.token ?? "", r = ln(e.platform), i = ln(e.deviceFamily);
|
|
1764
1788
|
return [
|
|
1765
1789
|
"v3",
|
|
1766
1790
|
e.deviceId,
|
|
@@ -1777,10 +1801,10 @@ function on(e) {
|
|
|
1777
1801
|
}
|
|
1778
1802
|
//#endregion
|
|
1779
1803
|
//#region src/modules/device/credential-builder.ts
|
|
1780
|
-
function
|
|
1804
|
+
function dn(e) {
|
|
1781
1805
|
let { deviceIdentity: t, clientName: n = "", clientMode: r = "cli", role: i = "operator", scopes: a = ["operator.admin"], platform: o = process.platform, deviceFamily: s, authToken: c = null, nonce: l, signedAtMs: u = Date.now() } = e;
|
|
1782
1806
|
if (!t) return;
|
|
1783
|
-
let d =
|
|
1807
|
+
let d = un({
|
|
1784
1808
|
deviceId: t.deviceId,
|
|
1785
1809
|
clientId: n,
|
|
1786
1810
|
clientMode: r,
|
|
@@ -1791,10 +1815,10 @@ function sn(e) {
|
|
|
1791
1815
|
nonce: l,
|
|
1792
1816
|
platform: o,
|
|
1793
1817
|
deviceFamily: s
|
|
1794
|
-
}), f =
|
|
1818
|
+
}), f = qt(t.privateKeyPem, d);
|
|
1795
1819
|
return {
|
|
1796
1820
|
id: t.deviceId,
|
|
1797
|
-
publicKey:
|
|
1821
|
+
publicKey: Jt(t.publicKeyPem),
|
|
1798
1822
|
signature: f,
|
|
1799
1823
|
signedAt: u,
|
|
1800
1824
|
nonce: l
|
|
@@ -1802,15 +1826,15 @@ function sn(e) {
|
|
|
1802
1826
|
}
|
|
1803
1827
|
//#endregion
|
|
1804
1828
|
//#region src/honor-auth/token-manager.ts
|
|
1805
|
-
async function
|
|
1829
|
+
async function fn(e, t = !0) {
|
|
1806
1830
|
try {
|
|
1807
|
-
let n =
|
|
1831
|
+
let n = M(), r = e.jwtToken;
|
|
1808
1832
|
if (!r && e.userId) {
|
|
1809
|
-
let t = e.deviceInfo || await
|
|
1833
|
+
let t = e.deviceInfo || await G();
|
|
1810
1834
|
r = (await N().exchangeToken(t, { userId: e.userId })).jwtToken;
|
|
1811
1835
|
}
|
|
1812
1836
|
if (!r) throw Error("no token available");
|
|
1813
|
-
if (!t) return
|
|
1837
|
+
if (!t) return k().info("💾 token got, but not to save"), { token: r };
|
|
1814
1838
|
let i = Math.floor(Date.now() / 1e3) + 720 * 60 * 60;
|
|
1815
1839
|
return await n.updateUserConfig({
|
|
1816
1840
|
token: r,
|
|
@@ -1818,53 +1842,53 @@ async function cn(e, t = !0) {
|
|
|
1818
1842
|
expired: i
|
|
1819
1843
|
}), { token: r };
|
|
1820
1844
|
} catch (e) {
|
|
1821
|
-
throw
|
|
1845
|
+
throw O(e, "保存Token失败");
|
|
1822
1846
|
}
|
|
1823
1847
|
}
|
|
1824
|
-
async function
|
|
1825
|
-
let t = await
|
|
1848
|
+
async function pn(e) {
|
|
1849
|
+
let t = await G(), n = await N().exchangeToken(t, { userId: e });
|
|
1826
1850
|
if (n.jwtToken) {
|
|
1827
1851
|
let e = Math.floor(Date.now() / 1e3) + 720 * 60 * 60;
|
|
1828
|
-
return await
|
|
1852
|
+
return await M().updateUserConfig({
|
|
1829
1853
|
token: n.jwtToken,
|
|
1830
1854
|
userId: void 0,
|
|
1831
1855
|
userName: void 0,
|
|
1832
1856
|
expired: e
|
|
1833
1857
|
}), { token: n.jwtToken };
|
|
1834
1858
|
}
|
|
1835
|
-
return await
|
|
1859
|
+
return await M().clearUserConfig(), null;
|
|
1836
1860
|
}
|
|
1837
|
-
async function
|
|
1838
|
-
let e =
|
|
1861
|
+
async function mn() {
|
|
1862
|
+
let e = k();
|
|
1839
1863
|
try {
|
|
1840
|
-
let t =
|
|
1841
|
-
if (e.debug?.(`[yoyoclaw-auth] env userId: ${r ? "present" : "absent"}, config userId: ${n?.userId ? "present" : "absent"}, config token: ${n?.token ? "present" : "absent"}`), n?.userId) return await
|
|
1864
|
+
let t = M(), n = t.getUserConfig(), r = me();
|
|
1865
|
+
if (e.debug?.(`[yoyoclaw-auth] env userId: ${r ? "present" : "absent"}, config userId: ${n?.userId ? "present" : "absent"}, config token: ${n?.token ? "present" : "absent"}`), n?.userId) return await pn(r || n.userId);
|
|
1842
1866
|
if (n?.token) {
|
|
1843
1867
|
if (!n.expired || n.expired >= Math.floor(Date.now() / 1e3)) return { token: n.token };
|
|
1844
1868
|
e.debug?.("[yoyoclaw-auth] cached token expired");
|
|
1845
1869
|
}
|
|
1846
|
-
return r ? (e.debug?.("[yoyoclaw-auth] token expired, using env userId to exchange token"), await
|
|
1870
|
+
return r ? (e.debug?.("[yoyoclaw-auth] token expired, using env userId to exchange token"), await pn(r)) : (n?.token && (e.debug?.("[yoyoclaw-auth] clearing expired token"), await t.clearUserConfig()), null);
|
|
1847
1871
|
} catch (e) {
|
|
1848
|
-
throw
|
|
1872
|
+
throw O(e, "加载Token失败");
|
|
1849
1873
|
}
|
|
1850
1874
|
}
|
|
1851
|
-
async function
|
|
1875
|
+
async function hn() {
|
|
1852
1876
|
try {
|
|
1853
|
-
await
|
|
1877
|
+
await M().clearUserConfig(), k().info("[yoyoclaw-auth] token cleared");
|
|
1854
1878
|
} catch (e) {
|
|
1855
|
-
throw
|
|
1879
|
+
throw O(e, "清除Token失败");
|
|
1856
1880
|
}
|
|
1857
1881
|
}
|
|
1858
1882
|
//#endregion
|
|
1859
1883
|
//#region src/honor-auth/browser.ts
|
|
1860
|
-
async function
|
|
1861
|
-
let n =
|
|
1862
|
-
|
|
1863
|
-
let r =
|
|
1884
|
+
async function gn(e, t) {
|
|
1885
|
+
let n = tt(t);
|
|
1886
|
+
k().debug?.("Starting Honor login flow...");
|
|
1887
|
+
let r = rt(n), a = r.generatePKCEParams(), o = r.buildAuthUrl(a), s = null, c = Qe({
|
|
1864
1888
|
port: n.localPort,
|
|
1865
1889
|
timeout: 6e5,
|
|
1866
1890
|
onCodeReceived: (e) => {
|
|
1867
|
-
|
|
1891
|
+
s = e;
|
|
1868
1892
|
},
|
|
1869
1893
|
onError: (e) => {
|
|
1870
1894
|
console.error("callback server error:", e);
|
|
@@ -1872,47 +1896,47 @@ async function fn(e, t) {
|
|
|
1872
1896
|
});
|
|
1873
1897
|
console.log("🌐 open browser...");
|
|
1874
1898
|
try {
|
|
1875
|
-
await
|
|
1899
|
+
await i(o);
|
|
1876
1900
|
} catch (e) {
|
|
1877
|
-
throw
|
|
1901
|
+
throw O(e, "failed to open browser, check your permissions");
|
|
1878
1902
|
}
|
|
1879
1903
|
try {
|
|
1880
|
-
await
|
|
1904
|
+
await c;
|
|
1881
1905
|
} catch (e) {
|
|
1882
|
-
throw
|
|
1906
|
+
throw O(e, "authorization timeout");
|
|
1883
1907
|
}
|
|
1884
|
-
if (!
|
|
1908
|
+
if (!s) throw Error("no auth code");
|
|
1885
1909
|
try {
|
|
1886
1910
|
let t = await N().exchangeToken(e, {
|
|
1887
|
-
code:
|
|
1911
|
+
code: s,
|
|
1888
1912
|
authConfig: n
|
|
1889
1913
|
});
|
|
1890
1914
|
if (!t?.jwtToken) throw Error("failed to get jwt token");
|
|
1891
|
-
return await
|
|
1915
|
+
return await fn({ jwtToken: t.jwtToken }, n.saveToFile !== !1), { token: t.jwtToken };
|
|
1892
1916
|
} catch (e) {
|
|
1893
|
-
throw
|
|
1917
|
+
throw O(e, "get token failed");
|
|
1894
1918
|
}
|
|
1895
1919
|
}
|
|
1896
1920
|
//#endregion
|
|
1897
1921
|
//#region src/honor-auth/cloud.ts
|
|
1898
|
-
async function
|
|
1899
|
-
let e =
|
|
1922
|
+
async function _n() {
|
|
1923
|
+
let e = M().getUserConfig();
|
|
1900
1924
|
if (!e?.token) throw Error("⚠️ Not logged in");
|
|
1901
|
-
let t = await
|
|
1902
|
-
if (!
|
|
1903
|
-
await
|
|
1925
|
+
let t = await G(), n = N(), r = { token: e.token }, i = await n.logoutDevice(t, r);
|
|
1926
|
+
if (!Le(i)) throw Error(i.data?.cnMessage || "Unknown error");
|
|
1927
|
+
await hn();
|
|
1904
1928
|
}
|
|
1905
1929
|
//#endregion
|
|
1906
1930
|
//#region src/modules/login/impl.ts
|
|
1907
|
-
async function
|
|
1908
|
-
let { userId: t } = e, n =
|
|
1931
|
+
async function vn(e = {}) {
|
|
1932
|
+
let { userId: t } = e, n = k();
|
|
1909
1933
|
try {
|
|
1910
1934
|
n.debug?.("Starting login process...");
|
|
1911
|
-
let e = await
|
|
1912
|
-
t ? (r = await
|
|
1935
|
+
let e = await G(), r;
|
|
1936
|
+
t ? (r = await fn({
|
|
1913
1937
|
userId: t,
|
|
1914
1938
|
deviceInfo: e
|
|
1915
|
-
}), n.debug?.("Using provided user info"), n.debug?.(`User: ${t}`), n.debug?.(`Device ID: ${e?.deviceId}`)) : (n.debug?.("Starting OAuth2 authentication..."), r = await
|
|
1939
|
+
}), n.debug?.("Using provided user info"), n.debug?.(`User: ${t}`), n.debug?.(`Device ID: ${e?.deviceId}`)) : (n.debug?.("Starting OAuth2 authentication..."), r = await gn(e), n.debug?.("OAuth2 authentication successful"), n.debug?.(`Device ID: ${e?.deviceId}`)), console.log("📡 Registering device to Claw Cloud..."), await Yt(e, r), console.log("✅ Device registered successfully"), console.log("🔗 Channel connection in progress, use 'openclaw honor status' to check device status");
|
|
1916
1940
|
} catch (e) {
|
|
1917
1941
|
let t = e instanceof Error ? e.message : String(e);
|
|
1918
1942
|
console.error("❌ Login process failed:", t);
|
|
@@ -1920,11 +1944,11 @@ async function mn(e = {}) {
|
|
|
1920
1944
|
}
|
|
1921
1945
|
//#endregion
|
|
1922
1946
|
//#region src/commands/login/impl.ts
|
|
1923
|
-
function
|
|
1947
|
+
function yn(e, t) {
|
|
1924
1948
|
let n = t.command("login").description("login to yoyoclaw and register devices");
|
|
1925
1949
|
return n = n.option("-u, --uid <userId>", "user ID for direct login").option("--token <token>", "token for direct login").action(async (t) => {
|
|
1926
1950
|
let { uid: n, token: r } = t;
|
|
1927
|
-
e.logger.debug?.("honor login CLI command called"), await
|
|
1951
|
+
e.logger.debug?.("honor login CLI command called"), await vn({
|
|
1928
1952
|
userId: n,
|
|
1929
1953
|
token: r
|
|
1930
1954
|
});
|
|
@@ -1932,11 +1956,11 @@ function hn(e, t) {
|
|
|
1932
1956
|
}
|
|
1933
1957
|
//#endregion
|
|
1934
1958
|
//#region src/commands/logout/impl.ts
|
|
1935
|
-
function
|
|
1959
|
+
function bn(e, t) {
|
|
1936
1960
|
return t.command("logout").description("Logout and clear user configuration").action(async () => {
|
|
1937
1961
|
e.logger.info("logout CLI command called");
|
|
1938
1962
|
try {
|
|
1939
|
-
await
|
|
1963
|
+
await _n(), console.log("✅ Logout successful, gateway will automatically restart to handle new configuration");
|
|
1940
1964
|
} catch (e) {
|
|
1941
1965
|
let t = e instanceof Error ? e.message : String(e);
|
|
1942
1966
|
console.error("❌ Logout failed:", t);
|
|
@@ -1945,28 +1969,28 @@ function gn(e, t) {
|
|
|
1945
1969
|
}
|
|
1946
1970
|
//#endregion
|
|
1947
1971
|
//#region src/services/connection/status-tracker/events.ts
|
|
1948
|
-
var
|
|
1972
|
+
var K = /* @__PURE__ */ function(e) {
|
|
1949
1973
|
return e.CLOUD_SOCKET_CONNECTING = "cloud_socket_connecting", e.CLOUD_SOCKET_CONNECTED = "cloud_socket_connected", e.CLOUD_SOCKET_DISCONNECTED = "cloud_socket_disconnected", e.CLOUD_SOCKET_ERROR = "cloud_socket_error", e.CLOUD_SOCKET_RETRY = "cloud_socket_retry", e.GATEWAY_CLIENT_CONNECTED = "gateway_client_connected", e.GATEWAY_CLIENT_DISCONNECTED = "gateway_client_disconnected", e.ADMIN_CLIENT_RECONNECT_FAILED = "admin_client_reconnect_failed", e.DEVICE_PAIRING = "device_pairing", e.DEVICE_UNPAIRING = "device_unpairing", e.CONNECTION_STATUS_CHANGED = "connection_status_changed", e;
|
|
1950
|
-
}({}),
|
|
1974
|
+
}({}), xn = class {
|
|
1951
1975
|
statusFilePath;
|
|
1952
1976
|
statusDir;
|
|
1953
1977
|
constructor() {
|
|
1954
|
-
let e =
|
|
1955
|
-
this.statusDir =
|
|
1978
|
+
let e = wt();
|
|
1979
|
+
this.statusDir = ne.join(e, ".yoyo-cache"), this.statusFilePath = ne.join(this.statusDir, "yoyo-status.json");
|
|
1956
1980
|
}
|
|
1957
1981
|
async save(e) {
|
|
1958
1982
|
try {
|
|
1959
|
-
await
|
|
1960
|
-
let
|
|
1961
|
-
await
|
|
1983
|
+
await x.mkdir(this.statusDir, { recursive: !0 });
|
|
1984
|
+
let t = JSON.stringify(e, null, 2);
|
|
1985
|
+
await x.writeFile(this.statusFilePath, t, "utf-8");
|
|
1962
1986
|
} catch (e) {
|
|
1963
1987
|
throw console.error(`[StatusStorage] Failed to save status: ${e instanceof Error ? e.message : String(e)}`), e;
|
|
1964
1988
|
}
|
|
1965
1989
|
}
|
|
1966
1990
|
async load() {
|
|
1967
1991
|
try {
|
|
1968
|
-
await
|
|
1969
|
-
let e = await
|
|
1992
|
+
await x.access(this.statusFilePath);
|
|
1993
|
+
let e = await x.readFile(this.statusFilePath, "utf-8");
|
|
1970
1994
|
return JSON.parse(e);
|
|
1971
1995
|
} catch (e) {
|
|
1972
1996
|
return e.code === "ENOENT" || console.error(`[StatusStorage] Failed to load status: ${e instanceof Error ? e.message : String(e)}`), null;
|
|
@@ -1974,7 +1998,7 @@ var G = /* @__PURE__ */ function(e) {
|
|
|
1974
1998
|
}
|
|
1975
1999
|
async clear() {
|
|
1976
2000
|
try {
|
|
1977
|
-
await
|
|
2001
|
+
await x.unlink(this.statusFilePath);
|
|
1978
2002
|
} catch (e) {
|
|
1979
2003
|
if (e.code !== "ENOENT") throw console.error(`[StatusStorage] Failed to clear status: ${e instanceof Error ? e.message : String(e)}`), e;
|
|
1980
2004
|
}
|
|
@@ -1984,7 +2008,7 @@ var G = /* @__PURE__ */ function(e) {
|
|
|
1984
2008
|
}
|
|
1985
2009
|
async exists() {
|
|
1986
2010
|
try {
|
|
1987
|
-
return await
|
|
2011
|
+
return await x.access(this.statusFilePath), !0;
|
|
1988
2012
|
} catch {
|
|
1989
2013
|
return !1;
|
|
1990
2014
|
}
|
|
@@ -1992,7 +2016,7 @@ var G = /* @__PURE__ */ function(e) {
|
|
|
1992
2016
|
};
|
|
1993
2017
|
//#endregion
|
|
1994
2018
|
//#region src/services/connection/status-tracker/types.ts
|
|
1995
|
-
function
|
|
2019
|
+
function Sn() {
|
|
1996
2020
|
return {
|
|
1997
2021
|
status: "idle",
|
|
1998
2022
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2027,48 +2051,48 @@ function vn() {
|
|
|
2027
2051
|
}
|
|
2028
2052
|
//#endregion
|
|
2029
2053
|
//#region src/services/connection/status-tracker/tracker.ts
|
|
2030
|
-
var
|
|
2054
|
+
var Cn = class {
|
|
2031
2055
|
currentStatus;
|
|
2032
2056
|
storage;
|
|
2033
2057
|
autoSave;
|
|
2034
2058
|
saveTimer;
|
|
2035
2059
|
constructor(e = !0) {
|
|
2036
|
-
this.currentStatus =
|
|
2060
|
+
this.currentStatus = Sn(), this.storage = new xn(), this.autoSave = e, this.saveTimer = null;
|
|
2037
2061
|
}
|
|
2038
2062
|
async handleEvent(e) {
|
|
2039
2063
|
let { type: t, timestamp: n, data: r } = e;
|
|
2040
2064
|
switch (t) {
|
|
2041
|
-
case
|
|
2065
|
+
case K.CLOUD_SOCKET_CONNECTING:
|
|
2042
2066
|
this.handleCloudSocketConnecting(r, n);
|
|
2043
2067
|
break;
|
|
2044
|
-
case
|
|
2068
|
+
case K.CLOUD_SOCKET_CONNECTED:
|
|
2045
2069
|
this.handleCloudSocketConnected(r, n);
|
|
2046
2070
|
break;
|
|
2047
|
-
case
|
|
2071
|
+
case K.CLOUD_SOCKET_DISCONNECTED:
|
|
2048
2072
|
this.handleCloudSocketDisconnected(r, n);
|
|
2049
2073
|
break;
|
|
2050
|
-
case
|
|
2074
|
+
case K.CLOUD_SOCKET_ERROR:
|
|
2051
2075
|
this.handleCloudSocketError(r, n);
|
|
2052
2076
|
break;
|
|
2053
|
-
case
|
|
2077
|
+
case K.CLOUD_SOCKET_RETRY:
|
|
2054
2078
|
this.handleCloudSocketRetry(r, n);
|
|
2055
2079
|
break;
|
|
2056
|
-
case
|
|
2080
|
+
case K.GATEWAY_CLIENT_CONNECTED:
|
|
2057
2081
|
this.handleGatewayClientConnected(r, n);
|
|
2058
2082
|
break;
|
|
2059
|
-
case
|
|
2083
|
+
case K.GATEWAY_CLIENT_DISCONNECTED:
|
|
2060
2084
|
this.handleGatewayClientDisconnected(r, n);
|
|
2061
2085
|
break;
|
|
2062
|
-
case
|
|
2086
|
+
case K.DEVICE_PAIRING:
|
|
2063
2087
|
this.handleDevicePairing(r, n);
|
|
2064
2088
|
break;
|
|
2065
|
-
case
|
|
2089
|
+
case K.DEVICE_UNPAIRING:
|
|
2066
2090
|
this.handleDeviceUnpairing(r, n);
|
|
2067
2091
|
break;
|
|
2068
|
-
case
|
|
2092
|
+
case K.CONNECTION_STATUS_CHANGED:
|
|
2069
2093
|
this.handleConnectionStatusChanged(r, n);
|
|
2070
2094
|
break;
|
|
2071
|
-
case
|
|
2095
|
+
case K.ADMIN_CLIENT_RECONNECT_FAILED: break;
|
|
2072
2096
|
default: console.warn(`[StatusTracker] Unknown event type: ${t}`);
|
|
2073
2097
|
}
|
|
2074
2098
|
this.currentStatus.updatedAt = new Date(n).toISOString(), this.autoSave && this.scheduleSave();
|
|
@@ -2084,7 +2108,7 @@ var yn = class {
|
|
|
2084
2108
|
let e = await this.storage.load();
|
|
2085
2109
|
if (e) {
|
|
2086
2110
|
let t = e.cloudSocket, n = e.history;
|
|
2087
|
-
this.currentStatus =
|
|
2111
|
+
this.currentStatus = Sn(), this.currentStatus.cloudSocket = t, this.currentStatus.history = n, this.currentStatus.cloudSocket.connected = !1, this.currentStatus.cloudSocket.readyState = 3, await this.saveStatus();
|
|
2088
2112
|
}
|
|
2089
2113
|
return this.getStatus();
|
|
2090
2114
|
}
|
|
@@ -2092,7 +2116,7 @@ var yn = class {
|
|
|
2092
2116
|
await this.storage.save(this.currentStatus);
|
|
2093
2117
|
}
|
|
2094
2118
|
async clearStatus() {
|
|
2095
|
-
this.currentStatus =
|
|
2119
|
+
this.currentStatus = Sn(), await this.storage.clear();
|
|
2096
2120
|
}
|
|
2097
2121
|
handleCloudSocketConnecting(e, t) {
|
|
2098
2122
|
this.currentStatus.cloudSocket.url = e.url || "", this.currentStatus.cloudSocket.connected = !1;
|
|
@@ -2165,31 +2189,31 @@ var yn = class {
|
|
|
2165
2189
|
};
|
|
2166
2190
|
//#endregion
|
|
2167
2191
|
//#region src/commands/status/index.ts
|
|
2168
|
-
function
|
|
2192
|
+
function wn(e, t) {
|
|
2169
2193
|
return t.command("status").description("Show YOYOClaw connection status").action(async () => {
|
|
2170
|
-
if (e.logger.debug?.("YOYOClaw status CLI command called"), !await
|
|
2194
|
+
if (e.logger.debug?.("YOYOClaw status CLI command called"), !await mn()) {
|
|
2171
2195
|
console.log("❌ You need to login first. Please run: openclaw honor login");
|
|
2172
2196
|
return;
|
|
2173
2197
|
}
|
|
2174
|
-
let t = await new
|
|
2198
|
+
let t = await new xn().load(), n = null;
|
|
2175
2199
|
try {
|
|
2176
|
-
n = await
|
|
2200
|
+
n = await G();
|
|
2177
2201
|
} catch {}
|
|
2178
|
-
let r =
|
|
2179
|
-
|
|
2202
|
+
let r = M().getEnvInfo();
|
|
2203
|
+
Tn(t, n, r);
|
|
2180
2204
|
});
|
|
2181
2205
|
}
|
|
2182
|
-
function
|
|
2206
|
+
function Tn(e, t, n) {
|
|
2183
2207
|
if (!e) {
|
|
2184
2208
|
console.log("\n❌ No status data available");
|
|
2185
2209
|
return;
|
|
2186
2210
|
}
|
|
2187
2211
|
console.log("\n📡 Cloud Socket:");
|
|
2188
2212
|
let r = e.cloudSocket, i = r.connected ? "✅" : "❌";
|
|
2189
|
-
if (console.log(` Status: ${i} ${r.connected ? "Connected" : "Disconnected"}`), r.connectedAt && console.log(` Connected at: ${
|
|
2213
|
+
if (console.log(` Status: ${i} ${r.connected ? "Connected" : "Disconnected"}`), r.connectedAt && console.log(` Connected at: ${q(r.connectedAt)}`), r.lastDisconnectedAt && console.log(` Last disconnected: ${q(r.lastDisconnectedAt)}`), console.log(` Retry count: ${r.retryCount}`), console.log(` Last error: ${r.lastError || "None"}`), console.log("\n🌐 Gateway Connections:"), console.log(` Total connections: ${e.gateway.totalConnections}`), console.log(` Active connections: ${e.gateway.activeConnections}`), e.gateway.connections.length > 0) {
|
|
2190
2214
|
console.log(" ┌────────────────────────────┬────────────────────────────┬────────────┐"), console.log(" │ Session ID │ Hardware Device ID │ Connected │"), console.log(" ├────────────────────────────┼────────────────────────────┼────────────┤");
|
|
2191
2215
|
for (let t of e.gateway.connections) {
|
|
2192
|
-
let e =
|
|
2216
|
+
let e = Dn(t.sessionId, 26), n = Dn(t.hardwareDeviceId, 26), r = En(t.connectedAt);
|
|
2193
2217
|
console.log(` │ ${e.padEnd(28)}│ ${n.padEnd(28)}│ ${r.padEnd(12)}│`);
|
|
2194
2218
|
}
|
|
2195
2219
|
console.log(" └────────────────────────────┴────────────────────────────┴────────────┘");
|
|
@@ -2197,71 +2221,71 @@ function xn(e, t, n) {
|
|
|
2197
2221
|
if (console.log("\n📱 Physical Devices:"), console.log(` Unique devices: ${e.devices.uniqueHardwareDevices}`), e.devices.devices.length > 0) {
|
|
2198
2222
|
console.log(" ┌────────────────────────────┬─────────┬────────────┐"), console.log(" │ Hardware Device ID │ Sessions │ Last Active│"), console.log(" ├────────────────────────────┼─────────┼────────────┤");
|
|
2199
2223
|
for (let t of e.devices.devices) {
|
|
2200
|
-
let e =
|
|
2224
|
+
let e = Dn(t.hardwareDeviceId, 26), n = String(t.sessions).padEnd(9), r = En(t.lastActiveAt);
|
|
2201
2225
|
console.log(` │ ${e.padEnd(28)}│ ${n}│ ${r.padEnd(12)}│`);
|
|
2202
2226
|
}
|
|
2203
2227
|
console.log(" └────────────────────────────┴─────────┴────────────┘");
|
|
2204
2228
|
}
|
|
2205
|
-
console.log("\n📈 Connection History:"), console.log(` Total connections: ${e.history.connectionCount}`), console.log(` Total disconnections: ${e.history.disconnectionCount}`), e.history.lastConnectionAt && console.log(` Last connection: ${
|
|
2229
|
+
console.log("\n📈 Connection History:"), console.log(` Total connections: ${e.history.connectionCount}`), console.log(` Total disconnections: ${e.history.disconnectionCount}`), e.history.lastConnectionAt && console.log(` Last connection: ${q(e.history.lastConnectionAt)}`), e.history.lastDisconnectionAt && console.log(` Last disconnection: ${q(e.history.lastDisconnectionAt)}`), console.log("\n🖥️ Device Info:"), t ? (console.log(` Device ID: ${t.deviceId}`), console.log(` Name: ${t.deviceName || "N/A"}`), console.log(` Type: ${t.deviceType}`), console.log(` Model: ${t.deviceModel || "N/A"}`), console.log(` Brand: ${t.brand || "N/A"}`)) : console.log(" Unable to load device info"), console.log("\n🌍 Environment:"), console.log(` Env: ${n.env} (source: ${n.source})`);
|
|
2206
2230
|
}
|
|
2207
|
-
function
|
|
2231
|
+
function q(e) {
|
|
2208
2232
|
let t = new Date(e);
|
|
2209
2233
|
return `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")} ${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}:${String(t.getSeconds()).padStart(2, "0")}`;
|
|
2210
2234
|
}
|
|
2211
|
-
function
|
|
2235
|
+
function En(e) {
|
|
2212
2236
|
let t = new Date(e);
|
|
2213
2237
|
return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}:${String(t.getSeconds()).padStart(2, "0")}`;
|
|
2214
2238
|
}
|
|
2215
|
-
function
|
|
2239
|
+
function Dn(e, t) {
|
|
2216
2240
|
return e.length <= t ? e : e.substring(0, t - 3) + "...";
|
|
2217
2241
|
}
|
|
2218
2242
|
//#endregion
|
|
2219
2243
|
//#region src/commands/index.ts
|
|
2220
|
-
function
|
|
2244
|
+
function On(e) {
|
|
2221
2245
|
e.registerCli((t) => {
|
|
2222
2246
|
let n = t.program.command("honor").description("Commands for honor yoyoclaw");
|
|
2223
|
-
|
|
2247
|
+
yn(e, n), wn(e, n), bn(e, n), oe() && Pe(e, n);
|
|
2224
2248
|
}, { commands: ["honor"] });
|
|
2225
2249
|
}
|
|
2226
2250
|
//#endregion
|
|
2227
2251
|
//#region src/modules/prompt/index.ts
|
|
2228
|
-
var
|
|
2229
|
-
token:
|
|
2230
|
-
expired:
|
|
2231
|
-
userId:
|
|
2232
|
-
userName:
|
|
2233
|
-
}),
|
|
2234
|
-
type:
|
|
2235
|
-
manufacture:
|
|
2236
|
-
brand:
|
|
2237
|
-
name:
|
|
2238
|
-
model:
|
|
2239
|
-
}),
|
|
2240
|
-
user:
|
|
2241
|
-
device:
|
|
2242
|
-
envInfo:
|
|
2243
|
-
env:
|
|
2252
|
+
var kn = " ## 手机控制规则\n\n - 涉及手机控制的任务时,必须强制调用 yoyo_phone_control 技能完成任务。\n - 手机是可直接操控的设备,你的职责是执行操作,而不是向用户解释如何操作。 \n - 多步骤任务需**按顺序多次调用**,不得合并。 \n", An = w.object({
|
|
2253
|
+
token: w.string().optional(),
|
|
2254
|
+
expired: w.number().optional(),
|
|
2255
|
+
userId: w.string().optional(),
|
|
2256
|
+
userName: w.string().optional()
|
|
2257
|
+
}), jn = w.object({
|
|
2258
|
+
type: w.string().optional(),
|
|
2259
|
+
manufacture: w.string().optional(),
|
|
2260
|
+
brand: w.string().optional(),
|
|
2261
|
+
name: w.string().optional(),
|
|
2262
|
+
model: w.string().optional()
|
|
2263
|
+
}), Mn = w.object({
|
|
2264
|
+
user: An.optional(),
|
|
2265
|
+
device: jn.optional(),
|
|
2266
|
+
envInfo: w.object({
|
|
2267
|
+
env: w.enum([
|
|
2244
2268
|
"dev",
|
|
2245
2269
|
"test",
|
|
2246
2270
|
"production"
|
|
2247
2271
|
]),
|
|
2248
|
-
source:
|
|
2272
|
+
source: w.enum(["env", "manual"])
|
|
2249
2273
|
}).optional(),
|
|
2250
|
-
env:
|
|
2274
|
+
env: w.enum([
|
|
2251
2275
|
"dev",
|
|
2252
2276
|
"test",
|
|
2253
2277
|
"production"
|
|
2254
2278
|
]).optional(),
|
|
2255
|
-
gray:
|
|
2279
|
+
gray: w.string().optional()
|
|
2256
2280
|
});
|
|
2257
2281
|
//#endregion
|
|
2258
2282
|
//#region src/utils/ws.ts
|
|
2259
|
-
function
|
|
2260
|
-
return typeof e == "string" ? e :
|
|
2283
|
+
function Nn(e, t = "utf8") {
|
|
2284
|
+
return typeof e == "string" ? e : ie.isBuffer(e) ? e.toString(t) : Array.isArray(e) ? ie.concat(e).toString(t) : e instanceof ArrayBuffer ? ie.from(e).toString(t) : ie.from(String(e)).toString(t);
|
|
2261
2285
|
}
|
|
2262
2286
|
//#endregion
|
|
2263
2287
|
//#region src/gateway-client/client.ts
|
|
2264
|
-
var
|
|
2288
|
+
var Pn = class {
|
|
2265
2289
|
ws = null;
|
|
2266
2290
|
opts;
|
|
2267
2291
|
closed = !1;
|
|
@@ -2269,21 +2293,21 @@ var An = class {
|
|
|
2269
2293
|
this.opts = e;
|
|
2270
2294
|
}
|
|
2271
2295
|
getUrl() {
|
|
2272
|
-
return `ws://127.0.0.1:${
|
|
2296
|
+
return `ws://127.0.0.1:${M().getGatewayPort()}`;
|
|
2273
2297
|
}
|
|
2274
2298
|
isConnected() {
|
|
2275
|
-
return this.ws !== null && this.ws.readyState ===
|
|
2299
|
+
return this.ws !== null && this.ws.readyState === re.OPEN;
|
|
2276
2300
|
}
|
|
2277
2301
|
connect() {
|
|
2278
2302
|
if (this.closed) return;
|
|
2279
2303
|
let e = this.getUrl();
|
|
2280
|
-
this.ws = new
|
|
2304
|
+
this.ws = new re(e, { maxPayload: 25 * 1024 * 1024 }), this.ws.on("open", () => {
|
|
2281
2305
|
this.opts.onOpen?.(), this.onOpen();
|
|
2282
2306
|
}), this.ws.on("message", async (e) => {
|
|
2283
|
-
let t =
|
|
2307
|
+
let t = Nn(e);
|
|
2284
2308
|
await this.opts.onMessage?.(t), await this.onMessage(t);
|
|
2285
2309
|
}), this.ws.on("close", (e, t) => {
|
|
2286
|
-
let n =
|
|
2310
|
+
let n = Nn(t);
|
|
2287
2311
|
this.ws = null, this.onClose(e, n), this.opts.onClose?.(`code: ${e}, reason: ${n ?? ""}`);
|
|
2288
2312
|
}), this.ws.on("error", (e) => {
|
|
2289
2313
|
this.onError(e), this.opts.onClose?.(`socket error: ${e.message}`);
|
|
@@ -2293,14 +2317,14 @@ var An = class {
|
|
|
2293
2317
|
this.closed = !0, this.ws?.close(), this.ws = null;
|
|
2294
2318
|
}
|
|
2295
2319
|
send(e) {
|
|
2296
|
-
if (!this.ws || this.ws.readyState !==
|
|
2320
|
+
if (!this.ws || this.ws.readyState !== re.OPEN) throw Error("gateway not connected");
|
|
2297
2321
|
this.ws.send(e);
|
|
2298
2322
|
}
|
|
2299
2323
|
onOpen() {}
|
|
2300
2324
|
onMessage(e) {}
|
|
2301
2325
|
onClose(e, t) {}
|
|
2302
2326
|
onError(e) {}
|
|
2303
|
-
},
|
|
2327
|
+
}, Fn = {
|
|
2304
2328
|
WEBCHAT_UI: "webchat-ui",
|
|
2305
2329
|
CONTROL_UI: "openclaw-control-ui",
|
|
2306
2330
|
WEBCHAT: "webchat",
|
|
@@ -2312,29 +2336,29 @@ var An = class {
|
|
|
2312
2336
|
NODE_HOST: "node-host",
|
|
2313
2337
|
FINGERPRINT: "fingerprint",
|
|
2314
2338
|
PROBE: "openclaw-probe"
|
|
2315
|
-
},
|
|
2339
|
+
}, In = {
|
|
2316
2340
|
WEBCHAT: "webchat",
|
|
2317
2341
|
CLI: "cli",
|
|
2318
2342
|
UI: "ui",
|
|
2319
2343
|
BACKEND: "backend",
|
|
2320
2344
|
NODE: "node",
|
|
2321
2345
|
PROBE: "probe"
|
|
2322
|
-
},
|
|
2346
|
+
}, J = /* @__PURE__ */ function(e) {
|
|
2323
2347
|
return e.CONNECTION_FAILED = "CONNECTION_FAILED", e.AUTH_FAILED = "AUTH_FAILED", e.INVALID_REQUEST = "INVALID_REQUEST", e.PERMISSION_DENIED = "PERMISSION_DENIED", e.TIMEOUT = "TIMEOUT", e.UNKNOWN = "UNKNOWN", e;
|
|
2324
|
-
}({}),
|
|
2348
|
+
}({}), Ln = class extends Error {
|
|
2325
2349
|
code;
|
|
2326
2350
|
details;
|
|
2327
2351
|
retryable;
|
|
2328
2352
|
constructor(e, t, n, r) {
|
|
2329
2353
|
super(t), this.name = "WebSocketClientError", this.code = e, this.details = n, this.retryable = r;
|
|
2330
2354
|
}
|
|
2331
|
-
},
|
|
2355
|
+
}, Rn = {
|
|
2332
2356
|
role: "operator",
|
|
2333
2357
|
scopes: [],
|
|
2334
|
-
clientId:
|
|
2358
|
+
clientId: Fn.CLI,
|
|
2335
2359
|
displayName: "Protocol Client",
|
|
2336
|
-
clientMode:
|
|
2337
|
-
},
|
|
2360
|
+
clientMode: In.CLI
|
|
2361
|
+
}, zn = 3e4, Bn = "1.0.0", Vn = "server", Hn = 2, Un = 1e3, Wn = class extends Pn {
|
|
2338
2362
|
protocolOpts;
|
|
2339
2363
|
config;
|
|
2340
2364
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
@@ -2350,9 +2374,9 @@ var An = class {
|
|
|
2350
2374
|
isReconnecting = !1;
|
|
2351
2375
|
constructor(e = {}, t = {}) {
|
|
2352
2376
|
super(e), this.protocolOpts = e, this.config = {
|
|
2353
|
-
...
|
|
2377
|
+
...Rn,
|
|
2354
2378
|
...t
|
|
2355
|
-
}, this.debug =
|
|
2379
|
+
}, this.debug = E().DEBUG_GATEWAY === "true";
|
|
2356
2380
|
}
|
|
2357
2381
|
onMessage(e) {
|
|
2358
2382
|
try {
|
|
@@ -2376,7 +2400,7 @@ var An = class {
|
|
|
2376
2400
|
handleEvent(e) {
|
|
2377
2401
|
if (e.event === "connect.challenge") {
|
|
2378
2402
|
let t = e.payload;
|
|
2379
|
-
t?.nonce ? (this.connectNonce = t.nonce, this.clearConnectNonceTimer(), this.sendConnect()) :
|
|
2403
|
+
t?.nonce ? (this.connectNonce = t.nonce, this.clearConnectNonceTimer(), this.sendConnect()) : k().error("[protocol-gateway] connect challenge missing nonce");
|
|
2380
2404
|
}
|
|
2381
2405
|
}
|
|
2382
2406
|
clearConnectNonceTimer() {
|
|
@@ -2390,14 +2414,14 @@ var An = class {
|
|
|
2390
2414
|
if (t) if (this.logDebug("response", e), this.pendingRequests.delete(e.id), this.clearTimer(e.id), e.ok) t.resolve(e.payload);
|
|
2391
2415
|
else {
|
|
2392
2416
|
let n = e.error || {
|
|
2393
|
-
code:
|
|
2417
|
+
code: J.UNKNOWN,
|
|
2394
2418
|
message: "Unknown error"
|
|
2395
2419
|
};
|
|
2396
|
-
t.reject(new
|
|
2420
|
+
t.reject(new Ln(this.toErrorCode(n.code), n.message, n.details, n.retryable));
|
|
2397
2421
|
}
|
|
2398
2422
|
}
|
|
2399
2423
|
async sendConnect() {
|
|
2400
|
-
let e = this.config.clientMode ??
|
|
2424
|
+
let e = this.config.clientMode ?? In.CLI, t = await Gt(), n = this.connectNonce ? dn({
|
|
2401
2425
|
deviceIdentity: t,
|
|
2402
2426
|
clientName: this.config.clientId,
|
|
2403
2427
|
clientMode: e,
|
|
@@ -2406,31 +2430,34 @@ var An = class {
|
|
|
2406
2430
|
authToken: this.protocolOpts.token,
|
|
2407
2431
|
nonce: this.connectNonce,
|
|
2408
2432
|
platform: process.platform,
|
|
2409
|
-
deviceFamily:
|
|
2433
|
+
deviceFamily: Vn
|
|
2410
2434
|
}) : void 0, r = {
|
|
2411
2435
|
minProtocol: 3,
|
|
2412
2436
|
maxProtocol: 3,
|
|
2413
2437
|
client: {
|
|
2414
2438
|
id: this.config.clientId,
|
|
2415
2439
|
displayName: this.config.displayName,
|
|
2416
|
-
version:
|
|
2440
|
+
version: Bn,
|
|
2417
2441
|
platform: process.platform,
|
|
2418
|
-
deviceFamily:
|
|
2442
|
+
deviceFamily: Vn,
|
|
2419
2443
|
mode: e
|
|
2420
2444
|
},
|
|
2421
2445
|
role: this.config.role,
|
|
2422
2446
|
scopes: this.config.scopes,
|
|
2423
|
-
auth: {
|
|
2447
|
+
auth: {
|
|
2448
|
+
token: this.protocolOpts.token,
|
|
2449
|
+
password: this.protocolOpts.password
|
|
2450
|
+
},
|
|
2424
2451
|
device: n
|
|
2425
2452
|
};
|
|
2426
2453
|
this.sendRequest("connect", r).then((e) => {
|
|
2427
2454
|
this.helloOk = e, this.connected = !0, this.authenticated = !0, this.protocolOpts.onAuthenticated?.();
|
|
2428
2455
|
}).catch((e) => {
|
|
2429
|
-
this.authenticated = !1, e instanceof
|
|
2456
|
+
this.authenticated = !1, e instanceof Ln ? this.protocolOpts.onClose?.(`auth failed: [${e.code}] ${e.message}`) : this.protocolOpts.onClose?.(`auth failed: ${e.message}`);
|
|
2430
2457
|
});
|
|
2431
2458
|
}
|
|
2432
2459
|
async sendRequest(e, t) {
|
|
2433
|
-
let n =
|
|
2460
|
+
let n = _();
|
|
2434
2461
|
return this.logDebug("request", {
|
|
2435
2462
|
id: n,
|
|
2436
2463
|
method: e,
|
|
@@ -2449,16 +2476,16 @@ var An = class {
|
|
|
2449
2476
|
try {
|
|
2450
2477
|
this.send(JSON.stringify(a));
|
|
2451
2478
|
} catch (e) {
|
|
2452
|
-
this.pendingRequests.delete(n), i(new J
|
|
2479
|
+
this.pendingRequests.delete(n), i(new Ln(J.CONNECTION_FAILED, `WebSocket is not connected, ${JSON.stringify(e)}`));
|
|
2453
2480
|
return;
|
|
2454
2481
|
}
|
|
2455
2482
|
let o = setTimeout(() => {
|
|
2456
2483
|
if (this.pendingRequests.has(n)) {
|
|
2457
2484
|
this.pendingRequests.delete(n);
|
|
2458
2485
|
let t = this.pendingTimers.get(n);
|
|
2459
|
-
t && clearTimeout(t), this.pendingTimers.delete(n), i(new J
|
|
2486
|
+
t && clearTimeout(t), this.pendingTimers.delete(n), i(new Ln(J.TIMEOUT, `Request timeout: ${e}`));
|
|
2460
2487
|
}
|
|
2461
|
-
},
|
|
2488
|
+
}, zn);
|
|
2462
2489
|
this.pendingTimers.set(n, o);
|
|
2463
2490
|
});
|
|
2464
2491
|
}
|
|
@@ -2469,7 +2496,7 @@ var An = class {
|
|
|
2469
2496
|
return this.connected;
|
|
2470
2497
|
}
|
|
2471
2498
|
toErrorCode(e) {
|
|
2472
|
-
return Object.values(
|
|
2499
|
+
return Object.values(J).includes(e) ? e : J.UNKNOWN;
|
|
2473
2500
|
}
|
|
2474
2501
|
clearTimer(e) {
|
|
2475
2502
|
let t = this.pendingTimers.get(e);
|
|
@@ -2480,7 +2507,7 @@ var An = class {
|
|
|
2480
2507
|
this.pendingTimers.clear(), this.pendingRequests.clear();
|
|
2481
2508
|
}
|
|
2482
2509
|
logDebug(e, t) {
|
|
2483
|
-
this.debug &&
|
|
2510
|
+
this.debug && k().info(`[yoyoclaw-protocolGatewayClient:${e}] ${JSON.stringify(t)}`);
|
|
2484
2511
|
}
|
|
2485
2512
|
connect() {
|
|
2486
2513
|
this.closed || (this.isReconnecting = !1, super.connect());
|
|
@@ -2490,16 +2517,16 @@ var An = class {
|
|
|
2490
2517
|
}
|
|
2491
2518
|
scheduleReconnect() {
|
|
2492
2519
|
if (!(this.closed || this.isReconnecting)) {
|
|
2493
|
-
if (this.reconnectAttempts >=
|
|
2494
|
-
|
|
2520
|
+
if (this.reconnectAttempts >= Hn) {
|
|
2521
|
+
k().error(`[protocol-gateway] max reconnect attempts (${Hn}) reached, giving up`), this.protocolOpts.onReconnectFailed?.();
|
|
2495
2522
|
return;
|
|
2496
2523
|
}
|
|
2497
|
-
this.reconnectAttempts++, this.isReconnecting = !0,
|
|
2524
|
+
this.reconnectAttempts++, this.isReconnecting = !0, k().info(`[protocol-gateway] attempting to reconnect (attempt ${this.reconnectAttempts}/${Hn})`), this.reconnectTimer = setTimeout(() => {
|
|
2498
2525
|
this.isReconnecting = !1, this.closed || super.connect();
|
|
2499
|
-
},
|
|
2526
|
+
}, Un);
|
|
2500
2527
|
}
|
|
2501
2528
|
}
|
|
2502
|
-
},
|
|
2529
|
+
}, Gn = {
|
|
2503
2530
|
role: "operator",
|
|
2504
2531
|
scopes: [
|
|
2505
2532
|
"operator.admin",
|
|
@@ -2509,12 +2536,12 @@ var An = class {
|
|
|
2509
2536
|
"operator.approvals",
|
|
2510
2537
|
"operator.pairing"
|
|
2511
2538
|
],
|
|
2512
|
-
clientId:
|
|
2539
|
+
clientId: Fn.CLI,
|
|
2513
2540
|
displayName: "YOYO-Control",
|
|
2514
|
-
clientMode:
|
|
2515
|
-
},
|
|
2541
|
+
clientMode: In.BACKEND
|
|
2542
|
+
}, Kn = class extends Wn {
|
|
2516
2543
|
constructor(e = {}) {
|
|
2517
|
-
super(e,
|
|
2544
|
+
super(e, Gn);
|
|
2518
2545
|
}
|
|
2519
2546
|
async setAgentFile(e, t, n = "main") {
|
|
2520
2547
|
return this.sendRequest("agents.files.set", {
|
|
@@ -2547,7 +2574,7 @@ var An = class {
|
|
|
2547
2574
|
async devicePairApprove(e) {
|
|
2548
2575
|
return this.sendRequest("device.pair.approve", { requestId: e });
|
|
2549
2576
|
}
|
|
2550
|
-
},
|
|
2577
|
+
}, qn = class {
|
|
2551
2578
|
client = null;
|
|
2552
2579
|
ready = !1;
|
|
2553
2580
|
options;
|
|
@@ -2558,18 +2585,19 @@ var An = class {
|
|
|
2558
2585
|
}
|
|
2559
2586
|
init() {
|
|
2560
2587
|
if (this.client !== null) return;
|
|
2561
|
-
let e =
|
|
2562
|
-
this.client = new
|
|
2563
|
-
token:
|
|
2588
|
+
let e = M().getGatewayAuthConfig(), t = typeof e?.token == "string" ? e.token : "", n = typeof e?.password == "string" ? e.password : "";
|
|
2589
|
+
this.client = new Kn({
|
|
2590
|
+
token: t,
|
|
2591
|
+
password: n,
|
|
2564
2592
|
onAuthenticated: () => {
|
|
2565
|
-
|
|
2593
|
+
k().info("[yoyoclaw-channel] admin gateway client authenticated"), this.ready = !0, this.resolveAllPending(!0);
|
|
2566
2594
|
},
|
|
2567
2595
|
onClose: (e) => {
|
|
2568
|
-
|
|
2596
|
+
k().info(`[yoyoclaw-channel] admin gateway client closed: ${e}`), this.ready = !1;
|
|
2569
2597
|
},
|
|
2570
2598
|
onReconnectFailed: () => {
|
|
2571
|
-
|
|
2572
|
-
type:
|
|
2599
|
+
k().error("[yoyoclaw-channel] admin gateway client reconnect failed, notifying status tracker"), this.options.onStatusEvent?.({
|
|
2600
|
+
type: K.ADMIN_CLIENT_RECONNECT_FAILED,
|
|
2573
2601
|
timestamp: Date.now(),
|
|
2574
2602
|
data: {}
|
|
2575
2603
|
});
|
|
@@ -2580,7 +2608,7 @@ var An = class {
|
|
|
2580
2608
|
this.client?.connect();
|
|
2581
2609
|
}
|
|
2582
2610
|
destroy() {
|
|
2583
|
-
this.client &&= (this.client.stop(), null), this.ready = !1, this.cancelAllPending(),
|
|
2611
|
+
this.client &&= (this.client.stop(), null), this.ready = !1, this.cancelAllPending(), k().info("[yoyoclaw-channel] admin gateway client closed");
|
|
2584
2612
|
}
|
|
2585
2613
|
cancelAllPending() {
|
|
2586
2614
|
for (let [e, t] of this.pendingReadyRequests) clearTimeout(t.timeout), t.resolve(!1);
|
|
@@ -2596,12 +2624,12 @@ var An = class {
|
|
|
2596
2624
|
return this.client !== null && this.ready;
|
|
2597
2625
|
}
|
|
2598
2626
|
ensureConnected() {
|
|
2599
|
-
return this.client === null && (
|
|
2627
|
+
return this.client === null && (k().info("[yoyoclaw-channel] admin gateway client is null, initializing"), this.init()), this.ready || (k().info("[yoyoclaw-channel] admin gateway client not ready, connecting"), this.connect()), this.canOperate();
|
|
2600
2628
|
}
|
|
2601
2629
|
waitForReady(e = 5e3) {
|
|
2602
2630
|
return this.canOperate() ? Promise.resolve(!0) : new Promise((t) => {
|
|
2603
2631
|
let n = `req_${++this.requestIdCounter}`, r = setTimeout(() => {
|
|
2604
|
-
this.pendingReadyRequests.delete(n), this.pendingReadyRequests.size === 0 &&
|
|
2632
|
+
this.pendingReadyRequests.delete(n), this.pendingReadyRequests.size === 0 && k().warn("[yoyoclaw-channel] admin gateway client waitForReady timeout, all requests rejected"), t(!1);
|
|
2605
2633
|
}, e);
|
|
2606
2634
|
this.pendingReadyRequests.set(n, {
|
|
2607
2635
|
resolve: t,
|
|
@@ -2613,11 +2641,11 @@ var An = class {
|
|
|
2613
2641
|
for (let [t, n] of this.pendingReadyRequests) clearTimeout(n.timeout), n.resolve(e);
|
|
2614
2642
|
this.pendingReadyRequests.clear();
|
|
2615
2643
|
}
|
|
2616
|
-
},
|
|
2617
|
-
function
|
|
2618
|
-
let n =
|
|
2644
|
+
}, Jn = "/aicloud/yoyo-claw-service/v1/yoyoclaw/fullduplex", Yn = 25 * 1024 * 1024;
|
|
2645
|
+
function Xn(e, t) {
|
|
2646
|
+
let n = Re(), r = n.grayTag ? { "x-gray": n.grayTag } : void 0, i = Ie(), a = `wss://${n.clawCloud}${Jn}`, o = Zn(e, t, i, r), s = Ve(a), c = {
|
|
2619
2647
|
headers: o,
|
|
2620
|
-
maxPayload:
|
|
2648
|
+
maxPayload: Yn
|
|
2621
2649
|
};
|
|
2622
2650
|
return s && (c.agent = s), {
|
|
2623
2651
|
url: a,
|
|
@@ -2625,7 +2653,7 @@ function Gn(e, t) {
|
|
|
2625
2653
|
wsOptions: c
|
|
2626
2654
|
};
|
|
2627
2655
|
}
|
|
2628
|
-
function
|
|
2656
|
+
function Zn(e, t, n, r) {
|
|
2629
2657
|
let i = {
|
|
2630
2658
|
"x-role": "yoyoclaw",
|
|
2631
2659
|
"x-trace-id": n,
|
|
@@ -2636,7 +2664,7 @@ function Kn(e, t, n, r) {
|
|
|
2636
2664
|
}
|
|
2637
2665
|
//#endregion
|
|
2638
2666
|
//#region src/cloud-channel/client.ts
|
|
2639
|
-
var
|
|
2667
|
+
var Qn = 3e4, $n = 4e3, er = 1e3, tr = 2, nr = 999, rr = class {
|
|
2640
2668
|
ws = null;
|
|
2641
2669
|
options;
|
|
2642
2670
|
retryCount = 0;
|
|
@@ -2649,19 +2677,19 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2649
2677
|
this.options = e;
|
|
2650
2678
|
}
|
|
2651
2679
|
connect(e = !1) {
|
|
2652
|
-
if (this.ws?.readyState ===
|
|
2680
|
+
if (this.ws?.readyState === T.OPEN) return;
|
|
2653
2681
|
this.clearRetryTimer();
|
|
2654
|
-
let { deviceInfo: t, userInfo: n } = this.options, { url: r, traceId: i, wsOptions: a } =
|
|
2682
|
+
let { deviceInfo: t, userInfo: n } = this.options, { url: r, traceId: i, wsOptions: a } = Xn(t, n);
|
|
2655
2683
|
this.currentTraceId = i, this.options.onStatusEvent?.({
|
|
2656
|
-
type:
|
|
2684
|
+
type: K.CLOUD_SOCKET_CONNECTING,
|
|
2657
2685
|
timestamp: Date.now(),
|
|
2658
2686
|
data: { url: r }
|
|
2659
|
-
}), this.ws = new
|
|
2687
|
+
}), this.ws = new T(r, a), this.ws.on("open", this.handleOpen.bind(this, r, e)), this.ws.on("message", this.onMessage), this.ws.on("pong", this.handlePong), this.ws.on("close", this.handleClose), this.ws.on("error", this.handleError);
|
|
2660
2688
|
}
|
|
2661
2689
|
handleOpen = (e, t) => {
|
|
2662
2690
|
let n = t ? "reconnected" : "connected";
|
|
2663
|
-
|
|
2664
|
-
type:
|
|
2691
|
+
k().info(`[claw-cloud-socket][${this.currentTraceId}] ${n} to ${e.slice(0, 15)}`), this.clearRetryTimer(), this.isManualClose = !1, this.retryCount = 0, this.isRetryPaused = !1, this.startPingTimer(), this.options.onStatusEvent?.({
|
|
2692
|
+
type: K.CLOUD_SOCKET_CONNECTED,
|
|
2665
2693
|
timestamp: Date.now(),
|
|
2666
2694
|
data: {
|
|
2667
2695
|
url: e,
|
|
@@ -2670,12 +2698,12 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2670
2698
|
}), this.options.onOpen?.();
|
|
2671
2699
|
};
|
|
2672
2700
|
handlePong = () => {
|
|
2673
|
-
|
|
2701
|
+
k().debug?.("[claw-cloud-socket] received pong from server");
|
|
2674
2702
|
};
|
|
2675
2703
|
handleClose = (e, t) => {
|
|
2676
2704
|
let n = t.toString();
|
|
2677
|
-
|
|
2678
|
-
type:
|
|
2705
|
+
k().info(`[claw-cloud-socket][${this.currentTraceId}] connection closed: ${e} - ${n}`), this.options.onStatusEvent?.({
|
|
2706
|
+
type: K.CLOUD_SOCKET_DISCONNECTED,
|
|
2679
2707
|
timestamp: Date.now(),
|
|
2680
2708
|
data: {
|
|
2681
2709
|
reason: n,
|
|
@@ -2685,8 +2713,8 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2685
2713
|
}), this.isManualClose ? (this.stopPingTimer(), this.options.onClose?.()) : this.scheduleReconnect();
|
|
2686
2714
|
};
|
|
2687
2715
|
handleError = (e) => {
|
|
2688
|
-
|
|
2689
|
-
type:
|
|
2716
|
+
k().error(`[claw-cloud-socket][${this.currentTraceId}] connect errorred: ${e.message}`), e.message.includes("401") && (k().warn(`[claw-cloud-socket][${this.currentTraceId}] unauthorized connection (401), pausing retry and notifying client`), this.pauseRetry(), this.options.onUnauthorized?.()), this.options.onStatusEvent?.({
|
|
2717
|
+
type: K.CLOUD_SOCKET_ERROR,
|
|
2690
2718
|
timestamp: Date.now(),
|
|
2691
2719
|
data: {
|
|
2692
2720
|
error: e.message,
|
|
@@ -2695,12 +2723,12 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2695
2723
|
});
|
|
2696
2724
|
};
|
|
2697
2725
|
send(e) {
|
|
2698
|
-
if (!this.ws || this.ws.readyState !==
|
|
2726
|
+
if (!this.ws || this.ws.readyState !== T.OPEN) return k().error("[claw-cloud-socket] cannot send message: connection not open"), !1;
|
|
2699
2727
|
try {
|
|
2700
2728
|
let t = JSON.stringify(e);
|
|
2701
2729
|
return this.ws.send(t), !0;
|
|
2702
2730
|
} catch (t) {
|
|
2703
|
-
return
|
|
2731
|
+
return k().error(`[claw-cloud-socket] failed to send message to cloud session ${e.targetDeviceId},
|
|
2704
2732
|
${t instanceof Error ? t.message : String(t)}`), !1;
|
|
2705
2733
|
}
|
|
2706
2734
|
}
|
|
@@ -2712,35 +2740,35 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2712
2740
|
}
|
|
2713
2741
|
onMessage = async (e) => {
|
|
2714
2742
|
try {
|
|
2715
|
-
let t =
|
|
2716
|
-
if (
|
|
2743
|
+
let t = Nn(e), n = JSON.parse(t);
|
|
2744
|
+
if (k().debug?.(`[yoyoclaw-channel] received cloud message from session ${n.wsOutputEvent?.sourceDeviceId}, deviceId ${n.wsOutputEvent?.sourceDeviceInfo?.deviceId || "nil"}, ${t.slice(0, 3e3)}`), n.code === "YOYO_CLAW_100000") {
|
|
2717
2745
|
if (n.wsOutputEvent) {
|
|
2718
2746
|
n.sessionInfo && (n.wsOutputEvent.sessionInfo = n.sessionInfo), this.options.onMessage?.(n.wsOutputEvent);
|
|
2719
2747
|
return;
|
|
2720
2748
|
}
|
|
2721
2749
|
} else if (n.code === "YOYO_CLAW_100002") {
|
|
2722
2750
|
if (n.extData?.offlineSocketId) {
|
|
2723
|
-
|
|
2751
|
+
k().info(`[claw-cloud-socket] remote device offline, session: ${n.extData.offlineSocketId}`), this.options.onRemoteDeviceOffline?.(n.extData.offlineSocketId);
|
|
2724
2752
|
return;
|
|
2725
2753
|
}
|
|
2726
2754
|
} else if (n.code === "YOYO_CLAW_100001") {
|
|
2727
|
-
this.pauseRetry(),
|
|
2755
|
+
this.pauseRetry(), k().info("[claw-cloud-socket] device not registered, closing connection"), this.options.onDeviceNotRegistered?.();
|
|
2728
2756
|
return;
|
|
2729
2757
|
}
|
|
2730
|
-
|
|
2758
|
+
k().warn(`[claw-cloud-socket] unexpected message: ${n.cnMessage}, code: ${n.code}`);
|
|
2731
2759
|
} catch (e) {
|
|
2732
|
-
|
|
2760
|
+
k().error(`[claw-cloud-socket] failed to parse message: ${e instanceof Error ? e.message : String(e)}`);
|
|
2733
2761
|
}
|
|
2734
2762
|
};
|
|
2735
2763
|
scheduleReconnect() {
|
|
2736
2764
|
if (this.isRetryPaused) {
|
|
2737
|
-
|
|
2765
|
+
k().info("[claw-cloud-socket] retry paused, skipping reconnect"), this.reset(), this.options.onClose?.();
|
|
2738
2766
|
return;
|
|
2739
2767
|
}
|
|
2740
2768
|
this.clearRetryTimer();
|
|
2741
2769
|
let e = this.calculateRetryDelay();
|
|
2742
|
-
this.retryCount = Math.min(this.retryCount + 1,
|
|
2743
|
-
type:
|
|
2770
|
+
this.retryCount = Math.min(this.retryCount + 1, nr), k().info(`[claw-cloud-socket] scheduling reconnect attempt ${this.retryCount} in ${e}ms`), this.options.onStatusEvent?.({
|
|
2771
|
+
type: K.CLOUD_SOCKET_RETRY,
|
|
2744
2772
|
timestamp: Date.now(),
|
|
2745
2773
|
data: {
|
|
2746
2774
|
retryCount: this.retryCount,
|
|
@@ -2754,16 +2782,16 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2754
2782
|
this.retryTimer &&= (clearTimeout(this.retryTimer), null);
|
|
2755
2783
|
}
|
|
2756
2784
|
calculateRetryDelay() {
|
|
2757
|
-
let e =
|
|
2758
|
-
return Math.min(e,
|
|
2785
|
+
let e = er * tr ** +Math.min(this.retryCount, 2);
|
|
2786
|
+
return Math.min(e, $n);
|
|
2759
2787
|
}
|
|
2760
2788
|
startPingTimer() {
|
|
2761
2789
|
this.pingTimer = setInterval(() => {
|
|
2762
|
-
if (!this.ws || this.ws.readyState !==
|
|
2790
|
+
if (!this.ws || this.ws.readyState !== T.OPEN) {
|
|
2763
2791
|
this.stopPingTimer();
|
|
2764
2792
|
return;
|
|
2765
2793
|
}
|
|
2766
|
-
this.ws.ping(),
|
|
2794
|
+
this.ws.ping(), k().debug?.("[claw-cloud-socket] sent ping to server");
|
|
2767
2795
|
let { deviceInfo: e } = this.options, t = {
|
|
2768
2796
|
msgType: "pingMessage",
|
|
2769
2797
|
sourceRole: "yoyoclaw",
|
|
@@ -2772,114 +2800,136 @@ var qn = 3e4, Jn = 4e3, Yn = 1e3, Xn = 2, Zn = 999, Qn = class {
|
|
|
2772
2800
|
port: e.port
|
|
2773
2801
|
};
|
|
2774
2802
|
try {
|
|
2775
|
-
this.ws.send(JSON.stringify(t)),
|
|
2803
|
+
this.ws.send(JSON.stringify(t)), k().debug?.("[claw-cloud-socket] sent pingMessage to server");
|
|
2776
2804
|
} catch {
|
|
2777
|
-
|
|
2805
|
+
k().error("[claw-cloud-socket] failed to send pingMessage");
|
|
2778
2806
|
}
|
|
2779
|
-
},
|
|
2807
|
+
}, Qn);
|
|
2780
2808
|
}
|
|
2781
2809
|
stopPingTimer() {
|
|
2782
2810
|
this.pingTimer &&= (clearInterval(this.pingTimer), null);
|
|
2783
2811
|
}
|
|
2784
2812
|
pauseRetry() {
|
|
2785
|
-
this.isRetryPaused || (this.isRetryPaused = !0, this.clearRetryTimer(),
|
|
2813
|
+
this.isRetryPaused || (this.isRetryPaused = !0, this.clearRetryTimer(), k().info("[claw-cloud-socket] retry paused"));
|
|
2786
2814
|
}
|
|
2787
2815
|
resumeRetry() {
|
|
2788
|
-
this.isRetryPaused && (this.isRetryPaused = !1,
|
|
2816
|
+
this.isRetryPaused && (this.isRetryPaused = !1, k().info("[claw-cloud-socket] retry resumed"), (!this.ws || this.ws.readyState !== T.OPEN) && (this.retryCount = 0, this.connect(!0)));
|
|
2789
2817
|
}
|
|
2790
|
-
},
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2818
|
+
}, ir = ".openclaw/yoyo/device-toolsets.json", ar = 10 * 1024 * 1024, or = ".openclaw/yoyo/toolset-md5.json", sr = 1024 * 1024, cr = ".openclaw/yoyo/tools", lr = /[<>:"/\\|?*]/, ur = r.join("skills", "yoyo-control", "SKILL.md"), dr = r.join("skills", "yoyo-control", "configs", "sub-skills.json"), fr = r.join("skills", "yoyo-control", "mcptools"), pr = "{{full-mcp-tool-list}}", mr = "<!-- yoyo-mcp-tools:start -->", hr = "<!-- yoyo-mcp-tools:end -->", gr = ".yoyo-device-toolset-copy-fallback";
|
|
2819
|
+
//#endregion
|
|
2820
|
+
//#region src/modules/device-toolset/archive.ts
|
|
2821
|
+
async function _r(e, t) {
|
|
2822
|
+
let n = 0, i = 0;
|
|
2823
|
+
for (let a of t) {
|
|
2824
|
+
let t = yr(a.name);
|
|
2795
2825
|
if (!t) {
|
|
2796
|
-
|
|
2826
|
+
i += 1;
|
|
2797
2827
|
continue;
|
|
2798
2828
|
}
|
|
2799
2829
|
await B({
|
|
2800
2830
|
rootDir: e,
|
|
2801
|
-
relativePath:
|
|
2802
|
-
data: JSON.stringify(
|
|
2831
|
+
relativePath: r.join(cr, t),
|
|
2832
|
+
data: JSON.stringify(a, null, 2),
|
|
2803
2833
|
encoding: "utf8",
|
|
2804
2834
|
mkdir: !0
|
|
2805
2835
|
}), n += 1;
|
|
2806
2836
|
}
|
|
2807
2837
|
return {
|
|
2808
|
-
archiveDir:
|
|
2838
|
+
archiveDir: vr(e),
|
|
2809
2839
|
writtenCount: n,
|
|
2810
|
-
skippedCount:
|
|
2840
|
+
skippedCount: i
|
|
2811
2841
|
};
|
|
2812
2842
|
}
|
|
2813
|
-
function
|
|
2843
|
+
function vr(e) {
|
|
2844
|
+
return r.join(e, cr);
|
|
2845
|
+
}
|
|
2846
|
+
function yr(e) {
|
|
2814
2847
|
let t = e.trim();
|
|
2815
|
-
if (!(!t ||
|
|
2848
|
+
if (!(!t || lr.test(t) || br(t))) return `${t}.json`;
|
|
2816
2849
|
}
|
|
2817
|
-
function
|
|
2850
|
+
function br(e) {
|
|
2818
2851
|
for (let t of e) if (t.codePointAt(0) < 32) return !0;
|
|
2819
2852
|
return !1;
|
|
2820
2853
|
}
|
|
2821
2854
|
//#endregion
|
|
2822
2855
|
//#region src/modules/device-toolset/copy-fallback.ts
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
await sr(t), await v.rm(t, {
|
|
2856
|
+
async function xr(e, t) {
|
|
2857
|
+
await Cr(t), await v.rm(t, {
|
|
2826
2858
|
recursive: !0,
|
|
2827
2859
|
force: !0
|
|
2828
|
-
}), await v.mkdir(t, { recursive: !0 }), await
|
|
2860
|
+
}), await v.mkdir(t, { recursive: !0 }), await wr(e, t), await v.writeFile(r.join(t, gr), "Managed copy fallback for DeviceToolSet MCP tools.\n", "utf8");
|
|
2829
2861
|
}
|
|
2830
|
-
async function
|
|
2862
|
+
async function Sr(e) {
|
|
2831
2863
|
try {
|
|
2832
|
-
return (await v.stat(
|
|
2864
|
+
return (await v.stat(r.join(e, gr))).isFile();
|
|
2833
2865
|
} catch {
|
|
2834
2866
|
return !1;
|
|
2835
2867
|
}
|
|
2836
2868
|
}
|
|
2837
|
-
async function
|
|
2869
|
+
async function Cr(e) {
|
|
2838
2870
|
let t;
|
|
2839
2871
|
try {
|
|
2840
2872
|
t = await v.lstat(e);
|
|
2841
2873
|
} catch (e) {
|
|
2842
|
-
if (
|
|
2874
|
+
if (Tr(e)) return;
|
|
2843
2875
|
throw e;
|
|
2844
2876
|
}
|
|
2845
2877
|
if (!t.isSymbolicLink()) {
|
|
2846
2878
|
if (!t.isDirectory()) throw Error(`Cannot replace unmanaged mcptools path: ${e}`);
|
|
2847
|
-
if (!((await v.readdir(e)).length === 0 || await
|
|
2879
|
+
if (!((await v.readdir(e)).length === 0 || await Sr(e))) throw Error(`Cannot replace unmanaged mcptools directory: ${e}`);
|
|
2848
2880
|
}
|
|
2849
2881
|
}
|
|
2850
|
-
async function
|
|
2882
|
+
async function wr(e, t) {
|
|
2851
2883
|
let n = await v.readdir(e, { withFileTypes: !0 });
|
|
2852
|
-
for (let
|
|
2853
|
-
let n =
|
|
2854
|
-
|
|
2884
|
+
for (let i of n) {
|
|
2885
|
+
let n = r.join(e, i.name), a = r.join(t, i.name);
|
|
2886
|
+
i.isDirectory() ? (await v.mkdir(a, { recursive: !0 }), await wr(n, a)) : i.isFile() && await v.copyFile(n, a);
|
|
2855
2887
|
}
|
|
2856
2888
|
}
|
|
2857
|
-
function
|
|
2889
|
+
function Tr(e) {
|
|
2858
2890
|
return !!(e && typeof e == "object" && "code" in e && e.code === "ENOENT");
|
|
2859
2891
|
}
|
|
2860
2892
|
//#endregion
|
|
2861
2893
|
//#region src/modules/device-toolset/link.ts
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2894
|
+
function Er(e) {
|
|
2895
|
+
return r.join(e, fr);
|
|
2896
|
+
}
|
|
2897
|
+
async function Dr(e, t, n = {}) {
|
|
2898
|
+
await v.mkdir(e, { recursive: !0 });
|
|
2899
|
+
let i = await v.realpath(e), a = await kr(t);
|
|
2900
|
+
if (a.exists) {
|
|
2901
|
+
if (a.isLink) {
|
|
2902
|
+
if (await Ar(t, i)) return { mode: "already-linked" };
|
|
2867
2903
|
throw Error(`Cannot replace unmanaged mcptools link: ${t}`);
|
|
2868
2904
|
}
|
|
2869
|
-
if (!await
|
|
2905
|
+
if (!await jr(t, a.isDirectory)) throw Error(`Cannot replace unmanaged mcptools directory: ${t}`);
|
|
2870
2906
|
await v.rm(t, {
|
|
2871
2907
|
recursive: !0,
|
|
2872
2908
|
force: !0
|
|
2873
2909
|
});
|
|
2874
2910
|
}
|
|
2875
|
-
await v.mkdir(
|
|
2911
|
+
await v.mkdir(r.dirname(t), { recursive: !0 });
|
|
2876
2912
|
try {
|
|
2877
|
-
return await (n.symlink ?? v.symlink)(
|
|
2913
|
+
return await (n.symlink ?? v.symlink)(i, t, process.platform === "win32" ? "junction" : "dir"), { mode: "linked" };
|
|
2878
2914
|
} catch {
|
|
2879
|
-
return await (n.copyFallback ??
|
|
2915
|
+
return await (n.copyFallback ?? xr)(i, t), { mode: "copy-fallback" };
|
|
2880
2916
|
}
|
|
2881
2917
|
}
|
|
2882
|
-
async function
|
|
2918
|
+
async function Or(e, t) {
|
|
2919
|
+
let n = await kr(t);
|
|
2920
|
+
if (!n.exists) return !1;
|
|
2921
|
+
if (n.isLink) {
|
|
2922
|
+
let n;
|
|
2923
|
+
try {
|
|
2924
|
+
n = await v.realpath(e);
|
|
2925
|
+
} catch {
|
|
2926
|
+
return !1;
|
|
2927
|
+
}
|
|
2928
|
+
return Ar(t, n);
|
|
2929
|
+
}
|
|
2930
|
+
return n.isDirectory ? Sr(t) : !1;
|
|
2931
|
+
}
|
|
2932
|
+
async function kr(e) {
|
|
2883
2933
|
try {
|
|
2884
2934
|
let t = await v.lstat(e);
|
|
2885
2935
|
return {
|
|
@@ -2888,7 +2938,7 @@ async function dr(e) {
|
|
|
2888
2938
|
isDirectory: t.isDirectory()
|
|
2889
2939
|
};
|
|
2890
2940
|
} catch (e) {
|
|
2891
|
-
if (
|
|
2941
|
+
if (Nr(e)) return {
|
|
2892
2942
|
exists: !1,
|
|
2893
2943
|
isLink: !1,
|
|
2894
2944
|
isDirectory: !1
|
|
@@ -2896,66 +2946,231 @@ async function dr(e) {
|
|
|
2896
2946
|
throw e;
|
|
2897
2947
|
}
|
|
2898
2948
|
}
|
|
2899
|
-
async function
|
|
2949
|
+
async function Ar(e, t) {
|
|
2900
2950
|
try {
|
|
2901
|
-
return
|
|
2951
|
+
return Mr(await v.realpath(e), t);
|
|
2902
2952
|
} catch {
|
|
2903
2953
|
return !1;
|
|
2904
2954
|
}
|
|
2905
2955
|
}
|
|
2906
|
-
async function
|
|
2907
|
-
return t ? (await v.readdir(e)).length === 0 || await
|
|
2956
|
+
async function jr(e, t) {
|
|
2957
|
+
return t ? (await v.readdir(e)).length === 0 || await Sr(e) : !1;
|
|
2908
2958
|
}
|
|
2909
|
-
function
|
|
2959
|
+
function Mr(e, t) {
|
|
2910
2960
|
return process.platform === "win32" ? e.toLowerCase() === t.toLowerCase() : e === t;
|
|
2911
2961
|
}
|
|
2912
|
-
function
|
|
2962
|
+
function Nr(e) {
|
|
2913
2963
|
return !!(e && typeof e == "object" && "code" in e && e.code === "ENOENT");
|
|
2914
2964
|
}
|
|
2915
2965
|
//#endregion
|
|
2966
|
+
//#region src/modules/device-toolset/persist.ts
|
|
2967
|
+
function Pr() {
|
|
2968
|
+
return {
|
|
2969
|
+
version: 1,
|
|
2970
|
+
tools: {}
|
|
2971
|
+
};
|
|
2972
|
+
}
|
|
2973
|
+
async function Fr(e) {
|
|
2974
|
+
try {
|
|
2975
|
+
let t = await vt({
|
|
2976
|
+
rootDir: e,
|
|
2977
|
+
relativePath: ir,
|
|
2978
|
+
maxBytes: ar
|
|
2979
|
+
}), n = JSON.parse(t.buffer.toString("utf8"));
|
|
2980
|
+
return {
|
|
2981
|
+
version: 1,
|
|
2982
|
+
tools: n && typeof n.tools == "object" && n.tools ? n.tools : {}
|
|
2983
|
+
};
|
|
2984
|
+
} catch (e) {
|
|
2985
|
+
if (e instanceof I && e.code === "not-found") return Pr();
|
|
2986
|
+
throw e;
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
async function Ir(e, t, n) {
|
|
2990
|
+
let r = {
|
|
2991
|
+
version: 1,
|
|
2992
|
+
tools: Lr((await Fr(e)).tools, t, n)
|
|
2993
|
+
};
|
|
2994
|
+
return await B({
|
|
2995
|
+
rootDir: e,
|
|
2996
|
+
relativePath: ir,
|
|
2997
|
+
data: JSON.stringify(r, null, 2),
|
|
2998
|
+
encoding: "utf8",
|
|
2999
|
+
mkdir: !0
|
|
3000
|
+
}), {
|
|
3001
|
+
changed: !0,
|
|
3002
|
+
nodeCount: Br(r.tools),
|
|
3003
|
+
toolCount: Object.keys(r.tools).length,
|
|
3004
|
+
cache: r
|
|
3005
|
+
};
|
|
3006
|
+
}
|
|
3007
|
+
function Lr(e, t, n) {
|
|
3008
|
+
let r = Rr(e, t);
|
|
3009
|
+
for (let e of n) {
|
|
3010
|
+
let n = r[e.id];
|
|
3011
|
+
r[e.id] = {
|
|
3012
|
+
id: e.id,
|
|
3013
|
+
name: e.name,
|
|
3014
|
+
description: e.description,
|
|
3015
|
+
supportedNodeIds: zr(n?.supportedNodeIds ?? [], t)
|
|
3016
|
+
};
|
|
3017
|
+
}
|
|
3018
|
+
return r;
|
|
3019
|
+
}
|
|
3020
|
+
function Rr(e, t) {
|
|
3021
|
+
let n = {};
|
|
3022
|
+
for (let [r, i] of Object.entries(e)) {
|
|
3023
|
+
if (!i.supportedNodeIds.includes(t)) {
|
|
3024
|
+
n[r] = i;
|
|
3025
|
+
continue;
|
|
3026
|
+
}
|
|
3027
|
+
let e = i.supportedNodeIds.filter((e) => e !== t);
|
|
3028
|
+
e.length > 0 && (n[r] = {
|
|
3029
|
+
...i,
|
|
3030
|
+
supportedNodeIds: e
|
|
3031
|
+
});
|
|
3032
|
+
}
|
|
3033
|
+
return n;
|
|
3034
|
+
}
|
|
3035
|
+
function zr(e, t) {
|
|
3036
|
+
return [...new Set([...e, t])];
|
|
3037
|
+
}
|
|
3038
|
+
function Br(e) {
|
|
3039
|
+
let t = /* @__PURE__ */ new Set();
|
|
3040
|
+
for (let n of Object.values(e)) for (let e of n.supportedNodeIds) t.add(e);
|
|
3041
|
+
return t.size;
|
|
3042
|
+
}
|
|
3043
|
+
//#endregion
|
|
3044
|
+
//#region src/modules/device-toolset/skill-inject.ts
|
|
3045
|
+
async function Vr(e, t) {
|
|
3046
|
+
let n = r.join(e, ur), i = await v.readFile(n, "utf8"), a = Ur(t, await Hr(e)), o = Gr(i, Wr(a));
|
|
3047
|
+
return o !== i && await v.writeFile(n, o, "utf8"), {
|
|
3048
|
+
skillPath: n,
|
|
3049
|
+
rowCount: Object.keys(a).length
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
async function Hr(e) {
|
|
3053
|
+
let t = r.join(e, dr), n;
|
|
3054
|
+
try {
|
|
3055
|
+
n = await v.readFile(t, "utf8");
|
|
3056
|
+
} catch (e) {
|
|
3057
|
+
if (Jr(e) && e.code === "ENOENT") return /* @__PURE__ */ new Set();
|
|
3058
|
+
throw e;
|
|
3059
|
+
}
|
|
3060
|
+
let i = JSON.parse(n);
|
|
3061
|
+
if (!Array.isArray(i) || i.some((e) => typeof e != "string")) throw Error("sub-skills config must be a JSON array of tool names");
|
|
3062
|
+
return new Set(i.map((e) => e.trim()).filter(Boolean));
|
|
3063
|
+
}
|
|
3064
|
+
function Ur(e, t) {
|
|
3065
|
+
return t.size === 0 ? e : Object.fromEntries(Object.entries(e).filter(([e, n]) => !t.has(e) && !t.has(n.name)));
|
|
3066
|
+
}
|
|
3067
|
+
function Wr(e) {
|
|
3068
|
+
return [
|
|
3069
|
+
mr,
|
|
3070
|
+
...Object.values(e).toSorted((e, t) => e.name.localeCompare(t.name)).map((e) => `| ${Kr(e.name)} | ${Kr(e.description)} | ${Kr(e.supportedNodeIds.join(", "))} |`),
|
|
3071
|
+
hr
|
|
3072
|
+
].join("\n");
|
|
3073
|
+
}
|
|
3074
|
+
function Gr(e, t) {
|
|
3075
|
+
let n = RegExp(`${qr(mr)}[\\s\\S]*?${qr(hr)}`);
|
|
3076
|
+
if (n.test(e)) return e.replace(n, t);
|
|
3077
|
+
if (e.includes("{{full-mcp-tool-list}}")) return e.replace(pr, t);
|
|
3078
|
+
throw Error("Unable to find MCP tools placeholder or generated block in yoyo-control skill");
|
|
3079
|
+
}
|
|
3080
|
+
function Kr(e) {
|
|
3081
|
+
return e.replaceAll("|", "\\|").replace(/\r?\n/g, " ");
|
|
3082
|
+
}
|
|
3083
|
+
function qr(e) {
|
|
3084
|
+
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3085
|
+
}
|
|
3086
|
+
function Jr(e) {
|
|
3087
|
+
return e instanceof Error && "code" in e;
|
|
3088
|
+
}
|
|
3089
|
+
//#endregion
|
|
3090
|
+
//#region src/modules/device-toolset/artifacts.ts
|
|
3091
|
+
async function Yr(e = H(), t = wt()) {
|
|
3092
|
+
if (!e) throw Error("Unable to resolve home directory for DeviceToolSet artifacts");
|
|
3093
|
+
let n = vr(e), i = Er(t), a = r.join(t, ur);
|
|
3094
|
+
k().debug?.(`[yoyoclaw-device-toolset] checking artifacts, skillPath: ${a}, mcptoolsTarget: ${i}, archiveDir: ${n}`);
|
|
3095
|
+
let o = await Xr(t, n, i);
|
|
3096
|
+
if (o.length === 0) return k().debug?.("[yoyoclaw-device-toolset] artifacts are ready, skip restore"), {
|
|
3097
|
+
restored: !1,
|
|
3098
|
+
reasons: o,
|
|
3099
|
+
toolCount: 0
|
|
3100
|
+
};
|
|
3101
|
+
let s = (await Fr(e)).tools, c = Object.keys(s).length;
|
|
3102
|
+
if (k().info(`[yoyoclaw-device-toolset] artifact restore triggered, reasons: ${o.join(",")}, cachedTools: ${c}`), c === 0) return k().debug?.(`[yoyoclaw-device-toolset] artifacts need restore but cache is empty: ${o.join(",")}`), {
|
|
3103
|
+
restored: !1,
|
|
3104
|
+
reasons: o,
|
|
3105
|
+
toolCount: c
|
|
3106
|
+
};
|
|
3107
|
+
if (o.includes("skill")) {
|
|
3108
|
+
let e = await Vr(t, s);
|
|
3109
|
+
k().info(`[yoyoclaw-device-toolset] skill artifact restored, rows: ${e.rowCount}`);
|
|
3110
|
+
}
|
|
3111
|
+
if (o.includes("mcptools")) {
|
|
3112
|
+
let e = await Dr(n, i);
|
|
3113
|
+
k().info(`[yoyoclaw-device-toolset] mcptools artifact restored, mode: ${e.mode}`);
|
|
3114
|
+
}
|
|
3115
|
+
return {
|
|
3116
|
+
restored: !0,
|
|
3117
|
+
reasons: o,
|
|
3118
|
+
toolCount: c
|
|
3119
|
+
};
|
|
3120
|
+
}
|
|
3121
|
+
async function Xr(e, t, n) {
|
|
3122
|
+
let r = [];
|
|
3123
|
+
return await Zr(e) && r.push("skill"), await Or(t, n) || (k().info(`[yoyoclaw-device-toolset] mcptools mapping is missing or stale, target: ${n}, archiveDir: ${t}`), r.push("mcptools")), r;
|
|
3124
|
+
}
|
|
3125
|
+
async function Zr(e) {
|
|
3126
|
+
let t = r.join(e, ur), n = await v.readFile(t, "utf8");
|
|
3127
|
+
if (n.includes("{{full-mcp-tool-list}}")) return k().info(`[yoyoclaw-device-toolset] skill mcp tools block is not generated, placeholder found: ${t}`), !0;
|
|
3128
|
+
let i = n.indexOf(mr), a = n.indexOf(hr), o = i === -1 || a === -1 || a < i;
|
|
3129
|
+
return o && k().info(`[yoyoclaw-device-toolset] skill mcp tools block markers missing or invalid: ${t}`), o;
|
|
3130
|
+
}
|
|
3131
|
+
//#endregion
|
|
2916
3132
|
//#region src/modules/device-toolset/md5-index.ts
|
|
2917
|
-
|
|
2918
|
-
function vr() {
|
|
3133
|
+
function Qr() {
|
|
2919
3134
|
return {
|
|
2920
3135
|
version: 1,
|
|
2921
3136
|
nodes: {}
|
|
2922
3137
|
};
|
|
2923
3138
|
}
|
|
2924
|
-
function
|
|
2925
|
-
return JSON.stringify(
|
|
3139
|
+
function $r(e) {
|
|
3140
|
+
return JSON.stringify(ii(e));
|
|
2926
3141
|
}
|
|
2927
|
-
function
|
|
2928
|
-
return
|
|
3142
|
+
function ei(e) {
|
|
3143
|
+
return e.length === 0 ? "" : g("md5").update($r(e)).digest("hex");
|
|
2929
3144
|
}
|
|
2930
|
-
async function
|
|
3145
|
+
async function ti(e) {
|
|
2931
3146
|
try {
|
|
2932
|
-
let t = await
|
|
3147
|
+
let t = await vt({
|
|
2933
3148
|
rootDir: e,
|
|
2934
|
-
relativePath:
|
|
2935
|
-
maxBytes:
|
|
3149
|
+
relativePath: or,
|
|
3150
|
+
maxBytes: sr
|
|
2936
3151
|
}), n = JSON.parse(t.buffer.toString("utf8"));
|
|
2937
3152
|
return {
|
|
2938
3153
|
version: 1,
|
|
2939
3154
|
nodes: n && typeof n.nodes == "object" && n.nodes ? n.nodes : {}
|
|
2940
3155
|
};
|
|
2941
3156
|
} catch (e) {
|
|
2942
|
-
if (e instanceof I && e.code === "not-found") return
|
|
3157
|
+
if (e instanceof I && e.code === "not-found") return Qr();
|
|
2943
3158
|
throw e;
|
|
2944
3159
|
}
|
|
2945
3160
|
}
|
|
2946
|
-
async function
|
|
2947
|
-
let r = (await
|
|
3161
|
+
async function ni(e, t, n) {
|
|
3162
|
+
let r = (await ti(e)).nodes[t]?.md5;
|
|
2948
3163
|
return {
|
|
2949
3164
|
changed: r !== n,
|
|
2950
3165
|
md5: n,
|
|
2951
3166
|
previousMd5: r
|
|
2952
3167
|
};
|
|
2953
3168
|
}
|
|
2954
|
-
async function
|
|
3169
|
+
async function ri(e, t, n, r = Date.now()) {
|
|
2955
3170
|
let i = {
|
|
2956
3171
|
version: 1,
|
|
2957
3172
|
nodes: {
|
|
2958
|
-
...(await
|
|
3173
|
+
...(await ti(e)).nodes,
|
|
2959
3174
|
[t]: {
|
|
2960
3175
|
md5: n,
|
|
2961
3176
|
updatedAtMs: r
|
|
@@ -2964,19 +3179,19 @@ async function Cr(e, t, n, r = Date.now()) {
|
|
|
2964
3179
|
};
|
|
2965
3180
|
return await B({
|
|
2966
3181
|
rootDir: e,
|
|
2967
|
-
relativePath:
|
|
3182
|
+
relativePath: or,
|
|
2968
3183
|
data: JSON.stringify(i, null, 2),
|
|
2969
3184
|
encoding: "utf8",
|
|
2970
3185
|
mkdir: !0
|
|
2971
3186
|
}), i;
|
|
2972
3187
|
}
|
|
2973
|
-
function
|
|
2974
|
-
if (Array.isArray(e)) return e.map(
|
|
3188
|
+
function ii(e) {
|
|
3189
|
+
if (Array.isArray(e)) return e.map(ii);
|
|
2975
3190
|
if (!e || typeof e != "object") return e;
|
|
2976
3191
|
let t = {};
|
|
2977
3192
|
for (let n of Object.keys(e).toSorted()) {
|
|
2978
3193
|
let r = e[n];
|
|
2979
|
-
r !== void 0 && (t[n] =
|
|
3194
|
+
r !== void 0 && (t[n] = ii(r));
|
|
2980
3195
|
}
|
|
2981
3196
|
return t;
|
|
2982
3197
|
}
|
|
@@ -2985,26 +3200,26 @@ function wr(e) {
|
|
|
2985
3200
|
function Y(e) {
|
|
2986
3201
|
return typeof e == "string" && e.trim() ? e : void 0;
|
|
2987
3202
|
}
|
|
2988
|
-
function
|
|
3203
|
+
function ai(e) {
|
|
2989
3204
|
if (!e || typeof e != "object") throw Error("DeviceToolSet payload must be an object");
|
|
2990
3205
|
let t = e;
|
|
2991
3206
|
if (!Y(t.nodeId)) throw Error("DeviceToolSet payload missing nodeId");
|
|
2992
3207
|
if (!Array.isArray(t.toolSet)) throw Error("DeviceToolSet payload toolSet must be an array");
|
|
2993
|
-
return e;
|
|
3208
|
+
return k().debug?.(`DeviceToolSet payload received: ${JSON.stringify(t, null, 2)}`), e;
|
|
2994
3209
|
}
|
|
2995
|
-
function
|
|
2996
|
-
let t = e.nodeId, n =
|
|
3210
|
+
function oi(e) {
|
|
3211
|
+
let t = e.nodeId, n = /* @__PURE__ */ new Map(), r = 0;
|
|
2997
3212
|
for (let t of e.toolSet) {
|
|
2998
|
-
let e =
|
|
2999
|
-
e ? n.
|
|
3213
|
+
let e = si(t);
|
|
3214
|
+
e ? n.set(e.name, e) : r += 1;
|
|
3000
3215
|
}
|
|
3001
3216
|
return {
|
|
3002
3217
|
nodeId: t,
|
|
3003
|
-
tools: n,
|
|
3218
|
+
tools: Array.from(n.values()),
|
|
3004
3219
|
skippedCount: r
|
|
3005
3220
|
};
|
|
3006
3221
|
}
|
|
3007
|
-
function
|
|
3222
|
+
function si(e) {
|
|
3008
3223
|
let t = Y(e.tool?.id), n = Y(e.tool?.function?.name), r = Y(e.tool?.function?.description);
|
|
3009
3224
|
if (!t || e.tool?.type !== "function" || !n || !r) return;
|
|
3010
3225
|
let i = {
|
|
@@ -3018,120 +3233,30 @@ function Dr(e) {
|
|
|
3018
3233
|
return a && (i.pkgName = a), i;
|
|
3019
3234
|
}
|
|
3020
3235
|
//#endregion
|
|
3021
|
-
//#region src/modules/device-toolset/persist.ts
|
|
3022
|
-
var Or = ".openclaw/yoyo/device-toolsets.json", kr = 10 * 1024 * 1024;
|
|
3023
|
-
function Ar() {
|
|
3024
|
-
return {
|
|
3025
|
-
version: 1,
|
|
3026
|
-
tools: {}
|
|
3027
|
-
};
|
|
3028
|
-
}
|
|
3029
|
-
async function jr(e) {
|
|
3030
|
-
try {
|
|
3031
|
-
let t = await bt({
|
|
3032
|
-
rootDir: e,
|
|
3033
|
-
relativePath: Or,
|
|
3034
|
-
maxBytes: kr
|
|
3035
|
-
}), n = JSON.parse(t.buffer.toString("utf8"));
|
|
3036
|
-
return {
|
|
3037
|
-
version: 1,
|
|
3038
|
-
tools: n && typeof n.tools == "object" && n.tools ? n.tools : {}
|
|
3039
|
-
};
|
|
3040
|
-
} catch (e) {
|
|
3041
|
-
if (e instanceof I && e.code === "not-found") return Ar();
|
|
3042
|
-
throw e;
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3045
|
-
async function Mr(e, t, n) {
|
|
3046
|
-
let r = {
|
|
3047
|
-
version: 1,
|
|
3048
|
-
tools: Nr((await jr(e)).tools, t, n)
|
|
3049
|
-
};
|
|
3050
|
-
return await B({
|
|
3051
|
-
rootDir: e,
|
|
3052
|
-
relativePath: Or,
|
|
3053
|
-
data: JSON.stringify(r, null, 2),
|
|
3054
|
-
encoding: "utf8",
|
|
3055
|
-
mkdir: !0
|
|
3056
|
-
}), {
|
|
3057
|
-
changed: !0,
|
|
3058
|
-
nodeCount: Fr(r.tools),
|
|
3059
|
-
toolCount: Object.keys(r.tools).length,
|
|
3060
|
-
cache: r
|
|
3061
|
-
};
|
|
3062
|
-
}
|
|
3063
|
-
function Nr(e, t, n) {
|
|
3064
|
-
let r = { ...e };
|
|
3065
|
-
for (let e of n) {
|
|
3066
|
-
let n = r[e.id];
|
|
3067
|
-
r[e.id] = {
|
|
3068
|
-
id: e.id,
|
|
3069
|
-
name: e.name,
|
|
3070
|
-
description: e.description,
|
|
3071
|
-
supportedNodeIds: Pr(n?.supportedNodeIds ?? [], t)
|
|
3072
|
-
};
|
|
3073
|
-
}
|
|
3074
|
-
return r;
|
|
3075
|
-
}
|
|
3076
|
-
function Pr(e, t) {
|
|
3077
|
-
return [...new Set([...e, t])];
|
|
3078
|
-
}
|
|
3079
|
-
function Fr(e) {
|
|
3080
|
-
let t = /* @__PURE__ */ new Set();
|
|
3081
|
-
for (let n of Object.values(e)) for (let e of n.supportedNodeIds) t.add(e);
|
|
3082
|
-
return t.size;
|
|
3083
|
-
}
|
|
3084
|
-
//#endregion
|
|
3085
|
-
//#region src/modules/device-toolset/skill-inject.ts
|
|
3086
|
-
var Ir = u.join("skills", "yoyo-control", "SKILL.md"), Lr = "{{full-mcp-tool-list}}", Rr = "<!-- yoyo-mcp-tools:start -->", zr = "<!-- yoyo-mcp-tools:end -->";
|
|
3087
|
-
async function Br(e, t) {
|
|
3088
|
-
let n = u.join(e, Ir), r = await v.readFile(n, "utf8"), i = Hr(r, Vr(t));
|
|
3089
|
-
return i !== r && await v.writeFile(n, i, "utf8"), {
|
|
3090
|
-
skillPath: n,
|
|
3091
|
-
rowCount: Object.keys(t).length
|
|
3092
|
-
};
|
|
3093
|
-
}
|
|
3094
|
-
function Vr(e) {
|
|
3095
|
-
return [
|
|
3096
|
-
Rr,
|
|
3097
|
-
...Object.values(e).toSorted((e, t) => e.name.localeCompare(t.name)).map((e) => `| ${Ur(e.name)} | ${Ur(e.description)} | ${Ur(e.supportedNodeIds.join(", "))} |`),
|
|
3098
|
-
zr
|
|
3099
|
-
].join("\n");
|
|
3100
|
-
}
|
|
3101
|
-
function Hr(e, t) {
|
|
3102
|
-
let n = RegExp(`${Wr(Rr)}[\\s\\S]*?${Wr(zr)}`);
|
|
3103
|
-
if (n.test(e)) return e.replace(n, t);
|
|
3104
|
-
if (e.includes(Lr)) return e.replace(Lr, t);
|
|
3105
|
-
throw Error("Unable to find MCP tools placeholder or generated block in yoyo-control skill");
|
|
3106
|
-
}
|
|
3107
|
-
function Ur(e) {
|
|
3108
|
-
return e.replaceAll("|", "\\|").replace(/\r?\n/g, " ");
|
|
3109
|
-
}
|
|
3110
|
-
function Wr(e) {
|
|
3111
|
-
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3112
|
-
}
|
|
3113
|
-
//#endregion
|
|
3114
3236
|
//#region src/modules/device-toolset/processor.ts
|
|
3115
|
-
var
|
|
3116
|
-
async function
|
|
3117
|
-
let t =
|
|
3237
|
+
var ci = wt();
|
|
3238
|
+
async function li(e) {
|
|
3239
|
+
let t = ai(e), n = H();
|
|
3118
3240
|
if (!n) throw Error("Unable to resolve home directory for DeviceToolSet persistence");
|
|
3119
|
-
let r =
|
|
3120
|
-
|
|
3121
|
-
let i =
|
|
3122
|
-
if (
|
|
3123
|
-
|
|
3124
|
-
nodeId: r.nodeId,
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3241
|
+
let r = oi(t);
|
|
3242
|
+
k().info(`[yoyoclaw-device-toolset] process start, nodeId: ${r.nodeId}, tools: ${r.tools.length}, skipped: ${r.skippedCount}`);
|
|
3243
|
+
let i = ei(r.tools);
|
|
3244
|
+
if (k().debug?.(`[yoyoclaw-device-toolset] computed md5, nodeId: ${r.nodeId}, md5: ${i}`), !(await ni(n, r.nodeId, i)).changed) {
|
|
3245
|
+
let e = await Yr(n, ci);
|
|
3246
|
+
return k().info(`[yoyoclaw-device-toolset] unchanged, skip refresh, nodeId: ${r.nodeId}, artifactsRestored: ${e.restored}`), {
|
|
3247
|
+
changed: !1,
|
|
3248
|
+
nodeId: r.nodeId,
|
|
3249
|
+
skippedCount: r.skippedCount
|
|
3250
|
+
};
|
|
3251
|
+
}
|
|
3252
|
+
let a = await Ir(n, r.nodeId, r.tools);
|
|
3253
|
+
k().info(`[yoyoclaw-device-toolset] cache merged, nodeId: ${r.nodeId}, supportedNodes: ${a.nodeCount}, tools: ${a.toolCount}`);
|
|
3254
|
+
let o = a.cache.tools, s = await _r(n, r.tools);
|
|
3255
|
+
k().info(`[yoyoclaw-device-toolset] archive refreshed, nodeId: ${r.nodeId}, written: ${s.writtenCount}, skipped: ${s.skippedCount}`);
|
|
3256
|
+
let c = await Vr(ci, o);
|
|
3257
|
+
k().info(`[yoyoclaw-device-toolset] skill refreshed, nodeId: ${r.nodeId}, rows: ${c.rowCount}`);
|
|
3258
|
+
let l = await Dr(s.archiveDir, Er(ci));
|
|
3259
|
+
return k().info(`[yoyoclaw-device-toolset] mapping ready, nodeId: ${r.nodeId}, mode: ${l.mode}`), await ri(n, r.nodeId, i, Date.now()), k().info(`[yoyoclaw-device-toolset] process complete, nodeId: ${r.nodeId}`), {
|
|
3135
3260
|
changed: !0,
|
|
3136
3261
|
nodeId: r.nodeId,
|
|
3137
3262
|
nodeCount: a.nodeCount,
|
|
@@ -3141,7 +3266,7 @@ async function Kr(e) {
|
|
|
3141
3266
|
}
|
|
3142
3267
|
//#endregion
|
|
3143
3268
|
//#region src/cloud-channel/message-handler.ts
|
|
3144
|
-
var
|
|
3269
|
+
var ui = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", di = class {
|
|
3145
3270
|
sessionManager;
|
|
3146
3271
|
adminClientManager;
|
|
3147
3272
|
config;
|
|
@@ -3150,7 +3275,8 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3150
3275
|
contextUpdateHandlers = {
|
|
3151
3276
|
style: this.updateStyleContext.bind(this),
|
|
3152
3277
|
"model.primary": this.updatePrimaryModel.bind(this),
|
|
3153
|
-
DeviceToolSet: this.updateDeviceToolSetContext.bind(this)
|
|
3278
|
+
DeviceToolSet: this.updateDeviceToolSetContext.bind(this),
|
|
3279
|
+
UniversalToolSet: this.updateDeviceToolSetContext.bind(this)
|
|
3154
3280
|
};
|
|
3155
3281
|
contextFetchHandlers = {
|
|
3156
3282
|
skills: this.fetchSkillsStatus.bind(this),
|
|
@@ -3180,7 +3306,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3180
3306
|
let { sourceDeviceId: t, sourceDeviceInfo: n, targetDeviceId: r, port: i, sessionInfo: a, traceInfo: o } = e;
|
|
3181
3307
|
if (!t || !r || !i || !n?.deviceId) return;
|
|
3182
3308
|
let s = n.deviceId, c = a?.nodeConnectTimestamp;
|
|
3183
|
-
c ? (this.sessionManager.closePreviousNodeGatewayClients(s, c), this.flushPendingMessage(s), this.initializedDeviceIds.delete(s)) :
|
|
3309
|
+
c ? (this.sessionManager.closePreviousNodeGatewayClients(s, c), this.flushPendingMessage(s), this.initializedDeviceIds.delete(s)) : k().warn(`${X} pair message missing timestamp for device: ${t}`), k().info(`${X} received pair message, creating gateway client for device: ${t}, hardware device: ${s}, timestamp: ${c}`);
|
|
3184
3310
|
let l = {
|
|
3185
3311
|
sessionId: t,
|
|
3186
3312
|
timestamp: c || 0,
|
|
@@ -3191,7 +3317,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3191
3317
|
}
|
|
3192
3318
|
};
|
|
3193
3319
|
this.sessionManager.addSession(s, l), this.config.onStatusEvent?.({
|
|
3194
|
-
type:
|
|
3320
|
+
type: K.DEVICE_PAIRING,
|
|
3195
3321
|
timestamp: Date.now(),
|
|
3196
3322
|
data: {
|
|
3197
3323
|
sessionId: t,
|
|
@@ -3212,12 +3338,12 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3212
3338
|
handleUnPairMessage(e) {
|
|
3213
3339
|
let { sourceDeviceId: t } = e;
|
|
3214
3340
|
if (!t) {
|
|
3215
|
-
|
|
3341
|
+
k().warn(`${X} unpair message missing sourceDeviceId`);
|
|
3216
3342
|
return;
|
|
3217
3343
|
}
|
|
3218
3344
|
let n = this.sessionManager.getHardwareDeviceId(t);
|
|
3219
|
-
|
|
3220
|
-
type:
|
|
3345
|
+
k().info(`${X} received unpair message, session: ${t}, hardware device: ${n}`), this.config.onStatusEvent?.({
|
|
3346
|
+
type: K.DEVICE_UNPAIRING,
|
|
3221
3347
|
timestamp: Date.now(),
|
|
3222
3348
|
data: {
|
|
3223
3349
|
sessionId: t,
|
|
@@ -3230,27 +3356,27 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3230
3356
|
handleUserMessage(e) {
|
|
3231
3357
|
let { sourceDeviceId: t } = e || {};
|
|
3232
3358
|
if (!t) {
|
|
3233
|
-
|
|
3359
|
+
k().warn(`${X} user message missing sourceDeviceId`);
|
|
3234
3360
|
return;
|
|
3235
3361
|
}
|
|
3236
3362
|
let n = this.sessionManager.getHardwareDeviceId(t);
|
|
3237
3363
|
if (!n) {
|
|
3238
|
-
|
|
3364
|
+
k().warn(`${X} user message missing hardwareDeviceId, session: ${t}`);
|
|
3239
3365
|
return;
|
|
3240
3366
|
}
|
|
3241
3367
|
try {
|
|
3242
3368
|
let r = this.sessionManager.getNodeGatewayClient(t);
|
|
3243
3369
|
if (!r) {
|
|
3244
|
-
|
|
3370
|
+
k().warn(`${X} no node gateway client found for source device: ${n}, session: ${t}`);
|
|
3245
3371
|
return;
|
|
3246
3372
|
}
|
|
3247
3373
|
e.data && (this.initializedDeviceIds.has(n) || this.processMessageBuffer(t, n, e.data, r)) && this.forwardToNodeGateway(t, n, r, e.data);
|
|
3248
3374
|
} catch (e) {
|
|
3249
|
-
|
|
3375
|
+
k().error(`${X} failed to send gateway message to device: ${n}, session: ${t}, ${String(e)}`);
|
|
3250
3376
|
}
|
|
3251
3377
|
}
|
|
3252
3378
|
forwardToNodeGateway(e, t, n, r) {
|
|
3253
|
-
|
|
3379
|
+
k().info(`${X} forwarding user message to node gateway from ${t}, session: ${e}`), n.send(r);
|
|
3254
3380
|
}
|
|
3255
3381
|
processMessageBuffer(e, t, n, r) {
|
|
3256
3382
|
let i = this.pendingFirstMessages.get(t);
|
|
@@ -3278,22 +3404,22 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3278
3404
|
handleNodeGatewayMessage = async (e, t, n) => {
|
|
3279
3405
|
let r = this.sessionManager.getHardwareDeviceId(e), i = this.sessionManager.getSession(e), a = i?.sourceInfo.sourceDeviceInfo?.deviceId;
|
|
3280
3406
|
if (!r || !i) {
|
|
3281
|
-
|
|
3407
|
+
k().warn(`${X} gateway source offline, session: ${e}`);
|
|
3282
3408
|
return;
|
|
3283
3409
|
}
|
|
3284
|
-
|
|
3410
|
+
k().info(`${X} received gateway message from ${a}`);
|
|
3285
3411
|
try {
|
|
3286
3412
|
let e = i.sourceInfo.sourceDeviceId, r;
|
|
3287
3413
|
try {
|
|
3288
3414
|
r = JSON.parse(n);
|
|
3289
3415
|
} catch {
|
|
3290
|
-
|
|
3416
|
+
k().warn(`${X} gateway message is not valid JSON`);
|
|
3291
3417
|
return;
|
|
3292
3418
|
}
|
|
3293
3419
|
if (!r.ok && r.error?.code === "NOT_PAIRED") {
|
|
3294
3420
|
let n = r.error?.details?.requestId;
|
|
3295
3421
|
if (!n) {
|
|
3296
|
-
|
|
3422
|
+
k().warn(`${X} NOT_PAIRED without requestId, ignoring...`);
|
|
3297
3423
|
return;
|
|
3298
3424
|
}
|
|
3299
3425
|
await this.handleAutoPair(n);
|
|
@@ -3301,30 +3427,30 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3301
3427
|
id: r.id,
|
|
3302
3428
|
type: "reconnect-required"
|
|
3303
3429
|
};
|
|
3304
|
-
this.sendMessage("deviceControl", e, t, "", void 0, i),
|
|
3430
|
+
this.sendMessage("deviceControl", e, t, "", void 0, i), k().info(`${X} auto pair is completed, requestId: ${n}`);
|
|
3305
3431
|
return;
|
|
3306
3432
|
}
|
|
3307
|
-
|
|
3433
|
+
k().debug?.(`${X} trans gateway msg to cloud, session: ${e}, data: ${n.slice(0, 1e3)}`), this.sendMessage("userMessage", e, t, n) || (k().error(`${X} failed to send message, cloud socket closed, session ${e}, device ${a}`), this.sessionManager.closeNodeGatewayClient(e));
|
|
3308
3434
|
} catch (e) {
|
|
3309
|
-
|
|
3435
|
+
k().error(`${X} failed to handle gateway message: ${String(e)}`);
|
|
3310
3436
|
}
|
|
3311
3437
|
};
|
|
3312
3438
|
async handleAutoPair(e) {
|
|
3313
3439
|
let t = this.adminClientManager.getClient();
|
|
3314
|
-
if (!t) return
|
|
3440
|
+
if (!t) return k().warn(`${X} admin client not available for auto pair`), !1;
|
|
3315
3441
|
try {
|
|
3316
|
-
|
|
3442
|
+
k().info(`${X} auto pair approve, requestId: ${e}`), await t.devicePairApprove(e);
|
|
3317
3443
|
} catch (t) {
|
|
3318
|
-
|
|
3444
|
+
k().error(`${X} auto pair approve failed, requestId: ${e}, error: ${String(t)}, ignore...`);
|
|
3319
3445
|
}
|
|
3320
3446
|
}
|
|
3321
3447
|
async handleContextRequest(e) {
|
|
3322
3448
|
let { sourceDeviceId: t, traceInfo: n } = e, r = e.msgType, i = r === "updateContexts";
|
|
3323
3449
|
if (!t) {
|
|
3324
|
-
|
|
3450
|
+
k().warn(`${X} context request missing sourceDeviceId`);
|
|
3325
3451
|
return;
|
|
3326
3452
|
}
|
|
3327
|
-
|
|
3453
|
+
k().info(`${X} handling ${r} from ${t} traceInfo: ${JSON.stringify(n)}`);
|
|
3328
3454
|
let a = e.contexts?.[0], o = this.validateContext(a);
|
|
3329
3455
|
if (!o.valid) {
|
|
3330
3456
|
this.replyContextError(r, t, n, a, o.error);
|
|
@@ -3340,13 +3466,13 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3340
3466
|
if (this.contextHandlerRequiresAdminClient(i, c) && !await this.ensureAdminClientReady(r, t, n, s)) return;
|
|
3341
3467
|
let o = this.adminClientManager.getClient(), l = i ? await e(o ?? void 0, s.payload, s) : await e(o);
|
|
3342
3468
|
if (l.noReply) {
|
|
3343
|
-
|
|
3469
|
+
k().info(`${X} ${i ? "update" : "fetch"} context '${c}' processed (no reply)`);
|
|
3344
3470
|
return;
|
|
3345
3471
|
}
|
|
3346
|
-
l.ok ? (
|
|
3472
|
+
l.ok ? (k().info(`${X} ${i ? "update" : "fetch"} context successfully`), this.sendContextResponse(r, t, n, a, {
|
|
3347
3473
|
ok: !0,
|
|
3348
3474
|
...l.data
|
|
3349
|
-
})) : (
|
|
3475
|
+
})) : (k().error(`${X} failed to ${i ? "update" : "fetch"} context: ${l.error}`), this.sendContextResponse(r, t, n, a, {
|
|
3350
3476
|
ok: !1,
|
|
3351
3477
|
error: l.error,
|
|
3352
3478
|
...l?.data,
|
|
@@ -3354,7 +3480,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3354
3480
|
}));
|
|
3355
3481
|
} catch (e) {
|
|
3356
3482
|
let o = e instanceof Error ? e.message : String(e);
|
|
3357
|
-
|
|
3483
|
+
k().error(`${X} error ${i ? "updating" : "fetching"} context '${c}': ${o}`), this.replyContextError(r, t, n, a, o);
|
|
3358
3484
|
}
|
|
3359
3485
|
}
|
|
3360
3486
|
sendMessage(e, t, n, r, i, a) {
|
|
@@ -3391,7 +3517,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3391
3517
|
}];
|
|
3392
3518
|
}
|
|
3393
3519
|
replyContextError(e, t, n, r, i) {
|
|
3394
|
-
|
|
3520
|
+
k().error(`${X} ${i}`), this.sendContextResponse(e, t, n, r, {
|
|
3395
3521
|
ok: !1,
|
|
3396
3522
|
error: i
|
|
3397
3523
|
});
|
|
@@ -3417,7 +3543,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3417
3543
|
ok: !1,
|
|
3418
3544
|
error: "Missing content in context payload"
|
|
3419
3545
|
};
|
|
3420
|
-
let r =
|
|
3546
|
+
let r = ui.style, i = await e.setAgentFile(r, n);
|
|
3421
3547
|
return i.ok ? {
|
|
3422
3548
|
ok: !0,
|
|
3423
3549
|
data: { name: "style" }
|
|
@@ -3437,21 +3563,21 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3437
3563
|
error: "Missing provider or id in context payload"
|
|
3438
3564
|
};
|
|
3439
3565
|
try {
|
|
3440
|
-
return (await e.switchPrimaryModel(n, r)).ok ? (
|
|
3566
|
+
return (await e.switchPrimaryModel(n, r)).ok ? (k().info(`[yoyoclaw-channel] switchPrimaryModel success: ${n}/${r}`), {
|
|
3441
3567
|
ok: !0,
|
|
3442
3568
|
data: { resolved: {
|
|
3443
3569
|
provider: n,
|
|
3444
3570
|
id: r
|
|
3445
3571
|
} }
|
|
3446
|
-
}) : (
|
|
3572
|
+
}) : (k().error("[yoyoclaw-channel] switchPrimaryModel failed, try to fallback main session model"), this.getMainSessionModel(e));
|
|
3447
3573
|
} catch (t) {
|
|
3448
|
-
return
|
|
3574
|
+
return k().error(`[yoyoclaw-channel] updatePrimaryModel error: ${t}, try to fallback main session model`), this.getMainSessionModel(e);
|
|
3449
3575
|
}
|
|
3450
3576
|
}
|
|
3451
3577
|
async getMainSessionModel(e) {
|
|
3452
3578
|
try {
|
|
3453
3579
|
let t = await e.getMainSession(), { modelProvider: n = "", model: r = "" } = t;
|
|
3454
|
-
return
|
|
3580
|
+
return k().warn(`[yoyoclaw-channel] switchPrimaryModel failed, fallback to current: ${n}/${r}`), !n || !r ? {
|
|
3455
3581
|
ok: !1,
|
|
3456
3582
|
error: `Missing primary model: mainSession-${JSON.stringify(t)}`
|
|
3457
3583
|
} : {
|
|
@@ -3482,7 +3608,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3482
3608
|
async fetchModelsList(e) {
|
|
3483
3609
|
try {
|
|
3484
3610
|
let t = await e.getModelList(), { modelProvider: n = "", model: r = "" } = await e.getMainSession();
|
|
3485
|
-
return
|
|
3611
|
+
return k().info(`[yoyoclaw-channel] current primary model: ${n}/${r}`), {
|
|
3486
3612
|
ok: !0,
|
|
3487
3613
|
data: { models: t?.models?.map((e) => {
|
|
3488
3614
|
let t = e.provider === n && e.id === r;
|
|
@@ -3494,26 +3620,26 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3494
3620
|
};
|
|
3495
3621
|
} catch (e) {
|
|
3496
3622
|
let t = e instanceof Error ? e.message : String(e);
|
|
3497
|
-
return
|
|
3623
|
+
return k().error(`[yoyoclaw-channel] fetchModelsList failed: ${t}`), {
|
|
3498
3624
|
ok: !1,
|
|
3499
3625
|
error: `fetchModelsList error: ${t}`
|
|
3500
3626
|
};
|
|
3501
3627
|
}
|
|
3502
3628
|
}
|
|
3503
3629
|
contextHandlerRequiresAdminClient(e, t) {
|
|
3504
|
-
return !e || t !== "DeviceToolSet";
|
|
3630
|
+
return !e || t !== "DeviceToolSet" && t !== "UniversalToolSet";
|
|
3505
3631
|
}
|
|
3506
3632
|
async updateDeviceToolSetContext(e, t, n) {
|
|
3507
3633
|
return n?.header.namespace === "yoyoclaw" ? {
|
|
3508
3634
|
ok: !0,
|
|
3509
|
-
data: await
|
|
3635
|
+
data: await li(t),
|
|
3510
3636
|
noReply: !0
|
|
3511
3637
|
} : {
|
|
3512
3638
|
ok: !1,
|
|
3513
3639
|
error: `Unsupported DeviceToolSet namespace: ${n?.header.namespace ?? "unknown"}`
|
|
3514
3640
|
};
|
|
3515
3641
|
}
|
|
3516
|
-
},
|
|
3642
|
+
}, fi = class extends Pn {
|
|
3517
3643
|
nodeOpts;
|
|
3518
3644
|
sessionId;
|
|
3519
3645
|
hardwareDeviceId;
|
|
@@ -3529,8 +3655,8 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3529
3655
|
return this.hardwareDeviceId;
|
|
3530
3656
|
}
|
|
3531
3657
|
onOpen() {
|
|
3532
|
-
this.connectedAt = (/* @__PURE__ */ new Date()).toISOString(),
|
|
3533
|
-
type:
|
|
3658
|
+
this.connectedAt = (/* @__PURE__ */ new Date()).toISOString(), k().info(`[yoyoclaw-nodeGatewayClient] connected for session: ${this.sessionId}, device: ${this.hardwareDeviceId}`), this.nodeOpts.onStatusEvent?.({
|
|
3659
|
+
type: K.GATEWAY_CLIENT_CONNECTED,
|
|
3534
3660
|
timestamp: Date.now(),
|
|
3535
3661
|
data: {
|
|
3536
3662
|
sessionId: this.sessionId,
|
|
@@ -3541,8 +3667,8 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3541
3667
|
});
|
|
3542
3668
|
}
|
|
3543
3669
|
onClose(e, t) {
|
|
3544
|
-
|
|
3545
|
-
type:
|
|
3670
|
+
k().info(`[yoyoclaw-nodeGatewayClient] disconnected for session: ${this.sessionId}, device: ${this.hardwareDeviceId}, reason: ${t}`), this.nodeOpts.onStatusEvent?.({
|
|
3671
|
+
type: K.GATEWAY_CLIENT_DISCONNECTED,
|
|
3546
3672
|
timestamp: Date.now(),
|
|
3547
3673
|
data: {
|
|
3548
3674
|
sessionId: this.sessionId,
|
|
@@ -3553,9 +3679,9 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3553
3679
|
});
|
|
3554
3680
|
}
|
|
3555
3681
|
onError(e) {
|
|
3556
|
-
|
|
3682
|
+
k().error(`[yoyoclaw-nodeGatewayClient] error for session: ${this.sessionId}, device: ${this.hardwareDeviceId}: ${e.message}`);
|
|
3557
3683
|
}
|
|
3558
|
-
},
|
|
3684
|
+
}, pi = class {
|
|
3559
3685
|
nodeGatewayClientsMap = /* @__PURE__ */ new Map();
|
|
3560
3686
|
deviceSessionsMap = /* @__PURE__ */ new Map();
|
|
3561
3687
|
sessionIdToHardwareDeviceMap = /* @__PURE__ */ new Map();
|
|
@@ -3588,7 +3714,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3588
3714
|
this.nodeGatewayClientsMap.set(e, t);
|
|
3589
3715
|
}
|
|
3590
3716
|
createNodeGatewayClient(e) {
|
|
3591
|
-
let t = new
|
|
3717
|
+
let t = new fi({
|
|
3592
3718
|
sessionId: e.sessionId,
|
|
3593
3719
|
hardwareDeviceId: e.hardwareDeviceId,
|
|
3594
3720
|
deviceInfo: e.deviceInfo,
|
|
@@ -3599,19 +3725,19 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3599
3725
|
}
|
|
3600
3726
|
closeNodeGatewayClient(e) {
|
|
3601
3727
|
let t = this.nodeGatewayClientsMap.get(e);
|
|
3602
|
-
t && (t.stop(), this.nodeGatewayClientsMap.delete(e), this.removeSession(e),
|
|
3728
|
+
t && (t.stop(), this.nodeGatewayClientsMap.delete(e), this.removeSession(e), k().info(`[yoyoclaw-channel] closed node gateway client for session: ${e}`));
|
|
3603
3729
|
}
|
|
3604
3730
|
closePreviousNodeGatewayClients(e, t) {
|
|
3605
3731
|
let n = this.deviceSessionsMap.get(e);
|
|
3606
3732
|
if (!n || n.length === 0) return;
|
|
3607
3733
|
let r = n.filter((e) => e.timestamp < t);
|
|
3608
3734
|
if (r.length > 0) {
|
|
3609
|
-
|
|
3735
|
+
k().info(`[yoyoclaw-channel] closing ${r.length} previous node gateway client(s) for hardware device: ${e}, new timestamp: ${t}`);
|
|
3610
3736
|
for (let e of r) this.closeNodeGatewayClient(e.sessionId);
|
|
3611
3737
|
}
|
|
3612
3738
|
}
|
|
3613
3739
|
closeAllNodeGatewayClients() {
|
|
3614
|
-
for (let [e, t] of this.nodeGatewayClientsMap.entries()) t.stop(),
|
|
3740
|
+
for (let [e, t] of this.nodeGatewayClientsMap.entries()) t.stop(), k().info(`[yoyoclaw-channel] closed node gateway client for session: ${e}`);
|
|
3615
3741
|
this.nodeGatewayClientsMap.clear(), this.deviceSessionsMap.clear(), this.sessionIdToHardwareDeviceMap.clear();
|
|
3616
3742
|
}
|
|
3617
3743
|
hasSession(e) {
|
|
@@ -3620,14 +3746,14 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3620
3746
|
getSessionCount() {
|
|
3621
3747
|
return this.sessionIdToHardwareDeviceMap.size;
|
|
3622
3748
|
}
|
|
3623
|
-
},
|
|
3749
|
+
}, mi = class {
|
|
3624
3750
|
cloudClient;
|
|
3625
3751
|
sessionManager;
|
|
3626
3752
|
adminClientManager;
|
|
3627
3753
|
messageHandler;
|
|
3628
3754
|
config;
|
|
3629
3755
|
constructor(e) {
|
|
3630
|
-
this.config = e, this.sessionManager = new
|
|
3756
|
+
this.config = e, this.sessionManager = new pi(), this.adminClientManager = new qn({ onStatusEvent: this.handleStatusEvent }), this.messageHandler = new di({
|
|
3631
3757
|
sessionManager: this.sessionManager,
|
|
3632
3758
|
adminClientManager: this.adminClientManager,
|
|
3633
3759
|
config: {
|
|
@@ -3635,7 +3761,7 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3635
3761
|
onStatusEvent: this.handleStatusEvent,
|
|
3636
3762
|
onReply: (e) => this.cloudClient.send(e)
|
|
3637
3763
|
}
|
|
3638
|
-
}), this.cloudClient = new
|
|
3764
|
+
}), this.cloudClient = new rr({
|
|
3639
3765
|
deviceInfo: e.deviceInfo,
|
|
3640
3766
|
userInfo: e.userInfo,
|
|
3641
3767
|
onMessage: this.messageHandler.handleCloudMessage,
|
|
@@ -3648,73 +3774,96 @@ var qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", Jr = class {
|
|
|
3648
3774
|
}), this.adminClientManager.init();
|
|
3649
3775
|
}
|
|
3650
3776
|
start() {
|
|
3651
|
-
|
|
3777
|
+
k().info("[yoyoclaw-channel] starting connection"), this.adminClientManager.ensureConnected(), this.cloudClient.connect();
|
|
3652
3778
|
}
|
|
3653
3779
|
destroy() {
|
|
3654
|
-
|
|
3780
|
+
k().info("[yoyoclaw-channel] closing connection"), this.sessionManager.closeAllNodeGatewayClients(), this.adminClientManager.destroy(), this.cloudClient.close();
|
|
3655
3781
|
}
|
|
3656
3782
|
handleCloudOpen = () => {
|
|
3657
|
-
|
|
3783
|
+
k().info("[yoyoclaw-channel] cloud connection established"), this.config.onOpen?.();
|
|
3658
3784
|
};
|
|
3659
3785
|
handleStatusEvent = (e) => {
|
|
3660
3786
|
this.config.onStatusEvent?.(e);
|
|
3661
3787
|
};
|
|
3662
3788
|
handleCloudClose = () => {
|
|
3663
|
-
|
|
3789
|
+
k().info("[yoyoclaw-channel] cloud connection closed"), this.config.onClose?.();
|
|
3664
3790
|
};
|
|
3665
3791
|
handleRemoteDeviceOffline = (e) => {
|
|
3666
3792
|
this.sessionManager.closeNodeGatewayClient(e);
|
|
3667
3793
|
};
|
|
3668
3794
|
handleDeviceNotRegistered = () => {
|
|
3669
|
-
|
|
3795
|
+
k().info("[yoyoclaw-channel] device not registered, notifying connection layer"), this.config.onDeviceNotRegistered?.();
|
|
3670
3796
|
};
|
|
3671
3797
|
handleUnauthorized = () => {
|
|
3672
|
-
|
|
3798
|
+
k().info("[yoyoclaw-channel] unauthorized connection, notifying connection layer"), this.config.onUnauthorized?.();
|
|
3673
3799
|
};
|
|
3674
3800
|
}, Z = {
|
|
3675
3801
|
channel: null,
|
|
3676
3802
|
status: "idle"
|
|
3677
|
-
}, Q = null,
|
|
3803
|
+
}, Q = null, hi = (e) => ({
|
|
3678
3804
|
id: "yoyoclaw-connection",
|
|
3679
3805
|
async start() {
|
|
3680
|
-
|
|
3681
|
-
try {
|
|
3682
|
-
await Q.loadAndCleanStatus(), D().info("[yoyoclaw-conn] status tracker initialized and cleaned");
|
|
3683
|
-
} catch (e) {
|
|
3684
|
-
D().warn(`[yoyoclaw-conn] failed to load saved status: ${String(e)}`);
|
|
3685
|
-
}
|
|
3686
|
-
D().debug?.(`[yoyoclaw] agents: ${JSON.stringify(e.config.agents?.defaults)}`);
|
|
3687
|
-
try {
|
|
3688
|
-
await j().initializePluginConfig("yoyo"), D().info("[yoyoclaw] plugin config initialized");
|
|
3689
|
-
} catch (e) {
|
|
3690
|
-
D().error(`[yoyoclaw] failed to initialize plugin config: ${String(e)}`);
|
|
3691
|
-
}
|
|
3692
|
-
try {
|
|
3693
|
-
let e = await un();
|
|
3694
|
-
e?.token ? (D().info("[yoyoclaw-conn] token found, creating channel"), await $r(await W(), e)) : D().info("[yoyoclaw-conn] no token found, skipping channel creation");
|
|
3695
|
-
} catch (e) {
|
|
3696
|
-
D().error(`[yoyoclaw-conn] failed to initialize connection: ${String(e)}`);
|
|
3697
|
-
}
|
|
3806
|
+
k().info("[yoyoclaw-conn] plugin service enabled"), await gi(), await vi(), await yi(), await bi();
|
|
3698
3807
|
},
|
|
3699
3808
|
async stop(e) {
|
|
3700
|
-
$(),
|
|
3809
|
+
$(), k().info("[yoyoclaw-conn] stopping connection service"), await _i();
|
|
3701
3810
|
}
|
|
3702
3811
|
});
|
|
3703
|
-
async function
|
|
3704
|
-
|
|
3705
|
-
|
|
3812
|
+
async function gi() {
|
|
3813
|
+
Q = new Cn(!0);
|
|
3814
|
+
try {
|
|
3815
|
+
await Q.loadAndCleanStatus(), k().info("[yoyoclaw-status] status tracker initialized and cleaned");
|
|
3816
|
+
} catch (e) {
|
|
3817
|
+
k().warn(`[yoyoclaw-status] failed to load saved status: ${String(e)}`);
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
async function _i() {
|
|
3821
|
+
Q &&= (await Q.destroy(), null);
|
|
3822
|
+
}
|
|
3823
|
+
async function vi() {
|
|
3824
|
+
try {
|
|
3825
|
+
await M().initializePluginConfig("yoyo"), k().info("[yoyoclaw-config] plugin config initialized");
|
|
3826
|
+
} catch (e) {
|
|
3827
|
+
k().error(`[yoyoclaw-config] failed to initialize plugin config: ${String(e)}`);
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
async function yi() {
|
|
3831
|
+
try {
|
|
3832
|
+
let e = await Yr();
|
|
3833
|
+
k().info(`[yoyoclaw-device-toolset] startup artifact check complete, restored: ${e.restored}`);
|
|
3834
|
+
} catch (e) {
|
|
3835
|
+
k().warn(`[yoyoclaw-device-toolset] startup artifact check failed: ${String(e)}`);
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
async function bi() {
|
|
3839
|
+
try {
|
|
3840
|
+
let e = await mn();
|
|
3841
|
+
if (e?.token) {
|
|
3842
|
+
k().info("[yoyoclaw-conn] token found, creating channel"), await xi(await G(), e);
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
k().info("[yoyoclaw-conn] no token found, skipping channel creation");
|
|
3846
|
+
} catch (e) {
|
|
3847
|
+
k().error(`[yoyoclaw-conn] failed to initialize connection: ${String(e)}`);
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
async function xi(e, t) {
|
|
3851
|
+
k().info(`[yoyoclaw-conn] creating new channel for device: ${e.deviceId}`), await Xt(e, t);
|
|
3852
|
+
let n = Z.status;
|
|
3853
|
+
return Z.status = "connecting", Q && await Q.handleEvent({
|
|
3854
|
+
type: K.CONNECTION_STATUS_CHANGED,
|
|
3706
3855
|
timestamp: Date.now(),
|
|
3707
3856
|
data: {
|
|
3708
3857
|
status: "connecting",
|
|
3709
|
-
previousStatus:
|
|
3858
|
+
previousStatus: n
|
|
3710
3859
|
}
|
|
3711
3860
|
}), new Promise((n, r) => {
|
|
3712
|
-
Z.channel = new
|
|
3861
|
+
Z.channel = new mi({
|
|
3713
3862
|
deviceInfo: e,
|
|
3714
3863
|
userInfo: t,
|
|
3715
3864
|
onOpen: () => {
|
|
3716
|
-
Z.status = "connected",
|
|
3717
|
-
type:
|
|
3865
|
+
Z.status = "connected", k().info("[yoyoclaw-conn] channel connected successfully"), Q && Q.handleEvent({
|
|
3866
|
+
type: K.CONNECTION_STATUS_CHANGED,
|
|
3718
3867
|
timestamp: Date.now(),
|
|
3719
3868
|
data: {
|
|
3720
3869
|
status: "connected",
|
|
@@ -3723,8 +3872,8 @@ async function $r(e, t) {
|
|
|
3723
3872
|
}), n(void 0);
|
|
3724
3873
|
},
|
|
3725
3874
|
onClose: () => {
|
|
3726
|
-
Z.status = "idle", Z.channel = null,
|
|
3727
|
-
type:
|
|
3875
|
+
Z.status = "idle", Z.channel = null, k().info("[yoyoclaw-conn] channel closed"), Q && Q.handleEvent({
|
|
3876
|
+
type: K.CONNECTION_STATUS_CHANGED,
|
|
3728
3877
|
timestamp: Date.now(),
|
|
3729
3878
|
data: {
|
|
3730
3879
|
status: "idle",
|
|
@@ -3733,30 +3882,30 @@ async function $r(e, t) {
|
|
|
3733
3882
|
}), n(void 0);
|
|
3734
3883
|
},
|
|
3735
3884
|
onDeviceNotRegistered: async () => {
|
|
3736
|
-
|
|
3737
|
-
let t = await
|
|
3885
|
+
k().info("[yoyoclaw-conn] device not registered, handling...");
|
|
3886
|
+
let t = await mn();
|
|
3738
3887
|
if (!t?.token) {
|
|
3739
|
-
|
|
3888
|
+
k().info("[yoyoclaw-conn] no token available, treating as logout"), $();
|
|
3740
3889
|
return;
|
|
3741
3890
|
}
|
|
3742
3891
|
try {
|
|
3743
|
-
|
|
3892
|
+
k().info("[yoyoclaw-conn] attempting to register device"), await Yt(e, t), k().info("[yoyoclaw-conn] device registered successfully, reconnecting..."), $(), await xi(e, t);
|
|
3744
3893
|
} catch (e) {
|
|
3745
|
-
|
|
3894
|
+
k().error(`[yoyoclaw-conn] device registration failed: ${String(e)}`), k().info("[yoyoclaw-conn] clearing token and destroying channel");
|
|
3746
3895
|
try {
|
|
3747
|
-
await
|
|
3896
|
+
await hn();
|
|
3748
3897
|
} catch (e) {
|
|
3749
|
-
|
|
3898
|
+
k().error(`[yoyoclaw-conn] failed to clear token: ${String(e)}`);
|
|
3750
3899
|
}
|
|
3751
3900
|
$();
|
|
3752
3901
|
}
|
|
3753
3902
|
},
|
|
3754
3903
|
onUnauthorized: async () => {
|
|
3755
|
-
|
|
3904
|
+
k().warn("[yoyoclaw-conn] connection unauthorized (401), clearing token and destroying channel");
|
|
3756
3905
|
try {
|
|
3757
|
-
await
|
|
3906
|
+
await hn();
|
|
3758
3907
|
} catch (e) {
|
|
3759
|
-
|
|
3908
|
+
k().error(`[yoyoclaw-conn] failed to clear token: ${String(e)}`);
|
|
3760
3909
|
}
|
|
3761
3910
|
$();
|
|
3762
3911
|
},
|
|
@@ -3767,31 +3916,31 @@ async function $r(e, t) {
|
|
|
3767
3916
|
try {
|
|
3768
3917
|
Z.channel.start();
|
|
3769
3918
|
} catch (e) {
|
|
3770
|
-
Z.status = "idle", Z.channel = null,
|
|
3919
|
+
Z.status = "idle", Z.channel = null, k().error(`[yoyoclaw-conn] failed to launch channel: ${String(e)}`), r(e);
|
|
3771
3920
|
}
|
|
3772
3921
|
});
|
|
3773
3922
|
}
|
|
3774
3923
|
function $() {
|
|
3775
3924
|
try {
|
|
3776
3925
|
if (!Z.channel) {
|
|
3777
|
-
|
|
3926
|
+
k().warn("[yoyoclaw-conn] no channel to destroy");
|
|
3778
3927
|
return;
|
|
3779
3928
|
}
|
|
3780
|
-
|
|
3929
|
+
k().info("[yoyoclaw-conn] destroying channel"), Z.channel.destroy(), Z.channel = null, Z.status = "idle", k().info("[yoyoclaw-conn] channel destroyed successfully");
|
|
3781
3930
|
} catch (e) {
|
|
3782
|
-
|
|
3931
|
+
k().error(`[yoyoclaw-conn] failed to destroy channel: ${String(e)}`);
|
|
3783
3932
|
}
|
|
3784
3933
|
}
|
|
3785
3934
|
//#endregion
|
|
3786
3935
|
//#region index.ts
|
|
3787
|
-
var
|
|
3936
|
+
var Si = {
|
|
3788
3937
|
id: "yoyo",
|
|
3789
3938
|
name: "YOYOClaw",
|
|
3790
3939
|
description: "OpenClaw Honor Yoyo connection plugin",
|
|
3791
|
-
configSchema:
|
|
3940
|
+
configSchema: Mn,
|
|
3792
3941
|
register(e) {
|
|
3793
|
-
|
|
3942
|
+
ce(e.runtime), _e(e.logger), e.registerService(hi(e)), e.on("before_prompt_build", async () => ({ prependSystemContext: kn })), On(e);
|
|
3794
3943
|
}
|
|
3795
3944
|
};
|
|
3796
3945
|
//#endregion
|
|
3797
|
-
export {
|
|
3946
|
+
export { Si as default };
|