@honor-claw/yoyo 0.0.1-alpha.0

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.
Files changed (71) hide show
  1. package/index.ts +25 -0
  2. package/openclaw.plugin.json +28 -0
  3. package/package.json +59 -0
  4. package/skills/yoyo-control/SKILL.md +346 -0
  5. package/skills/yoyo-control/references/capture-screenshot.md +66 -0
  6. package/skills/yoyo-control/references/local-search.md +27 -0
  7. package/skills/yoyo-control/references/open-app.md +54 -0
  8. package/skills/yoyo-control/references/phone-call.md +217 -0
  9. package/skills/yoyo-control/references/schedule.md +107 -0
  10. package/skills/yoyo-control/references/screen-recorder.md +67 -0
  11. package/skills/yoyo-control/references/search-contact.md +37 -0
  12. package/skills/yoyo-control/references/send-message.md +155 -0
  13. package/skills/yoyo-control/references/volume.md +536 -0
  14. package/skills/yoyo-control/scripts/README.md +103 -0
  15. package/skills/yoyo-control/scripts/invoke.js +119 -0
  16. package/skills/yoyo-control/scripts/volume-up.json +7 -0
  17. package/src/apis/claw-cloud.ts +74 -0
  18. package/src/apis/helpers.ts +10 -0
  19. package/src/apis/honor-auth.ts +148 -0
  20. package/src/apis/http-client.ts +239 -0
  21. package/src/apis/index.ts +8 -0
  22. package/src/apis/types.ts +47 -0
  23. package/src/cloud-channel/channel.ts +230 -0
  24. package/src/cloud-channel/client.ts +312 -0
  25. package/src/cloud-channel/index.ts +4 -0
  26. package/src/cloud-channel/types.ts +81 -0
  27. package/src/commands/index.ts +19 -0
  28. package/src/commands/login/impl.ts +21 -0
  29. package/src/commands/login/index.ts +1 -0
  30. package/src/commands/logout/index.ts +53 -0
  31. package/src/commands/status/index.ts +64 -0
  32. package/src/gateway-client/client.deprecated.ts +376 -0
  33. package/src/gateway-client/client.ts +76 -0
  34. package/src/gateway-client/device/auth.ts +57 -0
  35. package/src/gateway-client/device/builder.ts +105 -0
  36. package/src/gateway-client/device/helpers.ts +40 -0
  37. package/src/gateway-client/device/identity.ts +251 -0
  38. package/src/gateway-client/device/index.ts +40 -0
  39. package/src/gateway-client/device/types.ts +57 -0
  40. package/src/gateway-client/index.ts +2 -0
  41. package/src/gateway-client/types.deprecated.ts +217 -0
  42. package/src/gateway-client/types.ts +8 -0
  43. package/src/honor-auth/browser.ts +82 -0
  44. package/src/honor-auth/callback-server.ts +112 -0
  45. package/src/honor-auth/cloud.ts +70 -0
  46. package/src/honor-auth/config.ts +35 -0
  47. package/src/honor-auth/index.ts +2 -0
  48. package/src/honor-auth/token-manager.ts +80 -0
  49. package/src/honor-auth/types.ts +43 -0
  50. package/src/index.ts +10 -0
  51. package/src/modules/claw-configs/config-manager.ts +172 -0
  52. package/src/modules/claw-configs/index.ts +7 -0
  53. package/src/modules/claw-configs/types.ts +30 -0
  54. package/src/modules/device/device-info.ts +70 -0
  55. package/src/modules/device/index.ts +3 -0
  56. package/src/modules/device/providers/base.ts +27 -0
  57. package/src/modules/device/providers/pad.ts +114 -0
  58. package/src/modules/device/providers/windows.ts +67 -0
  59. package/src/modules/device/registry.ts +34 -0
  60. package/src/modules/login/impl.ts +70 -0
  61. package/src/modules/login/index.ts +6 -0
  62. package/src/runtime.ts +14 -0
  63. package/src/schemas.ts +20 -0
  64. package/src/services/connection/impl.ts +259 -0
  65. package/src/services/connection/index.ts +1 -0
  66. package/src/services/connection/types.ts +20 -0
  67. package/src/types.ts +64 -0
  68. package/src/utils/id.ts +8 -0
  69. package/src/utils/jwt.ts +36 -0
  70. package/src/utils/logger.ts +20 -0
  71. package/src/utils/proxy.ts +58 -0
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Device Control Invoke Script
4
+ *
5
+ * 封装 openclaw nodes invoke 命令,提供统一的设备控制接口
6
+ * 使用配置文件方式避免 Windows PowerShell 对 JSON 参数的引号处理问题
7
+ */
8
+
9
+ import { exec } from "child_process";
10
+ import { readFileSync } from "fs";
11
+ import { resolve } from "path";
12
+ import { promisify } from "util";
13
+
14
+ const execAsync = promisify(exec);
15
+
16
+ /**
17
+ * 显示使用说明
18
+ */
19
+ function usage() {
20
+ console.error("用法: node invoke.js <config_file> [--debug]");
21
+ console.error("");
22
+ console.error("参数:");
23
+ console.error(" config_file - JSON 配置文件路径");
24
+ console.error(" --debug - 启用调试模式");
25
+ console.error("");
26
+ console.error("配置文件格式:");
27
+ console.error("{");
28
+ console.error(' "nodeId": "设备ID",');
29
+ console.error(' "command": "命令标识",');
30
+ console.error(' "params": { ...参数对象 }');
31
+ console.error("}");
32
+ console.error("");
33
+ console.error("示例:");
34
+ console.error(" node invoke.js config.json");
35
+ console.error(" node invoke.js config.json --debug");
36
+ process.exit(2);
37
+ }
38
+
39
+ /**
40
+ * 执行节点命令
41
+ */
42
+ async function invokeNode(nodeId, command, params, timeout = 15000, debug = false) {
43
+ const paramsStr = JSON.stringify(params);
44
+ const cmd = `npx openclaw nodes invoke --node ${nodeId} --command ${command} --params "${paramsStr.replace(/"/g, '\\"')}"`;
45
+
46
+ if (debug) {
47
+ console.log("=== 调试信息 ===");
48
+ console.log("执行命令:", cmd);
49
+ console.log("设备 ID:", nodeId);
50
+ console.log("命令标识:", command);
51
+ console.log("参数对象:", JSON.stringify(params, null, 2));
52
+ console.log("================");
53
+ }
54
+
55
+ try {
56
+ const { stdout, stderr } = await execAsync(cmd, {
57
+ timeout,
58
+ env: { ...process.env },
59
+ cwd: process.cwd()
60
+ });
61
+
62
+ if (debug) {
63
+ console.log("=== 执行结果 ===");
64
+ console.log("标准输出:", stdout.trim());
65
+ console.log("错误输出:", stderr.trim());
66
+ console.log("================");
67
+ }
68
+
69
+ return {
70
+ success: true,
71
+ data: stdout.trim(),
72
+ error: stderr.trim() || null
73
+ };
74
+ } catch (error) {
75
+ if (debug) {
76
+ console.log("=== 执行失败 ===");
77
+ console.log("错误信息:", error.message);
78
+ console.log("标准输出:", error.stdout?.trim() || "");
79
+ console.log("错误输出:", error.stderr?.trim() || "");
80
+ console.log("================");
81
+ }
82
+
83
+ return {
84
+ success: false,
85
+ data: error.stdout?.trim() || "",
86
+ error: error.stderr?.trim() || error.message
87
+ };
88
+ }
89
+ }
90
+
91
+ // 主程序
92
+ const args = process.argv.slice(2);
93
+ const debugIndex = args.indexOf("--debug");
94
+ const debug = debugIndex !== -1;
95
+ if (debug) args.splice(debugIndex, 1);
96
+
97
+ if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
98
+ usage();
99
+ }
100
+
101
+ const configPath = resolve(args[0]);
102
+
103
+ try {
104
+ const configContent = readFileSync(configPath, "utf-8");
105
+ const config = JSON.parse(configContent);
106
+ const { nodeId, command, params } = config;
107
+
108
+ if (!nodeId || !command) {
109
+ console.error("错误: 配置文件缺少必要字段: nodeId 或 command");
110
+ process.exit(1);
111
+ }
112
+
113
+ const result = await invokeNode(nodeId, command, params || {}, 15000, debug);
114
+ console.log(JSON.stringify(result, null, 2));
115
+ process.exit(result.success ? 0 : 1);
116
+ } catch (error) {
117
+ console.error(`错误: ${error.message}`);
118
+ process.exit(1);
119
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "nodeId": "YOUR_DEVICE_ID",
3
+ "command": "volume.operate",
4
+ "params": {
5
+ "actionType": "调大"
6
+ }
7
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Claw Cloud API 接口封装
3
+ */
4
+ import type { DeviceInfo, HonorUserInfo } from '../types.js';
5
+ import type { GatewayAuthConfig } from '../modules/claw-configs/types.js';
6
+ import { uuid } from '../utils/id.js';
7
+ import { generateAuthorization } from '../utils/jwt.js';
8
+ import { HttpClient, type HttpResponse, type HttpClientOptions } from './http-client.js';
9
+ import type { DeviceRegistryHeaders, DeviceRegistryRequest, DeviceRegistryResponse } from './types.js';
10
+
11
+ /**
12
+ * Claw Cloud API 客户端
13
+ */
14
+ export class ClawCloudClient {
15
+ private httpClient: HttpClient;
16
+
17
+ constructor(baseUrl: string, options?: HttpClientOptions) {
18
+ this.httpClient = new HttpClient(baseUrl, options);
19
+ }
20
+
21
+ /**
22
+ * 设备注册
23
+ * @param deviceInfo 设备信息
24
+ * @param userInfo 用户信息
25
+ * @param gatewayAuthConfig Gateway 认证配置(可选)
26
+ * @returns 注册响应
27
+ */
28
+ async registerDevice(
29
+ deviceInfo: DeviceInfo,
30
+ userInfo: HonorUserInfo,
31
+ gatewayAuthConfig?: GatewayAuthConfig
32
+ ): Promise<HttpResponse<DeviceRegistryResponse>> {
33
+ // 构造请求头
34
+ const headers: DeviceRegistryHeaders = {
35
+ 'x-trace-id': uuid(),
36
+ 'x-udid': deviceInfo.deviceId,
37
+ ...(userInfo.token && userInfo.token !== 'test'
38
+ ? {
39
+ 'x-jwt-token': userInfo.token,
40
+ }
41
+ : {
42
+ 'x-agw-userId': userInfo.userId,
43
+ }),
44
+ authorization: generateAuthorization(userInfo.userId),
45
+ };
46
+
47
+ const requestBody: DeviceRegistryRequest = {
48
+ businessTag: 'YOYO_CLAW',
49
+ role: 'yoyoclaw',
50
+ deviceInfo: {
51
+ ...deviceInfo,
52
+ userId: userInfo.userId,
53
+ /**
54
+ * todo 后面网关会去掉检查
55
+ */
56
+ manufacture: 'unknown',
57
+ brand: 'honor',
58
+ bizExtInfo: gatewayAuthConfig,
59
+ } as any,
60
+ };
61
+
62
+ return this.httpClient.post<DeviceRegistryResponse>('/v1/device/registry', {
63
+ headers: headers as unknown as Record<string, string>,
64
+ body: requestBody,
65
+ });
66
+ }
67
+ }
68
+
69
+ /**
70
+ * 创建 Claw Cloud 客户端实例
71
+ */
72
+ export function createClawCloudClient(baseUrl: string, options?: HttpClientOptions): ClawCloudClient {
73
+ return new ClawCloudClient(baseUrl, options);
74
+ }
@@ -0,0 +1,10 @@
1
+ import type { HttpResponse } from './http-client.js';
2
+ import type { HttpApiWrapper } from './types.js';
3
+
4
+ export function isOKResponse<T>(response: HttpResponse<HttpApiWrapper<T>>) {
5
+ if (response.status >= 200 && response.status < 300 && response.data.code === '1') {
6
+ return true;
7
+ }
8
+
9
+ return false;
10
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * 荣耀OAuth2认证客户端
3
+ * 提供授权URL构建、Token获取等API能力
4
+ */
5
+
6
+ import { createHash, randomBytes } from 'crypto';
7
+ import { HttpClient, type HttpClientOptions } from './http-client.js';
8
+ import type { TokenResponse, HonorAuthConfig } from '../honor-auth/types.js';
9
+ import { uuid } from '../utils/id.js';
10
+ import { isOKResponse } from './helpers.js';
11
+ import type { HttpApiWrapper } from './types.js';
12
+
13
+ /**
14
+ * PKCE参数
15
+ */
16
+ export interface PKCEParams {
17
+ codeVerifier: string;
18
+ codeChallenge: string;
19
+ }
20
+
21
+ /**
22
+ * 荣耀认证客户端
23
+ */
24
+ export class HonorAuthClient {
25
+ private httpClient: HttpClient;
26
+ private config: HonorAuthConfig;
27
+
28
+ constructor(config: HonorAuthConfig) {
29
+ this.config = config;
30
+ // 从 HonorAuthConfig 中提取 HttpClientOptions
31
+ const httpClientOptions: HttpClientOptions = {
32
+ proxy: config.proxy,
33
+ };
34
+ this.httpClient = new HttpClient(config.authHost, httpClientOptions);
35
+ }
36
+
37
+ /**
38
+ * 生成随机字符串
39
+ */
40
+ private generateRandomString(length: number): string {
41
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
42
+ const bytes = randomBytes(length);
43
+ let result = '';
44
+ for (let i = 0; i < length; i++) {
45
+ result += chars[bytes[i] % chars.length];
46
+ }
47
+ return result;
48
+ }
49
+
50
+ /**
51
+ * 生成PKCE code_verifier
52
+ */
53
+ generateCodeVerifier(length: number = 128): string {
54
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
55
+ const bytes = randomBytes(length);
56
+ let result = '';
57
+ for (let i = 0; i < length; i++) {
58
+ result += chars[bytes[i] % chars.length];
59
+ }
60
+ return result;
61
+ }
62
+
63
+ /**
64
+ * 生成PKCE code_challenge
65
+ */
66
+ generateCodeChallenge(verifier: string): string {
67
+ const hash = createHash('sha256').update(verifier).digest();
68
+ return hash.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
69
+ }
70
+
71
+ /**
72
+ * 生成PKCE参数
73
+ */
74
+ generatePKCEParams(): PKCEParams {
75
+ const codeVerifier = this.generateCodeVerifier();
76
+ const codeChallenge = this.generateCodeChallenge(codeVerifier);
77
+ return { codeVerifier, codeChallenge };
78
+ }
79
+
80
+ /**
81
+ * 构建授权URL
82
+ */
83
+ buildAuthUrl(pkceParams: PKCEParams): string {
84
+ const params = new URLSearchParams({
85
+ client_id: this.config.clientId,
86
+ redirect_uri: this.config.redirectUri,
87
+ scope: this.config.scope,
88
+ response_type: 'code',
89
+ access_type: 'offline',
90
+ state: this.generateRandomString(16),
91
+ reqClientType: this.config.reqClientType,
92
+ loginChannel: this.config.loginChannel,
93
+ code_challenge: pkceParams.codeChallenge,
94
+ code_challenge_method: 'S256',
95
+ });
96
+
97
+ return `${this.config.authHost}/oauth2/v3/authorize?${params.toString()}`;
98
+ }
99
+
100
+ /**
101
+ * 使用授权码换取Token
102
+ */
103
+ async exchangeToken(code: string) {
104
+ const tokenUrl = 'https://api-agd-test-drcn.hiboard.hihonorcloud.com/honorboard/auth/v1/oauth/jwtToken';
105
+
106
+ const data = {
107
+ clientId: this.config.clientId,
108
+ code,
109
+ redirectUri: this.config.redirectUri,
110
+ };
111
+
112
+ try {
113
+ const response = await this.httpClient.post<HttpApiWrapper<TokenResponse>>(tokenUrl, {
114
+ body: data,
115
+ headers: {
116
+ 'Content-Type': 'application/json',
117
+ 'x-origin-udid': this.config.clientId,
118
+ 'x-app-pkg': 'com.hihonor.pc.openclaw',
119
+ 'x-request-nonce': uuid(),
120
+ 'x-timestamp': String(Date.now()),
121
+ },
122
+ timeout: 15000,
123
+ });
124
+
125
+ if (isOKResponse(response)) {
126
+ return response.data.data;
127
+ }
128
+
129
+ throw new Error(`获取Token失败: ${response.data?.cnMessage}`);
130
+ } catch (error) {
131
+ throw new Error(`获取Token失败: ${error instanceof Error ? error.message : String(error)}`);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * 获取配置
137
+ */
138
+ getConfig(): HonorAuthConfig {
139
+ return { ...this.config };
140
+ }
141
+ }
142
+
143
+ /**
144
+ * 创建荣耀认证客户端
145
+ */
146
+ export function createHonorAuthClient(config: HonorAuthConfig): HonorAuthClient {
147
+ return new HonorAuthClient(config);
148
+ }
@@ -0,0 +1,239 @@
1
+ /**
2
+ * HTTP 请求客户端封装
3
+ * 基于 undici 实现
4
+ */
5
+
6
+ import { request, type Dispatcher, ProxyAgent } from "undici";
7
+ import { getProxyUrl, shouldUseProxy } from "../utils/proxy.js";
8
+
9
+ /**
10
+ * HTTP 客户端配置
11
+ */
12
+ export interface HttpClientOptions {
13
+ defaultHeaders?: Record<string, string>;
14
+ defaultTimeout?: number;
15
+ /**
16
+ * 代理地址,例如:http://127.0.0.1:7890
17
+ * 如果不设置,则使用环境变量 HTTP_PROXY 或 HTTPS_PROXY
18
+ */
19
+ proxy?: string;
20
+ }
21
+
22
+ /**
23
+ * HTTP 请求配置
24
+ */
25
+ export interface HttpRequestConfig {
26
+ url: string;
27
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
28
+ headers?: Record<string, string>;
29
+ body?: string | object | null;
30
+ timeout?: number;
31
+ query?: Record<string, string | number | boolean | undefined>;
32
+ /**
33
+ * 是否禁用代理(默认 false)
34
+ */
35
+ disableProxy?: boolean;
36
+ }
37
+
38
+ /**
39
+ * HTTP 响应
40
+ */
41
+ export interface HttpResponse<T = unknown> {
42
+ data: T;
43
+ status: number;
44
+ headers: Record<string, string | string[] | undefined>;
45
+ }
46
+
47
+ /**
48
+ * HTTP 错误
49
+ */
50
+ export class HttpError extends Error {
51
+ constructor(public status: number, public data: unknown, message: string) {
52
+ super(message);
53
+ this.name = "HttpError";
54
+ }
55
+ }
56
+
57
+ /**
58
+ * HTTP 客户端类
59
+ */
60
+ export class HttpClient {
61
+ private baseUrl: string;
62
+ private defaultHeaders: Record<string, string>;
63
+ private defaultTimeout: number;
64
+ private proxyAgent?: ProxyAgent;
65
+
66
+ constructor(baseUrl: string, options?: HttpClientOptions) {
67
+ this.baseUrl = baseUrl.replace(/\/$/, "");
68
+ this.defaultHeaders = options?.defaultHeaders || {};
69
+ this.defaultTimeout = options?.defaultTimeout || 30000;
70
+
71
+ // 初始化代理 agent,使用统一的代理配置获取逻辑
72
+ const proxyUrl = getProxyUrl(options?.proxy);
73
+
74
+ if (proxyUrl) {
75
+ this.proxyAgent = new ProxyAgent(proxyUrl);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * 执行 HTTP 请求
81
+ */
82
+ async request<T = unknown>(
83
+ config: HttpRequestConfig
84
+ ): Promise<HttpResponse<T>> {
85
+ const {
86
+ method = "GET",
87
+ headers = {},
88
+ body,
89
+ timeout = this.defaultTimeout,
90
+ query,
91
+ } = config;
92
+
93
+ // 构建 URL
94
+ let url = config.url;
95
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
96
+ url = `${this.baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
97
+ }
98
+
99
+ // 添加查询参数
100
+ if (query && Object.keys(query).length > 0) {
101
+ const params = new URLSearchParams();
102
+ Object.entries(query).forEach(([key, value]) => {
103
+ if (value !== undefined) {
104
+ params.append(key, String(value));
105
+ }
106
+ });
107
+ const queryString = params.toString();
108
+ if (queryString) {
109
+ url += (url.includes("?") ? "&" : "?") + queryString;
110
+ }
111
+ }
112
+
113
+ // 合并请求头
114
+ const mergedHeaders: Record<string, string> = {
115
+ ...this.defaultHeaders,
116
+ ...headers,
117
+ };
118
+
119
+ // 设置 Content-Type
120
+ if (body && !mergedHeaders["Content-Type"]) {
121
+ mergedHeaders["Content-Type"] = "application/json";
122
+ }
123
+
124
+ // 准备请求体
125
+ let requestBody: string | undefined;
126
+ if (body !== null && body !== undefined) {
127
+ if (typeof body === "string") {
128
+ requestBody = body;
129
+ } else {
130
+ requestBody = JSON.stringify(body);
131
+ }
132
+ }
133
+
134
+ try {
135
+ const dispatcher: Dispatcher = shouldUseProxy(
136
+ getProxyUrl(),
137
+ config.disableProxy
138
+ ) && this.proxyAgent
139
+ ? this.proxyAgent
140
+ : undefined;
141
+
142
+ const response = await request(url, {
143
+ method,
144
+ headers: mergedHeaders as HeadersInit,
145
+ body: requestBody,
146
+ headersTimeout: timeout,
147
+ bodyTimeout: timeout,
148
+ dispatcher,
149
+ });
150
+
151
+ // 读取响应体
152
+ const responseBody = await response.body.text();
153
+ let data: T;
154
+
155
+ try {
156
+ data = responseBody ? JSON.parse(responseBody) : ({} as T);
157
+ } catch {
158
+ data = responseBody as unknown as T;
159
+ }
160
+
161
+ // 检查响应状态
162
+ if (response.statusCode >= 200 && response.statusCode < 300) {
163
+ return {
164
+ data,
165
+ status: response.statusCode,
166
+ headers: response.headers as Record<
167
+ string,
168
+ string | string[] | undefined
169
+ >,
170
+ };
171
+ } else {
172
+ throw new HttpError(
173
+ response.statusCode,
174
+ data,
175
+ `HTTP request failed with status ${response.statusCode}`
176
+ );
177
+ }
178
+ } catch (error) {
179
+ if (error instanceof HttpError) {
180
+ throw error;
181
+ }
182
+ throw new Error(
183
+ `HTTP request failed: ${
184
+ error instanceof Error ? error.message : String(error)
185
+ }`
186
+ );
187
+ }
188
+ }
189
+
190
+ /**
191
+ * GET 请求
192
+ */
193
+ async get<T = unknown>(
194
+ url: string,
195
+ config?: Omit<HttpRequestConfig, "url" | "method">
196
+ ): Promise<HttpResponse<T>> {
197
+ return this.request<T>({ ...config, url, method: "GET" });
198
+ }
199
+
200
+ /**
201
+ * POST 请求
202
+ */
203
+ async post<T = unknown>(
204
+ url: string,
205
+ config?: Omit<HttpRequestConfig, "url" | "method">
206
+ ): Promise<HttpResponse<T>> {
207
+ return this.request<T>({ ...config, url, method: "POST" });
208
+ }
209
+
210
+ /**
211
+ * PUT 请求
212
+ */
213
+ async put<T = unknown>(
214
+ url: string,
215
+ config?: Omit<HttpRequestConfig, "url" | "method">
216
+ ): Promise<HttpResponse<T>> {
217
+ return this.request<T>({ ...config, url, method: "PUT" });
218
+ }
219
+
220
+ /**
221
+ * DELETE 请求
222
+ */
223
+ async delete<T = unknown>(
224
+ url: string,
225
+ config?: Omit<HttpRequestConfig, "url" | "method">
226
+ ): Promise<HttpResponse<T>> {
227
+ return this.request<T>({ ...config, url, method: "DELETE" });
228
+ }
229
+
230
+ /**
231
+ * PATCH 请求
232
+ */
233
+ async patch<T = unknown>(
234
+ url: string,
235
+ config?: Omit<HttpRequestConfig, "url" | "method">
236
+ ): Promise<HttpResponse<T>> {
237
+ return this.request<T>({ ...config, url, method: "PATCH" });
238
+ }
239
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Claw Cloud API 模块
3
+ */
4
+ export { createClawCloudClient, ClawCloudClient } from './claw-cloud.js';
5
+ export { HttpClient, HttpError, type HttpRequestConfig, type HttpResponse } from './http-client.js';
6
+ export { createHonorAuthClient, HonorAuthClient } from './honor-auth.js';
7
+ export * from './types.js';
8
+ export * from './helpers.js';
@@ -0,0 +1,47 @@
1
+ /**
2
+ * 设备注册接口相关类型定义
3
+ */
4
+ import type { ClawDeviceInfo, DeviceInfo, DeviceRole } from "../types.js";
5
+
6
+ /**
7
+ * 设备注册请求体
8
+ */
9
+ export interface DeviceRegistryRequest {
10
+ businessTag: "YOYO_CLAW";
11
+ role: DeviceRole;
12
+ deviceInfo: Omit<ClawDeviceInfo, "role">;
13
+ }
14
+
15
+ export interface HttpApiWrapper<T = any> {
16
+ code: string;
17
+ success: boolean;
18
+ cnMessage: string;
19
+ data?: T;
20
+ }
21
+
22
+ /**
23
+ * 设备注册响应体
24
+ */
25
+ export type DeviceRegistryResponse = HttpApiWrapper;
26
+
27
+ /**
28
+ * 设备注册请求头
29
+ */
30
+ export interface DeviceRegistryHeaders {
31
+ "x-trace-id": string;
32
+ "x-udid": string;
33
+ /**
34
+ * token信息
35
+ */
36
+ "x-jwt-token"?: string;
37
+ /**
38
+ * 用户id加密后的信息
39
+ */
40
+ authorization?: string;
41
+ /**
42
+ * 端用,claw侧不需要
43
+ */
44
+ // authorization?: string;
45
+ // debug mode
46
+ "x-agw-userId"?: string;
47
+ }