@cored-im/openclaw-plugin 0.1.3 → 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 CHANGED
@@ -20,9 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- default: () => register
23
+ default: () => index_default
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
+ var import_core2 = require("openclaw/plugin-sdk/core");
27
+
28
+ // src/channel.ts
29
+ var import_core = require("openclaw/plugin-sdk/core");
26
30
 
27
31
  // src/config.ts
28
32
  var DEFAULTS = {
@@ -332,23 +336,79 @@ function parseTarget(to) {
332
336
  }
333
337
 
334
338
  // src/channel.ts
335
- var coredPlugin = {
336
- id: "cored",
339
+ function resolveAccount(cfg, accountId) {
340
+ const section = cfg.channels?.["cored"];
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
337
394
  meta: {
338
395
  id: "cored",
339
396
  label: "Cored",
340
397
  selectionLabel: "Cored",
341
398
  docsPath: "/channels/cored",
342
- blurb: "Cored enterprise IM channel",
399
+ blurb: "Connect OpenClaw to Cored",
343
400
  aliases: ["cored", "co"]
344
401
  },
402
+ // Capabilities
345
403
  capabilities: {
346
404
  chatTypes: ["direct", "group"]
347
405
  },
406
+ // Config
348
407
  config: {
349
408
  listAccountIds: (cfg) => listAccountIds(cfg),
350
409
  resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId)
351
410
  },
411
+ // Outbound messaging
352
412
  outbound: {
353
413
  deliveryMode: "direct",
354
414
  resolveTarget: ({ to }) => {
@@ -377,8 +437,70 @@ var coredPlugin = {
377
437
  }
378
438
  return sendText(target.id, text, accountId);
379
439
  }
440
+ },
441
+ // Setup wizard for openclaw onboard
442
+ setupWizard: {
443
+ channel: "cored",
444
+ status: {
445
+ configuredLabel: "Connected",
446
+ unconfiguredLabel: "Not configured",
447
+ resolveConfigured: ({ cfg }) => {
448
+ const section = cfg.channels?.["cored"];
449
+ return Boolean(section?.appId && section?.appSecret && section?.backendUrl);
450
+ }
451
+ },
452
+ credentials: [
453
+ {
454
+ inputKey: "appId",
455
+ providerHint: "cored",
456
+ credentialLabel: "App ID",
457
+ preferredEnvVar: "CORED_APP_ID",
458
+ envPrompt: "Use CORED_APP_ID from environment?",
459
+ keepPrompt: "Keep current App ID?",
460
+ inputPrompt: "Enter your Cored App ID:",
461
+ inspect: ({ cfg }) => {
462
+ const section = cfg.channels?.["cored"];
463
+ return {
464
+ accountConfigured: Boolean(section?.appId),
465
+ hasConfiguredValue: Boolean(section?.appId)
466
+ };
467
+ }
468
+ },
469
+ {
470
+ inputKey: "appSecret",
471
+ providerHint: "cored",
472
+ credentialLabel: "App Secret",
473
+ preferredEnvVar: "CORED_APP_SECRET",
474
+ envPrompt: "Use CORED_APP_SECRET from environment?",
475
+ keepPrompt: "Keep current App Secret?",
476
+ inputPrompt: "Enter your Cored App Secret:",
477
+ inspect: ({ cfg }) => {
478
+ const section = cfg.channels?.["cored"];
479
+ return {
480
+ accountConfigured: Boolean(section?.appSecret),
481
+ hasConfiguredValue: Boolean(section?.appSecret)
482
+ };
483
+ }
484
+ },
485
+ {
486
+ inputKey: "backendUrl",
487
+ providerHint: "cored",
488
+ credentialLabel: "Backend URL",
489
+ preferredEnvVar: "CORED_BACKEND_URL",
490
+ envPrompt: "Use CORED_BACKEND_URL from environment?",
491
+ keepPrompt: "Keep current Backend URL?",
492
+ inputPrompt: "Enter your Cored backend server URL:",
493
+ inspect: ({ cfg }) => {
494
+ const section = cfg.channels?.["cored"];
495
+ return {
496
+ accountConfigured: Boolean(section?.backendUrl),
497
+ hasConfiguredValue: Boolean(section?.backendUrl)
498
+ };
499
+ }
500
+ }
501
+ ]
380
502
  }
381
- };
503
+ });
382
504
 
