@wu529778790/open-im 1.11.8-beta.2 → 1.11.8-beta.21

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 (60) hide show
  1. package/dist/adapters/codebuddy-adapter.js +3 -17
  2. package/dist/adapters/codex-adapter.js +3 -16
  3. package/dist/adapters/opencode-adapter.d.ts +0 -5
  4. package/dist/adapters/opencode-adapter.js +10 -25
  5. package/dist/adapters/registry.js +10 -1
  6. package/dist/clawbot/client.js +72 -78
  7. package/dist/clawbot/qr-login.d.ts +1 -0
  8. package/dist/clawbot/qr-login.js +7 -0
  9. package/dist/codebuddy/cli-runner.d.ts +2 -22
  10. package/dist/codebuddy/cli-runner.js +9 -27
  11. package/dist/codex/cli-runner.d.ts +2 -22
  12. package/dist/codex/cli-runner.js +24 -75
  13. package/dist/commands/handler.d.ts +1 -0
  14. package/dist/commands/handler.js +34 -0
  15. package/dist/config/types.d.ts +23 -0
  16. package/dist/config-web-auth.d.ts +13 -0
  17. package/dist/config-web-auth.js +114 -0
  18. package/dist/config-web-browser.d.ts +4 -0
  19. package/dist/config-web-browser.js +48 -0
  20. package/dist/config-web-cors.d.ts +5 -0
  21. package/dist/config-web-cors.js +48 -0
  22. package/dist/config-web-health.d.ts +7 -0
  23. package/dist/config-web-health.js +65 -0
  24. package/dist/config-web-http.d.ts +3 -0
  25. package/dist/config-web-http.js +31 -0
  26. package/dist/config-web-page-i18n.d.ts +36 -2
  27. package/dist/config-web-page-i18n.js +36 -2
  28. package/dist/config-web-payload.d.ts +84 -0
  29. package/dist/config-web-payload.js +260 -0
  30. package/dist/config-web-probes.d.ts +2 -0
  31. package/dist/config-web-probes.js +271 -0
  32. package/dist/config-web.d.ts +3 -11
  33. package/dist/config-web.js +45 -815
  34. package/dist/config.js +22 -1
  35. package/dist/constants.d.ts +10 -0
  36. package/dist/constants.js +11 -0
  37. package/dist/opencode/cli-runner.d.ts +2 -22
  38. package/dist/opencode/cli-runner.js +47 -68
  39. package/dist/opencode/sdk-manager.d.ts +11 -0
  40. package/dist/opencode/sdk-manager.js +46 -0
  41. package/dist/opencode/sdk-runner.d.ts +7 -0
  42. package/dist/opencode/sdk-runner.js +225 -0
  43. package/dist/platform/handle-ai-request.js +18 -1
  44. package/dist/qq/client.js +45 -53
  45. package/dist/shared/ai-task.d.ts +15 -0
  46. package/dist/shared/ai-task.js +174 -2
  47. package/dist/shared/cli-runner-base.d.ts +39 -0
  48. package/dist/shared/cli-runner-base.js +108 -0
  49. package/dist/shared/connection-manager.d.ts +111 -0
  50. package/dist/shared/connection-manager.js +157 -0
  51. package/dist/shared/session-invalid-detector.d.ts +5 -0
  52. package/dist/shared/session-invalid-detector.js +20 -0
  53. package/dist/wework/client.js +79 -127
  54. package/dist/workbuddy/client.js +40 -74
  55. package/package.json +4 -1
  56. package/web/dist/assets/index-6e51Wtaa.css +1 -0
  57. package/web/dist/assets/index-Da9qKWA2.js +57 -0
  58. package/web/dist/index.html +2 -2
  59. package/web/dist/assets/index-XKVTb-0p.css +0 -1
  60. package/web/dist/assets/index-yDVGC_84.js +0 -57
