@agentxjs/core 1.9.1-dev

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 (77) hide show
  1. package/package.json +31 -0
  2. package/src/agent/AgentStateMachine.ts +151 -0
  3. package/src/agent/README.md +296 -0
  4. package/src/agent/__tests__/AgentStateMachine.test.ts +346 -0
  5. package/src/agent/__tests__/createAgent.test.ts +728 -0
  6. package/src/agent/__tests__/engine/internal/messageAssemblerProcessor.test.ts +567 -0
  7. package/src/agent/__tests__/engine/internal/stateEventProcessor.test.ts +315 -0
  8. package/src/agent/__tests__/engine/internal/turnTrackerProcessor.test.ts +340 -0
  9. package/src/agent/__tests__/engine/mealy/Mealy.test.ts +370 -0
  10. package/src/agent/__tests__/engine/mealy/Store.test.ts +123 -0
  11. package/src/agent/__tests__/engine/mealy/combinators.test.ts +322 -0
  12. package/src/agent/createAgent.ts +467 -0
  13. package/src/agent/engine/AgentProcessor.ts +106 -0
  14. package/src/agent/engine/MealyMachine.ts +184 -0
  15. package/src/agent/engine/internal/index.ts +35 -0
  16. package/src/agent/engine/internal/messageAssemblerProcessor.ts +550 -0
  17. package/src/agent/engine/internal/stateEventProcessor.ts +313 -0
  18. package/src/agent/engine/internal/turnTrackerProcessor.ts +239 -0
  19. package/src/agent/engine/mealy/Mealy.ts +308 -0
  20. package/src/agent/engine/mealy/Processor.ts +70 -0
  21. package/src/agent/engine/mealy/Sink.ts +56 -0
  22. package/src/agent/engine/mealy/Source.ts +51 -0
  23. package/src/agent/engine/mealy/Store.ts +98 -0
  24. package/src/agent/engine/mealy/combinators.ts +176 -0
  25. package/src/agent/engine/mealy/index.ts +45 -0
  26. package/src/agent/index.ts +106 -0
  27. package/src/agent/types/engine.ts +395 -0
  28. package/src/agent/types/event.ts +478 -0
  29. package/src/agent/types/index.ts +197 -0
  30. package/src/agent/types/message.ts +387 -0
  31. package/src/common/index.ts +8 -0
  32. package/src/common/logger/ConsoleLogger.ts +137 -0
  33. package/src/common/logger/LoggerFactoryImpl.ts +123 -0
  34. package/src/common/logger/index.ts +26 -0
  35. package/src/common/logger/types.ts +98 -0
  36. package/src/container/Container.ts +185 -0
  37. package/src/container/index.ts +44 -0
  38. package/src/container/types.ts +71 -0
  39. package/src/driver/index.ts +42 -0
  40. package/src/driver/types.ts +363 -0
  41. package/src/event/EventBus.ts +260 -0
  42. package/src/event/README.md +237 -0
  43. package/src/event/__tests__/EventBus.test.ts +251 -0
  44. package/src/event/index.ts +46 -0
  45. package/src/event/types/agent.ts +512 -0
  46. package/src/event/types/base.ts +241 -0
  47. package/src/event/types/bus.ts +429 -0
  48. package/src/event/types/command.ts +749 -0
  49. package/src/event/types/container.ts +471 -0
  50. package/src/event/types/driver.ts +452 -0
  51. package/src/event/types/index.ts +26 -0
  52. package/src/event/types/session.ts +314 -0
  53. package/src/image/Image.ts +203 -0
  54. package/src/image/index.ts +36 -0
  55. package/src/image/types.ts +77 -0
  56. package/src/index.ts +20 -0
  57. package/src/mq/OffsetGenerator.ts +48 -0
  58. package/src/mq/README.md +166 -0
  59. package/src/mq/__tests__/OffsetGenerator.test.ts +121 -0
  60. package/src/mq/index.ts +18 -0
  61. package/src/mq/types.ts +172 -0
  62. package/src/network/RpcClient.ts +455 -0
  63. package/src/network/index.ts +76 -0
  64. package/src/network/jsonrpc.ts +336 -0
  65. package/src/network/protocol.ts +90 -0
  66. package/src/network/types.ts +284 -0
  67. package/src/persistence/index.ts +27 -0
  68. package/src/persistence/types.ts +226 -0
  69. package/src/runtime/AgentXRuntime.ts +501 -0
  70. package/src/runtime/index.ts +56 -0
  71. package/src/runtime/types.ts +236 -0
  72. package/src/session/Session.ts +71 -0
  73. package/src/session/index.ts +25 -0
  74. package/src/session/types.ts +77 -0
  75. package/src/workspace/index.ts +27 -0
  76. package/src/workspace/types.ts +131 -0
  77. package/tsconfig.json +10 -0
