@honor-claw/yoyo 1.6.1-beta.1 → 1.6.1-beta.2

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.
@@ -3,6 +3,8 @@ import { getProxyUrl as t, shouldUseProxy as n } from "../utils/proxy.mjs";
3
3
  import { ProxyAgent as r, request as i } from "undici";
4
4
  //#region src/apis/http-client.ts
5
5
  var a = class extends Error {
6
+ status;
7
+ data;
6
8
  constructor(e, t, n) {
7
9
  super(n), this.status = e, this.data = t, this.name = "HttpError";
8
10
  }
@@ -9,6 +9,7 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
9
9
  config;
10
10
  pendingFirstMessages = /* @__PURE__ */ new Map();
11
11
  initializedDeviceIds = /* @__PURE__ */ new Set();
12
+ pendingNodeConnects = /* @__PURE__ */ new Map();
12
13
  contextUpdateHandlers = {
13
14
  style: this.updateStyleContext.bind(this),
14
15
  "model.primary": this.updatePrimaryModel.bind(this),
@@ -116,7 +117,43 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
116
117
  }
117
118
  }
118
119
  forwardToNodeGateway(t, n, r, a) {
119
- e().info(`${i} forwarding user message to node gateway from ${n}, session: ${t}`), r.send(a);
120
+ e().info(`${i} forwarding user message to node gateway from ${n}, session: ${t}`);
121
+ let o = this.readNodeConnectRequest(a);
122
+ o && this.pendingNodeConnects.set(o.requestId, o.nodeId);
123
+ try {
124
+ r.send(a);
125
+ } catch (e) {
126
+ throw o && this.pendingNodeConnects.delete(o.requestId), e;
127
+ }
128
+ }
129
+ readNodeConnectRequest(e) {
130
+ let t;
131
+ try {
132
+ t = JSON.parse(e);
133
+ } catch {
134
+ return;
135
+ }
136
+ if (t.type !== "req" || t.method !== "connect" || typeof t.id != "string" || !t.params || typeof t.params != "object") return;
137
+ let n = t.params;
138
+ if (n.role !== "node" || !n.device || typeof n.device != "object") return;
139
+ let r = n.device;
140
+ if (!(typeof r.id != "string" || !r.id.trim())) return {
141
+ requestId: t.id,
142
+ nodeId: r.id
143
+ };
144
+ }
145
+ handleNodeConnectResponse(e) {
146
+ let t = e;
147
+ if (t.type !== "res" || typeof t.id != "string") return;
148
+ let n = this.pendingNodeConnects.get(t.id);
149
+ n && (this.pendingNodeConnects.delete(t.id), !(t.ok !== !0 || !t.payload || typeof t.payload != "object") && t.payload.type === "hello-ok" && this.armNodePairingAutoApproval(n));
150
+ }
151
+ async armNodePairingAutoApproval(t) {
152
+ if (!await this.adminClientManager.waitForReady()) {
153
+ e().warn(`${i} admin client not available for node pairing auto approval, nodeId: ${t}`);
154
+ return;
155
+ }
156
+ await this.adminClientManager.getClient()?.approvePendingNodePairing(t);
120
157
  }