@@ -0,0 +1,271 @@
1
+ import { DWClient } from "dingtalk-stream";
2
+ import { PLATFORM_TEST_TIMEOUT_MS } from "./constants.js";
3
+ import { initWeWork, stopWeWork } from "./wework/client.js";
4
+ import { clean } from "./config-web-payload.js";
5
+ export function toErrorMessage(error) {
6
+ return error instanceof Error ? error.message : String(error);
7
+ }
8
+ async function readJsonResponse(response) {
9
+ const text = await response.text();
10
+ if (!text)
11
+ return {};
12
+ try {
13
+ return JSON.parse(text);
14
+ }
15
+ catch {
16
+ throw new Error(`Unexpected non-JSON response: ${text.slice(0, 200)}`);
17
+ }
18
+ }
19
+ function createProbeConfig(values) {
20
+ return {
21
+ enabledPlatforms: [],
22
+ allowedUserIds: [],
23
+ telegramAllowedUserIds: [],
24
+ feishuAllowedUserIds: [],
25
+ qqAllowedUserIds: [],
26
+ weworkAllowedUserIds: [],
27
+ dingtalkAllowedUserIds: [],
28
+ workbuddyAllowedUserIds: [],
29
+ clawbotAllowedUserIds: [],
30
+ codexCliPath: "codex",
31
+ claudeWorkDir: process.cwd(),
32
+ claudeSessionIdleTtlMinutes: 30,
33
+ logDir: "",
34
+ logLevel: "INFO",
35
+ telemetry: { enabled: true },
36
+ autopilot: {
37
+ enabled: true,
38
+ maxRetries: 5,
39
+ defaultIntervalHours: 5,
40
+ shortRetrySeconds: 60,
41
+ autoResumePrompt: "继续",
42
+ },
43
+ codebuddyCliPath: "codebuddy",
44
+ opencodeCliPath: "opencode",
45
+ platforms: {},
46
+ ...values,
47
+ };
48
+ }
49
+ function validateConfigForPlatform(platform, config) {
50
+ const errors = [];
51
+ const c = config;
52
+ switch (platform) {
53
+ case "telegram":
54
+ if (!c.botToken || typeof c.botToken !== "string" || !clean(c.botToken)) {
55
+ errors.push("Telegram bot token is required and must be a non-empty string.");
56
+ }
57
+ if (c.proxy && typeof c.proxy !== "string") {
58
+ errors.push("Proxy must be a string if provided.");
59
+ }
60
+ break;
61
+ case "feishu":
62
+ if (!c.appId || typeof c.appId !== "string" || !clean(c.appId)) {
63
+ errors.push("Feishu app ID is required and must be a non-empty string.");
64
+ }
65
+ if (!c.appSecret || typeof c.appSecret !== "string" || !clean(c.appSecret)) {
66
+ errors.push("Feishu app secret is required and must be a non-empty string.");
67
+ }
68
+ break;
69
+ case "qq":
70
+ if (!c.appId || typeof c.appId !== "string" || !clean(c.appId)) {
71
+ errors.push("QQ app ID is required and must be a non-empty string.");
72
+ }
73
+ if (!c.secret || typeof c.secret !== "string" || !clean(c.secret)) {
74
+ errors.push("QQ app secret is required and must be a non-empty string.");
75
+ }
76
+ break;
77
+ case "wework":
78
+ if (!c.corpId || typeof c.corpId !== "string" || !clean(c.corpId)) {
79
+ errors.push("WeWork corp ID is required and must be a non-empty string.");
80
+ }
81
+ if (!c.secret || typeof c.secret !== "string" || !clean(c.secret)) {
82
+ errors.push("WeWork secret is required and must be a non-empty string.");
83
+ }
84
+ break;
85
+ case "dingtalk":
86
+ if (!c.clientId || typeof c.clientId !== "string" || !clean(c.clientId)) {
87
+ errors.push("DingTalk client ID is required and must be a non-empty string.");
88
+ }
89
+ if (!c.clientSecret || typeof c.clientSecret !== "string" || !clean(c.clientSecret)) {
90
+ errors.push("DingTalk client secret is required and must be a non-empty string.");
91
+ }
92
+ break;
93
+ case "workbuddy":
94
+ if (!c.accessToken || typeof c.accessToken !== "string" || !clean(c.accessToken)) {
95
+ errors.push("WorkBuddy access token is required and must be a non-empty string.");
96
+ }
97
+ if (!c.refreshToken || typeof c.refreshToken !== "string" || !clean(c.refreshToken)) {
98
+ errors.push("WorkBuddy refresh token is required and must be a non-empty string.");
99
+ }
100
+ if (!c.userId || typeof c.userId !== "string" || !clean(c.userId)) {
101
+ errors.push("WorkBuddy user ID is required and must be a non-empty string.");
102
+ }
103
+ break;
104
+ case "clawbot":
105
+ if (!c.apiToken || typeof c.apiToken !== "string" || !clean(c.apiToken)) {
106
+ errors.push("ClawBot API token is required and must be a non-empty string.");
107
+ }
108
+ break;
109
+ default:
110
+ errors.push(`Unknown platform: ${platform}`);
111
+ }
112
+ return errors;
113
+ }
114
+ async function probeTelegram(config) {
115
+ const botToken = clean(String(config.botToken ?? ""));
116
+ if (!botToken)
117
+ throw new Error("Telegram bot token is required.");
118
+ const response = await fetch(`https://api.telegram.org/bot${botToken}/getMe`, {
119
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
120
+ });
121
+ const body = await readJsonResponse(response);
122
+ if (!response.ok || body.ok !== true) {
123
+ throw new Error(String(body.description ?? body.error_code ?? `HTTP ${response.status}`));
124
+ }
125
+ const result = (body.result ?? {});
126
+ const username = typeof result.username === "string" ? `@${result.username}` : "bot";
127
+ return `Telegram reachable as ${username}.`;
128
+ }
129
+ async function probeFeishu(config) {
130
+ const appId = clean(String(config.appId ?? ""));
131
+ const appSecret = clean(String(config.appSecret ?? ""));
132
+ if (!appId || !appSecret)
133
+ throw new Error("Feishu app ID and app secret are required.");
134
+ const response = await fetch("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", {
135
+ method: "POST",
136
+ headers: { "content-type": "application/json" },
137
+ body: JSON.stringify({ app_id: appId, app_secret: appSecret }),
138
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
139
+ });
140
+ const body = await readJsonResponse(response);
141
+ if (!response.ok || body.code !== 0) {
142
+ throw new Error(String(body.msg ?? body.message ?? `HTTP ${response.status}`));
143
+ }
144
+ return "Feishu credentials are valid.";
145
+ }
146
+ async function probeQQ(config) {
147
+ const appId = clean(String(config.appId ?? ""));
148
+ const secret = clean(String(config.secret ?? ""));
149
+ if (!appId || !secret)
150
+ throw new Error("QQ app ID and app secret are required.");
151
+ const response = await fetch("https://bots.qq.com/app/getAppAccessToken", {
152
+ method: "POST",
153
+ headers: { "content-type": "application/json" },
154
+ body: JSON.stringify({ appId, clientSecret: secret }),
155
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
156
+ });
157
+ const body = await readJsonResponse(response);
158
+ if (!response.ok || typeof body.access_token !== "string" || body.access_token.length === 0) {
159
+ throw new Error(String(body.message ?? `HTTP ${response.status}`));
160
+ }
161
+ return "QQ credentials are valid.";
162
+ }
163
+ async function probeWeWork(config) {
164
+ const corpId = clean(String(config.corpId ?? ""));
165
+ const secret = clean(String(config.secret ?? ""));
166
+ if (!corpId || !secret)
167
+ throw new Error("WeWork corp ID and secret are required.");
168
+ try {
169
+ await initWeWork(createProbeConfig({ weworkCorpId: corpId, weworkSecret: secret }), async () => { });
170
+ return "WeWork WebSocket authentication succeeded.";
171
+ }
172
+ finally {
173
+ stopWeWork();
174
+ }
175
+ }
176
+ async function probeDingTalk(config) {
177
+ const clientId = clean(String(config.clientId ?? ""));
178
+ const clientSecret = clean(String(config.clientSecret ?? ""));
179
+ if (!clientId || !clientSecret)
180
+ throw new Error("DingTalk client ID and client secret are required.");
181
+ const client = new DWClient({
182
+ clientId,
183
+ clientSecret,
184
+ keepAlive: false,
185
+ debug: false,
186
+ });
187
+ const token = await Promise.race([
188
+ client.getAccessToken(),
189
+ new Promise((_, reject) => setTimeout(() => reject(new Error("DingTalk access token request timed out.")), PLATFORM_TEST_TIMEOUT_MS)),
190
+ ]);
191
+ if (typeof token !== "string" || token.length === 0) {
192
+ throw new Error("DingTalk did not return an access token.");
193
+ }
194
+ return "DingTalk credentials are valid.";
195
+ }
196
+ async function probeWorkBuddy(config) {
197
+ const accessToken = clean(String(config.accessToken ?? ""));
198
+ const refreshToken = clean(String(config.refreshToken ?? ""));
199
+ const userId = clean(String(config.userId ?? ""));
200
+ if (!accessToken || !refreshToken || !userId)
201
+ throw new Error("WorkBuddy access token, refresh token, and user ID are required.");
202
+ const baseUrl = clean(String(config.baseUrl ?? "")) || "https://copilot.tencent.com";
203
+ // Validate credentials by attempting to register workspace (same endpoint as runtime)
204
+ const response = await fetch(`${baseUrl}/v2/agentos/localagent/registerWorkspace`, {
205
+ method: "POST",
206
+ headers: {
207
+ "content-type": "application/json",
208
+ "authorization": `Bearer ${accessToken}`,
209
+ },
210
+ body: JSON.stringify({
211
+ userId,
212
+ hostId: "open-im-test",
213
+ workspaceId: "open-im-test-workspace",
214
+ workspaceName: "OpenIM Test Workspace",
215
+ localAgentType: "ide",
216
+ }),
217
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
218
+ });
219
+ if (!response.ok) {
220
+ const body = await response.text();
221
+ throw new Error(`WorkBuddy authentication failed: ${body.slice(0, 200) || `HTTP ${response.status}`}`);
222
+ }
223
+ return "WorkBuddy credentials are valid.";
224
+ }
225
+ async function probeClawBot(config) {
226
+ const apiUrl = clean(String(config.apiUrl ?? "http://127.0.0.1:26322"));
227
+ const apiToken = clean(String(config.apiToken ?? ""));
228
+ if (!apiToken)
229
+ throw new Error("ClawBot API token is required.");
230
+ const { randomUUID } = await import('node:crypto');
231
+ const response = await fetch(`${apiUrl}/ilink/bot/getupdates?timeout=1&bot_token=${encodeURIComponent(apiToken)}`, {
232
+ headers: {
233
+ 'Content-Type': 'application/json',
234
+ 'AuthorizationType': 'ilink_bot_token',
235
+ 'iLink-App-Id': 'bot',
236
+ 'iLink-App-ClientVersion': '131588',
237
+ 'X-WECHAT-UIN': randomUUID(),
238
+ },
239
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
240
+ });
241
+ const body = await readJsonResponse(response);
242
+ const ok = body.ok === true || body.ret === 0 || body.ret === '0';
243
+ if (!response.ok || !ok) {
244
+ throw new Error(String(body.error ?? body.description ?? `HTTP ${response.status}`));
245
+ }
246
+ return "ClawBot API reachable.";
247
+ }
248
+ export async function testPlatformConfig(platform, config) {
249
+ const errors = validateConfigForPlatform(platform, config);
250
+ if (errors.length > 0) {
251
+ throw new Error(errors.join("; "));
252
+ }
253
+ switch (platform) {
254
+ case "telegram":
255
+ return probeTelegram(config);
256
+ case "feishu":
257
+ return probeFeishu(config);
258
+ case "qq":
259
+ return probeQQ(config);
260
+ case "wework":
261
+ return probeWeWork(config);
262
+ case "dingtalk":
263
+ return probeDingTalk(config);
264
+ case "workbuddy":
265
+ return probeWorkBuddy(config);
266
+ case "clawbot":
267
+ return probeClawBot(config);
268
+ default:
269
+ throw new Error(`Unknown platform: ${platform}`);
270
+ }
271
+ }
@@ -1,4 +1,6 @@
1
- import { type FileConfig } from "./config.js";
1
+ export { getHealthPlatformSnapshot } from "./config-web-health.js";
2
+ export { getWebConfigUrl } from "./config-web-browser.js";
3
+ export { testPlatformConfig } from "./config-web-probes.js";
2
4
  type WebFlowMode = "init" | "start" | "dev";
3
5
  type WebFlowResult = "saved" | "cancel";
4
6
  export interface StartedWebConfigServer {
@@ -7,15 +9,6 @@ export interface StartedWebConfigServer {
7
9
  waitForResult: Promise<WebFlowResult>;
8
10
  loginUrl?: string;
9
11
  }
10
- export declare function getHealthPlatformSnapshot(file: FileConfig, env?: NodeJS.ProcessEnv): Record<string, {
11
- configured: boolean;
12
- enabled: boolean;
13
- healthy: boolean;
14
- message?: string;
15
- }>;
16
- export declare function testPlatformConfig(platform: string, config: Record<string, unknown>): Promise<string>;
17
- export declare function getWebConfigPort(): number;
18
- export declare function getWebConfigUrl(): string;
19
12
  export declare function startWebConfigServer(options: {
20
13
  mode: WebFlowMode;
21
14
  cwd: string;
@@ -25,4 +18,3 @@ export declare function runWebConfigFlow(options: {
25
18
  mode: WebFlowMode;
26
19
  cwd: string;
27
20
  }): Promise<WebFlowResult>;
28
- export {};