@ai-setting/roy-agent-core 1.5.17-beta.1 → 1.5.22

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 (54) hide show
  1. package/dist/env/index.js +20 -8
  2. package/dist/env/log-trace/index.js +1 -1
  3. package/dist/env/prompt/index.js +1 -1
  4. package/dist/env/workflow/engine/index.js +1 -1
  5. package/dist/env/workflow/index.js +2 -2
  6. package/dist/index.js +6 -7
  7. package/dist/shared/@ai-setting/{roy-agent-core-xq8hhqb8.js → roy-agent-core-4wjywp3c.js} +4 -2
  8. package/dist/shared/@ai-setting/roy-agent-core-8jxva565.js +19 -0
  9. package/dist/shared/@ai-setting/roy-agent-core-avq1x4t7.js +84 -0
  10. package/dist/shared/@ai-setting/{roy-agent-core-gq20wsgv.js → roy-agent-core-ffb9fq4v.js} +23 -2
  11. package/dist/shared/@ai-setting/{roy-agent-core-93zfb3r1.js → roy-agent-core-mrcxzpbg.js} +1 -1
  12. package/dist/shared/@ai-setting/{roy-agent-core-rhmtwnw1.js → roy-agent-core-pw7cv1px.js} +1 -1
  13. package/dist/shared/@ai-setting/{roy-agent-core-gbqcyegm.js → roy-agent-core-rccptwv0.js} +512 -673
  14. package/dist/shared/@ai-setting/{roy-agent-core-wrcy0h6z.js → roy-agent-core-ty94k28r.js} +1 -1
  15. package/package.json +8 -29
  16. package/dist/config/index.d.ts +0 -1250
  17. package/dist/env/agent/index.d.ts +0 -2279
  18. package/dist/env/commands/index.d.ts +0 -1131
  19. package/dist/env/debug/formatters/index.d.ts +0 -236
  20. package/dist/env/debug/index.d.ts +0 -1652
  21. package/dist/env/hook/index.d.ts +0 -279
  22. package/dist/env/index.d.ts +0 -3481
  23. package/dist/env/llm/index.d.ts +0 -1760
  24. package/dist/env/log-trace/index.d.ts +0 -1574
  25. package/dist/env/mcp/index.d.ts +0 -1331
  26. package/dist/env/mcp/tool/index.d.ts +0 -183
  27. package/dist/env/memory/built-in/index.d.ts +0 -232
  28. package/dist/env/memory/index.d.ts +0 -1799
  29. package/dist/env/memory/plugin/index.d.ts +0 -747
  30. package/dist/env/prompt/index.d.ts +0 -1164
  31. package/dist/env/session/index.d.ts +0 -1908
  32. package/dist/env/session/storage/index.d.ts +0 -564
  33. package/dist/env/skill/index.d.ts +0 -1266
  34. package/dist/env/skill/tool/index.d.ts +0 -193
  35. package/dist/env/task/delegate/index.d.ts +0 -1612
  36. package/dist/env/task/events/index.d.ts +0 -171
  37. package/dist/env/task/hooks/index.d.ts +0 -624
  38. package/dist/env/task/index.d.ts +0 -1553
  39. package/dist/env/task/plugins/index.d.ts +0 -466
  40. package/dist/env/task/storage/index.d.ts +0 -241
  41. package/dist/env/task/tools/index.d.ts +0 -1485
  42. package/dist/env/task/tools/operation/index.d.ts +0 -1484
  43. package/dist/env/tool/built-in/index.d.ts +0 -218
  44. package/dist/env/tool/index.d.ts +0 -1396
  45. package/dist/env/workflow/decorators/index.d.ts +0 -2161
  46. package/dist/env/workflow/engine/index.d.ts +0 -3453
  47. package/dist/env/workflow/index.d.ts +0 -3546
  48. package/dist/env/workflow/nodes/index.d.ts +0 -2092
  49. package/dist/env/workflow/service/index.d.ts +0 -227
  50. package/dist/env/workflow/storage/index.d.ts +0 -165
  51. package/dist/env/workflow/tools/index.d.ts +0 -416
  52. package/dist/env/workflow/types/index.d.ts +0 -2255
  53. package/dist/env/workflow/utils/index.d.ts +0 -2031
  54. package/dist/index.d.ts +0 -7858
@@ -426,8 +426,6 @@ __legacyDecorateClassTS([
426
426
  TracedAs("env.handle_query", { recordParams: true, recordResult: true, log: true })
427
427
  ], BaseEnvironment.prototype, "handle_query", null);
428
428
  // src/env/event-source/event-source-component.ts
429
- import { spawn, exec } from "child_process";
430
- import { promisify } from "util";
431
429
  import { join } from "path";
432
430
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
433
431
  init_logger();
@@ -449,11 +447,426 @@ var EVENT_SOURCE_CONFIG_REGISTRATION = {
449
447
  ]
450
448
  };
451
449
 
