@cored-im/openclaw-plugin 0.1.7 → 0.1.11
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/README.md +1 -5
- package/README.zh.md +1 -5
- package/dist/index.cjs +124 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -9
- package/dist/index.d.ts +11 -9
- package/dist/index.js +124 -143
- package/dist/index.js.map +1 -1
- package/dist/setup-entry.cjs +114 -117
- package/dist/setup-entry.cjs.map +1 -1
- package/dist/setup-entry.d.cts +4 -9
- package/dist/setup-entry.d.ts +4 -9
- package/dist/setup-entry.js +114 -117
- package/dist/setup-entry.js.map +1 -1
- package/dist/types-BEkT8vuK.d.cts +11 -0
- package/dist/types-BEkT8vuK.d.ts +11 -0
- package/openclaw.plugin.json +6 -53
- package/package.json +3 -2
- package/src/channel.ts +129 -134
- package/src/config.test.ts +4 -10
- package/src/config.ts +1 -11
- package/src/index.ts +15 -21
- package/src/messaging/inbound.test.ts +12 -160
- package/src/messaging/inbound.ts +12 -41
- package/src/setup-entry.ts +2 -2
- package/src/types.ts +3 -16
- package/src/typings/openclaw-plugin-sdk.d.ts +0 -162
package/README.md
CHANGED
|
@@ -93,12 +93,9 @@ openclaw gateway restart
|
|
|
93
93
|
| `appId` | string | required | Cored application ID |
|
|
94
94
|
| `appSecret` | string | required | Cored application secret |
|
|
95
95
|
| `backendUrl` | string | required | Cored backend URL |
|
|
96
|
+
| `enabled` | boolean | `true` | Enable/disable this account |
|
|
96
97
|
| `enableEncryption` | boolean | `true` | Whether to use encrypted transport |
|
|
97
98
|
| `requestTimeout` | number | `30000` | API request timeout in milliseconds |
|
|
98
|
-
| `requireMention` | boolean | `true` | In group chats, only respond when @mentioned |
|
|
99
|
-
| `botUserId` | string | optional | Bot's own user ID (for self-message filtering) |
|
|
100
|
-
| `inboundWhitelist` | string[] | `[]` | If non-empty, only accept messages from these user IDs |
|
|
101
|
-
| `enabled` | boolean | `true` | Enable/disable this account |
|
|
102
99
|
|
|
103
100
|
### Environment Variables
|
|
104
101
|
|
|
@@ -107,7 +104,6 @@ The `default` account supports environment variable fallback:
|
|
|
107
104
|
- `CORED_APP_ID`
|
|
108
105
|
- `CORED_APP_SECRET`
|
|
109
106
|
- `CORED_BACKEND_URL`
|
|
110
|
-
- `CORED_REQUIRE_MENTION`
|
|
111
107
|
|
|
112
108
|
## License
|
|
113
109
|
|
package/README.zh.md
CHANGED
|
@@ -93,12 +93,9 @@ openclaw gateway restart
|
|
|
93
93
|
| `appId` | string | 必填 | 应用 ID |
|
|
94
94
|
| `appSecret` | string | 必填 | 应用密钥 |
|
|
95
95
|
| `backendUrl` | string | 必填 | 后端地址 |
|
|
96
|
+
| `enabled` | boolean | `true` | 启用/禁用该账号 |
|
|
96
97
|
| `enableEncryption` | boolean | `true` | 是否启用加密传输 |
|
|
97
98
|
| `requestTimeout` | number | `30000` | API 请求超时时间(毫秒) |
|
|
98
|
-
| `requireMention` | boolean | `true` | 群聊中是否仅在被 @提及 时响应 |
|
|
99
|
-
| `botUserId` | string | 可选 | 机器人自身的用户 ID(用于过滤自身消息) |
|
|
100
|
-
| `inboundWhitelist` | string[] | `[]` | 非空时,仅接受这些用户 ID 的消息 |
|
|
101
|
-
| `enabled` | boolean | `true` | 启用/禁用该账号 |
|
|
102
99
|
|
|
103
100
|
### 环境变量
|
|
104
101
|
|
|
@@ -107,7 +104,6 @@ openclaw gateway restart
|
|
|
107
104
|
- `CORED_APP_ID`
|
|
108
105
|
- `CORED_APP_SECRET`
|
|
109
106
|
- `CORED_BACKEND_URL`
|
|
110
|
-
- `CORED_REQUIRE_MENTION`
|
|
111
107
|
|
|
112
108
|
## 许可证
|
|
113
109
|
|
package/dist/index.cjs
CHANGED
|
@@ -31,9 +31,7 @@ var import_core = require("openclaw/plugin-sdk/core");
|
|
|
31
31
|
// src/config.ts
|
|
32
32
|
var DEFAULTS = {
|
|
33
33
|
enableEncryption: true,
|
|
34
|
-
requestTimeout: 3e4
|
|
35
|
-
requireMention: true,
|
|
36
|
-
inboundWhitelist: []
|
|
34
|
+
requestTimeout: 3e4
|
|
37
35
|
};
|
|
38
36
|
var ENV_PREFIX = "CORED_";
|
|
39
37
|
function getChannelConfig(cfg) {
|
|
@@ -52,10 +50,6 @@ function readEnvConfig() {
|
|
|
52
50
|
result.enableEncryption = env[`${ENV_PREFIX}ENABLE_ENCRYPTION`] !== "false";
|
|
53
51
|
if (env[`${ENV_PREFIX}REQUEST_TIMEOUT`])
|
|
54
52
|
result.requestTimeout = Number(env[`${ENV_PREFIX}REQUEST_TIMEOUT`]);
|
|
55
|
-
if (env[`${ENV_PREFIX}REQUIRE_MENTION`] !== void 0)
|
|
56
|
-
result.requireMention = env[`${ENV_PREFIX}REQUIRE_MENTION`] !== "false";
|
|
57
|
-
if (env[`${ENV_PREFIX}BOT_USER_ID`])
|
|
58
|
-
result.botUserId = env[`${ENV_PREFIX}BOT_USER_ID`];
|
|
59
53
|
return result;
|
|
60
54
|
}
|
|
61
55
|
function listAccountIds(cfg) {
|
|
@@ -76,15 +70,12 @@ function resolveAccountConfig(cfg, accountId) {
|
|
|
76
70
|
const raw = ch?.accounts?.[id] ?? ch;
|
|
77
71
|
return {
|
|
78
72
|
accountId: id,
|
|
79
|
-
enabled: raw?.enabled ?? true,
|
|
80
73
|
appId: raw?.appId ?? envConfig.appId ?? "",
|
|
81
74
|
appSecret: raw?.appSecret ?? envConfig.appSecret ?? "",
|
|
82
75
|
backendUrl: raw?.backendUrl ?? envConfig.backendUrl ?? "",
|
|
76
|
+
enabled: raw?.enabled ?? true,
|
|
83
77
|
enableEncryption: raw?.enableEncryption ?? envConfig.enableEncryption ?? DEFAULTS.enableEncryption,
|
|
84
|
-
requestTimeout: raw?.requestTimeout ?? envConfig.requestTimeout ?? DEFAULTS.requestTimeout
|
|
85
|
-
requireMention: raw?.requireMention ?? envConfig.requireMention ?? DEFAULTS.requireMention,
|
|
86
|
-
botUserId: raw?.botUserId ?? envConfig.botUserId,
|
|
87
|
-
inboundWhitelist: raw?.inboundWhitelist ?? [...DEFAULTS.inboundWhitelist]
|
|
78
|
+
requestTimeout: raw?.requestTimeout ?? envConfig.requestTimeout ?? DEFAULTS.requestTimeout
|
|
88
79
|
};
|
|
89
80
|
}
|
|
90
81
|
function validateAccountConfig(config) {
|
|
@@ -336,171 +327,177 @@ function parseTarget(to) {
|
|
|
336
327
|
}
|
|
337
328
|
|
|
338
329
|
// src/channel.ts
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const accounts = section?.accounts;
|
|
342
|
-
const defaultAccount = section?.defaultAccount;
|
|
343
|
-
if (accounts && Object.keys(accounts).length > 0) {
|
|
344
|
-
const targetId = accountId ?? defaultAccount ?? Object.keys(accounts)[0];
|
|
345
|
-
const account = accounts[targetId];
|
|
346
|
-
if (!account) {
|
|
347
|
-
throw new Error(`cored: account "${targetId}" not found`);
|
|
348
|
-
}
|
|
349
|
-
return {
|
|
350
|
-
accountId: targetId,
|
|
351
|
-
appId: account.appId,
|
|
352
|
-
appSecret: account.appSecret,
|
|
353
|
-
backendUrl: account.backendUrl,
|
|
354
|
-
enableEncryption: account.enableEncryption ?? section.enableEncryption ?? true,
|
|
355
|
-
requestTimeout: account.requestTimeout ?? section.requestTimeout ?? 3e4,
|
|
356
|
-
requireMention: account.requireMention ?? section.requireMention ?? true
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
const appId = section?.appId;
|
|
360
|
-
const appSecret = section?.appSecret;
|
|
361
|
-
const backendUrl = section?.backendUrl;
|
|
362
|
-
if (!appId || !appSecret || !backendUrl) {
|
|
363
|
-
throw new Error("cored: appId, appSecret, and backendUrl are required");
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
accountId: null,
|
|
367
|
-
appId,
|
|
368
|
-
appSecret,
|
|
369
|
-
backendUrl,
|
|
370
|
-
enableEncryption: section?.enableEncryption ?? true,
|
|
371
|
-
requestTimeout: section?.requestTimeout ?? 3e4,
|
|
372
|
-
requireMention: section?.requireMention ?? true
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
var coredPlugin = (0, import_core.createChatChannelPlugin)({
|
|
376
|
-
base: (0, import_core.createChannelPluginBase)({
|
|
377
|
-
id: "cored",
|
|
378
|
-
setup: {
|
|
379
|
-
resolveAccount,
|
|
380
|
-
inspectAccount(cfg, accountId) {
|
|
381
|
-
const section = cfg.channels?.["cored"];
|
|
382
|
-
const hasConfig = Boolean(
|
|
383
|
-
section?.appId && section?.appSecret && section?.backendUrl
|
|
384
|
-
);
|
|
385
|
-
return {
|
|
386
|
-
enabled: Boolean(section?.enabled !== false),
|
|
387
|
-
configured: hasConfig,
|
|
388
|
-
tokenStatus: hasConfig ? "available" : "missing"
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}),
|
|
393
|
-
// Plugin metadata
|
|
330
|
+
var base = (0, import_core.createChannelPluginBase)({
|
|
331
|
+
id: "cored",
|
|
394
332
|
meta: {
|
|
395
333
|
id: "cored",
|
|
396
334
|
label: "Cored",
|
|
397
335
|
selectionLabel: "Cored",
|
|
398
336
|
docsPath: "/channels/cored",
|
|
399
337
|
blurb: "Connect OpenClaw to Cored",
|
|
400
|
-
aliases: ["
|
|
338
|
+
aliases: ["co"]
|
|
401
339
|
},
|
|
402
|
-
// Capabilities
|
|
403
340
|
capabilities: {
|
|
404
341
|
chatTypes: ["direct", "group"]
|
|
405
342
|
},
|
|
406
|
-
// Config
|
|
407
343
|
config: {
|
|
408
344
|
listAccountIds: (cfg) => listAccountIds(cfg),
|
|
409
|
-
resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId)
|
|
345
|
+
resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId ?? void 0),
|
|
346
|
+
inspectAccount(cfg, accountId) {
|
|
347
|
+
const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
|
|
348
|
+
const hasConfig = Boolean(
|
|
349
|
+
resolved.appId && resolved.appSecret && resolved.backendUrl
|
|
350
|
+
);
|
|
351
|
+
return {
|
|
352
|
+
enabled: resolved.enabled,
|
|
353
|
+
configured: hasConfig,
|
|
354
|
+
tokenStatus: hasConfig ? "available" : "missing"
|
|
355
|
+
};
|
|
356
|
+
}
|
|
410
357
|
},
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
if (!
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
return {
|
|
434
|
-
ok: false,
|
|
435
|
-
error: new Error(`[cored] invalid send target: ${to}`)
|
|
436
|
-
};
|
|
358
|
+
setup: {
|
|
359
|
+
applyAccountConfig: ({ cfg, accountId, input }) => {
|
|
360
|
+
const updated = structuredClone(cfg);
|
|
361
|
+
if (!updated.channels) updated.channels = {};
|
|
362
|
+
const ch = updated.channels;
|
|
363
|
+
if (!ch["cored"]) ch["cored"] = {};
|
|
364
|
+
const section = ch["cored"];
|
|
365
|
+
const appId = input.appToken;
|
|
366
|
+
const appSecret = input.token;
|
|
367
|
+
const backendUrl = input.url;
|
|
368
|
+
if (accountId && accountId !== "default") {
|
|
369
|
+
if (!section.accounts) section.accounts = {};
|
|
370
|
+
const accounts = section.accounts;
|
|
371
|
+
if (!accounts[accountId]) accounts[accountId] = {};
|
|
372
|
+
const account = accounts[accountId];
|
|
373
|
+
if (appId) account.appId = appId;
|
|
374
|
+
if (appSecret) account.appSecret = appSecret;
|
|
375
|
+
if (backendUrl) account.backendUrl = backendUrl;
|
|
376
|
+
} else {
|
|
377
|
+
if (appId) section.appId = appId;
|
|
378
|
+
if (appSecret) section.appSecret = appSecret;
|
|
379
|
+
if (backendUrl) section.backendUrl = backendUrl;
|
|
437
380
|
}
|
|
438
|
-
return
|
|
381
|
+
return updated;
|
|
439
382
|
}
|
|
440
383
|
},
|
|
441
|
-
// Setup wizard for openclaw onboard
|
|
442
384
|
setupWizard: {
|
|
443
385
|
channel: "cored",
|
|
444
386
|
status: {
|
|
445
387
|
configuredLabel: "Connected",
|
|
446
388
|
unconfiguredLabel: "Not configured",
|
|
447
389
|
resolveConfigured: ({ cfg }) => {
|
|
448
|
-
const
|
|
449
|
-
return
|
|
390
|
+
const ids = listAccountIds(cfg);
|
|
391
|
+
return ids.some((id) => {
|
|
392
|
+
const resolved = resolveAccountConfig(cfg, id);
|
|
393
|
+
return Boolean(resolved.appId && resolved.appSecret && resolved.backendUrl);
|
|
394
|
+
});
|
|
450
395
|
}
|
|
451
396
|
},
|
|
452
397
|
credentials: [
|
|
453
398
|
{
|
|
454
|
-
inputKey: "
|
|
399
|
+
inputKey: "appToken",
|
|
455
400
|
providerHint: "cored",
|
|
456
401
|
credentialLabel: "App ID",
|
|
457
402
|
preferredEnvVar: "CORED_APP_ID",
|
|
458
403
|
envPrompt: "Use CORED_APP_ID from environment?",
|
|
459
404
|
keepPrompt: "Keep current App ID?",
|
|
460
405
|
inputPrompt: "Enter your Cored App ID:",
|
|
461
|
-
inspect: ({ cfg }) => {
|
|
462
|
-
const
|
|
406
|
+
inspect: ({ cfg, accountId }) => {
|
|
407
|
+
const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
|
|
463
408
|
return {
|
|
464
|
-
accountConfigured: Boolean(
|
|
465
|
-
hasConfiguredValue: Boolean(
|
|
409
|
+
accountConfigured: Boolean(resolved.appId),
|
|
410
|
+
hasConfiguredValue: Boolean(resolved.appId)
|
|
466
411
|
};
|
|
467
412
|
}
|
|
468
413
|
},
|
|
469
414
|
{
|
|
470
|
-
inputKey: "
|
|
415
|
+
inputKey: "token",
|
|
471
416
|
providerHint: "cored",
|
|
472
417
|
credentialLabel: "App Secret",
|
|
473
418
|
preferredEnvVar: "CORED_APP_SECRET",
|
|
474
419
|
envPrompt: "Use CORED_APP_SECRET from environment?",
|
|
475
420
|
keepPrompt: "Keep current App Secret?",
|
|
476
421
|
inputPrompt: "Enter your Cored App Secret:",
|
|
477
|
-
inspect: ({ cfg }) => {
|
|
478
|
-
const
|
|
422
|
+
inspect: ({ cfg, accountId }) => {
|
|
423
|
+
const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
|
|
479
424
|
return {
|
|
480
|
-
accountConfigured: Boolean(
|
|
481
|
-
hasConfiguredValue: Boolean(
|
|
425
|
+
accountConfigured: Boolean(resolved.appSecret),
|
|
426
|
+
hasConfiguredValue: Boolean(resolved.appSecret)
|
|
482
427
|
};
|
|
483
428
|
}
|
|
484
429
|
},
|
|
485
430
|
{
|
|
486
|
-
inputKey: "
|
|
431
|
+
inputKey: "url",
|
|
487
432
|
providerHint: "cored",
|
|
488
433
|
credentialLabel: "Backend URL",
|
|
489
434
|
preferredEnvVar: "CORED_BACKEND_URL",
|
|
490
435
|
envPrompt: "Use CORED_BACKEND_URL from environment?",
|
|
491
436
|
keepPrompt: "Keep current Backend URL?",
|
|
492
437
|
inputPrompt: "Enter your Cored backend server URL:",
|
|
493
|
-
inspect: ({ cfg }) => {
|
|
494
|
-
const
|
|
438
|
+
inspect: ({ cfg, accountId }) => {
|
|
439
|
+
const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
|
|
495
440
|
return {
|
|
496
|
-
accountConfigured: Boolean(
|
|
497
|
-
hasConfiguredValue: Boolean(
|
|
441
|
+
accountConfigured: Boolean(resolved.backendUrl),
|
|
442
|
+
hasConfiguredValue: Boolean(resolved.backendUrl)
|
|
498
443
|
};
|
|
499
444
|
}
|
|
500
445
|
}
|
|
501
446
|
]
|
|
502
447
|
}
|
|
503
448
|
});
|
|
449
|
+
var coredPlugin = (0, import_core.createChatChannelPlugin)({
|
|
450
|
+
base,
|
|
451
|
+
// DM security: who can message the bot
|
|
452
|
+
security: {
|
|
453
|
+
dm: {
|
|
454
|
+
channelKey: "cored",
|
|
455
|
+
resolvePolicy: () => void 0,
|
|
456
|
+
resolveAllowFrom: () => [],
|
|
457
|
+
defaultPolicy: "allowlist"
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
// Threading: how replies are delivered
|
|
461
|
+
threading: { topLevelReplyToMode: "reply" },
|
|
462
|
+
// Outbound: send messages to the platform
|
|
463
|
+
outbound: {
|
|
464
|
+
attachedResults: {
|
|
465
|
+
channel: "cored",
|
|
466
|
+
sendText: async (ctx) => {
|
|
467
|
+
const target = parseTarget(ctx.to);
|
|
468
|
+
if (!target) {
|
|
469
|
+
throw new Error(`[cored] invalid send target: ${ctx.to}`);
|
|
470
|
+
}
|
|
471
|
+
const result = await sendText(
|
|
472
|
+
target.id,
|
|
473
|
+
ctx.text,
|
|
474
|
+
ctx.accountId ?? void 0,
|
|
475
|
+
ctx.replyToId ?? void 0
|
|
476
|
+
);
|
|
477
|
+
if (!result.ok) {
|
|
478
|
+
throw result.error ?? new Error("[cored] send failed");
|
|
479
|
+
}
|
|
480
|
+
return { messageId: result.messageId ?? "" };
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
base: {
|
|
484
|
+
deliveryMode: "direct",
|
|
485
|
+
resolveTarget: ({ to }) => {
|
|
486
|
+
if (!to) return { ok: false, error: new Error("[cored] --to is required") };
|
|
487
|
+
const target = parseTarget(to);
|
|
488
|
+
if (!target) {
|
|
489
|
+
return {
|
|
490
|
+
ok: false,
|
|
491
|
+
error: new Error(
|
|
492
|
+
`Cored requires --to <user:ID|chat:ID>, got: ${JSON.stringify(to)}`
|
|
493
|
+
)
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
return { ok: true, to: `${target.kind}:${target.id}` };
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
});
|
|
504
501
|
|
|
505
502
|
// src/messaging/inbound.ts
|
|
506
503
|
function parseMessageEvent(event) {
|
|
@@ -549,23 +546,8 @@ function extractTextBody(msg) {
|
|
|
549
546
|
return null;
|
|
550
547
|
}
|
|
551
548
|
function checkMessageGate(msg, account) {
|
|
552
|
-
if (account.botUserId && msg.senderId === account.botUserId) {
|
|
553
|
-
return { pass: false, reason: "self-message" };
|
|
554
|
-
}
|
|
555
|
-
if (account.inboundWhitelist.length > 0) {
|
|
556
|
-
if (!account.inboundWhitelist.includes(msg.senderId)) {
|
|
557
|
-
return { pass: false, reason: "sender-not-in-whitelist" };
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
if (msg.chatType === "group" && account.requireMention && !isBotMentioned(msg, account)) {
|
|
561
|
-
return { pass: false, reason: "group-no-mention" };
|
|
562
|
-
}
|
|
563
549
|
return { pass: true };
|
|
564
550
|
}
|
|
565
|
-
function isBotMentioned(msg, account) {
|
|
566
|
-
if (!account.botUserId) return false;
|
|
567
|
-
return msg.mentionUserIds.includes(account.botUserId);
|
|
568
|
-
}
|
|
569
551
|
var DEDUP_TTL_MS = 5 * 60 * 1e3;
|
|
570
552
|
var DEDUP_CLEANUP_INTERVAL_MS = 60 * 1e3;
|
|
571
553
|
var DEDUP_MAX_SIZE = 1e4;
|
|
@@ -600,7 +582,7 @@ function buildContext(msg, account) {
|
|
|
600
582
|
return {
|
|
601
583
|
Body: msg.body,
|
|
602
584
|
From: isGroup ? `cored:chat:${msg.chatId}` : `cored:user:${msg.senderId}`,
|
|
603
|
-
To: `cored:bot:${account.
|
|
585
|
+
To: `cored:bot:${account.appId}`,
|
|
604
586
|
SessionKey: sessionKey,
|
|
605
587
|
AccountId: account.accountId,
|
|
606
588
|
ChatType: isGroup ? "group" : "direct",
|
|
@@ -716,43 +698,42 @@ var index_default = (0, import_core2.defineChannelPluginEntry)({
|
|
|
716
698
|
description: "Connect OpenClaw with Cored",
|
|
717
699
|
plugin: coredPlugin,
|
|
718
700
|
registerFull(api) {
|
|
719
|
-
|
|
720
|
-
typedApi.registerService({
|
|
701
|
+
api.registerService({
|
|
721
702
|
id: "cored-sdk",
|
|
722
703
|
start: async () => {
|
|
723
704
|
if (clientCount() > 0) return;
|
|
724
|
-
const accounts = listEnabledAccountConfigs(
|
|
705
|
+
const accounts = listEnabledAccountConfigs(api.config);
|
|
725
706
|
if (accounts.length === 0) {
|
|
726
|
-
|
|
707
|
+
api.logger?.warn?.("[cored] no enabled account config found \u2014 service idle");
|
|
727
708
|
return;
|
|
728
709
|
}
|
|
729
710
|
for (const account of accounts) {
|
|
730
711
|
const errors = validateAccountConfig(account);
|
|
731
712
|
if (errors.length > 0) {
|
|
732
|
-
|
|
713
|
+
api.logger?.warn?.(
|
|
733
714
|
`[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
|
|
734
715
|
);
|
|
735
716
|
continue;
|
|
736
717
|
}
|
|
737
718
|
try {
|
|
738
|
-
await startAccount(
|
|
739
|
-
|
|
719
|
+
await startAccount(api, account);
|
|
720
|
+
api.logger?.info?.(
|
|
740
721
|
`[cored] account=${account.accountId} connected (appId=${account.appId})`
|
|
741
722
|
);
|
|
742
723
|
} catch (err) {
|
|
743
|
-
|
|
724
|
+
api.logger?.error?.(
|
|
744
725
|
`[cored] account=${account.accountId} failed to start: ${err instanceof Error ? err.message : String(err)}`
|
|
745
726
|
);
|
|
746
727
|
}
|
|
747
728
|
}
|
|
748
|
-
|
|
729
|
+
api.logger?.info?.(`[cored] service started with ${clientCount()} account(s)`);
|
|
749
730
|
},
|
|
750
731
|
stop: async () => {
|
|
751
732
|
await destroyAllClients();
|
|
752
|
-
|
|
733
|
+
api.logger?.info?.("[cored] service stopped \u2014 all clients disconnected");
|
|
753
734
|
}
|
|
754
735
|
});
|
|
755
|
-
|
|
736
|
+
api.logger?.info?.("[cored] plugin registered");
|
|
756
737
|
}
|
|
757
738
|
});
|
|
758
739
|
async function startAccount(api, account) {
|