@@ -0,0 +1,237 @@
1
+ # @agentxjs/core/event
2
+
3
+ Event System for AgentX - Pure memory EventBus with typed events.
4
+
5
+ ## Overview
6
+
7
+ The event module provides a central event bus for component communication within a process. It's a pure in-memory pub/sub system using RxJS, with no platform dependencies.
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────┐
11
+ │ EventBus │
12
+ │ │
13
+ │ Producer ──emit()──► Subject ──dispatch()──► Consumers │
14
+ │ │ │
15
+ │ ┌──────┴──────┐ │
16
+ │ │ Filter │ │
17
+ │ │ Priority │ │
18
+ │ │ Once │ │
19
+ │ └─────────────┘ │
20
+ └─────────────────────────────────────────────────────────────┘
21
+ ```
22
+
23
+ ## Key Concepts
24
+
25
+ ### Event-Driven Architecture
26
+
27
+ All components communicate through typed events:
28
+
29
+ | Source | Events | Examples |
30
+ | ------------- | ----------------- | ------------------------------------------ |
31
+ | `environment` | LLM API responses | `message_start`, `text_delta`, `tool_call` |
32
+ | `agent` | Agent internal | `conversation_start`, `assistant_message` |
33
+ | `session` | Session lifecycle | `session_created`, `session_saved` |
34
+ | `container` | Container ops | `container_created`, `agent_registered` |
35
+ | `command` | Request/Response | `container_create_request/response` |
36
+
37
+ ### Producer/Consumer Pattern
38
+
39
+ ```typescript
40
+ // Producer - can only emit events
41
+ class ClaudeReceptor {
42
+ constructor(private producer: EventProducer) {}
43
+
44
+ onChunk(text: string) {
45
+ this.producer.emit({
46
+ type: "text_delta",
47
+ timestamp: Date.now(),
48
+ data: { text },
49
+ source: "environment",
50
+ category: "stream",
51
+ intent: "notification",
52
+ });
53
+ }
54
+ }
55
+
56
+ // Consumer - can only subscribe to events
57
+ class BusDriver {
58
+ constructor(consumer: EventConsumer) {
59
+ consumer.on("text_delta", (e) => {
60
+ console.log("Received:", e.data.text);
61
+ });
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ ### Basic Usage
69
+
70
+ ```typescript
71
+ import { EventBus } from "@agentxjs/core/event";
72
+
73
+ const bus = new EventBus();
74
+
75
+ // Subscribe to specific event type
76
+ bus.on("text_delta", (event) => {
77
+ console.log("Text:", event.data.text);
78
+ });
79
+
80
+ // Subscribe to all events
81
+ bus.onAny((event) => {
82
+ console.log("Event:", event.type);
83
+ });
84
+
85
+ // Emit event
86
+ bus.emit({
87
+ type: "text_delta",
88
+ timestamp: Date.now(),
89
+ data: { text: "Hello!" },
90
+ source: "environment",
91
+ category: "stream",
92
+ intent: "notification",
93
+ });
94
+ ```
95
+
96
+ ### Subscription Options
97
+
98
+ ```typescript
99
+ // Filter events
100
+ bus.on("text_delta", handler, {
101
+ filter: (e) => e.context?.agentId === "agent-1",
102
+ });
103
+
104
+ // Priority (higher runs first)
105
+ bus.on("text_delta", criticalHandler, { priority: 10 });
106
+ bus.on("text_delta", normalHandler, { priority: 0 });
107
+
108
+ // One-time subscription
109
+ bus.once("message_stop", (e) => {
110
+ console.log("Stream ended");
111
+ });
112
+ ```
113
+
114
+ ### Command Request/Response
115
+
116
+ ```typescript
117
+ // Send request and wait for response
118
+ const response = await bus.request(
119
+ "container_create_request",
120
+ {
121
+ containerId: "my-container",
122
+ },
123
+ 30000
124
+ ); // 30s timeout
125
+
126
+ console.log("Created:", response.data.containerId);
127
+ ```
128
+
129
+ ### Restricted Views
130
+
131
+ ```typescript
132
+ const bus = new EventBus();
133
+
134
+ // Give producer to components that emit
135
+ const receptor = new ClaudeReceptor(bus.asProducer());
136
+
137
+ // Give consumer to components that subscribe
138
+ const driver = new BusDriver(bus.asConsumer());
139
+ ```
140
+
141
+ ## Architecture
142
+
143
+ ### Directory Structure
144
+
145
+ ```
146
+ event/
147
+ ├── types/
148
+ │ ├── index.ts # Re-exports all types
149
+ │ ├── base.ts # SystemEvent, EventSource, EventContext
150
+ │ ├── bus.ts # EventBus, EventProducer, EventConsumer
151
+ │ ├── agent.ts # Agent stream/state/message/turn events
152
+ │ ├── session.ts # Session lifecycle/persist/action events
153
+ │ ├── container.ts # Container lifecycle/sandbox events
154
+ │ ├── command.ts # Request/Response events + CommandEventMap
155
+ │ └── environment.ts # DriveableEvent, ConnectionEvent, StopReason
156
+
157
+ ├── EventBus.ts # RxJS-based implementation
158
+ ├── __tests__/
159
+ └── index.ts
160
+ ```
161
+
162
+ ### Type Hierarchy
163
+
164
+ ```
165
+ BusEvent (simple)
166
+ └── { type, timestamp, data }
167
+
168
+ SystemEvent (full)
169
+ └── { type, timestamp, data, source, category, intent, context?, broadcastable? }
170
+ ```
171
+
172
+ ## API Reference
173
+
174
+ ### EventBus
175
+
176
+ ```typescript
177
+ class EventBus implements EventBusInterface {
178
+ // Emit
179
+ emit(event: BusEvent): void;
180
+ emitBatch(events: BusEvent[]): void;
181
+ emitCommand<T>(type: T, data: CommandEventMap[T]["data"]): void;
182
+
183
+ // Subscribe
184
+ on(type: string, handler: BusEventHandler, options?: SubscribeOptions): Unsubscribe;
185
+ on(types: string[], handler: BusEventHandler, options?: SubscribeOptions): Unsubscribe;
186
+ onAny(handler: BusEventHandler, options?: SubscribeOptions): Unsubscribe;
187
+ once(type: string, handler: BusEventHandler): Unsubscribe;
188
+ onCommand<T>(type: T, handler: (event: CommandEventMap[T]) => void): Unsubscribe;
189
+
190
+ // Request/Response
191
+ request<T>(type: T, data: RequestDataFor<T>, timeout?: number): Promise<ResponseEventFor<T>>;
192
+
193
+ // Views
194
+ asProducer(): EventProducer;
195
+ asConsumer(): EventConsumer;
196
+
197
+ // Lifecycle
198
+ destroy(): void;
199
+ }
200
+ ```
201
+
202
+ ### SubscribeOptions
203
+
204
+ ```typescript
205
+ interface SubscribeOptions<E> {
206
+ filter?: (event: E) => boolean; // Filter events
207
+ priority?: number; // Execution order (higher first)
208
+ once?: boolean; // Auto-unsubscribe after first
209
+ }
210
+ ```
211
+
212
+ ## Platform Independence
213
+
214
+ This module has **zero platform dependencies**:
215
+
216
+ - No `node:*` imports
217
+ - No `bun:*` imports
218
+ - Only depends on `rxjs` (pure JavaScript)
219
+
220
+ Can run in: Node.js, Bun, Deno, Cloudflare Workers, Browser.
221
+
222
+ ## Not a Message Queue
223
+
224
+ EventBus is for **in-process** communication only:
225
+
226
+ | | EventBus | MessageQueue |
227
+ | ----------- | -------------------- | ----------------- |
228
+ | Scope | Process-internal | Cross-process |
229
+ | Persistence | None | SQLite/Redis |
230
+ | Delivery | Best-effort | At-least-once |
231
+ | Use case | Component decoupling | Reliable delivery |
232
+
233
+ For cross-process or persistent messaging, use the `mq` module.
234
+
235
+ ## License
236
+
237
+ MIT
@@ -0,0 +1,251 @@
1
+ /**
2
+ * EventBus.test.ts - Unit tests for EventBus implementation
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach } from "bun:test";
6
+ import { EventBus } from "../EventBus";
7
+ import type { BusEvent } from "../types";
8
+
9
+ // Test event factory
10
+ function createEvent(type: string, data: unknown = {}): BusEvent {
11
+ return {
12
+ type,
13
+ timestamp: Date.now(),
14
+ data,
15
+ source: "agent",
16
+ category: "message",
17
+ intent: "notification",
18
+ };
19
+ }
20
+
21
+ describe("EventBus", () => {
22
+ let bus: EventBus;
23
+
24
+ beforeEach(() => {
25
+ bus = new EventBus();
26
+ });
27
+
28
+ describe("emit and on", () => {
29
+ it("should emit event to subscriber", () => {
30
+ const received: BusEvent[] = [];
31
+ bus.on("test_event", (e) => received.push(e));
32
+
33
+ bus.emit(createEvent("test_event", { value: 1 }));
34
+
35
+ expect(received).toHaveLength(1);
36
+ expect(received[0].type).toBe("test_event");
37
+ expect(received[0].data).toEqual({ value: 1 });
38
+ });
39
+
40
+ it("should not receive events of different type", () => {
41
+ const received: BusEvent[] = [];
42
+ bus.on("type_a", (e) => received.push(e));
43
+
44
+ bus.emit(createEvent("type_b"));
45
+
46
+ expect(received).toHaveLength(0);
47
+ });
48
+
49
+ it("should support multiple subscribers", () => {
50
+ let count = 0;
51
+ bus.on("test", () => count++);
52
+ bus.on("test", () => count++);
53
+
54
+ bus.emit(createEvent("test"));
55
+
56
+ expect(count).toBe(2);
57
+ });
58
+
59
+ it("should support array of event types", () => {
60
+ const received: string[] = [];
61
+ bus.on(["type_a", "type_b"], (e) => received.push(e.type));
62
+
63
+ bus.emit(createEvent("type_a"));
64
+ bus.emit(createEvent("type_b"));
65
+ bus.emit(createEvent("type_c"));
66
+
67
+ expect(received).toEqual(["type_a", "type_b"]);
68
+ });
69
+ });
70
+
71
+ describe("unsubscribe", () => {
72
+ it("should stop receiving events after unsubscribe", () => {
73
+ const received: BusEvent[] = [];
74
+ const unsubscribe = bus.on("test", (e) => received.push(e));
75
+
76
+ bus.emit(createEvent("test"));
77
+ expect(received).toHaveLength(1);
78
+
79
+ unsubscribe();
80
+
81
+ bus.emit(createEvent("test"));
82
+ expect(received).toHaveLength(1);
83
+ });
84
+ });
85
+
86
+ describe("onAny", () => {
87
+ it("should receive all events", () => {
88
+ const received: string[] = [];
89
+ bus.onAny((e) => received.push(e.type));
90
+
91
+ bus.emit(createEvent("type_a"));
92
+ bus.emit(createEvent("type_b"));
93
+ bus.emit(createEvent("type_c"));
94
+
95
+ expect(received).toEqual(["type_a", "type_b", "type_c"]);
96
+ });
97
+ });
98
+
99
+ describe("once", () => {
100
+ it("should only receive first event", () => {
101
+ let count = 0;
102
+ bus.once("test", () => count++);
103
+
104
+ bus.emit(createEvent("test"));
105
+ bus.emit(createEvent("test"));
106
+ bus.emit(createEvent("test"));
107
+
108
+ expect(count).toBe(1);
109
+ });
110
+ });
111
+
112
+ describe("filter option", () => {
113
+ it("should filter events", () => {
114
+ const received: BusEvent[] = [];
115
+ bus.on("test", (e) => received.push(e), {
116
+ filter: (e) => (e.data as { value: number }).value > 5,
117
+ });
118
+
119
+ bus.emit(createEvent("test", { value: 3 }));
120
+ bus.emit(createEvent("test", { value: 7 }));
121
+ bus.emit(createEvent("test", { value: 10 }));
122
+
123
+ expect(received).toHaveLength(2);
124
+ expect((received[0].data as { value: number }).value).toBe(7);
125
+ expect((received[1].data as { value: number }).value).toBe(10);
126
+ });
127
+ });
128
+
129
+ describe("priority option", () => {
130
+ it("should execute higher priority handlers first", () => {
131
+ const order: number[] = [];
132
+
133
+ bus.on("test", () => order.push(1), { priority: 1 });
134
+ bus.on("test", () => order.push(10), { priority: 10 });
135
+ bus.on("test", () => order.push(5), { priority: 5 });
136
+
137
+ bus.emit(createEvent("test"));
138
+
139
+ expect(order).toEqual([10, 5, 1]);
140
+ });
141
+ });
142
+
143
+ describe("emitBatch", () => {
144
+ it("should emit multiple events", () => {
145
+ const received: string[] = [];
146
+ bus.onAny((e) => received.push(e.type));
147
+
148
+ bus.emitBatch([createEvent("a"), createEvent("b"), createEvent("c")]);
149
+
150
+ expect(received).toEqual(["a", "b", "c"]);
151
+ });
152
+ });
153
+
154
+ describe("asProducer and asConsumer", () => {
155
+ it("should return producer view with only emit methods", () => {
156
+ const producer = bus.asProducer();
157
+
158
+ expect(typeof producer.emit).toBe("function");
159
+ expect(typeof producer.emitBatch).toBe("function");
160
+ expect(typeof producer.emitCommand).toBe("function");
161
+ expect((producer as unknown as { on?: unknown }).on).toBeUndefined();
162
+ });
163
+
164
+ it("should return consumer view with only subscribe methods", () => {
165
+ const consumer = bus.asConsumer();
166
+
167
+ expect(typeof consumer.on).toBe("function");
168
+ expect(typeof consumer.onAny).toBe("function");
169
+ expect(typeof consumer.once).toBe("function");
170
+ expect(typeof consumer.onCommand).toBe("function");
171
+ expect(typeof consumer.request).toBe("function");
172
+ expect((consumer as unknown as { emit?: unknown }).emit).toBeUndefined();
173
+ });
174
+
175
+ it("should cache views", () => {
176
+ const producer1 = bus.asProducer();
177
+ const producer2 = bus.asProducer();
178
+ expect(producer1).toBe(producer2);
179
+
180
+ const consumer1 = bus.asConsumer();
181
+ const consumer2 = bus.asConsumer();
182
+ expect(consumer1).toBe(consumer2);
183
+ });
184
+
185
+ it("producer emit should work", () => {
186
+ const received: BusEvent[] = [];
187
+ bus.on("test", (e) => received.push(e));
188
+
189
+ const producer = bus.asProducer();
190
+ producer.emit(createEvent("test"));
191
+
192
+ expect(received).toHaveLength(1);
193
+ });
194
+
195
+ it("consumer on should work", () => {
196
+ const received: BusEvent[] = [];
197
+ const consumer = bus.asConsumer();
198
+ consumer.on("test", (e) => received.push(e));
199
+
200
+ bus.emit(createEvent("test"));
201
+
202
+ expect(received).toHaveLength(1);
203
+ });
204
+ });
205
+
206
+ describe("destroy", () => {
207
+ it("should stop emitting after destroy", () => {
208
+ const received: BusEvent[] = [];
209
+ bus.on("test", (e) => received.push(e));
210
+
211
+ bus.destroy();
212
+ bus.emit(createEvent("test"));
213
+
214
+ expect(received).toHaveLength(0);
215
+ });
216
+
217
+ it("should return no-op unsubscribe after destroy", () => {
218
+ bus.destroy();
219
+ const unsubscribe = bus.on("test", () => {});
220
+
221
+ // Should not throw
222
+ expect(() => unsubscribe()).not.toThrow();
223
+ });
224
+
225
+ it("should be idempotent", () => {
226
+ expect(() => {
227
+ bus.destroy();
228
+ bus.destroy();
229
+ bus.destroy();
230
+ }).not.toThrow();
231
+ });
232
+ });
233
+
234
+ describe("error handling", () => {
235
+ it("should not stop other handlers on error", () => {
236
+ const received: number[] = [];
237
+
238
+ bus.on("test", () => received.push(1));
239
+ bus.on("test", () => {
240
+ throw new Error("Handler error");
241
+ });
242
+ bus.on("test", () => received.push(3));
243
+
244
+ // Should not throw
245
+ expect(() => bus.emit(createEvent("test"))).not.toThrow();
246
+
247
+ // Other handlers should still run
248
+ expect(received).toEqual([1, 3]);
249
+ });
250
+ });
251
+ });
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Event Module
3
+ *
4
+ * Central event bus system for ecosystem communication.
5
+ * Provides type-safe pub/sub event handling with RxJS.
6
+ *
7
+ * ## Architecture
8
+ *
9
+ * ```
10
+ * EventBus (interface)
11
+ * ├── EventProducer (write-only view)
12
+ * └── EventConsumer (read-only view)
13
+ *
14
+ * EventBusImpl (implementation)
15
+ * ```
16
+ *
17
+ * ## Usage
18
+ *
19
+ * ```typescript
20
+ * import { EventBusImpl, type EventBus } from "@agentxjs/core/event";
21
+ *
22
+ * const bus: EventBus = new EventBusImpl();
23
+ *
24
+ * // Subscribe to events
25
+ * bus.on("text_delta", (event) => {
26
+ * console.log(event.data.text);
27
+ * });
28
+ *
29
+ * // Emit events
30
+ * bus.emit({
31
+ * type: "text_delta",
32
+ * timestamp: Date.now(),
33
+ * data: { text: "Hello" },
34
+ * });
35
+ *
36
+ * // Get restricted views for components
37
+ * const producer = bus.asProducer(); // Can only emit
38
+ * const consumer = bus.asConsumer(); // Can only subscribe
39
+ * ```
40
+ */
41
+
42
+ // Type definitions from types directory
43
+ export * from "./types";
44
+
45
+ // Implementation
46
+ export { EventBusImpl } from "./EventBus";