@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
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@agentxjs/core",
3
+ "version": "1.9.1-dev",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./common": "./src/common/index.ts",
8
+ "./agent": "./src/agent/index.ts",
9
+ "./driver": "./src/driver/index.ts",
10
+ "./event": "./src/event/index.ts",
11
+ "./session": "./src/session/index.ts",
12
+ "./image": "./src/image/index.ts",
13
+ "./container": "./src/container/index.ts",
14
+ "./workspace": "./src/workspace/index.ts",
15
+ "./runtime": "./src/runtime/index.ts",
16
+ "./mq": "./src/mq/index.ts",
17
+ "./persistence": "./src/persistence/index.ts",
18
+ "./network": "./src/network/index.ts"
19
+ },
20
+ "scripts": {
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "bun test"
23
+ },
24
+ "dependencies": {
25
+ "jsonrpc-lite": "2.2.0",
26
+ "rxjs": "^7.8.2"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^5.3.3"
30
+ }
31
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * AgentStateMachine - State management driven by StateEvents
3
+ *
4
+ * Manages agent state transitions driven by StateEvents.
5
+ * Single source of truth for agent state in AgentEngine.
6
+ *
7
+ * Flow:
8
+ * StreamEvent → MealyMachine → StateEvent → AgentStateMachine → state update
9
+ *
10
+ * Responsibilities:
11
+ * - Process StateEvents
12
+ * - Maintain current AgentState
13
+ * - Notify state change subscribers
14
+ */
15
+
16
+ import type {
17
+ AgentState,
18
+ StateChange,
19
+ StateChangeHandler,
20
+ AgentOutput,
21
+ Unsubscribe,
22
+ } from "./types";
23
+ import { isStateEvent } from "./types";
24
+ import { createLogger } from "commonxjs/logger";
25
+
26
+ const logger = createLogger("agent/AgentStateMachine");
27
+
28
+ /**
29
+ * AgentStateMachine implementation
30
+ */
31
+ export class AgentStateMachine {
32
+ private _state: AgentState = "idle";
33
+ private readonly handlers = new Set<StateChangeHandler>();
34
+
35
+ /**
36
+ * Current agent state
37
+ */
38
+ get state(): AgentState {
39
+ return this._state;
40
+ }
41
+
42
+ /**
43
+ * Process an event and update internal state if it's a StateEvent
44
+ *
45
+ * @param event - Event from MealyMachine (could be any AgentOutput)
46
+ */
47
+ process(event: AgentOutput): void {
48
+ // Only process StateEvents
49
+ if (!isStateEvent(event)) {
50
+ return;
51
+ }
52
+
53
+ const prev = this._state;
54
+ const next = this.mapEventToState(event);
55
+
56
+ if (next !== null && prev !== next) {
57
+ this._state = next;
58
+ logger.debug("State transition", {
59
+ eventType: event.type,
60
+ from: prev,
61
+ to: next,
62
+ });
63
+ this.notifyHandlers({ prev, current: next });
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Subscribe to state changes
69
+ *
70
+ * @param handler - Callback receiving { prev, current } state change
71
+ * @returns Unsubscribe function
72
+ */
73
+ onStateChange(handler: StateChangeHandler): Unsubscribe {
74
+ this.handlers.add(handler);
75
+ return () => {
76
+ this.handlers.delete(handler);
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Reset state machine (used on destroy)
82
+ */
83
+ reset(): void {
84
+ const prev = this._state;
85
+ this._state = "idle";
86
+
87
+ // Notify handlers of reset to idle
88
+ if (prev !== "idle") {
89
+ this.notifyHandlers({ prev, current: "idle" });
90
+ }
91
+
92
+ this.handlers.clear();
93
+ }
94
+
95
+ /**
96
+ * Map StateEvent type to AgentState
97
+ *
98
+ * @param event - StateEvent from MealyMachine
99
+ * @returns New AgentState or null if no transition needed
100
+ */
101
+ private mapEventToState(event: AgentOutput): AgentState | null {
102
+ switch (event.type) {
103
+ // Conversation lifecycle
104
+ case "conversation_start":
105
+ return "thinking";
106
+ case "conversation_thinking":
107
+ return "thinking";
108
+ case "conversation_responding":
109
+ return "responding";
110
+ case "conversation_end":
111
+ return "idle";
112
+ case "conversation_interrupted":
113
+ return "idle";
114
+
115
+ // Tool lifecycle
116
+ case "tool_planned":
117
+ return "planning_tool";
118
+ case "tool_executing":
119
+ return "awaiting_tool_result";
120
+ case "tool_completed":
121
+ return "responding";
122
+ case "tool_failed":
123
+ return "responding";
124
+
125
+ // Error
126
+ case "error_occurred":
127
+ return "error";
128
+
129
+ default:
130
+ // Unknown event type, no state change
131
+ return null;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Notify all registered handlers of state change
137
+ */
138
+ private notifyHandlers(change: StateChange): void {
139
+ for (const handler of this.handlers) {
140
+ try {
141
+ handler(change);
142
+ } catch (error) {
143
+ logger.error("State change handler error", {
144
+ from: change.prev,
145
+ to: change.current,
146
+ error,
147
+ });
148
+ }
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,296 @@
1
+ # @agentxjs/core/agent
2
+
3
+ Event Processing Unit for AI Conversations - Pure Mealy Machine implementation.
4
+
5
+ ## Overview
6
+
7
+ The agent module is the core event processing engine of AgentX. It transforms raw stream events from LLM providers into structured, typed events for UI consumption.
8
+
9
+ ```
10
+ StreamEvent (from LLM) AgentOutput (to UI)
11
+ │ ▲
12
+ ▼ │
13
+ ┌─────────────────────────────┴───┐
14
+ │ MealyMachine │
15
+ │ ┌───────────────────────────┐ │
16
+ │ │ AgentProcessor │ │
17
+ │ │ ┌─────────────────────┐ │ │
18
+ │ │ │ MessageAssembler │──┼──┼──► MessageEvent
19
+ │ │ ├─────────────────────┤ │ │
20
+ │ │ │ StateEventProcessor │──┼──┼──► StateEvent
21
+ │ │ ├─────────────────────┤ │ │
22
+ │ │ │ TurnTracker │──┼──┼──► TurnEvent
23
+ │ │ └─────────────────────┘ │ │
24
+ │ └───────────────────────────┘ │
25
+ └─────────────────────────────────┘
26
+ ```
27
+
28
+ ## Key Concepts
29
+
30
+ ### Mealy Machine Pattern
31
+
32
+ The core insight is that **state is a means, outputs are the goal**.
33
+
34
+ ```typescript
35
+ // Traditional Redux: state is the goal
36
+ (state, action) => newState
37
+
38
+ // Mealy Machine: outputs are the goal
39
+ (state, input) => [newState, outputs]
40
+ ```
41
+
42
+ This pattern enables:
43
+
44
+ - Pure functions (testable, no side effects)
45
+ - Event chaining (outputs can trigger more processing)
46
+ - Stateless processors (state managed externally)
47
+
48
+ ### Event Layers
49
+
50
+ | Layer | Events | Purpose |
51
+ | ----------- | ------------------------------------------------------------------- | -------------------- |
52
+ | **Stream** | `message_start`, `text_delta`, `tool_use_start`, `message_stop` | Raw LLM events |
53
+ | **Message** | `assistant_message`, `tool_call_message`, `tool_result_message` | Complete messages |
54
+ | **State** | `conversation_start`, `conversation_responding`, `conversation_end` | UI state transitions |
55
+ | **Turn** | `turn_request`, `turn_response` | Analytics & billing |
56
+
57
+ ## Usage
58
+
59
+ ### Basic Usage
60
+
61
+ ```typescript
62
+ import { createAgent, type AgentDriver, type AgentPresenter } from "@agentxjs/core/agent";
63
+
64
+ // Define a driver (produces stream events)
65
+ const driver: AgentDriver = {
66
+ receive: async function* (message) {
67
+ yield { type: "message_start", data: { messageId: "msg_1" }, timestamp: Date.now() };
68
+ yield { type: "text_delta", data: { text: "Hello!" }, timestamp: Date.now() };
69
+ yield { type: "message_stop", data: { stopReason: "end_turn" }, timestamp: Date.now() };
70
+ },
71
+ interrupt: () => {},
72
+ };
73
+
74
+ // Define a presenter (consumes agent output)
75
+ const presenter: AgentPresenter = {
76
+ present: (agentId, event) => {
77
+ console.log(`[${agentId}] ${event.type}:`, event.data);
78
+ },
79
+ };
80
+
81
+ // Create agent
82
+ const agent = createAgent({ driver, presenter });
83
+
84
+ // Subscribe to events
85
+ agent.on("text_delta", (e) => console.log(e.data.text));
86
+ agent.on("assistant_message", (e) => console.log("Complete:", e.data.content));
87
+
88
+ // Send message
89
+ await agent.receive("Hello, AI!");
90
+ ```
91
+
92
+ ### React-style Handlers
93
+
94
+ ```typescript
95
+ agent.react({
96
+ onTextDelta: (e) => updateUI(e.data.text),
97
+ onAssistantMessage: (e) => saveMessage(e.data),
98
+ onConversationStart: () => showThinking(),
99
+ onConversationEnd: () => hideThinking(),
100
+ });
101
+ ```
102
+
103
+ ### State Machine
104
+
105
+ ```typescript
106
+ import { AgentStateMachine } from "@agentxjs/core/agent";
107
+
108
+ const stateMachine = new AgentStateMachine();
109
+
110
+ stateMachine.onStateChange(({ prev, current }) => {
111
+ console.log(`State: ${prev} → ${current}`);
112
+ });
113
+
114
+ // States: idle → thinking → responding → idle
115
+ // ↓
116
+ // planning_tool → awaiting_tool_result → responding
117
+ ```
118
+
119
+ ### Custom Processors
120
+
121
+ ```typescript
122
+ import { combineProcessors, filterProcessor, type Processor } from "@agentxjs/core/agent";
123
+
124
+ // Create a custom processor
125
+ const myProcessor: Processor<MyState, StreamEvent, MyOutput> = (state, input) => {
126
+ if (input.type === "text_delta") {
127
+ return [state, [{ type: "custom_event", data: input.data }]];
128
+ }
129
+ return [state, []];
130
+ };
131
+
132
+ // Combine with existing processors
133
+ const combined = combineProcessors({
134
+ message: messageAssemblerProcessor,
135
+ custom: myProcessor,
136
+ });
137
+ ```
138
+
139
+ ## Architecture
140
+
141
+ ### Directory Structure
142
+
143
+ ```
144
+ agent/
145
+ ├── createAgent.ts # AgentEngine factory
146
+ ├── AgentStateMachine.ts # State management
147
+ ├── index.ts # Public exports
148
+
149
+ └── engine/
150
+ ├── MealyMachine.ts # Mealy runtime with state store
151
+ ├── AgentProcessor.ts # Combined processor
152
+
153
+ ├── mealy/ # Mealy framework
154
+ │ ├── Source.ts # Input adapter type
155
+ │ ├── Processor.ts # Pure transition function type
156
+ │ ├── Sink.ts # Output adapter type
157
+ │ ├── Store.ts # State storage interface
158
+ │ ├── Mealy.ts # Runtime orchestrator
159
+ │ └── combinators.ts # Processor composition utilities
160
+
161
+ └── internal/ # Built-in processors
162
+ ├── messageAssemblerProcessor.ts
163
+ ├── stateEventProcessor.ts
164
+ └── turnTrackerProcessor.ts
165
+ ```
166
+
167
+ ### Component Responsibilities
168
+
169
+ | Component | Responsibility |
170
+ | --------------------- | -------------------------------------- |
171
+ | `AgentEngine` | Coordinate driver, machine, presenter |
172
+ | `MealyMachine` | Process events, manage state per agent |
173
+ | `AgentProcessor` | Combine all internal processors |
174
+ | `MessageAssembler` | Stream → Message events |
175
+ | `StateEventProcessor` | Stream → State events |
176
+ | `TurnTracker` | Message → Turn events |
177
+ | `AgentStateMachine` | Track agent state from StateEvents |
178
+
179
+ ## API Reference
180
+
181
+ ### createAgent(options)
182
+
183
+ ```typescript
184
+ function createAgent(options: CreateAgentOptions): AgentEngine;
185
+
186
+ interface CreateAgentOptions {
187
+ driver: AgentDriver;
188
+ presenter: AgentPresenter;
189
+ }
190
+ ```
191
+
192
+ ### AgentEngine
193
+
194
+ ```typescript
195
+ interface AgentEngine {
196
+ readonly agentId: string;
197
+ readonly state: AgentState;
198
+ readonly messageQueue: MessageQueue;
199
+
200
+ // Send message
201
+ receive(message: string | UserMessage): Promise<void>;
202
+
203
+ // Event subscription
204
+ on(handler: AgentOutputCallback): Unsubscribe;
205
+ on(type: string, handler: AgentOutputCallback): Unsubscribe;
206
+ on(handlers: EventHandlerMap): Unsubscribe;
207
+ react(handlers: ReactHandlerMap): Unsubscribe;
208
+
209
+ // State subscription
210
+ onStateChange(handler: StateChangeHandler): Unsubscribe;
211
+
212
+ // Lifecycle
213
+ onReady(handler: () => void): Unsubscribe;
214
+ onDestroy(handler: () => void): Unsubscribe;
215
+
216
+ // Middleware
217
+ use(middleware: AgentMiddleware): Unsubscribe;
218
+ intercept(interceptor: AgentInterceptor): Unsubscribe;
219
+
220
+ // Control
221
+ interrupt(): void;
222
+ destroy(): Promise<void>;
223
+ }
224
+ ```
225
+
226
+ ### Processor Type
227
+
228
+ ```typescript
229
+ type Processor<TState, TInput, TOutput> = (
230
+ state: Readonly<TState>,
231
+ input: TInput
232
+ ) => [TState, TOutput[]];
233
+ ```
234
+
235
+ ### Combinators
236
+
237
+ ```typescript
238
+ // Combine multiple processors (parallel)
239
+ combineProcessors<TState, TInput, TOutput>(processors): Processor;
240
+
241
+ // Chain processors (sequential)
242
+ chainProcessors<TState, TEvent>(...processors): Processor;
243
+
244
+ // Filter events before processing
245
+ filterProcessor<TState, TInput, TOutput>(
246
+ predicate: (event: TInput) => boolean,
247
+ processor: Processor
248
+ ): Processor;
249
+
250
+ // Transform outputs
251
+ mapOutput<TState, TInput, TOutput, TMapped>(
252
+ processor: Processor,
253
+ mapper: (output: TOutput) => TMapped
254
+ ): Processor;
255
+
256
+ // Add logging
257
+ withLogging<TState, TInput, TOutput>(
258
+ processor: Processor,
259
+ name: string
260
+ ): Processor;
261
+ ```
262
+
263
+ ## Testing
264
+
265
+ ```bash
266
+ cd packages-new/core
267
+ bun test
268
+ ```
269
+
270
+ ```
271
+ ✅ 175 tests pass
272
+ ✅ 0 fail
273
+ ✅ 265ms
274
+ ```
275
+
276
+ ### Test Coverage
277
+
278
+ - Mealy framework: Store, combinators, runtime
279
+ - Internal processors: message assembly, state events, turn tracking
280
+ - AgentStateMachine: state transitions, subscriptions
281
+ - createAgent: full agent lifecycle, middleware, interceptors
282
+
283
+ ## Platform Independence
284
+
285
+ This module has **zero platform dependencies**:
286
+
287
+ - No `node:*` imports
288
+ - No `bun:*` imports
289
+ - No `ws`, `ioredis`, or other platform-specific packages
290
+ - Only depends on `rxjs` (pure JavaScript)
291
+
292
+ Can run in: Node.js, Bun, Deno, Cloudflare Workers, Browser.
293
+
294
+ ## License
295
+
296
+ MIT