evolclaw 3.2.0 → 3.4.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 (95) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +7 -4
  3. package/dist/agents/{resolve.js → baseagent.js} +34 -5
  4. package/dist/agents/claude-runner.js +120 -31
  5. package/dist/agents/codex-app-server-client.js +364 -0
  6. package/dist/agents/codex-runner.js +1152 -140
  7. package/dist/agents/gemini-runner.js +2 -2
  8. package/dist/agents/runner-types.js +58 -0
  9. package/dist/aun/aid/store.js +1 -1
  10. package/dist/aun/outbox.js +14 -2
  11. package/dist/aun/storage/download.js +1 -1
  12. package/dist/aun/storage/upload.js +13 -1
  13. package/dist/channels/aun.js +869 -358
  14. package/dist/channels/dingtalk.js +77 -140
  15. package/dist/channels/feishu.js +125 -154
  16. package/dist/channels/qqbot.js +75 -138
  17. package/dist/channels/wechat.js +75 -136
  18. package/dist/channels/wecom.js +75 -138
  19. package/dist/cli/agent-command.js +591 -0
  20. package/dist/cli/agent.js +23 -8
  21. package/dist/cli/aun-commands.js +1444 -0
  22. package/dist/cli/ctl-command.js +78 -0
  23. package/dist/cli/daemon-commands.js +2707 -0
  24. package/dist/cli/index.js +23 -4905
  25. package/dist/cli/init.js +33 -6
  26. package/dist/cli/model.js +1 -1
  27. package/dist/cli/restart-monitor.js +539 -0
  28. package/dist/cli/stats.js +558 -0
  29. package/dist/cli/version.js +87 -0
  30. package/dist/cli/watch-logs.js +33 -0
  31. package/dist/cli/watch-msg.js +5 -2
  32. package/dist/config-store.js +12 -6
  33. package/dist/core/channel-loader.js +88 -83
  34. package/dist/core/command/command-handler.js +1189 -0
  35. package/dist/core/command/menu-handler.js +1478 -0
  36. package/dist/core/command/slash-gate.js +142 -0
  37. package/dist/core/command/slash-handler.js +2090 -0
  38. package/dist/core/evolagent-registry.js +82 -0
  39. package/dist/core/evolagent.js +17 -1
  40. package/dist/core/interaction-router.js +8 -0
  41. package/dist/core/message/command-handler-agent-control.js +63 -1
  42. package/dist/core/message/im-renderer.js +91 -51
  43. package/dist/core/message/items-formatter.js +9 -1
  44. package/dist/core/message/message-bridge.js +73 -24
  45. package/dist/core/message/message-log.js +1 -0
  46. package/dist/core/message/message-processor.js +432 -94
  47. package/dist/core/message/message-queue.js +70 -2
  48. package/dist/core/message/pending-hints.js +232 -0
  49. package/dist/core/model/model-catalog.js +1 -1
  50. package/dist/core/model/model-scope.js +2 -2
  51. package/dist/core/permission.js +25 -12
  52. package/dist/core/relation/peer-identity.js +16 -1
  53. package/dist/core/session/adapters/codex-session-file-adapter.js +4 -2
  54. package/dist/core/session/session-manager.js +86 -26
  55. package/dist/core/session/session-title.js +26 -0
  56. package/dist/core/stats/billing.js +151 -0
  57. package/dist/core/stats/budget.js +93 -0
  58. package/dist/core/stats/db.js +334 -0
  59. package/dist/core/stats/eck-vars.js +84 -0
  60. package/dist/core/stats/index.js +10 -0
  61. package/dist/core/stats/normalizer.js +78 -0
  62. package/dist/core/stats/query.js +760 -0
  63. package/dist/core/stats/writer.js +115 -0
  64. package/dist/core/trigger/manager.js +34 -0
  65. package/dist/core/trigger/parser.js +9 -3
  66. package/dist/core/trigger/scheduler.js +20 -17
  67. package/dist/data/error-dict.json +7 -0
  68. package/dist/{agents → eck}/manifest-engine.js +20 -1
  69. package/dist/{agents → eck}/message-renderer.js +24 -1
  70. package/dist/index.js +174 -9
  71. package/dist/ipc.js +116 -1
  72. package/dist/utils/cross-platform.js +58 -5
  73. package/dist/utils/ecweb-launch.js +49 -0
  74. package/dist/utils/ecweb-pair.js +20 -0
  75. package/dist/utils/error-utils.js +18 -5
  76. package/dist/utils/npm-ops.js +38 -8
  77. package/dist/utils/stats.js +77 -6
  78. package/kits/docs/evolclaw/INDEX.md +3 -1
  79. package/kits/docs/evolclaw/fs-architecture.md +1215 -0
  80. package/kits/docs/evolclaw/fs.md +131 -0
  81. package/kits/docs/evolclaw/group-fs.md +209 -0
  82. package/kits/docs/evolclaw/stats.md +70 -0
  83. package/kits/docs/venues/aun-group.md +29 -6
  84. package/kits/docs/venues/group.md +5 -4
  85. package/kits/eck_message_manifest.json +30 -3
  86. package/kits/rules/05-venue.md +1 -1
  87. package/kits/templates/message-fragments/inject-default.md +2 -0
  88. package/package.json +5 -6
  89. package/dist/agents/baseagent-normalize.js +0 -19
  90. package/dist/core/command-handler.js +0 -3876
  91. package/dist/core/relation/peer-key.js +0 -16
  92. package/dist/evolclaw-config.js +0 -11
  93. package/dist/utils/channel-helpers.js +0 -46
  94. /package/dist/core/{cache/file-cache.js → daemon-file-cache.js} +0 -0
  95. /package/dist/{agents → eck}/kit-renderer.js +0 -0