452
- // src/env/event-source/event-source-component.ts
453
- var execAsyncImpl = promisify(exec);
454
- function getExecAsync() {
455
- return execAsyncImpl;
450
+ // src/env/event-source/event-source-handlers.ts
451
+ import { spawn } from "child_process";
452
+ function matchEventType(eventType, patterns) {
453
+ for (const pattern of patterns) {
454
+ if (pattern === "*")
455
+ return true;
456
+ if (pattern.endsWith(".*")) {
457
+ const prefix = pattern.slice(0, -2);
458
+ if (eventType.startsWith(prefix + ".") || eventType === prefix)
459
+ return true;
460
+ }
461
+ if (eventType === pattern)
462
+ return true;
463
+ }
464
+ return false;
465
+ }
466
+ function formatEventMessage(sourceType, rawEvent, eventType) {
467
+ const event = rawEvent;
468
+ switch (sourceType) {
469
+ case "lark-cli": {
470
+ const larkEvent = event;
471
+ const larkInnerEvent = larkEvent.event;
472
+ const larkMessage = larkInnerEvent?.message || larkEvent.message;
473
+ const larkSender = larkInnerEvent?.sender || larkEvent.sender;
474
+ const senderId = larkSender?.sender_id;
475
+ if (larkMessage) {
476
+ const openId = senderId?.open_id || senderId?.user_id || senderId?.email || senderId?.union_id || "未知用户";
477
+ let content = "无消息内容";
478
+ if (larkMessage.content) {
479
+ try {
480
+ const contentObj = JSON.parse(larkMessage.content);
481
+ content = contentObj.text || contentObj.content || larkMessage.content;
482
+ } catch {
483
+ content = larkMessage.content;
484
+ }
485
+ }
486
+ return `[飞书消息] ${openId}: ${content}`;
487
+ }
488
+ return `[飞书事件] ${eventType || larkEvent.schema || "unknown"}`;
489
+ }
490
+ case "timer": {
491
+ const timerMessage = event.payload?.message || event.message || "tick";
492
+ return `[定时任务] ${timerMessage}`;
493
+ }
494
+ case "websocket":
495
+ return `[WebSocket] ${JSON.stringify(rawEvent).substring(0, 200)}`;
496
+ default:
497
+ return `[${sourceType}] ${JSON.stringify(rawEvent).substring(0, 200)}`;
498
+ }
499
+ }
500
+ function extractMetadata(sourceType, rawEvent, eventType) {
501
+ const event = rawEvent;
502
+ const metadata = {};
503
+ switch (sourceType) {
504
+ case "lark-cli": {
505
+ const larkInnerEvent = event.event;
506
+ const header = event.header;
507
+ const message = larkInnerEvent?.message || event.message;
508
+ const sender = larkInnerEvent?.sender || event.sender;
509
+ const senderId = sender?.sender_id;
510
+ if (header) {
511
+ metadata.eventType = header.event_type;
512
+ metadata.appId = header.app_id;
513
+ metadata.tenantKey = header.tenant_key;
514
+ }
515
+ if (message) {
516
+ metadata.chatId = message.chat_id;
517
+ metadata.chatType = message.chat_type;
518
+ metadata.messageId = message.message_id;
519
+ metadata.messageType = message.message_type;
520
+ }
521
+ if (senderId) {
522
+ metadata.senderId = senderId.open_id || senderId.user_id || senderId.union_id;
523
+ }
524
+ break;
525
+ }
526
+ case "timer":
527
+ metadata.eventType = "timer.tick";
528
+ break;
529
+ case "websocket":
530
+ metadata.eventType = eventType;
531
+ break;
532
+ default:
533
+ metadata.eventType = eventType;
534
+ }
535
+ let recommendedAction;
536
+ if (sourceType === "lark-cli" && eventType === "im.message.receive_v1") {
537
+ recommendedAction = {
538
+ action: "处理飞书消息并回复",
539
+ replyTo: {
540
+ appId: metadata.appId,
541
+ chatId: metadata.chatId,
542
+ messageId: metadata.messageId
543
+ }
544
+ };
545
+ } else if (sourceType === "timer") {
546
+ recommendedAction = { action: "执行定时任务" };
547
+ } else if (sourceType === "websocket") {
548
+ recommendedAction = { action: "处理 WebSocket 消息" };
549
+ }
550
+ let replyChannel;
551
+ if (sourceType === "lark-cli") {
552
+ replyChannel = {
553
+ type: "lark-cli",
554
+ appId: metadata.appId,
555
+ chatId: metadata.chatId,
556
+ messageId: metadata.messageId
557
+ };
558
+ } else if (sourceType === "websocket") {
559
+ replyChannel = { type: "websocket" };
560
+ }
561
+ return { metadata, replyChannel, recommendedAction };
562
+ }
563
+
564
+ class LarkCliInstance {
565
+ config;
566
+ status = "created";
567
+ child;
568
+ buffer = "";
569
+ eventHandler;
570
+ constructor(config) {
571
+ this.config = config;
572
+ }
573
+ async start() {
574
+ if (this.status === "running")
575
+ return;
576
+ const command = this.config.command || "lark-cli event +subscribe";
577
+ const isWindows = process.platform === "win32";
578
+ const shell = isWindows ? "cmd.exe" : "sh";
579
+ const shellArgs = isWindows ? ["/c", command] : ["-c", `exec ${command}`];
580
+ this.child = spawn(shell, shellArgs, {
581
+ stdio: ["ignore", "pipe", "pipe"],
582
+ detached: false,
583
+ windowsHide: true
584
+ });
585
+ this.child.stdout?.on("data", (data) => {
586
+ this.processStream(data.toString());
587
+ });
588
+ this.child.stderr?.on("data", (data) => {
589
+ const output = data.toString();
590
+ if (output.includes('"ok": false')) {
591
+ this.status = "error";
592
+ }
593
+ });
594
+ this.child.on("exit", (code) => {
595
+ if (code !== 0 && code !== null) {
596
+ this.status = "error";
597
+ }
598
+ });
599
+ await new Promise((resolve2) => setTimeout(resolve2, 1000));
600
+ this.status = "running";
601
+ }
602
+ async stop() {
603
+ if (this.status === "stopped" || this.status === "created")
604
+ return;
605
+ this.child?.kill("SIGTERM");
606
+ this.child = undefined;
607
+ this.buffer = "";
608
+ this.status = "stopped";
609
+ }
610
+ getStatus() {
611
+ return this.status;
612
+ }
613
+ onEvent(handler) {
614
+ this.eventHandler = handler;
615
+ }
616
+ offEvent() {
617
+ this.eventHandler = undefined;
618
+ }
619
+ processStream(data) {
620
+ this.buffer += data;
621
+ const lines = this.buffer.split(`
622
+ `);
623
+ this.buffer = lines.pop() || "";
624
+ for (const line of lines) {
625
+ if (line.trim()) {
626
+ this.handleEvent(line);
627
+ }
628
+ }
629
+ }
630
+ handleEvent(rawData) {
631
+ try {
632
+ let rawEvent;
633
+ try {
634
+ rawEvent = JSON.parse(rawData);
635
+ } catch {
636
+ rawEvent = { event: "message", data: { content: { type: "text", body: rawData } } };
637
+ }
638
+ const event = rawEvent;
639
+ let eventType;
640
+ if (event.header?.event_type) {
641
+ eventType = event.header.event_type;
642
+ } else if (event.schema) {
643
+ eventType = `lark.${event.schema}`;
644
+ } else if (event.type) {
645
+ eventType = event.type;
646
+ } else {
647
+ eventType = "unknown";
648
+ }
649
+ if (this.config.eventTypes?.length && !matchEventType(eventType, this.config.eventTypes)) {
650
+ return;
651
+ }
652
+ const { metadata, replyChannel, recommendedAction } = extractMetadata("lark-cli", rawEvent, eventType);
653
+ const message = formatEventMessage("lark-cli", rawEvent, eventType);
654
+ const evt = {
655
+ sourceId: this.config.id,
656
+ type: eventType,
657
+ timestamp: Date.now(),
658
+ payload: {
659
+ sourceId: this.config.id,
660
+ sourceType: "lark-cli",
661
+ rawEvent,
662
+ message,
663
+ metadata,
664
+ replyChannel,
665
+ recommendedAction,
666
+ timestamp: Date.now()
667
+ }
668
+ };
669
+ this.eventHandler?.(evt);
670
+ } catch (error) {}
671
+ }
456
672
  }
673
+ var larkCliHandler = {
674
+ type: "lark-cli",
675
+ validateConfig(config) {
676
+ const errors = [];
677
+ if (!config.command) {
678
+ errors.push("lark-cli command is required");
679
+ }
680
+ return errors;
681
+ },
682
+ createInstance(config) {
683
+ return new LarkCliInstance(config);
684
+ }
685
+ };
686
+
687
+ class TimerInstance {
688
+ config;
689
+ status = "created";
690
+ timer;
691
+ eventHandler;
692
+ constructor(config) {
693
+ this.config = config;
694
+ }
695
+ async start() {
696
+ if (this.status === "running")
697
+ return;
698
+ const interval = this.config.interval || 60000;
699
+ const message = this.config.options?.message || `Timer event from ${this.config.name}`;
700
+ this.timer = setInterval(() => {
701
+ this.emitEvent(message);
702
+ }, interval);
703
+ this.emitEvent(message);
704
+ this.status = "running";
705
+ }
706
+ async stop() {
707
+ if (this.timer) {
708
+ clearInterval(this.timer);
709
+ this.timer = undefined;
710
+ }
711
+ this.status = "stopped";
712
+ }
713
+ getStatus() {
714
+ return this.status;
715
+ }
716
+ onEvent(handler) {
717
+ this.eventHandler = handler;
718
+ }
719
+ offEvent() {
720
+ this.eventHandler = undefined;
721
+ }
722
+ emitEvent(message) {
723
+ const rawEvent = {
724
+ type: "timer.tick",
725
+ payload: {
726
+ message,
727
+ timestamp: Date.now()
728
+ }
729
+ };
730
+ const { metadata, recommendedAction } = extractMetadata("timer", rawEvent, "timer.tick");
731
+ const evt = {
732
+ sourceId: this.config.id,
733
+ type: "timer.tick",
734
+ timestamp: Date.now(),
735
+ payload: {
736
+ sourceId: this.config.id,
737
+ sourceType: "timer",
738
+ rawEvent,
739
+ message: formatEventMessage("timer", rawEvent),
740
+ metadata,
741
+ recommendedAction,
742
+ timestamp: Date.now()
743
+ }
744
+ };
745
+ this.eventHandler?.(evt);
746
+ }
747
+ }
748
+ var timerHandler = {
749
+ type: "timer",
750
+ validateConfig(config) {
751
+ const errors = [];
752
+ if (!config.interval || config.interval <= 0) {
753
+ errors.push("Timer interval must be a positive number");
754
+ }
755
+ return errors;
756
+ },
757
+ createInstance(config) {
758
+ return new TimerInstance(config);
759
+ }
760
+ };
761
+
762
+ class WebSocketInstance {
763
+ config;
764
+ status = "created";
765
+ ws;
766
+ buffer = "";
767
+ eventHandler;
768
+ constructor(config) {
769
+ this.config = config;
770
+ }
771
+ async start() {
772
+ if (this.status === "running")
773
+ return;
774
+ const url = this.config.url;
775
+ if (!url) {
776
+ throw new Error("WebSocket URL is required");
777
+ }
778
+ const { WebSocket } = await import("ws");
779
+ this.ws = new WebSocket(url, { headers: this.config.headers });
780
+ this.ws.on("open", () => {
781
+ this.status = "running";
782
+ });
783
+ this.ws.on("message", (data) => {
784
+ this.processStream(data.toString());
785
+ });
786
+ this.ws.on("error", () => {
787
+ this.status = "error";
788
+ });
789
+ this.ws.on("close", () => {
790
+ this.status = "stopped";
791
+ });
792
+ await new Promise((resolve2) => setTimeout(resolve2, 5000));
793
+ }
794
+ async stop() {
795
+ if (this.ws) {
796
+ this.ws.close();
797
+ this.ws = undefined;
798
+ }
799
+ this.buffer = "";
800
+ this.status = "stopped";
801
+ }
802
+ getStatus() {
803
+ return this.status;
804
+ }
805
+ onEvent(handler) {
806
+ this.eventHandler = handler;
807
+ }
808
+ offEvent() {
809
+ this.eventHandler = undefined;
810
+ }
811
+ processStream(data) {
812
+ this.buffer += data;
813
+ const lines = this.buffer.split(`
814
+ `);
815
+ this.buffer = lines.pop() || "";
816
+ for (const line of lines) {
817
+ if (line.trim()) {
818
+ this.handleEvent(line);
819
+ }
820
+ }
821
+ }
822
+ handleEvent(rawData) {
823
+ try {
824
+ let rawEvent;
825
+ try {
826
+ rawEvent = JSON.parse(rawData);
827
+ } catch {
828
+ rawEvent = rawData;
829
+ }
830
+ const { metadata, replyChannel, recommendedAction } = extractMetadata("websocket", rawEvent);
831
+ const evt = {
832
+ sourceId: this.config.id,
833
+ type: "websocket.message",
834
+ timestamp: Date.now(),
835
+ payload: {
836
+ sourceId: this.config.id,
837
+ sourceType: "websocket",
838
+ rawEvent,
839
+ message: formatEventMessage("websocket", rawEvent),
840
+ metadata,
841
+ replyChannel,
842
+ recommendedAction,
843
+ timestamp: Date.now()
844
+ }
845
+ };
846
+ this.eventHandler?.(evt);
847
+ } catch (error) {}
848
+ }
849
+ }
850
+ var websocketHandler = {
851
+ type: "websocket",
852
+ validateConfig(config) {
853
+ const errors = [];
854
+ if (!config.url) {
855
+ errors.push("WebSocket URL is required");
856
+ }
857
+ return errors;
858
+ },
859
+ createInstance(config) {
860
+ return new WebSocketInstance(config);
861
+ }
862
+ };
863
+ var builtInHandlers = [
864
+ larkCliHandler,
865
+ timerHandler,
866
+ websocketHandler
867
+ ];
868
+
869
+ // src/env/event-source/event-source-component.ts
457
870
  var logger2 = createLogger("event-source");
458
871
 
459
872
  class EventSourceComponent extends BaseComponent {
@@ -461,15 +874,16 @@ class EventSourceComponent extends BaseComponent {
461
874
  version = "1.0.0";
462
875
  sources = new Map;
463
876
  statuses = new Map;
464
- processes = new Map;
465
877
  handlers = new Map;
466
- timers = new Map;
878
+ instances = new Map;
879
+ eventHandlers = new Map;
467
880
  buffers = new Map;
468
881
  configPath = "";
469
882
  persistenceEnabled = true;
470
883
  configComponent;
471
884
  configWatcher;
472
885
  async onInit() {
886
+ await this.executeInitHooks();
473
887
  await this.loadConfig();
474
888
  }
475
889
  async init(options) {
@@ -487,6 +901,9 @@ class EventSourceComponent extends BaseComponent {
487
901
  if (opts?.configComponent) {
488
902
  this.configComponent = opts.configComponent;
489
903
  await this.registerConfig(opts);
904
+ if (opts.registerBuiltInHandlers !== false) {
905
+ this.registerBuiltInHandlers();
906
+ }
490
907
  } else {
491
908
  throw new Error("ConfigComponent is required for EventSourceComponent initialization");
492
909
  }
@@ -503,11 +920,43 @@ class EventSourceComponent extends BaseComponent {
503
920
  }
504
921
  this.sources.clear();
505
922
  this.statuses.clear();
506
- this.processes.clear();
923
+ this.instances.clear();
924
+ this.eventHandlers.clear();
507
925
  this.handlers.clear();
508
- this.timers.clear();
509
926
  this.buffers.clear();
510
927
  }
928
+ registerBuiltInHandlers() {
929
+ for (const handler of builtInHandlers) {
930
+ if (!this.handlers.has(handler.type)) {
931
+ this.handlers.set(handler.type, handler);
932
+ logger2.debug(`Registered built-in handler: ${handler.type}`);
933
+ }
934
+ }
935
+ }
936
+ async executeInitHooks() {
937
+ const { EventSourceInitHooks } = await import("./roy-agent-core-8jxva565.js");
938
+ await EventSourceInitHooks.execute(this);
939
+ }
940
+ registerHandler(handler) {
941
+ if (this.handlers.has(handler.type)) {
942
+ logger2.warn(`Handler already registered for type: ${handler.type}, overwriting`);
943
+ }
944
+ this.handlers.set(handler.type, handler);
945
+ logger2.debug(`Handler registered: ${handler.type}`);
946
+ }
947
+ unregisterHandler(type) {
948
+ const deleted = this.handlers.delete(type);
949
+ if (deleted) {
950
+ logger2.debug(`Handler unregistered: ${type}`);
951
+ }
952
+ return deleted;
953
+ }
954
+ getHandler(type) {
955
+ return this.handlers.get(type);
956
+ }
957
+ listHandlers() {
958
+ return Array.from(this.handlers.values());
959
+ }
511
960
  async registerConfig(options) {
512
961
  const configComponent = options.configComponent;
513
962
  if (!configComponent)
@@ -560,11 +1009,7 @@ class EventSourceComponent extends BaseComponent {
560
1009
  buildConfig() {
561
1010
  const configComponent = this.configComponent;
562
1011
  if (!configComponent) {
563
- return {
564
- enabled: true,
565
- persistenceEnabled: true,
566
- configPath: ""
567
- };
1012
+ return { enabled: true, persistenceEnabled: true, configPath: "" };
568
1013
  }
569
1014
  return {
570
1015
  enabled: configComponent.get("event-source.enabled") ?? true,
@@ -585,9 +1030,8 @@ class EventSourceComponent extends BaseComponent {
585
1030
  return result;
586
1031
  }
587
1032
  registerConfigWatcher(configComponent) {
588
- if (typeof configComponent.watch !== "function") {
1033
+ if (typeof configComponent.watch !== "function")
589
1034
  return;
590
- }
591
1035
  this.configWatcher = configComponent.watch("event-source.*", (event) => {
592
1036
  this.onConfigChange(event);
593
1037
  });
@@ -602,6 +1046,14 @@ class EventSourceComponent extends BaseComponent {
602
1046
  if (this.sources.has(config.id)) {
603
1047
  throw new Error(`EventSource already exists: ${config.id}`);
604
1048
  }
1049
+ const handler = this.handlers.get(config.type);
1050
+ if (!handler) {
1051
+ throw new Error(`No handler registered for event source type: ${config.type}`);
1052
+ }
1053
+ const errors = handler.validateConfig(config);
1054
+ if (errors.length > 0) {
1055
+ throw new Error(`Invalid config: ${errors.join(", ")}`);
1056
+ }
605
1057
  this.sources.set(config.id, config);
606
1058
  this.statuses.set(config.id, "created");
607
1059
  logger2.debug(`EventSource registered: ${config.id} (${config.type})`);
@@ -617,7 +1069,8 @@ class EventSourceComponent extends BaseComponent {
617
1069
  const existed = this.sources.has(id);
618
1070
  this.sources.delete(id);
619
1071
  this.statuses.delete(id);
620
- this.handlers.delete(id);
1072
+ this.instances.delete(id);
1073
+ this.eventHandlers.delete(id);
621
1074
  this.buffers.delete(id);
622
1075
  if (existed) {
623
1076
  logger2.debug(`EventSource unregistered: ${id}`);
@@ -633,17 +1086,25 @@ class EventSourceComponent extends BaseComponent {
633
1086
  list() {
634
1087
  return Array.from(this.sources.values());
635
1088
  }
636
- getEventSourceStatus(id) {
1089
+ getStatus(id) {
637
1090
  return this.statuses.get(id);
638
1091
  }
639
- getEventSourceStatusById(id) {
640
- return this.statuses.get(id);
1092
+ getEventSourceStatus(id) {
1093
+ return this.getStatus(id);
641
1094
  }
642
1095
  onEvent(id, handler) {
643
- this.handlers.set(id, handler);
1096
+ this.eventHandlers.set(id, handler);
1097
+ const instance = this.instances.get(id);
1098
+ if (instance) {
1099
+ instance.onEvent(handler);
1100
+ }
644
1101
  }
645
1102
  offEvent(id) {
646
- this.handlers.delete(id);
1103
+ this.eventHandlers.delete(id);
1104
+ const instance = this.instances.get(id);
1105
+ if (instance) {
1106
+ instance.offEvent();
1107
+ }
647
1108
  }
648
1109
  async startSource(id) {
649
1110
  const config = this.sources.get(id);
@@ -656,19 +1117,17 @@ class EventSourceComponent extends BaseComponent {
656
1117
  }
657
1118
  this.statuses.set(id, "starting");
658
1119
  try {
659
- switch (config.type) {
660
- case "lark-cli":
661
- await this.startLarkCli(id, config);
662
- break;
663
- case "timer":
664
- await this.startTimer(id, config);
665
- break;
666
- case "websocket":
667
- await this.startWebSocket(id, config);
668
- break;
669
- default:
670
- throw new Error(`Unsupported event source type: ${config.type}`);
1120
+ const handler = this.handlers.get(config.type);
1121
+ if (!handler) {
1122
+ throw new Error(`No handler registered for event source type: ${config.type}`);
671
1123
  }
1124
+ const instance = handler.createInstance(config);
1125
+ this.instances.set(id, instance);
1126
+ const eventHandler = this.eventHandlers.get(id);
1127
+ if (eventHandler) {
1128
+ instance.onEvent(eventHandler);
1129
+ }
1130
+ await instance.start();
672
1131
  this.statuses.set(id, "running");
673
1132
  this.getEnv()?.pushEnvEvent({
674
1133
  type: "event-source.started",
@@ -689,550 +1148,23 @@ class EventSourceComponent extends BaseComponent {
689
1148
  return;
690
1149
  }
691
1150
  this.statuses.set(id, "stopping");
692
- const processInfo = this.processes.get(id);
693
- const child = processInfo?.child;
694
- logger2.info(`[EventSource ${id}] process info: ${processInfo ? `pid=${processInfo.child.pid}` : "none"}`);
695
- if (processInfo && child) {
696
- child.removeAllListeners("exit");
697
- child.removeAllListeners("error");
698
- child.stdout?.removeAllListeners("data");
699
- child.stderr?.removeAllListeners("data");
700
- const killProcess = (pid, signal) => {
701
- try {
702
- process.kill(pid, signal);
703
- return true;
704
- } catch (e) {
705
- return false;
706
- }
707
- };
708
- const pidsToKill = processInfo.pids.length > 0 ? processInfo.pids : processInfo.child.pid ? [processInfo.child.pid] : [];
709
- logger2.info(`[EventSource ${id}] sending SIGTERM to ${pidsToKill.length} processes: ${pidsToKill.join(", ")}`);
710
- for (const pid of pidsToKill) {
711
- killProcess(pid, "SIGTERM");
712
- }
713
- await new Promise((resolve2) => {
714
- const timeout = setTimeout(() => {
715
- logger2.warn(`[EventSource ${id}] SIGTERM timeout, sending SIGKILL to ${pidsToKill.length} processes`);
716
- for (const pid of pidsToKill) {
717
- killProcess(pid, "SIGKILL");
718
- }
719
- resolve2();
720
- }, 3000);
721
- try {
722
- const onceResult = child.once?.("exit", () => {
723
- clearTimeout(timeout);
724
- for (const pid of pidsToKill) {
725
- if (pid !== processInfo.child.pid) {
726
- killProcess(pid, "SIGKILL");
727
- }
728
- }
729
- resolve2();
730
- });
731
- if (!onceResult || typeof onceResult.once !== "function") {
732
- child.on("exit", () => {
733
- clearTimeout(timeout);
734
- for (const pid of pidsToKill) {
735
- if (pid !== processInfo.child.pid) {
736
- killProcess(pid, "SIGKILL");
737
- }
738
- }
739
- resolve2();
740
- });
741
- }
742
- } catch (e) {
743
- logger2.warn(`[EventSource ${id}] failed to register exit listener: ${e}`);
744
- }
745
- });
746
- this.processes.delete(id);
747
- } else if (child) {
748
- child.removeAllListeners("exit");
749
- child.removeAllListeners("error");
750
- child.stdout?.removeAllListeners("data");
751
- child.stderr?.removeAllListeners("data");
752
- const pid = child.pid;
753
- const pgid = child.pgid;
754
- try {
755
- if (pgid && pgid > 0 && pgid !== pid) {
756
- logger2.info(`[EventSource ${id}] killing process group ${pgid}`);
757
- try {
758
- process.kill(-pgid, "SIGTERM");
759
- } catch (e) {
760
- logger2.warn(`[EventSource ${id}] failed to kill process group: ${e}`);
761
- }
762
- }
763
- logger2.info(`[EventSource ${id}] killing main process ${pid}`);
764
- child.kill("SIGTERM");
765
- await new Promise((resolve2) => {
766
- const timeout = setTimeout(() => {
767
- logger2.warn(`[EventSource ${id}] SIGTERM timeout, sending SIGKILL`);
768
- if (pgid && pgid > 0 && pgid !== pid) {
769
- try {
770
- process.kill(-pgid, "SIGKILL");
771
- } catch (e) {
772
- logger2.warn(`[EventSource ${id}] failed to kill process group with SIGKILL: ${e}`);
773
- }
774
- }
775
- child.kill("SIGKILL");
776
- resolve2();
777
- }, 3000);
778
- child.once("exit", () => {
779
- clearTimeout(timeout);
780
- resolve2();
781
- });
782
- });
783
- } catch (error) {
784
- logger2.error(`[EventSource ${id}] Failed to kill process:`, error);
785
- try {
786
- child.kill("SIGKILL");
787
- } catch {}
788
- }
789
- this.processes.delete(id);
790
- } else {
791
- logger2.warn(`[EventSource ${id}] no child process found in processes map`);
792
- }
793
- const timer = this.timers.get(id);
794
- if (timer) {
795
- clearInterval(timer);
796
- this.timers.delete(id);
797
- }
798
- this.buffers.delete(id);
799
- const config = this.sources.get(id);
800
- this.statuses.set(id, "stopped");
801
- this.getEnv()?.pushEnvEvent({
802
- type: "event-source.stopped",
803
- payload: { sourceId: id, sourceType: config?.type }
804
- });
805
- logger2.info(`EventSource stopped: ${id}`);
806
- }
807
- async findRelatedProcesses(pattern) {
808
- const pids = [];
809
- const platform = process.platform;
810
1151
  try {
811
- const exec2 = getExecAsync();
812
- if (platform === "win32") {
813
- const escapedPattern = pattern.replace(/'/g, "''").replace(/"/g, '`"');
814
- const psCommand = `Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like '*${escapedPattern}*' } | Select-Object -ExpandProperty ProcessId`;
815
- const { stdout } = await exec2(`powershell -Command "${psCommand}"`);
816
- const matches = stdout.replace(/\r\n/g, `
817
- `).match(/\d+/g);
818
- if (matches) {
819
- for (const match of matches) {
820
- const pid = parseInt(match, 10);
821
- if (!isNaN(pid) && pid > 0) {
822
- pids.push(pid);
823
- }
824
- }
825
- }
826
- } else {
827
- const { stdout } = await exec2(`pgrep -f "${pattern.replace(/"/g, "\\\"")}"`);
828
- const lines = stdout.trim().split(`
829
- `);
830
- for (const line of lines) {
831
- const trimmed = line.trim();
832
- if (trimmed) {
833
- const pid = parseInt(trimmed, 10);
834
- if (!isNaN(pid) && pid > 0) {
835
- pids.push(pid);
836
- }
837
- }
838
- }
839
- }
840
- } catch (error) {
841
- logger2.debug(`[EventSource] findRelatedProcesses: no processes found for pattern "${pattern}"`);
842
- }
843
- return pids;
844
- }
845
- async trackRelatedProcesses(id) {
846
- const processInfo = this.processes.get(id);
847
- if (!processInfo)
848
- return;
849
- const command = processInfo?.command || "";
850
- const commandParts = command.split(" ");
851
- const baseCommand = commandParts[0];
852
- const eventKeyword = "event";
853
- let relatedPids = await this.findRelatedProcesses(baseCommand);
854
- if (relatedPids.length < 2) {
855
- const morePids = await this.findRelatedProcesses(eventKeyword);
856
- for (const pid of morePids) {
857
- if (!relatedPids.includes(pid)) {
858
- relatedPids.push(pid);
859
- }
860
- }
861
- }
862
- const ownPid = process.pid;
863
- relatedPids = relatedPids.filter((pid) => pid !== ownPid);
864
- for (const pid of relatedPids) {
865
- if (!processInfo.pids.includes(pid)) {
866
- processInfo.pids.push(pid);
867
- }
868
- }
869
- const mainPid = processInfo.child.pid;
870
- if (mainPid && !processInfo.pids.includes(mainPid)) {
871
- processInfo.pids.unshift(mainPid);
872
- }
873
- logger2.info(`[EventSource ${id}] tracked ${processInfo.pids.length} related processes: ${processInfo.pids.join(", ")}`);
874
- }
875
- startLarkCli(id, config) {
876
- return new Promise((resolve2, reject) => {
877
- const command = config.command || "lark-cli event +subscribe";
878
- logger2.info(`Starting lark-cli event source: ${id}`);
879
- logger2.debug(`Executing command: ${command}`);
880
- const isWindows = process.platform === "win32";
881
- const shell = isWindows ? "cmd.exe" : "sh";
882
- const shellArgs = isWindows ? ["/c", command] : ["-c", `exec ${command}`];
883
- const child = spawn(shell, shellArgs, {
884
- stdio: ["ignore", "pipe", "pipe"],
885
- detached: false,
886
- windowsHide: true
887
- });
888
- this.processes.set(id, {
889
- child,
890
- pgid: child.pgid,
891
- pids: [],
892
- command
893
- });
894
- let startupTimeout = null;
895
- let settled = false;
896
- let startupConfirmed = false;
897
- const handleStartupSuccess = async () => {
898
- if (settled)
899
- return;
900
- settled = true;
901
- startupConfirmed = true;
902
- clearTimeout(startupTimeout);
903
- this.statuses.set(id, "running");
904
- logger2.info(`[EventSource ${id}] confirmed running`);
905
- try {
906
- await this.trackRelatedProcesses(id);
907
- } catch (e) {
908
- logger2.warn(`[EventSource ${id}] failed to track related processes: ${e}`);
909
- }
910
- resolve2();
911
- };
912
- startupTimeout = setTimeout(() => {
913
- if (!settled && !startupConfirmed) {
914
- handleStartupSuccess();
915
- }
916
- }, 1000);
917
- child.stdout?.on("data", (data) => {
918
- const output = data.toString();
919
- this.processStream(id, output);
920
- if (output.includes('"ok": true') || output.includes('"ok":true')) {
921
- if (!settled) {
922
- handleStartupSuccess();
923
- }
924
- }
925
- });
926
- child.stderr?.on("data", (data) => {
927
- const output = data.toString();
928
- if (output.includes('"ok": false') || output.includes('"ok":false')) {
929
- if (!settled) {
930
- settled = true;
931
- clearTimeout(startupTimeout);
932
- this.statuses.set(id, "error");
933
- child.kill();
934
- try {
935
- const errorObj = JSON.parse(output);
936
- reject(new Error(errorObj.error?.message || `lark-cli error: ${output}`));
937
- } catch {
938
- reject(new Error(`lark-cli error: ${output}`));
939
- }
940
- }
941
- }
942
- });
943
- child.on("exit", (code) => {
944
- if (!settled) {
945
- if (code !== 0 && code !== null) {
946
- settled = true;
947
- clearTimeout(startupTimeout);
948
- logger2.warn(`[EventSource ${id}] exited with code ${code}`);
949
- this.statuses.set(id, "error");
950
- reject(new Error(`lark-cli exited with code ${code}`));
951
- }
952
- }
953
- });
954
- child.on("error", (error) => {
955
- if (!settled) {
956
- settled = true;
957
- clearTimeout(startupTimeout);
958
- logger2.error(`[EventSource ${id}] process error:`, error);
959
- this.statuses.set(id, "error");
960
- reject(error);
961
- }
962
- });
963
- });
964
- }
965
- async startTimer(id, config) {
966
- const interval = config.interval || 60000;
967
- logger2.info(`Starting timer event source: ${id}, interval: ${interval}ms`);
968
- const timer = setInterval(() => {
969
- const message = config.options?.message || `Timer event from ${config.name}`;
970
- this.handleEvent(id, JSON.stringify({
971
- type: "timer.tick",
972
- payload: {
973
- message,
974
- timestamp: Date.now()
975
- }
976
- }));
977
- }, interval);
978
- this.timers.set(id, timer);
979
- this.handleEvent(id, JSON.stringify({
980
- type: "timer.tick",
981
- payload: {
982
- message: config.options?.message || `Timer event from ${config.name}`,
983
- timestamp: Date.now()
984
- }
985
- }));
986
- }
987
- async startWebSocket(id, config) {
988
- const url = config.url;
989
- if (!url) {
990
- throw new Error("WebSocket URL is required");
991
- }
992
- logger2.info(`Starting WebSocket event source: ${id}, url: ${url}`);
993
- try {
994
- const { WebSocket } = await import("ws");
995
- const ws = new WebSocket(url, {
996
- headers: config.headers
997
- });
998
- const wrapper = {
999
- child: {
1000
- kill: () => ws.close(),
1001
- on: (event, cb) => {
1002
- ws.on(event, cb);
1003
- }
1004
- },
1005
- pids: []
1006
- };
1007
- this.processes.set(id, wrapper);
1008
- ws.on("message", (data) => {
1009
- this.processStream(id, data.toString());
1010
- });
1011
- ws.on("error", (error) => {
1012
- logger2.error(`[EventSource ${id}] WebSocket error:`, error);
1013
- });
1014
- ws.on("close", () => {
1015
- logger2.info(`[EventSource ${id}] WebSocket closed`);
1016
- this.statuses.set(id, "stopped");
1017
- });
1018
- } catch (error) {
1019
- throw new Error(`Failed to import ws module: ${error}`);
1020
- }
1021
- }
1022
- processStream(sourceId, data) {
1023
- let buffer = this.buffers.get(sourceId) || "";
1024
- buffer += data;
1025
- const lines = buffer.split(`
1026
- `);
1027
- buffer = lines.pop() || "";
1028
- this.buffers.set(sourceId, buffer);
1029
- for (const line of lines) {
1030
- if (line.trim()) {
1031
- this.handleEvent(sourceId, line);
1032
- }
1033
- }
1034
- }
1035
- handleEvent(sourceId, rawData) {
1036
- const config = this.sources.get(sourceId);
1037
- if (!config)
1038
- return;
1039
- try {
1040
- const rawEvent = JSON.parse(rawData);
1041
- let eventType;
1042
- if (rawEvent.header?.event_type) {
1043
- eventType = rawEvent.header.event_type;
1044
- } else if (rawEvent.schema) {
1045
- eventType = `lark.${rawEvent.schema}`;
1046
- } else if (rawEvent.type) {
1047
- eventType = rawEvent.type;
1048
- } else {
1049
- eventType = "unknown";
1050
- }
1051
- if (config.eventTypes?.length && !this.matchEventType(eventType, config.eventTypes)) {
1052
- return;
1053
- }
1054
- const { metadata, replyChannel, recommendedAction } = this.extractMetadata(config.type, rawEvent, eventType);
1055
- const message = this.formatEventMessage(config.type, rawEvent, eventType);
1056
- const event = {
1057
- sourceId,
1058
- type: eventType,
1059
- timestamp: Date.now(),
1060
- payload: {
1061
- sourceId,
1062
- sourceType: config.type,
1063
- rawEvent,
1064
- message,
1065
- metadata,
1066
- replyChannel,
1067
- recommendedAction,
1068
- timestamp: Date.now()
1069
- }
1070
- };
1071
- const handler = this.handlers.get(sourceId);
1072
- if (handler) {
1073
- try {
1074
- const result = handler(event);
1075
- if (result instanceof Promise) {
1076
- result.catch((error) => {
1077
- logger2.error(`[EventSource ${sourceId}] Handler error:`, error);
1078
- });
1079
- }
1080
- } catch (error) {
1081
- logger2.error(`[EventSource ${sourceId}] Handler error:`, error);
1082
- }
1152
+ const instance = this.instances.get(id);
1153
+ if (instance) {
1154
+ await instance.stop();
1155
+ this.instances.delete(id);
1083
1156
  }
1157
+ const config = this.sources.get(id);
1158
+ this.statuses.set(id, "stopped");
1084
1159
  this.getEnv()?.pushEnvEvent({
1085
- type: `event-source.event.${config.type}`,
1086
- payload: event
1160
+ type: "event-source.stopped",
1161
+ payload: { sourceId: id, sourceType: config?.type }
1087
1162
  });
1163
+ logger2.info(`EventSource stopped: ${id}`);
1088
1164
  } catch (error) {
1089
- if (error instanceof SyntaxError) {
1090
- logger2.debug(`[EventSource ${sourceId}] Non-JSON data: ${rawData.substring(0, 100)}`);
1091
- const config2 = this.sources.get(sourceId);
1092
- if (config2) {
1093
- const event = {
1094
- sourceId,
1095
- type: "raw",
1096
- timestamp: Date.now(),
1097
- payload: {
1098
- sourceId,
1099
- sourceType: config2.type,
1100
- rawEvent: rawData,
1101
- message: rawData,
1102
- metadata: {},
1103
- timestamp: Date.now()
1104
- }
1105
- };
1106
- const handler = this.handlers.get(sourceId);
1107
- if (handler) {
1108
- handler(event);
1109
- }
1110
- }
1111
- } else {
1112
- logger2.error(`[EventSource ${sourceId}] Failed to handle event:`, error);
1113
- }
1114
- }
1115
- }
1116
- matchEventType(eventType, patterns) {
1117
- for (const pattern of patterns) {
1118
- if (pattern === "*")
1119
- return true;
1120
- if (pattern.endsWith(".*")) {
1121
- const prefix = pattern.slice(0, -2);
1122
- if (eventType.startsWith(prefix + ".") || eventType === prefix)
1123
- return true;
1124
- }
1125
- if (eventType === pattern)
1126
- return true;
1127
- }
1128
- return false;
1129
- }
1130
- extractMetadata(sourceType, rawEvent, eventType) {
1131
- const event = rawEvent;
1132
- const metadata = {};
1133
- let replyChannel;
1134
- let recommendedAction;
1135
- switch (sourceType) {
1136
- case "lark-cli":
1137
- const larkInnerEvent = event.event;
1138
- const header = event.header;
1139
- const message = larkInnerEvent?.message || event.message;
1140
- const sender = larkInnerEvent?.sender || event.sender;
1141
- const senderId = sender?.sender_id;
1142
- if (header) {
1143
- metadata.eventType = header.event_type;
1144
- metadata.appId = header.app_id;
1145
- metadata.tenantKey = header.tenant_key;
1146
- }
1147
- if (message) {
1148
- metadata.chatId = message.chat_id;
1149
- metadata.chatType = message.chat_type;
1150
- metadata.messageId = message.message_id;
1151
- metadata.messageType = message.message_type;
1152
- }
1153
- if (senderId) {
1154
- metadata.senderId = senderId.open_id || senderId.user_id || senderId.union_id;
1155
- }
1156
- if (eventType === "im.message.receive_v1") {
1157
- replyChannel = {
1158
- type: "lark-cli",
1159
- appId: metadata.appId,
1160
- chatId: metadata.chatId,
1161
- messageId: metadata.messageId
1162
- };
1163
- recommendedAction = {
1164
- action: "处理飞书消息并回复",
1165
- replyTo: {
1166
- appId: metadata.appId,
1167
- chatId: metadata.chatId,
1168
- messageId: metadata.messageId
1169
- }
1170
- };
1171
- }
1172
- break;
1173
- case "timer":
1174
- metadata.eventType = "timer.tick";
1175
- recommendedAction = {
1176
- action: "执行定时任务"
1177
- };
1178
- break;
1179
- case "websocket":
1180
- metadata.eventType = eventType;
1181
- replyChannel = {
1182
- type: "websocket"
1183
- };
1184
- recommendedAction = {
1185
- action: "处理 WebSocket 消息"
1186
- };
1187
- break;
1188
- default:
1189
- metadata.eventType = eventType;
1190
- recommendedAction = {
1191
- action: "处理事件"
1192
- };
1193
- }
1194
- return { metadata, replyChannel, recommendedAction };
1195
- }
1196
- formatEventMessage(sourceType, rawEvent, eventType) {
1197
- const event = rawEvent;
1198
- switch (sourceType) {
1199
- case "lark-cli": {
1200
- const larkEvent = event;
1201
- const larkInnerEvent = larkEvent.event;
1202
- const larkMessage = larkInnerEvent?.message || larkEvent.message;
1203
- const larkSender = larkInnerEvent?.sender || larkEvent.sender;
1204
- if (larkMessage) {
1205
- const senderId = larkSender?.sender_id;
1206
- const openId = senderId?.open_id || senderId?.user_id || senderId?.email || senderId?.union_id || "未知用户";
1207
- let content = "无消息内容";
1208
- if (larkMessage.content) {
1209
- try {
1210
- const contentObj = JSON.parse(larkMessage.content);
1211
- content = contentObj.text || contentObj.content || larkMessage.content;
1212
- } catch {
1213
- content = larkMessage.content;
1214
- }
1215
- }
1216
- return `[飞书消息] ${openId}: ${content}`;
1217
- }
1218
- const larkSenderRecord = larkEvent.sender;
1219
- const senderIdRecord = larkSenderRecord?.sender_id;
1220
- if (larkEvent.message_id || larkEvent.schema?.includes("message")) {
1221
- const senderId = senderIdRecord?.open_id || senderIdRecord?.user_id || senderIdRecord?.email || senderIdRecord?.union_id || "未知用户";
1222
- const content = larkEvent.text || larkEvent.content || JSON.stringify(larkEvent);
1223
- return `[飞书消息] ${senderId}: ${content}`;
1224
- }
1225
- return `[飞书事件] ${eventType || larkEvent.schema || "unknown"}`;
1226
- }
1227
- case "timer": {
1228
- const timerEvent = event;
1229
- const timerMessage = timerEvent.payload?.message || timerEvent.message || "tick";
1230
- return `[定时任务] ${timerMessage}`;
1231
- }
1232
- case "websocket":
1233
- return `[WebSocket] ${JSON.stringify(rawEvent).substring(0, 200)}`;
1234
- default:
1235
- return `[${sourceType}] ${JSON.stringify(rawEvent).substring(0, 200)}`;
1165
+ this.statuses.set(id, "error");
1166
+ logger2.error(`EventSource failed to stop: ${id}`, error);
1167
+ throw error;
1236
1168
  }
1237
1169
  }
1238
1170
  getConfigFilePath() {
@@ -1247,27 +1179,24 @@ class EventSourceComponent extends BaseComponent {
1247
1179
  return join(dataDir, "event-sources.json");
1248
1180
  }
1249
1181
  async saveConfig() {
1250
- if (!this.persistenceEnabled) {
1182
+ if (!this.persistenceEnabled)
1251
1183
  return;
1252
- }
1253
1184
  try {
1254
1185
  const configPath = this.getConfigFilePath();
1255
1186
  const config = {
1256
1187
  version: "1.0.0",
1257
1188
  sources: Array.from(this.sources.values())
1258
1189
  };
1259
- const content = JSON.stringify(config, null, 2);
1260
- writeFileSync(configPath, content, "utf-8");
1261
- logger2.debug(`Saved ${this.sources.size} event source configurations to ${configPath}`);
1190
+ writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
1191
+ logger2.debug(`Saved ${this.sources.size} event source configurations`);
1262
1192
  } catch (error) {
1263
1193
  logger2.error("Failed to save event source configurations:", error);
1264
1194
  throw error;
1265
1195
  }
1266
1196
  }
1267
1197
  async loadConfig() {
1268
- if (!this.persistenceEnabled) {
1198
+ if (!this.persistenceEnabled)
1269
1199
  return;
1270
- }
1271
1200
  try {
1272
1201
  const configPath = this.getConfigFilePath();
1273
1202
  if (!existsSync2(configPath)) {
@@ -1288,100 +1217,10 @@ class EventSourceComponent extends BaseComponent {
1288
1217
  loadedCount++;
1289
1218
  }
1290
1219
  }
1291
- logger2.info(`Loaded ${loadedCount} event source configurations from ${configPath}`);
1220
+ logger2.info(`Loaded ${loadedCount} event source configurations`);
1292
1221
  } catch (error) {
1293
1222
  logger2.error("Failed to load event source configurations:", error);
1294
1223
  }
1295
1224
  }
1296
1225
  }
1297
- // src/env/event-source/event-source-agent-handler.ts
1298
- init_logger();
1299
- var logger3 = createLogger("event-source-agent-handler");
1300
-
1301
- class EventSourceAgentHandler {
1302
- config;
1303
- constructor(config = {}) {
1304
- this.config = {
1305
- enabled: config.enabled ?? true,
1306
- prefix: config.prefix ?? "[事件源]",
1307
- includeRawEvent: config.includeRawEvent ?? false,
1308
- includeTimestamp: config.includeTimestamp ?? true
1309
- };
1310
- }
1311
- createHandler() {
1312
- return (event) => {
1313
- if (!this.config.enabled) {
1314
- return;
1315
- }
1316
- const message = this.formatEventForAgent(event);
1317
- logger3.debug(`[AgentHandler] Formatted event: ${message.substring(0, 100)}`);
1318
- return message;
1319
- };
1320
- }
1321
- formatEventForAgent(event) {
1322
- const parts = [];
1323
- parts.push(this.config.prefix);
1324
- if (this.config.includeTimestamp) {
1325
- const time = new Date(event.timestamp).toLocaleString("zh-CN");
1326
- parts.push(`[${time}]`);
1327
- }
1328
- parts.push(`来源: ${event.payload.sourceType}`);
1329
- parts.push(`类型: ${event.type}`);
1330
- parts.push(`内容: ${event.payload.message}`);
1331
- if (this.config.includeRawEvent) {
1332
- const rawStr = typeof event.payload.rawEvent === "string" ? event.payload.rawEvent : JSON.stringify(event.payload.rawEvent);
1333
- parts.push(`原始数据: ${rawStr}`);
1334
- }
1335
- return parts.join(" ");
1336
- }
1337
- updateConfig(config) {
1338
- this.config = {
1339
- ...this.config,
1340
- ...config
1341
- };
1342
- }
1343
- getConfig() {
1344
- return { ...this.config };
1345
- }
1346
- }
1347
- // src/env/event-source/types.ts
1348
- function isValidEventSourceType(type) {
1349
- return ["lark-cli", "websocket", "timer", "http-webhook", "file-watcher"].includes(type);
1350
- }
1351
- function getDefaultConfigForType(type) {
1352
- switch (type) {
1353
- case "timer":
1354
- return { interval: 60000 };
1355
- case "lark-cli":
1356
- return { command: "lark-cli event +subscribe" };
1357
- case "websocket":
1358
- return {};
1359
- default:
1360
- return {};
1361
- }
1362
- }
1363
- function validateEventSourceConfig(config) {
1364
- const errors = [];
1365
- if (!config.id) {
1366
- errors.push("EventSource ID is required");
1367
- }
1368
- if (!config.name) {
1369
- errors.push("EventSource name is required");
1370
- }
1371
- if (!isValidEventSourceType(config.type)) {
1372
- errors.push(`Invalid EventSource type: ${config.type}`);
1373
- }
1374
- if (config.type === "timer") {
1375
- if (!config.interval || config.interval <= 0) {
1376
- errors.push("Timer interval must be a positive number");
1377
- }
1378
- }
1379
- if (config.type === "lark-cli" && !config.command) {
1380
- errors.push("lark-cli command is required");
1381
- }
1382
- if (config.type === "websocket" && !config.url) {
1383
- errors.push("WebSocket URL is required");
1384
- }
1385
- return errors;
1386
- }
1387
- export { generateId, generateDescendingId, BaseEnvironment, EventSourceComponent, EventSourceAgentHandler, isValidEventSourceType, getDefaultConfigForType, validateEventSourceConfig };
1226
+ export { generateId, generateDescendingId, BaseEnvironment, larkCliHandler, timerHandler, websocketHandler, builtInHandlers, EventSourceComponent };