@cored-im/openclaw-plugin 0.1.4 → 0.1.5
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/dist/index.cjs +196 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -60
- package/dist/index.d.ts +11 -60
- package/dist/index.js +201 -54
- package/dist/index.js.map +1 -1
- package/dist/setup-entry.cjs +311 -36
- package/dist/setup-entry.cjs.map +1 -1
- package/dist/setup-entry.d.cts +9 -1
- package/dist/setup-entry.d.ts +9 -1
- package/dist/setup-entry.js +314 -36
- package/dist/setup-entry.js.map +1 -1
- package/openclaw.plugin.json +2 -3
- package/package.json +3 -3
- package/src/channel.ts +152 -4
- package/src/index.test.ts +52 -26
- package/src/index.ts +56 -44
- package/src/messaging/inbound.ts +43 -11
- package/src/setup-entry.ts +2 -46
- package/src/types.ts +3 -33
- package/src/typings/openclaw-plugin-sdk.d.ts +152 -19
package/dist/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
|
3
|
+
|
|
4
|
+
// src/channel.ts
|
|
5
|
+
import {
|
|
6
|
+
createChatChannelPlugin,
|
|
7
|
+
createChannelPluginBase
|
|
8
|
+
} from "openclaw/plugin-sdk/core";
|
|
9
|
+
|
|
1
10
|
// src/config.ts
|
|
2
11
|
var DEFAULTS = {
|
|
3
12
|
enableEncryption: true,
|
|
@@ -306,23 +315,79 @@ function parseTarget(to) {
|
|
|
306
315
|
}
|
|
307
316
|
|
|
308
317
|
// src/channel.ts
|
|
309
|
-
|
|
310
|
-
|
|
318
|
+
function resolveAccount(cfg, accountId) {
|
|
319
|
+
const section = cfg.channels?.["cored"];
|
|
320
|
+
const accounts = section?.accounts;
|
|
321
|
+
const defaultAccount = section?.defaultAccount;
|
|
322
|
+
if (accounts && Object.keys(accounts).length > 0) {
|
|
323
|
+
const targetId = accountId ?? defaultAccount ?? Object.keys(accounts)[0];
|
|
324
|
+
const account = accounts[targetId];
|
|
325
|
+
if (!account) {
|
|
326
|
+
throw new Error(`cored: account "${targetId}" not found`);
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
accountId: targetId,
|
|
330
|
+
appId: account.appId,
|
|
331
|
+
appSecret: account.appSecret,
|
|
332
|
+
backendUrl: account.backendUrl,
|
|
333
|
+
enableEncryption: account.enableEncryption ?? section.enableEncryption ?? true,
|
|
334
|
+
requestTimeout: account.requestTimeout ?? section.requestTimeout ?? 3e4,
|
|
335
|
+
requireMention: account.requireMention ?? section.requireMention ?? true
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
const appId = section?.appId;
|
|
339
|
+
const appSecret = section?.appSecret;
|
|
340
|
+
const backendUrl = section?.backendUrl;
|
|
341
|
+
if (!appId || !appSecret || !backendUrl) {
|
|
342
|
+
throw new Error("cored: appId, appSecret, and backendUrl are required");
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
accountId: null,
|
|
346
|
+
appId,
|
|
347
|
+
appSecret,
|
|
348
|
+
backendUrl,
|
|
349
|
+
enableEncryption: section?.enableEncryption ?? true,
|
|
350
|
+
requestTimeout: section?.requestTimeout ?? 3e4,
|
|
351
|
+
requireMention: section?.requireMention ?? true
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
var coredPlugin = createChatChannelPlugin({
|
|
355
|
+
base: createChannelPluginBase({
|
|
356
|
+
id: "cored",
|
|
357
|
+
setup: {
|
|
358
|
+
resolveAccount,
|
|
359
|
+
inspectAccount(cfg, accountId) {
|
|
360
|
+
const section = cfg.channels?.["cored"];
|
|
361
|
+
const hasConfig = Boolean(
|
|
362
|
+
section?.appId && section?.appSecret && section?.backendUrl
|
|
363
|
+
);
|
|
364
|
+
return {
|
|
365
|
+
enabled: Boolean(section?.enabled !== false),
|
|
366
|
+
configured: hasConfig,
|
|
367
|
+
tokenStatus: hasConfig ? "available" : "missing"
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}),
|
|
372
|
+
// Plugin metadata
|
|
311
373
|
meta: {
|
|
312
374
|
id: "cored",
|
|
313
375
|
label: "Cored",
|
|
314
376
|
selectionLabel: "Cored",
|
|
315
377
|
docsPath: "/channels/cored",
|
|
316
|
-
blurb: "
|
|
378
|
+
blurb: "Connect OpenClaw to Cored",
|
|
317
379
|
aliases: ["cored", "co"]
|
|
318
380
|
},
|
|
381
|
+
// Capabilities
|
|
319
382
|
capabilities: {
|
|
320
383
|
chatTypes: ["direct", "group"]
|
|
321
384
|
},
|
|
385
|
+
// Config
|
|
322
386
|
config: {
|
|
323
387
|
listAccountIds: (cfg) => listAccountIds(cfg),
|
|
324
388
|
resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId)
|
|
325
389
|
},
|
|
390
|
+
// Outbound messaging
|
|
326
391
|
outbound: {
|
|
327
392
|
deliveryMode: "direct",
|
|
328
393
|
resolveTarget: ({ to }) => {
|
|
@@ -351,8 +416,70 @@ var coredPlugin = {
|
|
|
351
416
|
}
|
|
352
417
|
return sendText(target.id, text, accountId);
|
|
353
418
|
}
|
|
419
|
+
},
|
|
420
|
+
// Setup wizard for openclaw onboard
|
|
421
|
+
setupWizard: {
|
|
422
|
+
channel: "cored",
|
|
423
|
+
status: {
|
|
424
|
+
configuredLabel: "Connected",
|
|
425
|
+
unconfiguredLabel: "Not configured",
|
|
426
|
+
resolveConfigured: ({ cfg }) => {
|
|
427
|
+
const section = cfg.channels?.["cored"];
|
|
428
|
+
return Boolean(section?.appId && section?.appSecret && section?.backendUrl);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
credentials: [
|
|
432
|
+
{
|
|
433
|
+
inputKey: "appId",
|
|
434
|
+
providerHint: "cored",
|
|
435
|
+
credentialLabel: "App ID",
|
|
436
|
+
preferredEnvVar: "CORED_APP_ID",
|
|
437
|
+
envPrompt: "Use CORED_APP_ID from environment?",
|
|
438
|
+
keepPrompt: "Keep current App ID?",
|
|
439
|
+
inputPrompt: "Enter your Cored App ID:",
|
|
440
|
+
inspect: ({ cfg }) => {
|
|
441
|
+
const section = cfg.channels?.["cored"];
|
|
442
|
+
return {
|
|
443
|
+
accountConfigured: Boolean(section?.appId),
|
|
444
|
+
hasConfiguredValue: Boolean(section?.appId)
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
inputKey: "appSecret",
|
|
450
|
+
providerHint: "cored",
|
|
451
|
+
credentialLabel: "App Secret",
|
|
452
|
+
preferredEnvVar: "CORED_APP_SECRET",
|
|
453
|
+
envPrompt: "Use CORED_APP_SECRET from environment?",
|
|
454
|
+
keepPrompt: "Keep current App Secret?",
|
|
455
|
+
inputPrompt: "Enter your Cored App Secret:",
|
|
456
|
+
inspect: ({ cfg }) => {
|
|
457
|
+
const section = cfg.channels?.["cored"];
|
|
458
|
+
return {
|
|
459
|
+
accountConfigured: Boolean(section?.appSecret),
|
|
460
|
+
hasConfiguredValue: Boolean(section?.appSecret)
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
inputKey: "backendUrl",
|
|
466
|
+
providerHint: "cored",
|
|
467
|
+
credentialLabel: "Backend URL",
|
|
468
|
+
preferredEnvVar: "CORED_BACKEND_URL",
|
|
469
|
+
envPrompt: "Use CORED_BACKEND_URL from environment?",
|
|
470
|
+
keepPrompt: "Keep current Backend URL?",
|
|
471
|
+
inputPrompt: "Enter your Cored backend server URL:",
|
|
472
|
+
inspect: ({ cfg }) => {
|
|
473
|
+
const section = cfg.channels?.["cored"];
|
|
474
|
+
return {
|
|
475
|
+
accountConfigured: Boolean(section?.backendUrl),
|
|
476
|
+
hasConfiguredValue: Boolean(section?.backendUrl)
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
]
|
|
354
481
|
}
|
|
355
|
-
};
|
|
482
|
+
});
|
|
356
483
|
|
|
357
484
|
// src/messaging/inbound.ts
|
|
358
485
|
function parseMessageEvent(event) {
|
|
@@ -471,33 +598,47 @@ function buildContext(msg, account) {
|
|
|
471
598
|
}
|
|
472
599
|
async function processInboundMessage(api, account, event, opts) {
|
|
473
600
|
const logger = api.logger;
|
|
601
|
+
const log = {
|
|
602
|
+
debug: (msg) => {
|
|
603
|
+
logger?.debug?.(msg);
|
|
604
|
+
},
|
|
605
|
+
info: (msg) => {
|
|
606
|
+
logger?.info?.(msg);
|
|
607
|
+
},
|
|
608
|
+
warn: (msg) => {
|
|
609
|
+
logger?.warn?.(msg);
|
|
610
|
+
},
|
|
611
|
+
error: (msg) => {
|
|
612
|
+
logger?.error?.(msg);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
474
615
|
const parsed = parseMessageEvent(event);
|
|
475
616
|
if (!parsed) {
|
|
476
|
-
|
|
617
|
+
log.debug(
|
|
477
618
|
`[cored] ignoring unparseable event (messageId=${event?.message?.messageId ?? "unknown"} messageType=${event?.message?.messageType ?? "undefined"})`
|
|
478
619
|
);
|
|
479
620
|
return false;
|
|
480
621
|
}
|
|
481
622
|
const gate = checkMessageGate(parsed, account);
|
|
482
623
|
if (!gate.pass) {
|
|
483
|
-
|
|
624
|
+
log.debug(
|
|
484
625
|
`[cored] gated message=${parsed.messageId} reason=${gate.reason} chat=${parsed.chatId}`
|
|
485
626
|
);
|
|
486
627
|
return false;
|
|
487
628
|
}
|
|
488
629
|
if (isDuplicate(parsed.messageId)) {
|
|
489
|
-
|
|
630
|
+
log.debug(
|
|
490
631
|
`[cored] duplicate message=${parsed.messageId} chat=${parsed.chatId}`
|
|
491
632
|
);
|
|
492
633
|
return false;
|
|
493
634
|
}
|
|
494
635
|
const ctx = buildContext(parsed, account);
|
|
495
|
-
|
|
636
|
+
log.info(
|
|
496
637
|
`[cored] dispatching message=${parsed.messageId} chat=${parsed.chatId} sender=${parsed.senderId} type=${parsed.chatType}`
|
|
497
638
|
);
|
|
498
639
|
const runtime = api.runtime;
|
|
499
640
|
if (!runtime?.channel?.reply?.dispatchReplyWithBufferedBlockDispatcher) {
|
|
500
|
-
|
|
641
|
+
log.warn("[cored] runtime.channel.reply not available \u2014 cannot dispatch");
|
|
501
642
|
return false;
|
|
502
643
|
}
|
|
503
644
|
const cfgSession = api.config?.session;
|
|
@@ -516,7 +657,7 @@ async function processInboundMessage(api, account, event, opts) {
|
|
|
516
657
|
accountId: account.accountId
|
|
517
658
|
} : void 0
|
|
518
659
|
});
|
|
519
|
-
|
|
660
|
+
log.debug(
|
|
520
661
|
`[cored] dispatch starting for message=${parsed.messageId} session=${ctx.SessionKey}`
|
|
521
662
|
);
|
|
522
663
|
await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
@@ -524,77 +665,83 @@ async function processInboundMessage(api, account, event, opts) {
|
|
|
524
665
|
cfg: api.config,
|
|
525
666
|
dispatcherOptions: {
|
|
526
667
|
deliver: async (payload) => {
|
|
527
|
-
|
|
668
|
+
log.info(
|
|
528
669
|
`[cored] deliver callback called for message=${parsed.messageId} hasText=${!!payload.text} textLen=${payload.text?.length ?? 0}`
|
|
529
670
|
);
|
|
530
671
|
if (payload.text) {
|
|
531
672
|
await opts.deliver(parsed.chatId, payload.text);
|
|
532
|
-
|
|
673
|
+
log.info(
|
|
533
674
|
`[cored] deliver completed for message=${parsed.messageId} chat=${parsed.chatId}`
|
|
534
675
|
);
|
|
535
676
|
}
|
|
536
677
|
},
|
|
537
678
|
onError: (err, info) => {
|
|
538
|
-
|
|
679
|
+
log.error(
|
|
539
680
|
`[cored] ${info?.kind ?? "reply"} error for message=${parsed.messageId}: ${err}`
|
|
540
681
|
);
|
|
541
682
|
}
|
|
542
683
|
}
|
|
543
684
|
});
|
|
544
|
-
|
|
685
|
+
log.info(
|
|
545
686
|
`[cored] dispatch finished for message=${parsed.messageId}`
|
|
546
687
|
);
|
|
547
688
|
return true;
|
|
548
689
|
}
|
|
549
690
|
|
|
550
691
|
// src/index.ts
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
`[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
|
|
567
|
-
);
|
|
568
|
-
continue;
|
|
692
|
+
var index_default = defineChannelPluginEntry({
|
|
693
|
+
id: "cored",
|
|
694
|
+
name: "Cored",
|
|
695
|
+
description: "Connect OpenClaw with Cored",
|
|
696
|
+
plugin: coredPlugin,
|
|
697
|
+
registerFull(api) {
|
|
698
|
+
const typedApi = api;
|
|
699
|
+
typedApi.registerService({
|
|
700
|
+
id: "cored-sdk",
|
|
701
|
+
start: async () => {
|
|
702
|
+
if (clientCount() > 0) return;
|
|
703
|
+
const accounts = listEnabledAccountConfigs(typedApi.config);
|
|
704
|
+
if (accounts.length === 0) {
|
|
705
|
+
typedApi.logger?.warn?.("[cored] no enabled account config found \u2014 service idle");
|
|
706
|
+
return;
|
|
569
707
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
708
|
+
for (const account of accounts) {
|
|
709
|
+
const errors = validateAccountConfig(account);
|
|
710
|
+
if (errors.length > 0) {
|
|
711
|
+
typedApi.logger?.warn?.(
|
|
712
|
+
`[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
|
|
713
|
+
);
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
try {
|
|
717
|
+
await startAccount(typedApi, account);
|
|
718
|
+
typedApi.logger?.info?.(
|
|
719
|
+
`[cored] account=${account.accountId} connected (appId=${account.appId})`
|
|
720
|
+
);
|
|
721
|
+
} catch (err) {
|
|
722
|
+
typedApi.logger?.error?.(
|
|
723
|
+
`[cored] account=${account.accountId} failed to start: ${err instanceof Error ? err.message : String(err)}`
|
|
724
|
+
);
|
|
725
|
+
}
|
|
579
726
|
}
|
|
727
|
+
typedApi.logger?.info?.(`[cored] service started with ${clientCount()} account(s)`);
|
|
728
|
+
},
|
|
729
|
+
stop: async () => {
|
|
730
|
+
await destroyAllClients();
|
|
731
|
+
typedApi.logger?.info?.("[cored] service stopped \u2014 all clients disconnected");
|
|
580
732
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
api.logger?.info("[cored] service stopped \u2014 all clients disconnected");
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
api.logger?.info("[cored] plugin registered");
|
|
589
|
-
}
|
|
733
|
+
});
|
|
734
|
+
typedApi.logger?.info?.("[cored] plugin registered");
|
|
735
|
+
}
|
|
736
|
+
});
|
|
590
737
|
async function startAccount(api, account) {
|
|
591
|
-
const deliver = makeDeliver(account.accountId, (msg) => api.logger?.warn(msg));
|
|
738
|
+
const deliver = makeDeliver(account.accountId, (msg) => api.logger?.warn?.(msg));
|
|
592
739
|
await createClient({
|
|
593
740
|
config: account,
|
|
594
|
-
log: (msg) => api.logger?.debug(msg),
|
|
741
|
+
log: (msg) => api.logger?.debug?.(msg),
|
|
595
742
|
onMessage: (event, accountConfig) => {
|
|
596
743
|
handleInbound(api, accountConfig, event, deliver).catch((err) => {
|
|
597
|
-
api.logger?.error(
|
|
744
|
+
api.logger?.error?.(
|
|
598
745
|
`[cored] unhandled inbound error for account=${accountConfig.accountId}: ${err}`
|
|
599
746
|
);
|
|
600
747
|
});
|
|
@@ -622,6 +769,6 @@ async function handleInbound(api, account, event, deliver) {
|
|
|
622
769
|
}
|
|
623
770
|
}
|
|
624
771
|
export {
|
|
625
|
-
|
|
772
|
+
index_default as default
|
|
626
773
|
};
|
|
627
774
|
//# sourceMappingURL=index.js.map
|