@honor-claw/yoyo 1.1.4-beta.2 → 1.1.4-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honor-claw/yoyo",
3
- "version": "1.1.4-beta.2",
3
+ "version": "1.1.4-beta.3",
4
4
  "description": "OpenClaw Honor Yoyo connection plugin",
5
5
  "keywords": [
6
6
  "ai",
@@ -10,6 +10,7 @@ import { uuid } from "../utils/id.js";
10
10
  import { isOKResponse } from "./helpers.js";
11
11
  import { HttpClient, type HttpClientOptions } from "./http-client.js";
12
12
  import type { HttpApiWrapper } from "./types.js";
13
+ import { wrapError } from "../utils/error.js";
13
14
 
14
15
  /**
15
16
  * PKCE参数
@@ -138,9 +139,7 @@ export class HonorAuthClient {
138
139
 
139
140
  throw new Error(`failed to get token: ${response.data?.cnMessage}`);
140
141
  } catch (error) {
141
- throw new Error(
142
- `failed to get token: ${error instanceof Error ? error.message : String(error)}`,
143
- );
142
+ throw wrapError(error, "failed to get token");
144
143
  }
145
144
  }
146
145
 
@@ -2,6 +2,7 @@ import open from "open";
2
2
  import { createHonorAuthClient } from "../apis/honor-auth.js";
3
3
  import type { DeviceInfo, HonorUserInfo } from "../types.js";
4
4
  import { useClawLogger } from "../utils/logger.js";
5
+ import { wrapError } from "../utils/error.js";
5
6
  import { startCallbackServer } from "./callback-server.js";
6
7
  import { getConfig } from "./config.js";
7
8
  import { saveToken } from "./token-manager.js";
@@ -46,16 +47,14 @@ export async function performOAuth2AuthWithBrowser(
46
47
  try {
47
48
  await open(authUrl);
48
49
  } catch (error) {
49
- throw new Error("failed to open browser, check your permissions");
50
+ throw wrapError(error, "failed to open browser, check your permissions");
50
51
  }
51
52
 
52
53
  // 等待回调
53
54
  try {
54
55
  await serverPromise;
55
56
  } catch (error) {
56
- throw new Error(
57
- `authorization timeout: ${error instanceof Error ? error.message : String(error)}`,
58
- );
57
+ throw wrapError(error, "authorization timeout");
59
58
  }
60
59
 
61
60
  if (!receivedCode) {
@@ -79,6 +78,6 @@ export async function performOAuth2AuthWithBrowser(
79
78
  userName: tokenInfo.userInfo.displayName,
80
79
  } as HonorUserInfo;
81
80
  } catch (error) {
82
- throw new Error(`get token failed: ${error instanceof Error ? error.message : String(error)}`);
81
+ throw wrapError(error, "get token failed");
83
82
  }
84
83
  }
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
- import { safeReadFile, safeWriteFile, SafeFsError } from "../../utils/fs-safe.js";
2
+ import { safeReadFile, safeWriteFile } from "../../utils/fs-safe.js";
3
3
  import { resolveEffectiveHomeDir } from "../../utils/home-dir.js";
4
+ import { useClawLogger } from "../../utils/logger.js";
4
5
 
5
6
  /**
6
7
  * Identity 配置版本枚举
@@ -43,12 +44,7 @@ function getConfigPath(): string {
43
44
  /**
44
45
  * 内部方法:读取配置
45
46
  */
46
- async function loadConfig(): Promise<PersistedIdentity> {
47
- const homeDir = resolveEffectiveHomeDir();
48
- if (!homeDir) {
49
- throw new SafeFsError("not-found", "failed to find home dir");
50
- }
51
-
47
+ async function loadConfig(homeDir: string): Promise<PersistedIdentity | null> {
52
48
  const configPath = getConfigPath();
53
49
 
54
50
  try {
@@ -70,13 +66,8 @@ async function loadConfig(): Promise<PersistedIdentity> {
70
66
  ...parsed,
71
67
  };
72
68
  } catch (error) {
73
- if (error instanceof SafeFsError && error.code === "not-found") {
74
- return createDefaultConfig();
75
- }
76
- if (error instanceof SyntaxError) {
77
- return createDefaultConfig();
78
- }
79
- throw error;
69
+ useClawLogger().warn(`[yoyo-identity] failed to read identity: ${error.message}`);
70
+ return null;
80
71
  }
81
72
  }
82
73
 
@@ -85,7 +76,13 @@ async function loadConfig(): Promise<PersistedIdentity> {
85
76
  * @returns 如果存在则返回 Identity,否则返回 null
86
77
  */
87
78
  export async function getPersistedIdentity(): Promise<PersistedIdentity | null> {
88
- const config = await loadConfig();
79
+ const homeDir = resolveEffectiveHomeDir();
80
+ if (!homeDir) {
81
+ useClawLogger().warn("[yoyo-identity] failed to find home dir");
82
+ return null;
83
+ }
84
+
85
+ const config = await loadConfig(homeDir);
89
86
 
90
87
  if (config) {
91
88
  return config;
@@ -101,19 +98,21 @@ export async function getPersistedIdentity(): Promise<PersistedIdentity | null>
101
98
  * @throws SafeFsError 当写入失败时
102
99
  */
103
100
  export async function updatePersistedIdentity(
104
- identity: Partial<PersistedIdentity>
105
- ): Promise<PersistedIdentity> {
101
+ identity: Partial<PersistedIdentity>,
102
+ ): Promise<PersistedIdentity | null> {
106
103
  const homeDir = resolveEffectiveHomeDir();
107
104
  if (!homeDir) {
108
- throw new SafeFsError("not-found", "failed to find home dir");
105
+ useClawLogger().warn("[yoyo-identity] failed to find home dir");
106
+ return null;
109
107
  }
110
108
 
111
109
  // 读取现有配置
112
- const existingConfig = await loadConfig();
110
+ const existingConfig = await loadConfig(homeDir);
113
111
 
114
112
  // 合并配置
115
113
  const updatedConfig: PersistedIdentity = {
116
114
  ...existingConfig,
115
+ version: existingConfig?.version || IdentityVersion.LEGACY,
117
116
  };
118
117
 
119
118
  if (identity.legacyDeviceId) {
@@ -162,25 +161,22 @@ function createDefaultConfig(): PersistedIdentity {
162
161
  export async function upgradeIdentityToV2(): Promise<PersistedIdentity | null> {
163
162
  const homeDir = resolveEffectiveHomeDir();
164
163
  if (!homeDir) {
165
- throw new SafeFsError("not-found", "failed to find home dir");
164
+ useClawLogger().warn("[yoyo-identity] failed to find home dir");
165
+ return null;
166
166
  }
167
167
 
168
168
  // 读取现有配置
169
- const existingConfig = await loadConfig();
169
+ const existingConfig = await loadConfig(homeDir);
170
170
 
171
- // 如果已经是 v2,不需要处理
172
- if (existingConfig.version === IdentityVersion.NEW) {
171
+ // 如果已经有配置了,不做处理,这里老版本不删除这个问题就不走缓存咧
172
+ if (existingConfig) {
173
+ useClawLogger().warn("[yoyo-identity] identity exist, upgrade ignored");
173
174
  return null;
174
175
  }
175
176
 
176
177
  // 升级到 v2,移除 legacyDeviceId
177
178
  const upgradedConfig: PersistedIdentity = {
178
179
  version: IdentityVersion.NEW,
179
- deviceId: existingConfig.deviceId,
180
- publicKeyPem: existingConfig.publicKeyPem,
181
- privateKeyPem: existingConfig.privateKeyPem,
182
- createdAtMs: existingConfig.createdAtMs,
183
- // 故意不复制 legacyDeviceId,实现移除
184
180
  };
185
181
 
186
182
  // 写入升级后的配置
@@ -194,4 +190,4 @@ export async function upgradeIdentityToV2(): Promise<PersistedIdentity | null> {
194
190
  });
195
191
 
196
192
  return upgradedConfig;
197
- }
193
+ }
@@ -55,7 +55,7 @@ function fingerprintPublicKey(publicKeyPem: string): string {
55
55
  /**
56
56
  * Generate a new device identity with ED25519 key pair
57
57
  */
58
- function generateIdentity(identity: PersistedIdentity): DeviceIdentity {
58
+ function generateIdentity(identity: PersistedIdentity | null): DeviceIdentity {
59
59
  const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
60
60
  const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
61
61
  const privateKeyPem = privateKey.export({ type: "pkcs8", format: "pem" }).toString();
@@ -68,7 +68,7 @@ function generateIdentity(identity: PersistedIdentity): DeviceIdentity {
68
68
  createdAtMs: Date.now(),
69
69
  } as DeviceIdentity;
70
70
 
71
- if (identity.version === IdentityVersion.LEGACY) {
71
+ if (!identity || identity.version === IdentityVersion.LEGACY) {
72
72
  // 补充legacyDeviceId
73
73
  const provider = getDeviceInfoProvider();
74
74
  fullIdentity.legacyDeviceId = provider.getDeviceId();
@@ -87,6 +87,7 @@ export async function loadOrCreateDeviceIdentity(): Promise<DeviceIdentity> {
87
87
  const persisted = await getPersistedIdentity();
88
88
 
89
89
  if (
90
+ persisted &&
90
91
  persisted.deviceId &&
91
92
  persisted.publicKeyPem &&
92
93
  persisted.privateKeyPem &&
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 将错误封装为带有上下文信息的 Error
3
+ * @param error 原始错误
4
+ * @param context 错误上下文描述
5
+ * @returns 封装后的 Error 对象
6
+ */
7
+ export function wrapError(error: unknown, context: string): Error {
8
+ const message = error instanceof Error ? error.message : String(error);
9
+
10
+ return new Error(`${context}: ${message}`, {
11
+ cause: error,
12
+ });
13
+ }