@insta-dev01/intclaw 1.0.10 → 1.1.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 (49) hide show
  1. package/LICENSE +1 -1
  2. package/README.en.md +424 -0
  3. package/README.md +365 -164
  4. package/index.ts +28 -0
  5. package/openclaw.plugin.json +12 -41
  6. package/package.json +69 -40
  7. package/src/channel.ts +557 -0
  8. package/src/config/accounts.ts +230 -0
  9. package/src/config/schema.ts +144 -0
  10. package/src/core/connection.ts +733 -0
  11. package/src/core/message-handler.ts +1268 -0
  12. package/src/core/provider.ts +106 -0
  13. package/src/core/state.ts +54 -0
  14. package/src/directory.ts +95 -0
  15. package/src/gateway-methods.ts +237 -0
  16. package/src/onboarding.ts +387 -0
  17. package/src/policy.ts +19 -0
  18. package/src/probe.ts +213 -0
  19. package/src/reply-dispatcher.ts +674 -0
  20. package/src/runtime.ts +7 -0
  21. package/src/sdk/helpers.ts +317 -0
  22. package/src/sdk/types.ts +515 -0
  23. package/src/secret-input.ts +19 -0
  24. package/src/services/media/audio.ts +54 -0
  25. package/src/services/media/chunk-upload.ts +293 -0
  26. package/src/services/media/common.ts +154 -0
  27. package/src/services/media/file.ts +70 -0
  28. package/src/services/media/image.ts +67 -0
  29. package/src/services/media/index.ts +10 -0
  30. package/src/services/media/video.ts +162 -0
  31. package/src/services/media.ts +1134 -0
  32. package/src/services/messaging/index.ts +16 -0
  33. package/src/services/messaging/send.ts +137 -0
  34. package/src/services/messaging.ts +800 -0
  35. package/src/targets.ts +45 -0
  36. package/src/types/index.ts +52 -0
  37. package/src/utils/agent.ts +63 -0
  38. package/src/utils/async.ts +51 -0
  39. package/src/utils/constants.ts +9 -0
  40. package/src/utils/http-client.ts +84 -0
  41. package/src/utils/index.ts +8 -0
  42. package/src/utils/logger.ts +78 -0
  43. package/src/utils/session.ts +118 -0
  44. package/src/utils/token.ts +94 -0
  45. package/src/utils/utils-legacy.ts +506 -0
  46. package/.env.example +0 -11
  47. package/skills/intclaw_matrix/SKILL.md +0 -20
  48. package/src/channel/intclaw_channel.js +0 -155
  49. package/src/index.js +0 -23