383
505
  // src/messaging/inbound.ts
384
506
  function parseMessageEvent(event) {
@@ -497,33 +619,47 @@ function buildContext(msg, account) {
497
619
  }
498
620
  async function processInboundMessage(api, account, event, opts) {
499
621
  const logger = api.logger;
622
+ const log = {
623
+ debug: (msg) => {
624
+ logger?.debug?.(msg);
625
+ },
626
+ info: (msg) => {
627
+ logger?.info?.(msg);
628
+ },
629
+ warn: (msg) => {
630
+ logger?.warn?.(msg);
631
+ },
632
+ error: (msg) => {
633
+ logger?.error?.(msg);
634
+ }
635
+ };
500
636
  const parsed = parseMessageEvent(event);
501
637
  if (!parsed) {
502
- logger?.debug(
638
+ log.debug(
503
639
  `[cored] ignoring unparseable event (messageId=${event?.message?.messageId ?? "unknown"} messageType=${event?.message?.messageType ?? "undefined"})`
504
640
  );
505
641
  return false;
506
642
  }
507
643
  const gate = checkMessageGate(parsed, account);
508
644
  if (!gate.pass) {
509
- logger?.debug(
645
+ log.debug(
510
646
  `[cored] gated message=${parsed.messageId} reason=${gate.reason} chat=${parsed.chatId}`
511
647
  );
512
648
  return false;
513
649
  }
514
650
  if (isDuplicate(parsed.messageId)) {
515
- logger?.debug(
651
+ log.debug(
516
652
  `[cored] duplicate message=${parsed.messageId} chat=${parsed.chatId}`
517
653
  );
518
654
  return false;
519
655
  }
520
656
  const ctx = buildContext(parsed, account);
521
- logger?.info(
657
+ log.info(
522
658
  `[cored] dispatching message=${parsed.messageId} chat=${parsed.chatId} sender=${parsed.senderId} type=${parsed.chatType}`
523
659
  );
524
660
  const runtime = api.runtime;
525
661
  if (!runtime?.channel?.reply?.dispatchReplyWithBufferedBlockDispatcher) {
526
- logger?.warn("[cored] runtime.channel.reply not available \u2014 cannot dispatch");
662
+ log.warn("[cored] runtime.channel.reply not available \u2014 cannot dispatch");
527
663
  return false;
528
664
  }
529
665
  const cfgSession = api.config?.session;
@@ -542,7 +678,7 @@ async function processInboundMessage(api, account, event, opts) {
542
678
  accountId: account.accountId
543
679
  } : void 0
544
680
  });
545
- logger?.debug(
681
+ log.debug(
546
682
  `[cored] dispatch starting for message=${parsed.messageId} session=${ctx.SessionKey}`
547
683
  );
548
684
  await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
@@ -550,77 +686,83 @@ async function processInboundMessage(api, account, event, opts) {
550
686
  cfg: api.config,
551
687
  dispatcherOptions: {
552
688
  deliver: async (payload) => {
553
- logger?.info(
689
+ log.info(
554
690
  `[cored] deliver callback called for message=${parsed.messageId} hasText=${!!payload.text} textLen=${payload.text?.length ?? 0}`
555
691
  );
556
692
  if (payload.text) {
557
693
  await opts.deliver(parsed.chatId, payload.text);
558
- logger?.info(
694
+ log.info(
559
695
  `[cored] deliver completed for message=${parsed.messageId} chat=${parsed.chatId}`
560
696
  );
561
697
  }
562
698
  },
563
699
  onError: (err, info) => {
564
- logger?.error(
700
+ log.error(
565
701
  `[cored] ${info?.kind ?? "reply"} error for message=${parsed.messageId}: ${err}`
566
702
  );
567
703
  }
568
704
  }
569
705
  });
570
- logger?.info(
706
+ log.info(
571
707
  `[cored] dispatch finished for message=${parsed.messageId}`
572
708
  );
573
709
  return true;
574
710
  }
575
711
 
576
712
  // src/index.ts
577
- function register(api) {
578
- api.registerChannel({ plugin: coredPlugin });
579
- api.registerService({
580
- id: "cored-sdk",
581
- start: async () => {
582
- if (clientCount() > 0) return;
583
- const accounts = listEnabledAccountConfigs(api.config);
584
- if (accounts.length === 0) {
585
- api.logger?.warn("[cored] no enabled account config found \u2014 service idle");
586
- return;
587
- }
588
- for (const account of accounts) {
589
- const errors = validateAccountConfig(account);
590
- if (errors.length > 0) {
591
- api.logger?.warn(
592
- `[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
593
- );
594
- continue;
713
+ var index_default = (0, import_core2.defineChannelPluginEntry)({
714
+ id: "cored",
715
+ name: "Cored",
716
+ description: "Connect OpenClaw with Cored",
717
+ plugin: coredPlugin,
718
+ registerFull(api) {
719
+ const typedApi = api;
720
+ typedApi.registerService({
721
+ id: "cored-sdk",
722
+ start: async () => {
723
+ if (clientCount() > 0) return;
724
+ const accounts = listEnabledAccountConfigs(typedApi.config);
725
+ if (accounts.length === 0) {
726
+ typedApi.logger?.warn?.("[cored] no enabled account config found \u2014 service idle");
727
+ return;
595
728
  }
596
- try {
597
- await startAccount(api, account);
598
- api.logger?.info(
599
- `[cored] account=${account.accountId} connected (appId=${account.appId})`
600
- );
601
- } catch (err) {
602
- api.logger?.error(
603
- `[cored] account=${account.accountId} failed to start: ${err instanceof Error ? err.message : String(err)}`
604
- );
729
+ for (const account of accounts) {
730
+ const errors = validateAccountConfig(account);
731
+ if (errors.length > 0) {
732
+ typedApi.logger?.warn?.(
733
+ `[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
734
+ );
735
+ continue;
736
+ }
737
+ try {
738
+ await startAccount(typedApi, account);
739
+ typedApi.logger?.info?.(
740
+ `[cored] account=${account.accountId} connected (appId=${account.appId})`
741
+ );
742
+ } catch (err) {
743
+ typedApi.logger?.error?.(
744
+ `[cored] account=${account.accountId} failed to start: ${err instanceof Error ? err.message : String(err)}`
745
+ );
746
+ }
605
747
  }
748
+ typedApi.logger?.info?.(`[cored] service started with ${clientCount()} account(s)`);
749
+ },
750
+ stop: async () => {
751
+ await destroyAllClients();
752
+ typedApi.logger?.info?.("[cored] service stopped \u2014 all clients disconnected");
606
753
  }
607
- api.logger?.info(`[cored] service started with ${clientCount()} account(s)`);
608
- },
609
- stop: async () => {
610
- await destroyAllClients();
611
- api.logger?.info("[cored] service stopped \u2014 all clients disconnected");
612
- }
613
- });
614
- api.logger?.info("[cored] plugin registered");
615
- }
754
+ });
755
+ typedApi.logger?.info?.("[cored] plugin registered");
756
+ }
757
+ });
616
758
  async function startAccount(api, account) {
617
- const deliver = makeDeliver(account.accountId, (msg) => api.logger?.warn(msg));
759
+ const deliver = makeDeliver(account.accountId, (msg) => api.logger?.warn?.(msg));
618
760
  await createClient({
619
761
  config: account,
620
- log: (msg) => api.logger?.debug(msg),
762
+ log: (msg) => api.logger?.debug?.(msg),
621
763
  onMessage: (event, accountConfig) => {
622
764
  handleInbound(api, accountConfig, event, deliver).catch((err) => {
623
- api.logger?.error(
765
+ api.logger?.error?.(
624
766
  `[cored] unhandled inbound error for account=${accountConfig.accountId}: ${err}`
625
767
  );
626
768
  });