@z-qinghui/migpt-claw 1.0.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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +690 -0
  3. package/dist/index.d.ts +23 -0
  4. package/dist/index.js +33 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/setup-entry.d.ts +3 -0
  7. package/dist/setup-entry.js +7 -0
  8. package/dist/setup-entry.js.map +1 -0
  9. package/dist/src/channel.d.ts +10 -0
  10. package/dist/src/channel.js +444 -0
  11. package/dist/src/channel.js.map +1 -0
  12. package/dist/src/config.d.ts +125 -0
  13. package/dist/src/config.js +146 -0
  14. package/dist/src/config.js.map +1 -0
  15. package/dist/src/message.d.ts +51 -0
  16. package/dist/src/message.js +145 -0
  17. package/dist/src/message.js.map +1 -0
  18. package/dist/src/mi/account.d.ts +5 -0
  19. package/dist/src/mi/account.js +162 -0
  20. package/dist/src/mi/account.js.map +1 -0
  21. package/dist/src/mi/common.d.ts +15 -0
  22. package/dist/src/mi/common.js +80 -0
  23. package/dist/src/mi/common.js.map +1 -0
  24. package/dist/src/mi/index.d.ts +4 -0
  25. package/dist/src/mi/index.js +10 -0
  26. package/dist/src/mi/index.js.map +1 -0
  27. package/dist/src/mi/mina.d.ts +66 -0
  28. package/dist/src/mi/mina.js +225 -0
  29. package/dist/src/mi/mina.js.map +1 -0
  30. package/dist/src/mi/miot.d.ts +35 -0
  31. package/dist/src/mi/miot.js +168 -0
  32. package/dist/src/mi/miot.js.map +1 -0
  33. package/dist/src/mi/typing.d.ts +90 -0
  34. package/dist/src/mi/typing.js +1 -0
  35. package/dist/src/mi/typing.js.map +1 -0
  36. package/dist/src/onboarding.d.ts +5 -0
  37. package/dist/src/onboarding.js +118 -0
  38. package/dist/src/onboarding.js.map +1 -0
  39. package/dist/src/openclaw-plugin-sdk.d.d.ts +185 -0
  40. package/dist/src/openclaw-plugin-sdk.d.js +1 -0
  41. package/dist/src/openclaw-plugin-sdk.d.js.map +1 -0
  42. package/dist/src/outbound.d.ts +5 -0
  43. package/dist/src/outbound.js +108 -0
  44. package/dist/src/outbound.js.map +1 -0
  45. package/dist/src/runtime.d.ts +6 -0
  46. package/dist/src/runtime.js +15 -0
  47. package/dist/src/runtime.js.map +1 -0
  48. package/dist/src/service.d.ts +70 -0
  49. package/dist/src/service.js +200 -0
  50. package/dist/src/service.js.map +1 -0
  51. package/dist/src/speaker.d.ts +62 -0
  52. package/dist/src/speaker.js +211 -0
  53. package/dist/src/speaker.js.map +1 -0
  54. package/dist/src/tts/mimo.d.ts +50 -0
  55. package/dist/src/tts/mimo.js +214 -0
  56. package/dist/src/tts/mimo.js.map +1 -0
  57. package/dist/src/types.d.ts +30 -0
  58. package/dist/src/types.js +1 -0
  59. package/dist/src/types.js.map +1 -0
  60. package/dist/src/utils/codec.d.ts +31 -0
  61. package/dist/src/utils/codec.js +144 -0
  62. package/dist/src/utils/codec.js.map +1 -0
  63. package/dist/src/utils/debug.d.ts +10 -0
  64. package/dist/src/utils/debug.js +15 -0
  65. package/dist/src/utils/debug.js.map +1 -0
  66. package/dist/src/utils/hash.d.ts +40 -0
  67. package/dist/src/utils/hash.js +75 -0
  68. package/dist/src/utils/hash.js.map +1 -0
  69. package/dist/src/utils/http.d.ts +24 -0
  70. package/dist/src/utils/http.js +151 -0
  71. package/dist/src/utils/http.js.map +1 -0
  72. package/dist/src/utils/index.d.ts +6 -0
  73. package/dist/src/utils/index.js +10 -0
  74. package/dist/src/utils/index.js.map +1 -0
  75. package/dist/src/utils/io.d.ts +26 -0
  76. package/dist/src/utils/io.js +53 -0
  77. package/dist/src/utils/io.js.map +1 -0
  78. package/dist/src/utils/parse.d.ts +26 -0
  79. package/dist/src/utils/parse.js +51 -0
  80. package/dist/src/utils/parse.js.map +1 -0
  81. package/index.ts +26 -0
  82. package/openclaw.plugin.json +344 -0
  83. package/package.json +106 -0
  84. package/setup-entry.ts +12 -0
  85. package/skills/migpt-volume/SKILL.md +182 -0
  86. package/skills/migpt-volume/index.ts +50 -0
  87. package/src/channel.ts +519 -0
  88. package/src/config.ts +299 -0
  89. package/src/message.ts +186 -0
  90. package/src/mi/account.ts +184 -0
  91. package/src/mi/common.ts +105 -0
  92. package/src/mi/index.ts +4 -0
  93. package/src/mi/mina.ts +261 -0
  94. package/src/mi/miot.ts +193 -0
  95. package/src/mi/typing.ts +93 -0
  96. package/src/onboarding.ts +136 -0
  97. package/src/openclaw-plugin-sdk.d.ts +185 -0
  98. package/src/outbound.ts +137 -0
  99. package/src/runtime.ts +14 -0
  100. package/src/service.ts +246 -0
  101. package/src/speaker.ts +264 -0
  102. package/src/tts/mimo.ts +300 -0
  103. package/src/types.ts +34 -0
  104. package/src/utils/codec.ts +206 -0
  105. package/src/utils/debug.ts +16 -0
  106. package/src/utils/hash.ts +104 -0
  107. package/src/utils/http.ts +193 -0
  108. package/src/utils/index.ts +5 -0
  109. package/src/utils/io.ts +68 -0
  110. package/src/utils/parse.ts +64 -0
  111. package/tsconfig.json +25 -0
