@cored-im/openclaw-plugin 0.1.7 → 0.1.10

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
@@ -336,171 +336,177 @@ function parseTarget(to) {
336
336
  }
337
337
 
338
338
  // src/channel.ts
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
339
+ var base = (0, import_core.createChannelPluginBase)({
340
+ id: "cored",
394
341
  meta: {
395
342
  id: "cored",
396
343
  label: "Cored",
397
344
  selectionLabel: "Cored",
398
345
  docsPath: "/channels/cored",
399
346
  blurb: "Connect OpenClaw to Cored",
400
- aliases: ["cored", "co"]
347
+ aliases: ["co"]
401
348
  },
402
- // Capabilities
403
349
  capabilities: {
404
350
  chatTypes: ["direct", "group"]
405
351
  },
406
- // Config
407
352
  config: {
408
353
  listAccountIds: (cfg) => listAccountIds(cfg),
409
- resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId)
354
+ resolveAccount: (cfg, accountId) => resolveAccountConfig(cfg, accountId ?? void 0),
355
+ inspectAccount(cfg, accountId) {
356
+ const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
357
+ const hasConfig = Boolean(
358
+ resolved.appId && resolved.appSecret && resolved.backendUrl
359
+ );
360
+ return {
361
+ enabled: resolved.enabled,
362
+ configured: hasConfig,
363
+ tokenStatus: hasConfig ? "available" : "missing"
364
+ };
365
+ }
410
366
  },
411
- // Outbound messaging
412
- outbound: {
413
- deliveryMode: "direct",
414
- resolveTarget: ({ to }) => {
415
- const target = parseTarget(to);
416
- if (!target) {
417
- return {
418
- ok: false,
419
- error: new Error(
420
- `Cored requires --to <user:ID|chat:ID>, got: ${JSON.stringify(to)}`
421
- )
422
- };
367
+ setup: {
368
+ applyAccountConfig: ({ cfg, accountId, input }) => {
369
+ const updated = structuredClone(cfg);
370
+ if (!updated.channels) updated.channels = {};
371
+ const ch = updated.channels;
372
+ if (!ch["cored"]) ch["cored"] = {};
373
+ const section = ch["cored"];
374
+ const appId = input.appToken;
375
+ const appSecret = input.token;
376
+ const backendUrl = input.url;
377
+ if (accountId && accountId !== "default") {
378
+ if (!section.accounts) section.accounts = {};
379
+ const accounts = section.accounts;
380
+ if (!accounts[accountId]) accounts[accountId] = {};
381
+ const account = accounts[accountId];
382
+ if (appId) account.appId = appId;
383
+ if (appSecret) account.appSecret = appSecret;
384
+ if (backendUrl) account.backendUrl = backendUrl;
385
+ } else {
386
+ if (appId) section.appId = appId;
387
+ if (appSecret) section.appSecret = appSecret;
388
+ if (backendUrl) section.backendUrl = backendUrl;
423
389
  }
424
- return { ok: true, to: `${target.kind}:${target.id}` };
425
- },
426
- sendText: async ({
427
- to,
428
- text,
429
- accountId
430
- }) => {
431
- const target = parseTarget(to);
432
- if (!target) {
433
- return {
434
- ok: false,
435
- error: new Error(`[cored] invalid send target: ${to}`)
436
- };
437
- }
438
- return sendText(target.id, text, accountId);
390
+ return updated;
439
391
  }
440
392
  },
441
- // Setup wizard for openclaw onboard
442
393
  setupWizard: {
443
394
  channel: "cored",
444
395
  status: {
445
396
  configuredLabel: "Connected",
446
397
  unconfiguredLabel: "Not configured",
447
398
  resolveConfigured: ({ cfg }) => {
448
- const section = cfg.channels?.["cored"];
449
- return Boolean(section?.appId && section?.appSecret && section?.backendUrl);
399
+ const ids = listAccountIds(cfg);
400
+ return ids.some((id) => {
401
+ const resolved = resolveAccountConfig(cfg, id);
402
+ return Boolean(resolved.appId && resolved.appSecret && resolved.backendUrl);
403
+ });
450
404
  }
451
405
  },
452
406
  credentials: [
453
407
  {
454
- inputKey: "appId",
408
+ inputKey: "appToken",
455
409
  providerHint: "cored",
456
410
  credentialLabel: "App ID",
457
411
  preferredEnvVar: "CORED_APP_ID",
458
412
  envPrompt: "Use CORED_APP_ID from environment?",
459
413
  keepPrompt: "Keep current App ID?",
460
414
  inputPrompt: "Enter your Cored App ID:",
461
- inspect: ({ cfg }) => {
462
- const section = cfg.channels?.["cored"];
415
+ inspect: ({ cfg, accountId }) => {
416
+ const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
463
417
  return {
464
- accountConfigured: Boolean(section?.appId),
465
- hasConfiguredValue: Boolean(section?.appId)
418
+ accountConfigured: Boolean(resolved.appId),
419
+ hasConfiguredValue: Boolean(resolved.appId)
466
420
  };
467
421
  }
468
422
  },
469
423
  {
470
- inputKey: "appSecret",
424
+ inputKey: "token",
471
425
  providerHint: "cored",
472
426
  credentialLabel: "App Secret",
473
427
  preferredEnvVar: "CORED_APP_SECRET",
474
428
  envPrompt: "Use CORED_APP_SECRET from environment?",
475
429
  keepPrompt: "Keep current App Secret?",
476
430
  inputPrompt: "Enter your Cored App Secret:",
477
- inspect: ({ cfg }) => {
478
- const section = cfg.channels?.["cored"];
431
+ inspect: ({ cfg, accountId }) => {
432
+ const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
479
433
  return {
480
- accountConfigured: Boolean(section?.appSecret),
481
- hasConfiguredValue: Boolean(section?.appSecret)
434
+ accountConfigured: Boolean(resolved.appSecret),
435
+ hasConfiguredValue: Boolean(resolved.appSecret)
482
436
  };
483
437
  }
484
438
  },
485
439
  {
486
- inputKey: "backendUrl",
440
+ inputKey: "url",
487
441
  providerHint: "cored",
488
442
  credentialLabel: "Backend URL",
489
443
  preferredEnvVar: "CORED_BACKEND_URL",
490
444
  envPrompt: "Use CORED_BACKEND_URL from environment?",
491
445
  keepPrompt: "Keep current Backend URL?",
492
446
  inputPrompt: "Enter your Cored backend server URL:",
493
- inspect: ({ cfg }) => {
494
- const section = cfg.channels?.["cored"];
447
+ inspect: ({ cfg, accountId }) => {
448
+ const resolved = resolveAccountConfig(cfg, accountId ?? void 0);
495
449
  return {
496
- accountConfigured: Boolean(section?.backendUrl),
497
- hasConfiguredValue: Boolean(section?.backendUrl)
450
+ accountConfigured: Boolean(resolved.backendUrl),
451
+ hasConfiguredValue: Boolean(resolved.backendUrl)
498
452
  };
499
453
  }
500
454
  }
501
455
  ]
502
456
  }
503
457
  });
458
+ var coredPlugin = (0, import_core.createChatChannelPlugin)({
459
+ base,
460
+ // DM security: who can message the bot
461
+ security: {
462
+ dm: {
463
+ channelKey: "cored",
464
+ resolvePolicy: () => void 0,
465
+ resolveAllowFrom: () => [],
466
+ defaultPolicy: "allowlist"
467
+ }
468
+ },
469
+ // Threading: how replies are delivered
470
+ threading: { topLevelReplyToMode: "reply" },
471
+ // Outbound: send messages to the platform
472
+ outbound: {
473
+ attachedResults: {
474
+ channel: "cored",
475
+ sendText: async (ctx) => {
476
+ const target = parseTarget(ctx.to);
477
+ if (!target) {
478
+ throw new Error(`[cored] invalid send target: ${ctx.to}`);
479
+ }
480
+ const result = await sendText(
481
+ target.id,
482
+ ctx.text,
483
+ ctx.accountId ?? void 0,
484
+ ctx.replyToId ?? void 0
485
+ );
486
+ if (!result.ok) {
487
+ throw result.error ?? new Error("[cored] send failed");
488
+ }
489
+ return { messageId: result.messageId ?? "" };
490
+ }
491
+ },
492
+ base: {
493
+ deliveryMode: "direct",
494
+ resolveTarget: ({ to }) => {
495
+ if (!to) return { ok: false, error: new Error("[cored] --to is required") };
496
+ const target = parseTarget(to);
497
+ if (!target) {
498
+ return {
499
+ ok: false,
500
+ error: new Error(
501
+ `Cored requires --to <user:ID|chat:ID>, got: ${JSON.stringify(to)}`
502
+ )
503
+ };
504
+ }
505
+ return { ok: true, to: `${target.kind}:${target.id}` };
506
+ }
507
+ }
508
+ }
509
+ });
504
510
 
505
511
  // src/messaging/inbound.ts
506
512
  function parseMessageEvent(event) {
@@ -716,43 +722,42 @@ var index_default = (0, import_core2.defineChannelPluginEntry)({
716
722
  description: "Connect OpenClaw with Cored",
717
723
  plugin: coredPlugin,
718
724
  registerFull(api) {
719
- const typedApi = api;
720
- typedApi.registerService({
725
+ api.registerService({
721
726
  id: "cored-sdk",
722
727
  start: async () => {
723
728
  if (clientCount() > 0) return;
724
- const accounts = listEnabledAccountConfigs(typedApi.config);
729
+ const accounts = listEnabledAccountConfigs(api.config);
725
730
  if (accounts.length === 0) {
726
- typedApi.logger?.warn?.("[cored] no enabled account config found \u2014 service idle");
731
+ api.logger?.warn?.("[cored] no enabled account config found \u2014 service idle");
727
732
  return;
728
733
  }
729
734
  for (const account of accounts) {
730
735
  const errors = validateAccountConfig(account);
731
736
  if (errors.length > 0) {
732
- typedApi.logger?.warn?.(
737
+ api.logger?.warn?.(
733
738
  `[cored] skipping account=${account.accountId}: ${errors.map((e) => e.message).join("; ")}`
734
739
  );
735
740
  continue;
736
741
  }
737
742
  try {
738
- await startAccount(typedApi, account);
739
- typedApi.logger?.info?.(
743
+ await startAccount(api, account);
744
+ api.logger?.info?.(
740
745
  `[cored] account=${account.accountId} connected (appId=${account.appId})`
741
746
  );
742
747
  } catch (err) {
743
- typedApi.logger?.error?.(
748
+ api.logger?.error?.(
744
749
  `[cored] account=${account.accountId} failed to start: ${err instanceof Error ? err.message : String(err)}`
745
750
  );
746
751
  }
747
752
  }
748
- typedApi.logger?.info?.(`[cored] service started with ${clientCount()} account(s)`);
753
+ api.logger?.info?.(`[cored] service started with ${clientCount()} account(s)`);
749
754
  },
750
755
  stop: async () => {
751
756
  await destroyAllClients();
752
- typedApi.logger?.info?.("[cored] service stopped \u2014 all clients disconnected");
757
+ api.logger?.info?.("[cored] service stopped \u2014 all clients disconnected");
753
758
  }
754
759
  });
755
- typedApi.logger?.info?.("[cored] plugin registered");
760
+ api.logger?.info?.("[cored] plugin registered");
756
761
  }
757
762
  });
758
763
  async function startAccount(api, account) {