package/src/channel.ts ADDED
@@ -0,0 +1,557 @@
1
+ import type {
2
+ ChannelMeta,
3
+ ChannelPlugin,
4
+ ClawdbotConfig,
5
+ } from "openclaw/plugin-sdk";
6
+ import {
7
+ buildBaseChannelStatusSummary,
8
+ createDefaultChannelRuntimeState,
9
+ DEFAULT_ACCOUNT_ID,
10
+ resolveAllowlistProviderRuntimeGroupPolicy,
11
+ resolveDefaultGroupPolicy,
12
+ } from "./sdk/helpers.ts";
13
+ import { createLogger } from "./utils/logger.ts";
14
+ import {
15
+ resolveIntclawAccount,
16
+ resolveIntclawCredentials,
17
+ listIntclawAccountIds,
18
+ resolveDefaultIntclawAccountId,
19
+ } from "./config/accounts.ts";
20
+ import {
21
+ listIntclawDirectoryPeers,
22
+ listIntclawDirectoryGroups,
23
+ listIntclawDirectoryPeersLive,
24
+ listIntclawDirectoryGroupsLive,
25
+ } from "./directory.ts";
26
+ import { resolveIntclawGroupToolPolicy } from "./policy.ts";
27
+ import { probeIntclaw } from "./probe.ts";
28
+ import { normalizeIntclawTarget, looksLikeIntclawId } from "./targets.ts";
29
+ import { intclawOnboardingAdapter } from "./onboarding.ts";
30
+ import { monitorIntclawProvider } from "./core/provider.ts";
31
+ import { sendTextToIntClaw, sendMediaToIntClaw } from "./services/messaging/index.ts";
32
+ import type { ResolvedIntclawAccount, IntclawConfig } from "./types/index.ts";
33
+
34
+ const meta: ChannelMeta = {
35
+ id: "intclaw",
36
+ label: "IntClaw",
37
+ selectionLabel: "IntClaw (IntClaw)",
38
+ docsPath: "/channels/intclaw",
39
+ docsLabel: "intclaw",
40
+ blurb: "IntClaw企业内部机器人,使用 Stream 模式,无需公网 IP,支持 AI Card 流式响应。",
41
+ aliases: ["int"],
42
+ order: 70,
43
+ };
44
+
45
+ const secretInputJsonSchema = {
46
+ oneOf: [
47
+ { type: "string" },
48
+ {
49
+ type: "object",
50
+ additionalProperties: false,
51
+ required: ["source", "provider", "id"],
52
+ properties: {
53
+ source: { type: "string", enum: ["env", "file", "exec"] },
54
+ provider: { type: "string", minLength: 1 },
55
+ id: { type: "string", minLength: 1 },
56
+ },
57
+ },
58
+ ],
59
+ } as const;
60
+
61
+ export const intclawPlugin: ChannelPlugin<ResolvedIntclawAccount> = {
62
+ id: "intclaw-connector",
63
+ meta: {
64
+ ...meta,
65
+ },
66
+ pairing: {
67
+ idLabel: "intclawUserId",
68
+ normalizeAllowEntry: (entry) => entry.replace(/^(intclaw|user|dd):/i, ""),
69
+ notifyApproval: async ({ cfg, id }) => {
70
+ // TODO: Implement notification when pairing is approved
71
+ const logger = createLogger(false, 'IntClaw:Pairing');
72
+ logger.info(`Pairing approved for user: ${id}`);
73
+ },
74
+ },
75
+ capabilities: {
76
+ chatTypes: ["direct", "group"],
77
+ polls: false,
78
+ threads: false,
79
+ media: true, // ✅ 启用媒体支持
80
+ reactions: false,
81
+ edit: false,
82
+ reply: false,
83
+ },
84
+ agentPrompt: {
85
+ messageToolHints: () => [
86
+ "- IntClaw targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:userId` or `group:conversationId`.",
87
+ "- IntClaw supports interactive cards for rich messages.",
88
+ ],
89
+ },
90
+ groups: {
91
+ resolveToolPolicy: resolveIntclawGroupToolPolicy,
92
+ },
93
+ mentions: {
94
+ stripPatterns: () => ['@[^\\s]+'], // Strip @mentions
95
+ },
96
+ reload: { configPrefixes: ["channels.intclaw-connector"] },
97
+ configSchema: {
98
+ schema: {
99
+ type: "object",
100
+ additionalProperties: false,
101
+ properties: {
102
+ enabled: { type: "boolean" },
103
+ defaultAccount: { type: "string" },
104
+ clientId: { oneOf: [{ type: "string" }, { type: "number" }] },
105
+ clientSecret: secretInputJsonSchema,
106
+ enableMediaUpload: { type: "boolean" },
107
+ systemPrompt: { type: "string" },
108
+ dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
109
+ allowFrom: { type: "array", items: { oneOf: [{ type: "string" }, { type: "number" }] } },
110
+ groupPolicy: { type: "string", enum: ["open", "allowlist", "disabled"] },
111
+ groupAllowFrom: {
112
+ type: "array",
113
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
114
+ },
115
+ requireMention: { type: "boolean" },
116
+ groupSessionScope: {
117
+ type: "string",
118
+ enum: ["group", "group_sender"],
119
+ },
120
+ separateSessionByConversation: { type: "boolean" },
121
+ sharedMemoryAcrossConversations: { type: "boolean" },
122
+ historyLimit: { type: "integer", minimum: 0 },
123
+ dmHistoryLimit: { type: "integer", minimum: 0 },
124
+ textChunkLimit: { type: "integer", minimum: 1 },
125
+ mediaMaxMb: { type: "number", minimum: 0 },
126
+ typingIndicator: { type: "boolean" },
127
+ resolveSenderNames: { type: "boolean" },
128
+ tools: {
129
+ type: "object",
130
+ additionalProperties: false,
131
+ properties: {
132
+ media: { type: "boolean" },
133
+ },
134
+ },
135
+ groups: {
136
+ type: "object",
137
+ additionalProperties: {
138
+ type: "object",
139
+ properties: {
140
+ requireMention: { type: "boolean" },
141
+ tools: {
142
+ type: "object",
143
+ properties: {
144
+ allow: { type: "array", items: { type: "string" } },
145
+ deny: { type: "array", items: { type: "string" } },
146
+ },
147
+ },
148
+ enabled: { type: "boolean" },
149
+ allowFrom: { type: "array", items: { oneOf: [{ type: "string" }, { type: "number" }] } },
150
+ systemPrompt: { type: "string" },
151
+ groupSessionScope: {
152
+ type: "string",
153
+ enum: ["group", "group_sender"],
154
+ },
155
+ },
156
+ },
157
+ },
158
+ accounts: {
159
+ type: "object",
160
+ additionalProperties: {
161
+ type: "object",
162
+ properties: {
163
+ enabled: { type: "boolean" },
164
+ name: { type: "string" },
165
+ clientId: { oneOf: [{ type: "string" }, { type: "number" }] },
166
+ clientSecret: secretInputJsonSchema,
167
+ enableMediaUpload: { type: "boolean" },
168
+ systemPrompt: { type: "string" },
169
+ dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
170
+ allowFrom: { type: "array", items: { oneOf: [{ type: "string" }, { type: "number" }] } },
171
+ groupPolicy: { type: "string", enum: ["open", "allowlist", "disabled"] },
172
+ groupAllowFrom: {
173
+ type: "array",
174
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
175
+ },
176
+ requireMention: { type: "boolean" },
177
+ groupSessionScope: {
178
+ type: "string",
179
+ enum: ["group", "group_sender"],
180
+ },
181
+ separateSessionByConversation: { type: "boolean" },
182
+ sharedMemoryAcrossConversations: { type: "boolean" },
183
+ historyLimit: { type: "integer", minimum: 0 },
184
+ textChunkLimit: { type: "integer", minimum: 1 },
185
+ mediaMaxMb: { type: "number", minimum: 0 },
186
+ typingIndicator: { type: "boolean" },
187
+ tools: {
188
+ type: "object",
189
+ additionalProperties: false,
190
+ properties: {
191
+ media: { type: "boolean" },
192
+ },
193
+ },
194
+ },
195
+ },
196
+ },
197
+ },
198
+ },
199
+ },
200
+ config: {
201
+ listAccountIds: (cfg) => listIntclawAccountIds(cfg),
202
+ resolveAccount: (cfg, accountId) => resolveIntclawAccount({ cfg, accountId }),
203
+ defaultAccountId: (cfg) => resolveDefaultIntclawAccountId(cfg),
204
+ setAccountEnabled: ({ cfg, accountId, enabled }) => {
205
+ const account = resolveIntclawAccount({ cfg, accountId });
206
+ const isDefault = accountId === DEFAULT_ACCOUNT_ID;
207
+
208
+ if (isDefault) {
209
+ // For default account, set top-level enabled
210
+ return {
211
+ ...cfg,
212
+ channels: {
213
+ ...cfg.channels,
214
+ "intclaw-connector": {
215
+ ...cfg.channels?.["intclaw-connector"],
216
+ enabled,
217
+ },
218
+ },
219
+ };
220
+ }
221
+
222
+ // For named accounts, set enabled in accounts[accountId]
223
+ const intclawCfg = cfg.channels?.["intclaw-connector"] as IntclawConfig | undefined;
224
+ return {
225
+ ...cfg,
226
+ channels: {
227
+ ...cfg.channels,
228
+ "intclaw-connector": {
229
+ ...intclawCfg,
230
+ accounts: {
231
+ ...intclawCfg?.accounts,
232
+ [accountId]: {
233
+ ...intclawCfg?.accounts?.[accountId],
234
+ enabled,
235
+ },
236
+ },
237
+ },
238
+ },
239
+ };
240
+ },
241
+ deleteAccount: ({ cfg, accountId }) => {
242
+ const isDefault = accountId === DEFAULT_ACCOUNT_ID;
243
+
244
+ if (isDefault) {
245
+ // Delete entire intclaw-connector config
246
+ const next = { ...cfg } as ClawdbotConfig;
247
+ const nextChannels = { ...cfg.channels };
248
+ delete (nextChannels as Record<string, unknown>)["intclaw-connector"];
249
+ if (Object.keys(nextChannels).length > 0) {
250
+ next.channels = nextChannels;
251
+ } else {
252
+ delete next.channels;
253
+ }
254
+ return next;
255
+ }
256
+
257
+ // Delete specific account from accounts
258
+ const intclawCfg = cfg.channels?.["intclaw-connector"] as IntclawConfig | undefined;
259
+ const accounts = { ...intclawCfg?.accounts };
260
+ delete accounts[accountId];
261
+
262
+ return {
263
+ ...cfg,
264
+ channels: {
265
+ ...cfg.channels,
266
+ "intclaw-connector": {
267
+ ...intclawCfg,
268
+ accounts: Object.keys(accounts).length > 0 ? accounts : undefined,
269
+ },
270
+ },
271
+ };
272
+ },
273
+ isConfigured: (account) => account.configured,
274
+ describeAccount: (account) => ({
275
+ accountId: account.accountId,
276
+ enabled: account.enabled,
277
+ configured: account.configured,
278
+ name: account.name,
279
+ clientId: account.clientId,
280
+ }),
281
+ resolveAllowFrom: ({ cfg, accountId }) => {
282
+ const account = resolveIntclawAccount({ cfg, accountId });
283
+ return (account.config?.allowFrom ?? []).map((entry) => String(entry));
284
+ },
285
+ formatAllowFrom: ({ allowFrom }) =>
286
+ allowFrom
287
+ .map((entry) => String(entry).trim())
288
+ .filter(Boolean)
289
+ .map((entry) => entry.toLowerCase()),
290
+ },
291
+ security: {
292
+ collectWarnings: ({ cfg, accountId }) => {
293
+ const account = resolveIntclawAccount({ cfg, accountId });
294
+ const intclawCfg = account.config;
295
+ const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
296
+ const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
297
+ providerConfigPresent: cfg.channels?.["intclaw-connector"] !== undefined,
298
+ groupPolicy: intclawCfg?.groupPolicy,
299
+ defaultGroupPolicy,
300
+ });
301
+ if (groupPolicy !== "open") return [];
302
+ return [
303
+ `- IntClaw[${account.accountId}] groups: groupPolicy="open" allows any member to trigger (mention-gated). Set channels.intclaw-connector.groupPolicy="allowlist" + channels.intclaw-connector.groupAllowFrom to restrict senders.`,
304
+ ];
305
+ },
306
+ },
307
+ setup: {
308
+ resolveAccountId: () => DEFAULT_ACCOUNT_ID,
309
+ applyAccountConfig: ({ cfg, accountId }) => {
310
+ const isDefault = !accountId || accountId === DEFAULT_ACCOUNT_ID;
311
+
312
+ if (isDefault) {
313
+ return {
314
+ ...cfg,
315
+ channels: {
316
+ ...cfg.channels,
317
+ "intclaw-connector": {
318
+ ...cfg.channels?.["intclaw-connector"],
319
+ enabled: true,
320
+ },
321
+ },
322
+ };
323
+ }
324
+
325
+ const intclawCfg = cfg.channels?.["intclaw-connector"] as IntclawConfig | undefined;
326
+ return {
327
+ ...cfg,
328
+ channels: {
329
+ ...cfg.channels,
330
+ "intclaw-connector": {
331
+ ...intclawCfg,
332
+ accounts: {
333
+ ...intclawCfg?.accounts,
334
+ [accountId]: {
335
+ ...intclawCfg?.accounts?.[accountId],
336
+ enabled: true,
337
+ },
338
+ },
339
+ },
340
+ },
341
+ };
342
+ },
343
+ },
344
+ onboarding: intclawOnboardingAdapter,
345
+ messaging: {
346
+ normalizeTarget: (raw) => normalizeIntclawTarget(raw) ?? undefined,
347
+ targetResolver: {
348
+ looksLikeId: looksLikeIntclawId,
349
+ hint: "<userId|user:userId|group:conversationId>",
350
+ },
351
+ },
352
+ directory: {
353
+ self: async () => null,
354
+ listPeers: async ({ cfg, query, limit, accountId }) =>
355
+ listIntclawDirectoryPeers({
356
+ cfg,
357
+ query: query ?? undefined,
358
+ limit: limit ?? undefined,
359
+ accountId: accountId ?? undefined,
360
+ }),
361
+ listGroups: async ({ cfg, query, limit, accountId }) =>
362
+ listIntclawDirectoryGroups({
363
+ cfg,
364
+ query: query ?? undefined,
365
+ limit: limit ?? undefined,
366
+ accountId: accountId ?? undefined,
367
+ }),
368
+ listPeersLive: async ({ cfg, query, limit, accountId }) =>
369
+ listIntclawDirectoryPeersLive({
370
+ cfg,
371
+ query: query ?? undefined,
372
+ limit: limit ?? undefined,
373
+ accountId: accountId ?? undefined,
374
+ }),
375
+ listGroupsLive: async ({ cfg, query, limit, accountId }) =>
376
+ listIntclawDirectoryGroupsLive({
377
+ cfg,
378
+ query: query ?? undefined,
379
+ limit: limit ?? undefined,
380
+ accountId: accountId ?? undefined,
381
+ }),
382
+ },
383
+ outbound: {
384
+ deliveryMode: "direct",
385
+ chunker: (text, limit) => {
386
+ // Simple markdown chunking - split by newlines
387
+ const chunks: string[] = [];
388
+ const lines = text.split("\n");
389
+ let currentChunk = "";
390
+
391
+ for (const line of lines) {
392
+ const testChunk = currentChunk + (currentChunk ? "\n" : "") + line;
393
+ if (testChunk.length <= limit) {
394
+ currentChunk = testChunk;
395
+ } else {
396
+ if (currentChunk) chunks.push(currentChunk);
397
+ currentChunk = line;
398
+ }
399
+ }
400
+ if (currentChunk) chunks.push(currentChunk);
401
+
402
+ return chunks;
403
+ },
404
+ chunkerMode: "markdown",
405
+ textChunkLimit: 2000,
406
+ sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
407
+ const account = resolveIntclawAccount({ cfg, accountId });
408
+ const result = await sendTextToIntClaw({
409
+ config: account.config,
410
+ target: to,
411
+ text,
412
+ replyToId,
413
+ });
414
+ return {
415
+ channel: "intclaw-connector",
416
+ messageId: result.processQueryKey ?? result.cardInstanceId ?? "unknown",
417
+ conversationId: to,
418
+ };
419
+ },
420
+ sendMedia: async ({ cfg, to, text, mediaUrl, accountId, mediaLocalRoots, replyToId, threadId }) => {
421
+ const account = resolveIntclawAccount({ cfg, accountId });
422
+ const logger = createLogger(account.config?.debug ?? false, 'IntClaw:SendMedia');
423
+
424
+ logger.info('开始处理,参数:', JSON.stringify({
425
+ to,
426
+ text,
427
+ mediaUrl,
428
+ accountId,
429
+ replyToId,
430
+ threadId,
431
+ toType: typeof to,
432
+ mediaUrlType: typeof mediaUrl,
433
+ }));
434
+
435
+ // 参数校验
436
+ if (!to || typeof to !== 'string') {
437
+ throw new Error(`Invalid 'to' parameter: ${to}`);
438
+ }
439
+
440
+ if (!mediaUrl || typeof mediaUrl !== 'string') {
441
+ throw new Error(`Invalid 'mediaUrl' parameter: ${mediaUrl}`);
442
+ }
443
+
444
+ const result = await sendMediaToIntClaw({
445
+ config: account.config,
446
+ target: to,
447
+ text,
448
+ mediaUrl,
449
+ replyToId,
450
+ });
451
+
452
+ logger.info('sendMediaToIntClaw 返回结果:', JSON.stringify({
453
+ ok: result.ok,
454
+ error: result.error,
455
+ hasProcessQueryKey: !!result.processQueryKey,
456
+ hasCardInstanceId: !!result.cardInstanceId,
457
+ }));
458
+
459
+ return {
460
+ channel: "intclaw-connector",
461
+ messageId: result.processQueryKey ?? result.cardInstanceId ?? "unknown",
462
+ conversationId: to,
463
+ };
464
+ },
465
+ },
466
+ status: {
467
+ defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID, { port: null }),
468
+ buildChannelSummary: ({ snapshot }) => ({
469
+ ...buildBaseChannelStatusSummary(snapshot),
470
+ port: snapshot.port ?? null,
471
+ probe: snapshot.probe,
472
+ lastProbeAt: snapshot.lastProbeAt ?? null,
473
+ }),
474
+ probeAccount: async ({ account }) => await probeIntclaw({
475
+ clientId: account.clientId!,
476
+ clientSecret: account.clientSecret!,
477
+ accountId: account.accountId,
478
+ }),
479
+ buildAccountSnapshot: ({ account, runtime, probe }) => ({
480
+ accountId: account.accountId,
481
+ enabled: account.enabled,
482
+ configured: account.configured,
483
+ name: account.name,
484
+ clientId: account.clientId,
485
+ running: runtime?.running ?? false,
486
+ lastStartAt: runtime?.lastStartAt ?? null,
487
+ lastStopAt: runtime?.lastStopAt ?? null,
488
+ lastError: runtime?.lastError ?? null,
489
+ port: runtime?.port ?? null,
490
+ probe,
491
+ }),
492
+ },
493
+ gateway: {
494
+ startAccount: async (ctx) => {
495
+ const account = resolveIntclawAccount({ cfg: ctx.cfg, accountId: ctx.accountId });
496
+ const logger = createLogger(account.config?.debug ?? false, 'IntClaw:Gateway');
497
+
498
+ logger.info(`startAccount 被调用:accountId=${ctx.accountId}`);
499
+ try {
500
+ logger.info('='.repeat(60));
501
+ logger.info('开始加载 provider 模块...');
502
+ const monitorModule = await import("./core/provider.ts");
503
+ logger.info(`monitor module 加载完成`);
504
+ logger.info(`monitor module keys: ${Object.keys(monitorModule).join(', ')}`);
505
+ logger.info(`monitorModule 类型: ${typeof monitorModule}`);
506
+ logger.info(`monitorModule 是否为 null: ${monitorModule === null}`);
507
+ logger.info(`monitorModule 是否为 undefined: ${monitorModule === undefined}`);
508
+
509
+ // 使用 Object.getOwnPropertyDescriptor 检查属性
510
+ const descriptor = Object.getOwnPropertyDescriptor(monitorModule, 'monitorSingleAccount');
511
+ logger.info(`monitorSingleAccount descriptor: ${JSON.stringify(descriptor)}`);
512
+
513
+ // 尝试安全地访问 monitorSingleAccount
514
+ let monitorSingleAccountType = 'unknown';
515
+ try {
516
+ monitorSingleAccountType = typeof monitorModule.monitorSingleAccount;
517
+ } catch (e) {
518
+ monitorSingleAccountType = `error: ${e.message}`;
519
+ }
520
+ logger.info(`monitorModule.monitorSingleAccount: ${monitorSingleAccountType}`);
521
+
522
+ logger.info(`monitorModule.monitorIntclawProvider: ${typeof monitorModule.monitorIntclawProvider}`);
523
+
524
+ // 使用直接属性访问而不是解构
525
+ const monitorIntclawProvider = monitorModule.monitorIntclawProvider;
526
+ logger.info(`解构 monitorIntclawProvider 完成: ${typeof monitorIntclawProvider}`);
527
+
528
+ if (!monitorIntclawProvider) {
529
+ ctx.log?.error?.(`monitorIntclawProvider 未找到!可用导出: ${Object.keys(monitorModule).join(', ')}`);
530
+ throw new Error("monitorIntclawProvider not found in monitor module");
531
+ }
532
+ logger.info(`monitorIntclawProvider 找到`);
533
+
534
+ logger.info(`account 解析完成: ${account.accountId}, enabled=${account.enabled}, configured=${account.configured}`);
535
+
536
+ ctx.setStatus({ accountId: ctx.accountId, port: null });
537
+ ctx.log?.info(
538
+ `starting intclaw-connector[${ctx.accountId}] (mode: stream)`,
539
+ );
540
+ logger.info(`准备调用 monitorIntclawProvider`);
541
+
542
+ const result = await monitorIntclawProvider({
543
+ config: ctx.cfg,
544
+ runtime: ctx.runtime,
545
+ abortSignal: ctx.abortSignal,
546
+ accountId: ctx.accountId,
547
+ });
548
+ logger.info(`monitorIntclawProvider 调用完成`);
549
+ return result;
550
+ } catch (error) {
551
+ ctx.log?.error?.(`startAccount 发生错误: ${error.message}`);
552
+ ctx.log?.error?.(`错误堆栈: ${error.stack}`);
553
+ throw error;
554
+ }
555
+ },
556
+ },
557
+ };