@@ -0,0 +1,151 @@
1
+ import { sleep } from "./parse.js";
2
+ import { jsonEncode } from "./parse.js";
3
+ import axios from "axios";
4
+ import { Debugger } from "./debug.js";
5
+ const _baseConfig = {
6
+ proxy: false,
7
+ decompress: true,
8
+ headers: {
9
+ "Accept-Encoding": "gzip, deflate",
10
+ "Content-Type": "application/x-www-form-urlencoded",
11
+ "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 10; RMX2111 Build/QP1A.190711.020) APP/xiaomi.mico APPV/2004040 MK/Uk1YMjExMQ== PassportSDK/3.8.3 passport-ui/3.8.3"
12
+ }
13
+ };
14
+ const _http = axios.create(_baseConfig);
15
+ _http.interceptors.response.use(
16
+ (res) => {
17
+ if (res.config.rawResponse) {
18
+ return res;
19
+ }
20
+ return res.data;
21
+ },
22
+ async (err) => {
23
+ const newResult = await tokenRefresher.refreshTokenAndRetry(err);
24
+ if (newResult) {
25
+ return newResult;
26
+ }
27
+ const error = err.response?.data?.error || err.response?.data;
28
+ const request = {
29
+ method: err.config.method,
30
+ url: err.config.url,
31
+ headers: jsonEncode(err.config.headers),
32
+ data: jsonEncode({ body: err.config.data })
33
+ };
34
+ const response = !err.response ? void 0 : {
35
+ url: err.config.url,
36
+ status: err.response.status,
37
+ headers: jsonEncode(err.response.headers),
38
+ data: jsonEncode({ body: err.response.data })
39
+ };
40
+ return {
41
+ isError: true,
42
+ code: error?.code || err.response?.status || err.code || "\u672A\u77E5",
43
+ message: error?.message || err.response?.statusText || err.message || "\u672A\u77E5",
44
+ error: { request, response }
45
+ };
46
+ }
47
+ );
48
+ class HTTPClient {
49
+ // 默认 5 秒超时
50
+ timeout = 5 * 1e3;
51
+ async get(url, _query, _config) {
52
+ let query = _query;
53
+ let config = _config;
54
+ if (_config === void 0) {
55
+ config = _query;
56
+ query = void 0;
57
+ }
58
+ return _http.get(HTTPClient.buildURL(url, query), HTTPClient.buildConfig(config));
59
+ }
60
+ async post(url, data, config) {
61
+ return _http.post(url, data, HTTPClient.buildConfig(config));
62
+ }
63
+ static buildURL = (url, query) => {
64
+ const _url = new URL(url);
65
+ for (const [key, value] of Object.entries(query ?? {})) {
66
+ if (isNotEmpty(value)) {
67
+ _url.searchParams.append(key, value.toString());
68
+ }
69
+ }
70
+ return _url.href;
71
+ };
72
+ static buildConfig = (config) => {
73
+ if (config?.cookies) {
74
+ config.headers = {
75
+ ...config.headers,
76
+ Cookie: Object.entries(config.cookies).map(([key, value]) => `${key}=${value == null ? "" : value.toString()};`).join(" ")
77
+ };
78
+ }
79
+ if (config && !config.timeout) {
80
+ config.timeout = Http.timeout;
81
+ }
82
+ return config;
83
+ };
84
+ }
85
+ const Http = new HTTPClient();
86
+ function isNotEmpty(value) {
87
+ return value !== null && value !== void 0 && value !== "";
88
+ }
89
+ class TokenRefresher {
90
+ isRefreshing = false;
91
+ /**
92
+ * 自动刷新过期的凭证,并重新发送请求
93
+ */
94
+ async refreshTokenAndRetry(err, maxRetry = 3) {
95
+ const isMiNA = err?.config?.url?.includes("mina.mi.com");
96
+ const isMIoT = err?.config?.url?.includes("io.mi.com");
97
+ if (!isMiNA && !isMIoT || err.response?.status !== 401) {
98
+ return;
99
+ }
100
+ if (this.isRefreshing) {
101
+ return;
102
+ }
103
+ let result;
104
+ this.isRefreshing = true;
105
+ let newServiceAccount = void 0;
106
+ for (let i = 0; i < maxRetry; i++) {
107
+ if (Debugger.debug) {
108
+ console.log(`\u274C \u767B\u5F55\u51ED\u8BC1\u5DF2\u8FC7\u671F\uFF0C\u6B63\u5728\u5C1D\u8BD5\u5237\u65B0 Token ${i + 1}`);
109
+ }
110
+ newServiceAccount = await this.refreshToken(err);
111
+ if (newServiceAccount) {
112
+ result = await this.retry(err, newServiceAccount);
113
+ break;
114
+ }
115
+ await sleep(3e3);
116
+ }
117
+ this.isRefreshing = false;
118
+ if (!newServiceAccount) {
119
+ console.error("\u274C \u5237\u65B0\u767B\u5F55\u51ED\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8D26\u53F7\u5BC6\u7801\u662F\u5426\u4ECD\u7136\u6709\u6548\u3002");
120
+ }
121
+ return result;
122
+ }
123
+ /**
124
+ * 刷新登录凭证并同步到本地
125
+ */
126
+ async refreshToken(_err) {
127
+ return void 0;
128
+ }
129
+ /**
130
+ * 重新请求
131
+ */
132
+ async retry(_err, account) {
133
+ const cookies = _err.config.cookies ?? {};
134
+ for (const key of ["serviceToken"]) {
135
+ if (cookies[key] && account[key]) {
136
+ cookies[key] = account[key];
137
+ }
138
+ }
139
+ for (const key of ["deviceSNProfile"]) {
140
+ if (cookies[key] && account.device?.[key]) {
141
+ cookies[key] = account.device[key];
142
+ }
143
+ }
144
+ return _http(HTTPClient.buildConfig(_err.config));
145
+ }
146
+ }
147
+ const tokenRefresher = new TokenRefresher();
148
+ export {
149
+ Http
150
+ };
151
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/http.ts"],"sourcesContent":["import { sleep } from './parse.js';\nimport { jsonEncode } from './parse.js';\nimport axios from 'axios';\nimport type { MiAccount } from '../mi/typing.js';\nimport { Debugger } from './debug.js';\n\nconst _baseConfig: any = {\n proxy: false,\n decompress: true,\n headers: {\n 'Accept-Encoding': 'gzip, deflate',\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'User-Agent':\n 'Dalvik/2.1.0 (Linux; U; Android 10; RMX2111 Build/QP1A.190711.020) APP/xiaomi.mico APPV/2004040 MK/Uk1YMjExMQ== PassportSDK/3.8.3 passport-ui/3.8.3',\n },\n};\n\nconst _http = axios.create(_baseConfig);\n\ninterface HttpError {\n isError: true;\n error: any;\n code: string;\n message: string;\n}\n\ntype RequestConfig = any & {\n account?: MiAccount;\n setAccount?: (newAccount: any) => void;\n rawResponse?: boolean;\n cookies?: Record<string, string | number | boolean | undefined>;\n};\n\n_http.interceptors.response.use(\n (res: any) => {\n if (res.config.rawResponse) {\n return res;\n }\n return res.data;\n },\n async (err) => {\n // 401 登录凭证过期后,自动刷新 token\n const newResult = await tokenRefresher.refreshTokenAndRetry(err);\n if (newResult) {\n return newResult;\n }\n const error = err.response?.data?.error || err.response?.data;\n const request = {\n method: err.config.method,\n url: err.config.url,\n headers: jsonEncode(err.config.headers),\n data: jsonEncode({ body: err.config.data }),\n };\n const response = !err.response\n ? undefined\n : {\n url: err.config.url,\n status: err.response.status,\n headers: jsonEncode(err.response.headers),\n data: jsonEncode({ body: err.response.data }),\n };\n return {\n isError: true,\n code: error?.code || err.response?.status || err.code || '未知',\n message: error?.message || err.response?.statusText || err.message || '未知',\n error: { request, response },\n };\n },\n);\n\nclass HTTPClient {\n // 默认 5 秒超时\n timeout = 5 * 1000;\n\n async get<T = any>(\n url: string,\n _query?: Record<string, string | number | boolean | undefined> | RequestConfig,\n _config?: RequestConfig,\n ): Promise<T | HttpError> {\n let query = _query;\n let config = _config;\n if (_config === undefined) {\n config = _query;\n query = undefined;\n }\n return _http.get<T>(HTTPClient.buildURL(url, query), HTTPClient.buildConfig(config)) as any;\n }\n\n async post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T | HttpError> {\n return _http.post<T>(url, data, HTTPClient.buildConfig(config)) as any;\n }\n\n static buildURL = (url: string, query?: Record<string, any>) => {\n const _url = new URL(url);\n for (const [key, value] of Object.entries(query ?? {})) {\n if (isNotEmpty(value)) {\n _url.searchParams.append(key, value.toString());\n }\n }\n return _url.href;\n };\n\n static buildConfig = (config?: RequestConfig) => {\n if (config?.cookies) {\n config.headers = {\n ...config.headers,\n Cookie: Object.entries(config.cookies)\n .map(([key, value]) => `${key}=${value == null ? '' : value.toString()};`)\n .join(' '),\n };\n }\n if (config && !config.timeout) {\n config.timeout = Http.timeout; // 默认超时时间为 5 秒\n }\n return config;\n };\n}\n\nexport const Http = new HTTPClient();\n\nfunction isNotEmpty(value: any): boolean {\n return value !== null && value !== undefined && value !== '';\n}\n\nclass TokenRefresher {\n isRefreshing = false;\n\n /**\n * 自动刷新过期的凭证,并重新发送请求\n */\n async refreshTokenAndRetry(err: any, maxRetry = 3) {\n const isMiNA = err?.config?.url?.includes('mina.mi.com');\n const isMIoT = err?.config?.url?.includes('io.mi.com');\n if ((!isMiNA && !isMIoT) || err.response?.status !== 401) {\n return;\n }\n if (this.isRefreshing) {\n return;\n }\n let result: any;\n this.isRefreshing = true;\n let newServiceAccount = undefined;\n for (let i = 0; i < maxRetry; i++) {\n if (Debugger.debug) {\n console.log(`❌ 登录凭证已过期,正在尝试刷新 Token ${i + 1}`);\n }\n newServiceAccount = await this.refreshToken(err);\n if (newServiceAccount) {\n // 刷新成功,重新请求\n result = await this.retry(err, newServiceAccount);\n break;\n }\n // 隔 3 秒后重试\n await sleep(3000);\n }\n this.isRefreshing = false;\n if (!newServiceAccount) {\n console.error('❌ 刷新登录凭证失败,请检查账号密码是否仍然有效。');\n }\n return result;\n }\n\n /**\n * 刷新登录凭证并同步到本地\n */\n async refreshToken(_err: any) {\n // 注意:这里需要循环依赖,暂时简化处理\n // 实际应该从配置中读取并刷新\n return undefined;\n }\n\n /**\n * 重新请求\n */\n async retry(_err: any, account: any) {\n // 更新 cookies\n const cookies = _err.config.cookies ?? {};\n for (const key of ['serviceToken']) {\n if (cookies[key] && account[key]) {\n cookies[key] = account[key];\n }\n }\n for (const key of ['deviceSNProfile']) {\n if (cookies[key] && account.device?.[key]) {\n cookies[key] = account.device[key];\n }\n }\n // 重新请求\n return _http(HTTPClient.buildConfig(_err.config)!);\n }\n}\n\nconst tokenRefresher = new TokenRefresher();\n"],"mappings":"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","names":[]}
@@ -0,0 +1,6 @@
1
+ export { Http } from './http.js';
2
+ export { Debugger } from './debug.js';
3
+ export { decodeMIoT, decodeQuery, encodeFormData, encodeMIoT, encodeQuery, parseAuthPass } from './codec.js';
4
+ export { md5, randomNoise, randomString, rc4Decrypt, rc4Encrypt, sha1, sha256, signNonce, uuid } from './hash.js';
5
+ export { fileExists, getDataDir, readFile, readJSON, writeFile, writeJSON } from './io.js';
6
+ import '../mi/typing.js';
@@ -0,0 +1,10 @@
1
+ import { Http } from "./http.js";
2
+ import { Debugger } from "./debug.js";
3
+ export * from "./codec.js";
4
+ export * from "./hash.js";
5
+ export * from "./io.js";
6
+ export {
7
+ Debugger,
8
+ Http
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/index.ts"],"sourcesContent":["export { Http } from './http.js';\nexport { Debugger } from './debug.js';\nexport * from './codec.js';\nexport * from './hash.js';\nexport * from './io.js';\n"],"mappings":"AAAA,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 获取数据目录
3
+ */
4
+ declare function getDataDir(subdir?: string): string;
5
+ /**
6
+ * 读取 JSON 文件
7
+ */
8
+ declare function readJSON<T = any>(filename: string): Promise<T | undefined>;
9
+ /**
10
+ * 写入 JSON 文件
11
+ */
12
+ declare function writeJSON(filename: string, data: any): Promise<void>;
13
+ /**
14
+ * 检查文件是否存在
15
+ */
16
+ declare function fileExists(filepath: string): Promise<boolean>;
17
+ /**
18
+ * 读取文件
19
+ */
20
+ declare function readFile(filepath: string): Promise<Buffer>;
21
+ /**
22
+ * 写入文件
23
+ */
24
+ declare function writeFile(filepath: string, content: string | Buffer): Promise<void>;
25
+
26
+ export { fileExists, getDataDir, readFile, readJSON, writeFile, writeJSON };
@@ -0,0 +1,53 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { join } from "node:path";
3
+ function getDataDir(subdir) {
4
+ const baseDir = join(process.cwd(), ".migpt");
5
+ if (subdir) {
6
+ return join(baseDir, subdir);
7
+ }
8
+ return baseDir;
9
+ }
10
+ async function readJSON(filename) {
11
+ try {
12
+ const filepath = join(getDataDir(), filename);
13
+ const content = await fs.readFile(filepath, "utf-8");
14
+ return JSON.parse(content);
15
+ } catch {
16
+ return void 0;
17
+ }
18
+ }
19
+ async function writeJSON(filename, data) {
20
+ try {
21
+ const dir = getDataDir();
22
+ await fs.mkdir(dir, { recursive: true });
23
+ const filepath = join(dir, filename);
24
+ await fs.writeFile(filepath, JSON.stringify(data, null, 2), "utf-8");
25
+ } catch (err) {
26
+ console.error("\u274C \u5199\u5165\u6587\u4EF6\u5931\u8D25:", err.message);
27
+ }
28
+ }
29
+ async function fileExists(filepath) {
30
+ try {
31
+ await fs.access(filepath);
32
+ return true;
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+ async function readFile(filepath) {
38
+ return fs.readFile(filepath);
39
+ }
40
+ async function writeFile(filepath, content) {
41
+ const dir = join(filepath, "..");
42
+ await fs.mkdir(dir, { recursive: true });
43
+ await fs.writeFile(filepath, content);
44
+ }
45
+ export {
46
+ fileExists,
47
+ getDataDir,
48
+ readFile,
49
+ readJSON,
50
+ writeFile,
51
+ writeJSON
52
+ };
53
+ //# sourceMappingURL=io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/io.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * 获取数据目录\n */\nexport function getDataDir(subdir?: string): string {\n const baseDir = join(process.cwd(), '.migpt');\n if (subdir) {\n return join(baseDir, subdir);\n }\n return baseDir;\n}\n\n/**\n * 读取 JSON 文件\n */\nexport async function readJSON<T = any>(filename: string): Promise<T | undefined> {\n try {\n const filepath = join(getDataDir(), filename);\n const content = await fs.readFile(filepath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return undefined;\n }\n}\n\n/**\n * 写入 JSON 文件\n */\nexport async function writeJSON(filename: string, data: any): Promise<void> {\n try {\n const dir = getDataDir();\n await fs.mkdir(dir, { recursive: true });\n const filepath = join(dir, filename);\n await fs.writeFile(filepath, JSON.stringify(data, null, 2), 'utf-8');\n } catch (err: any) {\n console.error('❌ 写入文件失败:', err.message);\n }\n}\n\n/**\n * 检查文件是否存在\n */\nexport async function fileExists(filepath: string): Promise<boolean> {\n try {\n await fs.access(filepath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 读取文件\n */\nexport async function readFile(filepath: string): Promise<Buffer> {\n return fs.readFile(filepath);\n}\n\n/**\n * 写入文件\n */\nexport async function writeFile(filepath: string, content: string | Buffer): Promise<void> {\n const dir = join(filepath, '..');\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(filepath, content);\n}\n"],"mappings":"AAAA,SAAS,YAAY,UAAU;AAC/B,SAAS,YAAY;AAKd,SAAS,WAAW,QAAyB;AAClD,QAAM,UAAU,KAAK,QAAQ,IAAI,GAAG,QAAQ;AAC5C,MAAI,QAAQ;AACV,WAAO,KAAK,SAAS,MAAM;AAAA,EAC7B;AACA,SAAO;AACT;AAKA,eAAsB,SAAkB,UAA0C;AAChF,MAAI;AACF,UAAM,WAAW,KAAK,WAAW,GAAG,QAAQ;AAC5C,UAAM,UAAU,MAAM,GAAG,SAAS,UAAU,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,UAAU,UAAkB,MAA0B;AAC1E,MAAI;AACF,UAAM,MAAM,WAAW;AACvB,UAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,UAAM,WAAW,KAAK,KAAK,QAAQ;AACnC,UAAM,GAAG,UAAU,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAAA,EACrE,SAAS,KAAU;AACjB,YAAQ,MAAM,gDAAa,IAAI,OAAO;AAAA,EACxC;AACF;AAKA,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAM,GAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,SAAS,UAAmC;AAChE,SAAO,GAAG,SAAS,QAAQ;AAC7B;AAKA,eAAsB,UAAU,UAAkB,SAAyC;AACzF,QAAM,MAAM,KAAK,UAAU,IAAI;AAC/B,QAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,GAAG,UAAU,UAAU,OAAO;AACtC;","names":[]}
@@ -0,0 +1,26 @@
1
+ declare function jsonEncode<T>(obj: T, options?: {
2
+ prettier?: boolean;
3
+ }): string | undefined;
4
+ declare function jsonDecode<T = any>(json: string | null | undefined): T | undefined;
5
+ /**
6
+ * 清理 JSON 字符串并解码
7
+ */
8
+ declare function cleanJsonAndDecode(input: string | undefined | null): any;
9
+ /**
10
+ * 获取数组第一个元素
11
+ */
12
+ declare function firstOf<T>(items?: T[]): T | undefined;
13
+ /**
14
+ * 获取数组最后一个元素
15
+ */
16
+ declare function lastOf<T>(items?: T[]): T | undefined;
17
+ /**
18
+ * 休眠
19
+ */
20
+ declare function sleep(ms: number): Promise<void>;
21
+ /**
22
+ * 断言
23
+ */
24
+ declare function assert(condition: boolean, message: string): asserts condition;
25
+
26
+ export { assert, cleanJsonAndDecode, firstOf, jsonDecode, jsonEncode, lastOf, sleep };
@@ -0,0 +1,51 @@
1
+ function jsonEncode(obj, options) {
2
+ const { prettier } = options ?? {};
3
+ try {
4
+ return JSON.stringify(obj, void 0, prettier ? 4 : 0);
5
+ } catch (_) {
6
+ return void 0;
7
+ }
8
+ }
9
+ function jsonDecode(json) {
10
+ if (!json) {
11
+ return void 0;
12
+ }
13
+ try {
14
+ return JSON.parse(json);
15
+ } catch (_) {
16
+ return void 0;
17
+ }
18
+ }
19
+ function cleanJsonAndDecode(input) {
20
+ if (input == void 0) return void 0;
21
+ const pattern = /(\{[\s\S]*?"\s*:\s*[\s\S]*?})/;
22
+ const match = input.match(pattern);
23
+ if (!match) {
24
+ return void 0;
25
+ }
26
+ return jsonDecode(match[0]);
27
+ }
28
+ function firstOf(items) {
29
+ return items ? items.length < 1 ? void 0 : items[0] : void 0;
30
+ }
31
+ function lastOf(items) {
32
+ return items?.length ? items[items.length - 1] : void 0;
33
+ }
34
+ function sleep(ms) {
35
+ return new Promise((resolve) => setTimeout(resolve, ms));
36
+ }
37
+ function assert(condition, message) {
38
+ if (!condition) {
39
+ throw new Error(message);
40
+ }
41
+ }
42
+ export {
43
+ assert,
44
+ cleanJsonAndDecode,
45
+ firstOf,
46
+ jsonDecode,
47
+ jsonEncode,
48
+ lastOf,
49
+ sleep
50
+ };
51
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/parse.ts"],"sourcesContent":["export function jsonEncode<T>(obj: T, options?: { prettier?: boolean }) {\n const { prettier } = options ?? {};\n try {\n return JSON.stringify(obj, undefined, prettier ? 4 : 0);\n } catch (_) {\n return undefined;\n }\n}\n\nexport function jsonDecode<T = any>(json: string | null | undefined) {\n if (!json) {\n return undefined;\n }\n try {\n return JSON.parse(json) as T;\n } catch (_) {\n return undefined;\n }\n}\n\n/**\n * 清理 JSON 字符串并解码\n */\nexport function cleanJsonAndDecode(input: string | undefined | null) {\n if (input == undefined) return undefined;\n const pattern = /(\\{[\\s\\S]*?\"\\s*:\\s*[\\s\\S]*?})/;\n const match = input.match(pattern);\n\n if (!match) {\n return undefined;\n }\n\n return jsonDecode(match[0]);\n}\n\n/**\n * 获取数组第一个元素\n */\nexport function firstOf<T>(items?: T[]) {\n return items ? (items.length < 1 ? undefined : items[0]) : undefined;\n}\n\n/**\n * 获取数组最后一个元素\n */\nexport function lastOf<T>(items?: T[]) {\n return items?.length ? items[items.length - 1] : undefined;\n}\n\n/**\n * 休眠\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * 断言\n */\nexport function assert(condition: boolean, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n"],"mappings":"AAAO,SAAS,WAAc,KAAQ,SAAkC;AACtE,QAAM,EAAE,SAAS,IAAI,WAAW,CAAC;AACjC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,QAAW,WAAW,IAAI,CAAC;AAAA,EACxD,SAAS,GAAG;AACV,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAoB,MAAiC;AACnE,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,SAAS,GAAG;AACV,WAAO;AAAA,EACT;AACF;AAKO,SAAS,mBAAmB,OAAkC;AACnE,MAAI,SAAS,OAAW,QAAO;AAC/B,QAAM,UAAU;AAChB,QAAM,QAAQ,MAAM,MAAM,OAAO;AAEjC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,MAAM,CAAC,CAAC;AAC5B;AAKO,SAAS,QAAW,OAAa;AACtC,SAAO,QAAS,MAAM,SAAS,IAAI,SAAY,MAAM,CAAC,IAAK;AAC7D;AAKO,SAAS,OAAU,OAAa;AACrC,SAAO,OAAO,SAAS,MAAM,MAAM,SAAS,CAAC,IAAI;AACnD;AAKO,SAAS,MAAM,IAA2B;AAC/C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAKO,SAAS,OAAO,WAAoB,SAAoC;AAC7E,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACF;","names":[]}
package/index.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
2
+ import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk';
3
+ import { miGPTPlugin } from './src/channel.js';
4
+ import { setMiGPTRuntime } from './src/runtime.js';
5
+
6
+ const plugin = {
7
+ id: 'migpt-claw',
8
+ name: 'MiGPT',
9
+ description: '小米小爱音箱 OpenClaw Channel 插件',
10
+ configSchema: emptyPluginConfigSchema(),
11
+ register(api: OpenClawPluginApi) {
12
+ setMiGPTRuntime(api.runtime);
13
+ api.registerChannel({ plugin: miGPTPlugin });
14
+ },
15
+ };
16
+
17
+ export default plugin;
18
+
19
+ export { miGPTPlugin } from './src/channel.js';
20
+ export { setMiGPTRuntime, getMiGPTRuntime } from './src/runtime.js';
21
+ export { miGPTOnboardingAdapter } from './src/onboarding.js';
22
+ export { MiService, type MiServiceConfig } from './src/service.js';
23
+ export { MiMessage, type IMessage } from './src/message.js';
24
+ export { MiSpeaker } from './src/speaker.js';
25
+ export * from './src/config.js';
26
+ export * from './src/types.js';