121
158
  processMessageBuffer(e, t, n, r) {
122
159
  let i = this.pendingFirstMessages.get(t);
@@ -156,7 +193,7 @@ var r = { style: "SOUL.md" }, i = "[yoyoclaw-channel]", a = class {
156
193
  e().warn(`${i} gateway message is not valid JSON`);
157
194
  return;
158
195
  }
159
- if (!a.ok && a.error?.code === "NOT_PAIRED") {
196
+ if (this.handleNodeConnectResponse(a), !a.ok && a.error?.code === "NOT_PAIRED") {
160
197
  let r = a.error?.details?.requestId;
161
198
  if (!r) {
162
199
  e().warn(`${i} NOT_PAIRED without requestId, ignoring...`);
@@ -1,7 +1,8 @@
1
- import { GATEWAY_CLIENT_IDS as e, GATEWAY_CLIENT_MODES as t } from "./types/client.mjs";
2
- import { ProtocolGatewayClient as n } from "./protocol-client.mjs";
1
+ import { useClawLogger as e } from "../utils/logger.mjs";
2
+ import { GATEWAY_CLIENT_IDS as t, GATEWAY_CLIENT_MODES as n } from "./types/client.mjs";
3
+ import { ProtocolGatewayClient as r } from "./protocol-client.mjs";
3
4
  //#region src/gateway-client/admin-client.ts
4
- var r = {
5
+ var i = {
5
6
  role: "operator",
6
7
  scopes: [
7
8
  "operator.admin",
@@ -11,12 +12,12 @@ var r = {
11
12
  "operator.approvals",
12
13
  "operator.pairing"
13
14
  ],
14
- clientId: e.CLI,
15
+ clientId: t.CLI,
15
16
  displayName: "YOYO-Control",
16
- clientMode: t.BACKEND
17
- }, i = class extends n {
17
+ clientMode: n.BACKEND
18
+ }, a = "[yoyoclaw-adminGatewayClient]", o = class extends r {
18
19
  constructor(e = {}) {
19
- super(e, r);
20
+ super(e, i);
20
21
  }
21
22
  async setAgentFile(e, t, n = "main") {
22
23
  return this.sendRequest("agents.files.set", {
@@ -49,6 +50,16 @@ var r = {
49
50
  async devicePairApprove(e) {
50
51
  return this.sendRequest("device.pair.approve", { requestId: e });
51
52
  }
53
+ async approvePendingNodePairing(t) {
54
+ let n = t.trim();
55
+ if (!n) return !1;
56
+ try {
57
+ let t = (await this.sendRequest("node.pair.list", {})).pending?.find((e) => e.nodeId === n);
58
+ return t ? (e().info(`${a} auto approving node pairing, nodeId: ${n}, requestId: ${t.requestId}`), await this.sendRequest("node.pair.approve", { requestId: t.requestId }), !0) : !1;
59
+ } catch (t) {
60
+ return e().error(`${a} node pairing auto approve failed, nodeId: ${n}, error: ${String(t)}`), !1;
61
+ }
62
+ }
52
63
  };
53
64
  //#endregion
54
- export { i as default };
65
+ export { o as default };
@@ -85,8 +85,8 @@ var l = {
85
85
  platform: process.platform,
86
86
  deviceFamily: f
87
87
  }) : void 0, a = {
88
- minProtocol: 3,
89
- maxProtocol: 3,
88
+ minProtocol: 4,
89
+ maxProtocol: 4,
90
90
  client: {
91
91
  id: this.config.clientId,
92
92
  displayName: this.config.displayName,
@@ -10,14 +10,23 @@ import { STATE_FLAG as c, hasPersistedStateFlag as l, markPersistedStateFlag as
10
10
  var d = "yoyo", f = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,alarm.enable,alarm.query,alarm.update,app.close,app.open,call.phone,call.search,capture-screenshot,contact.search,file-upload,hotspot,local-search,message.search,message.send,mobile-data,no-disturb,quiet-mode,ringing-mode,schedule.create,schedule.delete,schedule.search,schedule.update,screen-record,vibration-mode,volume.operate,wlan,bluetooth,location-service,nfc,usb-shared-network,eyecomfort,status-bar-show,brightness,autoscreen-onnotice,dark-mode,device-operation,camera,app.uninstall,audio-record,battery,gui.create,gui.pause,gui.terminate,mcp.tool.call,task_result_query".split(","), p = class {
11
11
  loadConfig() {
12
12
  try {
13
- return t().config.loadConfig();
13
+ let e = t().config, n = e.current;
14
+ return typeof n == "function" ? structuredClone(n()) : structuredClone(e.loadConfig());
14
15
  } catch (e) {
15
16
  throw i(e, "Failed to load config");
16
17
  }
17
18
  }
18
19
  async saveConfig(e) {
19
20
  try {
20
- await t().config.writeConfigFile(e);
21
+ let n = t().config, r = n.replaceConfigFile;
22
+ if (typeof r == "function") {
23
+ await r({
24
+ nextConfig: e,
25
+ afterWrite: { mode: "auto" }
26
+ });
27
+ return;
28
+ }
29
+ await n.writeConfigFile(e);
21
30
  } catch (e) {
22
31
  throw i(e, "Failed to save config");
23
32
  }
@@ -4,70 +4,68 @@ import { safeReadFile as n, safeWriteFile as r } from "../../utils/fs-safe.mjs";
4
4
  import { resolveEffectiveHomeDir as i } from "../../utils/home-dir.mjs";
5
5
  import a from "node:path";
6
6
  //#region src/modules/configs/identity-persist.ts
7
- var o = /* @__PURE__ */ function(e) {
8
- return e[e.LEGACY = 1] = "LEGACY", e[e.NEW = 2] = "NEW", e;
9
- }({}), s = ".openclaw", c = "yoyo", l = "identity.json", u = 6e4;
10
- function d() {
11
- return a.join(s, c, l);
7
+ var o = ".openclaw", s = "yoyo", c = "identity.json", l = 6e4;
8
+ function u() {
9
+ return a.join(o, s, c);
12
10
  }
13
- async function f(t) {
14
- let r = d();
11
+ async function d(t) {
12
+ let r = u();
15
13
  try {
16
14
  let e = (await n({
17
15
  rootDir: t,
18
16
  relativePath: r,
19
17
  maxBytes: 10 * 1024
20
18
  })).buffer.toString("utf8"), i = JSON.parse(e);
21
- return typeof i != "object" || !i ? v() : {
22
- ...v(),
19
+ return typeof i != "object" || !i ? _() : {
20
+ ..._(),
23
21
  ...i
24
22
  };
25
23
  } catch (t) {
26
24
  return e(t, "[yoyo-identity] failed to read identity"), null;
27
25
  }
28
26
  }
29
- async function p() {
27
+ async function f() {
30
28
  let e = i();
31
- return e ? await f(e) || null : (t().warn("[yoyo-identity] failed to find home dir"), null);
29
+ return e ? await d(e) || null : (t().warn("[yoyo-identity] failed to find home dir"), null);
32
30
  }
33
- async function m(e) {
31
+ async function p(e) {
34
32
  let n = i();
35
33
  if (!n) return t().warn("[yoyo-identity] failed to find home dir"), null;
36
- let a = await f(n), s = {
34
+ let a = await d(n), o = {
37
35
  ...a,
38
- version: a?.version || o.NEW
36
+ version: a?.version || 2
39
37
  };
40
- return e.legacyDeviceId && (s.legacyDeviceId = e.legacyDeviceId), e.deviceId && (s.deviceId = e.deviceId, s.publicKeyPem = e.publicKeyPem, s.privateKeyPem = e.privateKeyPem, s.createdAtMs = e.createdAtMs), e.version && (s.version = e.version), "gatewayAuthMd5" in e && (s.gatewayAuthMd5 = e.gatewayAuthMd5), "pluginVersionCode" in e && (s.pluginVersionCode = e.pluginVersionCode), "authorizationCache" in e && (s.authorizationCache = e.authorizationCache), await r({
38
+ return e.legacyDeviceId && (o.legacyDeviceId = e.legacyDeviceId), e.deviceId && (o.deviceId = e.deviceId, o.publicKeyPem = e.publicKeyPem, o.privateKeyPem = e.privateKeyPem, o.createdAtMs = e.createdAtMs), e.version && (o.version = e.version), "gatewayAuthMd5" in e && (o.gatewayAuthMd5 = e.gatewayAuthMd5), "pluginVersionCode" in e && (o.pluginVersionCode = e.pluginVersionCode), "authorizationCache" in e && (o.authorizationCache = e.authorizationCache), await r({
41
39
  rootDir: n,
42
- relativePath: d(),
43
- data: JSON.stringify(s, null, 2),
40
+ relativePath: u(),
41
+ data: JSON.stringify(o, null, 2),
44
42
  encoding: "utf8",
45
43
  mkdir: !0
46
- }), s;
44
+ }), o;
47
45
  }
48
- function h(e) {
46
+ function m(e) {
49
47
  let t = typeof e == "number" ? e : typeof e == "string" && e.trim() ? Number(e) : 0;
50
- return !Number.isFinite(t) || t < u ? 0 : Math.floor(t);
48
+ return !Number.isFinite(t) || t < l ? 0 : Math.floor(t);
51
49
  }
52
- async function g(e, t, n = Date.now()) {
53
- let r = await m({ authorizationCache: {
50
+ async function h(e, t, n = Date.now()) {
51
+ let r = await p({ authorizationCache: {
54
52
  jwtToken: e,
55
53
  receivedAtMs: n,
56
- expireMs: h(t)
54
+ expireMs: m(t)
57
55
  } });
58
56
  if (!r) throw Error("failed to write authorization cache");
59
57
  return r;
60
58
  }
61
- async function _() {
62
- let e = await p(), t = e?.authorizationCache;
63
- return t?.jwtToken ? m({ authorizationCache: {
59
+ async function g() {
60
+ let e = await f(), t = e?.authorizationCache;
61
+ return t?.jwtToken ? p({ authorizationCache: {
64
62
  jwtToken: void 0,
65
63
  receivedAtMs: t.receivedAtMs,
66
- expireMs: h(t.expireMs)
64
+ expireMs: m(t.expireMs)
67
65
  } }) : e;
68
66
  }
69
- function v() {
70
- return { version: o.NEW };
67
+ function _() {
68
+ return { version: 2 };
71
69
  }
72
70
  //#endregion
73
- export { o as IdentityVersion, g as cacheAuthorizationToken, _ as clearCachedAuthorizationToken, p as getPersistedIdentity, h as parseAuthorizationExpireMs, m as updatePersistedIdentity };
71
+ export { h as cacheAuthorizationToken, g as clearCachedAuthorizationToken, f as getPersistedIdentity, m as parseAuthorizationExpireMs, p as updatePersistedIdentity };
@@ -1,5 +1,5 @@
1
1
  import e from "os";
2
- import * as t from "winreg";
2
+ import t from "winreg";
3
3
  //#region src/modules/device/providers/windows.ts
4
4
  function n(e, n, r) {
5
5
  return new Promise((i) => {
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "id": "yoyo",
3
3
  "skills": ["./skills"],
4
+ "enabledByDefault": true,
5
+ "activation": {
6
+ "onStartup": true
7
+ },
4
8
  "configSchema": {
5
9
  "type": "object",
6
10
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honor-claw/yoyo",
3
- "version": "1.6.1-beta.1",
3
+ "version": "1.6.1-beta.2",
4
4
  "description": "OpenClaw Honor Yoyo connection plugin",
5
5
  "keywords": [
6
6
  "ai",
@@ -26,6 +26,10 @@
26
26
  "scripts": {
27
27
  "build": "vite build",
28
28
  "ci:check": "npx tsc --noEmit && npm run test:coverage",
29
+ "format": "oxfmt",
30
+ "format:fix": "oxfmt --write",
31
+ "lint": "oxlint src/",
32
+ "lint:fix": "oxlint --fix src/",
29
33
  "publish:alpha": "npm run build && node scripts/publish.js --alpha",
30
34
  "publish:beta": "npm run build && node scripts/publish.js",
31
35
  "publish:latest": "npm run build && node scripts/publish.js --release",
@@ -49,6 +53,8 @@
49
53
  "@types/node": "^25.0.10",
50
54
  "@types/ws": "^8.5.13",
51
55
  "@vitest/coverage-v8": "^2.1.8",
56
+ "oxfmt": "^0.55.0",
57
+ "oxlint": "^1.70.0",
52
58
  "typescript": "^6.0.2",
53
59
  "vite": "^8.0.10",
54
60
  "vitest": "^2.1.8"