@@ -1,7 +1,7 @@
1
1
  import crypto from 'node:crypto';
2
2
  import { logger } from '../utils/logger.js';
3
3
  import { requireOptional } from '../utils/npm-ops.js';
4
- import { normalizeChannelInstances, getChannelShowActivities } from '../utils/channel-helpers.js';
4
+ import { resolveShowActivities, showActivitiesPolicy } from '../core/channel-loader.js';
5
5
  import { formatItemsAsText } from '../core/message/items-formatter.js';
6
6
  // ── WecomChannel ───────────────────────────────────────────────────────────────
7
7
  export class WecomChannel {
@@ -465,143 +465,80 @@ function isValidCredential(value) {
465
465
  }
466
466
  export class WecomChannelPlugin {
467
467
  name = 'wecom';
468
- isEnabled(config) {
469
- const raw = config.channels?.wecom;
470
- if (!raw)
471
- return false;
472
- if (Array.isArray(raw)) {
473
- return raw.some(inst => inst.enabled !== false && isValidCredential(inst.botId) && isValidCredential(inst.secret));
474
- }
475
- if (raw.enabled === false)
476
- return false;
477
- return isValidCredential(raw.botId) && isValidCredential(raw.secret);
478
- }
479
- async createChannels(config) {
480
- const instances = normalizeChannelInstances(config.channels?.wecom, 'wecom');
481
- const result = [];
482
- for (const inst of instances) {
483
- if (inst.enabled === false)
484
- continue;
485
- if (!isValidCredential(inst.botId) || !isValidCredential(inst.secret))
486
- continue;
487
- const channel = new WecomChannel({
488
- botId: inst.botId,
489
- secret: inst.secret,
490
- });
491
- const adapter = {
492
- channelName: inst.name,
493
- channelKey: inst.name,
494
- capabilities: { file: true, image: true, interaction: false, markdown: true, thought: false, status: false, thread: false },
495
- send: async (envelope, payload) => {
496
- const ctx = envelope.replyContext;
497
- const channelId = envelope.channelId;
498
- switch (payload.kind) {
499
- case 'result.text':
500
- case 'command.result':
501
- case 'command.error':
502
- case 'system.notice':
503
- case 'system.error':
504
- case 'result.error':
505
- await channel.sendMessage(channelId, payload.text);
506
- return;
507
- case 'result.file':
508
- await channel.sendFile(channelId, payload.filePath);
509
- return;
510
- case 'result.image':
511
- await channel.sendImage(channelId, payload.data);
512
- return;
513
- case 'activity.batch': {
514
- const filtered = payload.items.filter((i) => !(i.kind === 'tool_result' && i.ok));
515
- const text = formatItemsAsText(filtered);
516
- if (text)
517
- await channel.sendMessage(channelId, text);
518
- return;
519
- }
520
- case 'interaction':
521
- if (payload.fallbackText)
522
- await channel.sendMessage(channelId, payload.fallbackText);
523
- return;
524
- case 'status.started':
525
- case 'status.completed':
526
- case 'status.interrupted':
527
- case 'status.error':
528
- case 'status.timeout':
529
- case 'status.progress':
530
- case 'custom':
531
- return;
532
- default:
533
- logger.warn(`[WeCom] Unhandled payload kind: ${payload.kind}`);
468
+ async createInstance(inst, ctx) {
469
+ if (inst.enabled === false)
470
+ return null;
471
+ if (!isValidCredential(inst.botId) || !isValidCredential(inst.secret))
472
+ return null;
473
+ const channel = new WecomChannel({
474
+ botId: inst.botId,
475
+ secret: inst.secret,
476
+ });
477
+ const mode = resolveShowActivities(inst);
478
+ const adapter = {
479
+ channelName: inst.name,
480
+ channelKey: inst.name,
481
+ capabilities: { file: true, image: true, interaction: false, markdown: true, thought: false, status: false, thread: false },
482
+ send: async (envelope, payload) => {
483
+ const channelId = envelope.channelId;
484
+ switch (payload.kind) {
485
+ case 'result.text':
486
+ case 'command.result':
487
+ case 'command.error':
488
+ case 'system.notice':
489
+ case 'system.error':
490
+ case 'result.error':
491
+ await channel.sendMessage(channelId, payload.text);
492
+ return;
493
+ case 'result.file':
494
+ await channel.sendFile(channelId, payload.filePath);
495
+ return;
496
+ case 'result.image':
497
+ await channel.sendImage(channelId, payload.data);
498
+ return;
499
+ case 'activity.batch': {
500
+ const filtered = payload.items.filter((i) => !(i.kind === 'tool_result' && i.ok));
501
+ const text = formatItemsAsText(filtered);
502
+ if (text)
503
+ await channel.sendMessage(channelId, text);
504
+ return;
534
505
  }
535
- },
536
- };
537
- const policy = {
538
- canSwitchProject: (_chatType, identity) => identity === 'owner' || identity === 'admin',
539
- canListProjects: (_chatType, identity) => identity === 'owner' || identity === 'admin',
540
- canCreateSession: () => true,
541
- canDeleteSession: () => true,
542
- canImportCliSession: (_chatType, identity) => identity === 'owner' || identity === 'admin',
543
- messagePrefix: (chatType, peerName) => (chatType === 'group' && peerName) ? `[${peerName}] ` : '',
544
- showMiddleResult: (chatType, identity) => {
545
- const mode = getChannelShowActivities(config, inst.name);
546
- if (mode === 'none')
547
- return false;
548
- if (mode === 'dm-only')
549
- return chatType === 'private';
550
- if (mode === 'owner-dm-only')
551
- return chatType === 'private' && identity === 'owner';
552
- return true;
553
- },
554
- showIdleMonitor: (chatType, identity) => {
555
- const mode = getChannelShowActivities(config, inst.name);
556
- if (mode === 'none')
557
- return false;
558
- if (mode === 'dm-only')
559
- return chatType === 'private';
560
- if (mode === 'owner-dm-only')
561
- return chatType === 'private' && identity === 'owner';
562
- return true;
563
- },
564
- accumulateErrors: () => true,
565
- };
566
- const options = {
567
- fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g,
568
- supportsImages: true,
569
- flushDelay: inst.flushDelay,
570
- };
571
- result.push({
572
- channelType: 'wecom',
573
- adapter,
574
- channel,
575
- policy,
576
- options,
577
- connect: () => channel.connect(),
578
- disconnect: () => channel.disconnect(),
579
- onProjectPathRequest: () => Promise.resolve(config.projects?.defaultPath || process.cwd()),
580
- registerBridge(bridge, channelType) {
581
- bridge.register(adapter.channelName, (handler) => channel.onMessage(async (event) => {
582
- handler({
583
- channel: adapter.channelName,
584
- channelType,
585
- channelId: event.channelId,
586
- selfAID: inst.agentName,
587
- content: event.content,
588
- images: event.images,
589
- chatType: event.chatType || 'private',
590
- peerId: event.peerId || '',
591
- peerName: event.peerName,
592
- messageId: event.messageId,
593
- });
594
- }), (channelId, text) => channel.sendMessage(channelId, text), adapter, channelType);
595
- },
596
- });
597
- }
598
- return result;
599
- }
600
- async createChannel(config) {
601
- const instances = await this.createChannels(config);
602
- if (instances.length === 0) {
603
- throw new Error('WeCom config missing or invalid');
604
- }
605
- return instances[0];
506
+ case 'interaction':
507
+ if (payload.fallbackText)
508
+ await channel.sendMessage(channelId, payload.fallbackText);
509
+ return;
510
+ default: return;
511
+ }
512
+ },
513
+ };
514
+ const policy = {
515
+ canSwitchProject: (_, identity) => identity === 'owner' || identity === 'admin',
516
+ canListProjects: (_, identity) => identity === 'owner' || identity === 'admin',
517
+ canCreateSession: () => true,
518
+ canDeleteSession: () => true,
519
+ canImportCliSession: (_, identity) => identity === 'owner' || identity === 'admin',
520
+ messagePrefix: (chatType, peerName) => (chatType === 'group' && peerName) ? `[${peerName}] ` : '',
521
+ showMiddleResult: (chatType, identity) => showActivitiesPolicy(mode, chatType, identity),
522
+ showIdleMonitor: (chatType, identity) => showActivitiesPolicy(mode, chatType, identity),
523
+ accumulateErrors: () => true,
524
+ };
525
+ return {
526
+ channelType: 'wecom', adapter, channel,
527
+ policy,
528
+ options: { fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g, supportsImages: true, flushDelay: inst.flushDelay },
529
+ connect: () => channel.connect(),
530
+ disconnect: () => channel.disconnect(),
531
+ onProjectPathRequest: () => Promise.resolve(ctx.defaultProjectPath),
532
+ registerBridge(bridge, channelType) {
533
+ bridge.register(adapter.channelName, (handler) => channel.onMessage(async (event) => {
534
+ handler({
535
+ channel: adapter.channelName, channelType, channelId: event.channelId,
536
+ selfAID: ctx.agentName, content: event.content, images: event.images,
537
+ chatType: event.chatType || 'private', peerId: event.peerId || '',
538
+ peerName: event.peerName, messageId: event.messageId,
539
+ });
540
+ }), (channelId, text) => channel.sendMessage(channelId, text), adapter, channelType);
541
+ },
542
+ };
606
543
  }
607
544
  }