@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,176 @@
1
+ /**
2
+ * Combinators - Functions to compose multiple Processors
3
+ *
4
+ * These utilities allow building complex stream processing pipelines
5
+ * from simple, composable Processor functions.
6
+ */
7
+
8
+ import type { Processor } from "./Processor";
9
+
10
+ /**
11
+ * combineProcessors - Combine multiple processors into one
12
+ *
13
+ * Each sub-processor manages its own slice of state.
14
+ * All processors receive the same event and their outputs are merged.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * interface CombinedState {
19
+ * message: MessageState;
20
+ * state: StateMachineState;
21
+ * turn: TurnState;
22
+ * }
23
+ *
24
+ * const combinedProcessor = combineProcessors<CombinedState, Event, Event>({
25
+ * message: messageProcessor,
26
+ * state: stateMachineProcessor,
27
+ * turn: turnTrackerProcessor,
28
+ * });
29
+ * ```
30
+ */
31
+ export function combineProcessors<
32
+ TState extends Record<string, unknown>,
33
+ TInput,
34
+ TOutput,
35
+ >(processors: {
36
+ [K in keyof TState]: Processor<TState[K], TInput, TOutput>;
37
+ }): Processor<TState, TInput, TOutput> {
38
+ return (state: Readonly<TState>, event: TInput): [TState, TOutput[]] => {
39
+ const newState = {} as TState;
40
+ const allOutputs: TOutput[] = [];
41
+
42
+ for (const key in processors) {
43
+ const processor = processors[key];
44
+ const subState = state[key];
45
+ const [newSubState, outputs] = processor(subState, event);
46
+
47
+ newState[key] = newSubState;
48
+ allOutputs.push(...outputs);
49
+ }
50
+
51
+ return [newState, allOutputs];
52
+ };
53
+ }
54
+
55
+ /**
56
+ * combineInitialStates - Helper to create initial state for combined processors
57
+ */
58
+ export function combineInitialStates<TState extends Record<string, unknown>>(initialStates: {
59
+ [K in keyof TState]: () => TState[K];
60
+ }): () => TState {
61
+ return () => {
62
+ const state = {} as TState;
63
+ for (const key in initialStates) {
64
+ state[key] = initialStates[key]();
65
+ }
66
+ return state;
67
+ };
68
+ }
69
+
70
+ /**
71
+ * chainProcessors - Chain processors where output of one feeds into the next
72
+ *
73
+ * Useful for layered event processing:
74
+ * Stream Events → Message Events → Turn Events
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const pipeline = chainProcessors(
79
+ * streamToMessageProcessor,
80
+ * messageToTurnProcessor,
81
+ * );
82
+ * ```
83
+ */
84
+ export function chainProcessors<TState, TEvent>(
85
+ ...processors: Processor<TState, TEvent, TEvent>[]
86
+ ): Processor<TState, TEvent, TEvent> {
87
+ return (state: Readonly<TState>, event: TEvent): [TState, TEvent[]] => {
88
+ let currentState = state as TState;
89
+ const finalOutputs: TEvent[] = [];
90
+
91
+ // Run the event through all processors
92
+ for (const processor of processors) {
93
+ const [newState, outputs] = processor(currentState, event);
94
+ currentState = newState;
95
+ finalOutputs.push(...outputs);
96
+ }
97
+
98
+ return [currentState, finalOutputs];
99
+ };
100
+ }
101
+
102
+ /**
103
+ * filterProcessor - Create a processor that only processes certain events
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * const textOnlyProcessor = filterProcessor(
108
+ * (event) => event.type === 'text_delta',
109
+ * textProcessor,
110
+ * );
111
+ * ```
112
+ */
113
+ export function filterProcessor<TState, TInput, TOutput>(
114
+ predicate: (event: TInput) => boolean,
115
+ processor: Processor<TState, TInput, TOutput>
116
+ ): Processor<TState, TInput, TOutput> {
117
+ return (state: Readonly<TState>, event: TInput): [TState, TOutput[]] => {
118
+ if (predicate(event)) {
119
+ return processor(state, event);
120
+ }
121
+ return [state as TState, []];
122
+ };
123
+ }
124
+
125
+ /**
126
+ * mapOutput - Transform output events
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * const withTimestamp = mapOutput(
131
+ * myProcessor,
132
+ * (output) => ({ ...output, processedAt: Date.now() }),
133
+ * );
134
+ * ```
135
+ */
136
+ export function mapOutput<TState, TInput, TOutput, TMapped>(
137
+ processor: Processor<TState, TInput, TOutput>,
138
+ mapper: (output: TOutput) => TMapped
139
+ ): Processor<TState, TInput, TMapped> {
140
+ return (state: Readonly<TState>, event: TInput): [TState, TMapped[]] => {
141
+ const [newState, outputs] = processor(state, event);
142
+ return [newState, outputs.map(mapper)];
143
+ };
144
+ }
145
+
146
+ /**
147
+ * withLogging - Add logging to a processor (for debugging)
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const debugProcessor = withLogging(myProcessor, 'MyProcessor');
152
+ * ```
153
+ */
154
+ export function withLogging<TState, TInput, TOutput>(
155
+ processor: Processor<TState, TInput, TOutput>,
156
+ name: string,
157
+ logger: {
158
+ debug: (message: string, data?: unknown) => void;
159
+ } = console
160
+ ): Processor<TState, TInput, TOutput> {
161
+ return (state: Readonly<TState>, event: TInput): [TState, TOutput[]] => {
162
+ logger.debug(`[${name}] Input:`, { event, state });
163
+ const [newState, outputs] = processor(state, event);
164
+ logger.debug(`[${name}] Output:`, { newState, outputs });
165
+ return [newState, outputs];
166
+ };
167
+ }
168
+
169
+ /**
170
+ * identityProcessor - A processor that does nothing (useful as default)
171
+ */
172
+ export function identityProcessor<TState, TEvent>(): Processor<TState, TEvent, TEvent> {
173
+ return (state: Readonly<TState>, _event: TEvent): [TState, TEvent[]] => {
174
+ return [state as TState, []];
175
+ };
176
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Mealy - Functional Mealy Machine Framework
3
+ *
4
+ * A Mealy Machine is a finite-state machine where outputs depend on
5
+ * both the current state AND the input: (state, input) => (state, output)
6
+ *
7
+ * Components:
8
+ * - Source: Receives external input (input adapter with side effects)
9
+ * - Processor: Pure Mealy transition function (state is means, outputs are goal)
10
+ * - Sink: Produces output effects (output adapter with side effects)
11
+ * - Store: State storage (external state persistence)
12
+ *
13
+ * Key Insight: Unlike Redux reducers where state is the goal,
14
+ * in Mealy Machine the state is just a means - outputs are the goal.
15
+ */
16
+
17
+ // ===== Core Components =====
18
+
19
+ // Source - Input (input adapter)
20
+ export { type Source, type SourceDefinition } from "./Source";
21
+
22
+ // Processor - Processing (pure Mealy transition function)
23
+ export { type Processor, type ProcessorResult, type ProcessorDefinition } from "./Processor";
24
+
25
+ // Sink - Output (output adapter)
26
+ export { type Sink, type SinkDefinition } from "./Sink";
27
+
28
+ // Store - State storage
29
+ export { type Store, MemoryStore } from "./Store";
30
+
31
+ // ===== Mealy Runtime =====
32
+
33
+ export { Mealy, createMealy, type MealyConfig, type ProcessResult } from "./Mealy";
34
+
35
+ // ===== Combinators =====
36
+
37
+ export {
38
+ combineProcessors,
39
+ combineInitialStates,
40
+ chainProcessors,
41
+ filterProcessor,
42
+ mapOutput,
43
+ withLogging,
44
+ identityProcessor,
45
+ } from "./combinators";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @agentxjs/agent
3
+ *
4
+ * Agent package - Event Processing Unit for AI conversations.
5
+ *
6
+ * ## Core API
7
+ *
8
+ * ```typescript
9
+ * import { createAgent } from "@agentxjs/agent";
10
+ *
11
+ * const agent = createAgent({
12
+ * driver: myDriver,
13
+ * presenter: myPresenter,
14
+ * });
15
+ *
16
+ * agent.on("text_delta", (e) => console.log(e.data.text));
17
+ * await agent.receive("Hello!");
18
+ * ```
19
+ *
20
+ * ## Architecture
21
+ *
22
+ * - Driver: Produces StreamEvents from LLM
23
+ * - Agent: Processes events, manages state and queue
24
+ * - Presenter: Consumes AgentOutput events
25
+ *
26
+ * @packageDocumentation
27
+ */
28
+
29
+ // ============================================================================
30
+ // Core API
31
+ // ============================================================================
32
+
33
+ export { createAgent } from "./createAgent";
34
+ export { AgentStateMachine } from "./AgentStateMachine";
35
+ export type { AgentEngine, CreateAgentOptions } from "./types";
36
+
37
+ // ============================================================================
38
+ // Types (re-export all types from types.ts)
39
+ // ============================================================================
40
+
41
+ export * from "./types";
42
+
43
+ // ============================================================================
44
+ // Engine (Stateless)
45
+ // ============================================================================
46
+
47
+ // MealyMachine
48
+ export { MealyMachine, createMealyMachine } from "./engine/MealyMachine";
49
+
50
+ // AgentProcessor (for advanced use cases)
51
+ export {
52
+ agentProcessor,
53
+ createInitialAgentEngineState,
54
+ type AgentEngineState,
55
+ type AgentProcessorInput,
56
+ type AgentProcessorOutput,
57
+ } from "./engine/AgentProcessor";
58
+
59
+ // Internal Processors (for advanced use cases)
60
+ export {
61
+ // MessageAssembler
62
+ messageAssemblerProcessor,
63
+ messageAssemblerProcessorDef,
64
+ type MessageAssemblerInput,
65
+ type MessageAssemblerOutput,
66
+ type MessageAssemblerState,
67
+ type PendingContent,
68
+ createInitialMessageAssemblerState,
69
+ // StateEventProcessor
70
+ stateEventProcessor,
71
+ stateEventProcessorDef,
72
+ type StateEventProcessorInput,
73
+ type StateEventProcessorOutput,
74
+ type StateEventProcessorContext,
75
+ createInitialStateEventProcessorContext,
76
+ // TurnTracker
77
+ turnTrackerProcessor,
78
+ turnTrackerProcessorDef,
79
+ type TurnTrackerInput,
80
+ type TurnTrackerOutput,
81
+ type TurnTrackerState,
82
+ type PendingTurn,
83
+ createInitialTurnTrackerState,
84
+ } from "./engine/internal";
85
+
86
+ // Mealy Machine Core (for building custom processors)
87
+ export {
88
+ // Core types
89
+ type Source,
90
+ type SourceDefinition,
91
+ type Processor,
92
+ type ProcessorResult,
93
+ type ProcessorDefinition,
94
+ type Sink,
95
+ type SinkDefinition,
96
+ type Store,
97
+ MemoryStore,
98
+ // Combinators
99
+ combineProcessors,
100
+ combineInitialStates,
101
+ chainProcessors,
102
+ filterProcessor,
103
+ mapOutput,
104
+ withLogging,
105
+ identityProcessor,
106
+ } from "./engine/mealy";
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Engine Types - AgentEngine, Driver, Presenter, and related infrastructure
3
+ *
4
+ * This file defines:
5
+ * - MessageQueue: Read-only view of message queue state
6
+ * - AgentEngine: Event processing unit interface
7
+ * - AgentDriver: Input adapter for external events
8
+ * - AgentPresenter: Output adapter for external systems
9
+ * - Middleware and Interceptor types
10
+ * - StateMachine interface
11
+ * - CreateAgentOptions: Factory options
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+
16
+ import type { UserMessage } from "./message";
17
+ import type {
18
+ AgentState,
19
+ AgentOutput,
20
+ StreamEvent,
21
+ Unsubscribe,
22
+ AgentOutputCallback,
23
+ } from "./event";
24
+
25
+ // =============================================================================
26
+ // Message Queue
27
+ // =============================================================================
28
+
29
+ /**
30
+ * MessageQueue interface
31
+ *
32
+ * Read-only view of the message queue state.
33
+ */
34
+ export interface MessageQueue {
35
+ /**
36
+ * Number of messages in queue
37
+ */
38
+ readonly length: number;
39
+
40
+ /**
41
+ * Whether queue is empty
42
+ */
43
+ readonly isEmpty: boolean;
44
+ }
45
+
46
+ // =============================================================================
47
+ // Middleware & Interceptor
48
+ // =============================================================================
49
+
50
+ /**
51
+ * Next function to continue the middleware chain
52
+ */
53
+ export type AgentMiddlewareNext = (message: UserMessage) => Promise<void>;
54
+
55
+ /**
56
+ * Middleware function type
57
+ *
58
+ * @param message - The user message being processed
59
+ * @param next - Call to continue to next middleware or actual receive
60
+ */
61
+ export type AgentMiddleware = (message: UserMessage, next: AgentMiddlewareNext) => Promise<void>;
62
+
63
+ /**
64
+ * Next function to continue the interceptor chain
65
+ */
66
+ export type AgentInterceptorNext = (event: AgentOutput) => void;
67
+
68
+ /**
69
+ * Interceptor function type
70
+ *
71
+ * @param event - The event being dispatched
72
+ * @param next - Call to continue to next interceptor or actual dispatch
73
+ */
74
+ export type AgentInterceptor = (event: AgentOutput, next: AgentInterceptorNext) => void;
75
+
76
+ // =============================================================================
77
+ // State Machine
78
+ // =============================================================================
79
+
80
+ /**
81
+ * State change event payload
82
+ */
83
+ export interface StateChange {
84
+ prev: AgentState;
85
+ current: AgentState;
86
+ }
87
+
88
+ /**
89
+ * State change handler type
90
+ */
91
+ export type StateChangeHandler = (change: StateChange) => void;
92
+
93
+ /**
94
+ * AgentStateMachine interface
95
+ *
96
+ * Processes StateEvents to update internal agent state and notify subscribers.
97
+ */
98
+ export interface AgentStateMachineInterface {
99
+ /**
100
+ * Current agent state
101
+ */
102
+ readonly state: AgentState;
103
+
104
+ /**
105
+ * Process a StateEvent and update internal state
106
+ *
107
+ * @param event - StateEvent from MealyMachine
108
+ */
109
+ process(event: AgentOutput): void;
110
+
111
+ /**
112
+ * Subscribe to state changes
113
+ *
114
+ * @param handler - Callback receiving { prev, current } state change
115
+ * @returns Unsubscribe function
116
+ */
117
+ onStateChange(handler: StateChangeHandler): Unsubscribe;
118
+
119
+ /**
120
+ * Reset state machine (used on destroy)
121
+ */
122
+ reset(): void;
123
+ }
124
+
125
+ // =============================================================================
126
+ // Event Handler Maps
127
+ // =============================================================================
128
+
129
+ /**
130
+ * Event handler map for batch subscription
131
+ *
132
+ * Generic handler map - concrete event types are defined in runtime/event.
133
+ * AgentEngine package is independent of specific event type definitions.
134
+ *
135
+ * Usage:
136
+ * ```typescript
137
+ * engine.on({
138
+ * text_delta: (event) => console.log(event.data.text),
139
+ * assistant_message: (event) => setMessages(prev => [...prev, event.data]),
140
+ * });
141
+ * ```
142
+ */
143
+ export type EventHandlerMap = Record<string, ((event: AgentOutput) => void) | undefined>;
144
+
145
+ /**
146
+ * React-style handler map for fluent event subscription
147
+ *
148
+ * Generic handler map - concrete event types are defined in runtime/event.
149
+ * AgentEngine package is independent of specific event type definitions.
150
+ *
151
+ * Usage:
152
+ * ```typescript
153
+ * engine.react({
154
+ * onTextDelta: (event) => console.log(event.data.text),
155
+ * onAssistantMessage: (event) => setMessages(prev => [...prev, event.data]),
156
+ * });
157
+ * ```
158
+ */
159
+ export type ReactHandlerMap = Record<string, ((event: AgentOutput) => void) | undefined>;
160
+
161
+ // =============================================================================
162
+ // Agent Engine
163
+ // =============================================================================
164
+
165
+ /**
166
+ * AgentEngine interface - Event Processing Unit
167
+ *
168
+ * Core responsibilities:
169
+ * - State management (AgentState)
170
+ * - Event subscription and distribution
171
+ * - Middleware/Interceptor chain
172
+ */
173
+ export interface AgentEngine {
174
+ /**
175
+ * Unique agent instance ID
176
+ */
177
+ readonly agentId: string;
178
+
179
+ /**
180
+ * Creation timestamp
181
+ */
182
+ readonly createdAt: number;
183
+
184
+ /**
185
+ * Current conversation state
186
+ */
187
+ readonly state: AgentState;
188
+
189
+ /**
190
+ * Message queue for pending messages
191
+ */
192
+ readonly messageQueue: MessageQueue;
193
+
194
+ /**
195
+ * Receive a message from user
196
+ *
197
+ * @param message - String content or UserMessage object
198
+ * @deprecated Use handleStreamEvent for push-based event processing
199
+ */
200
+ receive(message: string | UserMessage): Promise<void>;
201
+
202
+ /**
203
+ * Handle a stream event from the driver
204
+ *
205
+ * This is the push-based API for event processing.
206
+ * Events are pushed by BusDriver when DriveableEvents arrive.
207
+ *
208
+ * @param event - StreamEvent to process through MealyMachine
209
+ */
210
+ handleStreamEvent(event: StreamEvent): void;
211
+
212
+ /**
213
+ * Subscribe to all events
214
+ */
215
+ on(handler: AgentOutputCallback): Unsubscribe;
216
+
217
+ /**
218
+ * Batch subscribe to multiple event types
219
+ */
220
+ on(handlers: EventHandlerMap): Unsubscribe;
221
+
222
+ /**
223
+ * Subscribe to specific event type by name
224
+ */
225
+ on(type: string, handler: AgentOutputCallback): Unsubscribe;
226
+
227
+ /**
228
+ * Subscribe to multiple event types by name
229
+ */
230
+ on(types: string[], handler: AgentOutputCallback): Unsubscribe;
231
+
232
+ /**
233
+ * Subscribe to state changes
234
+ *
235
+ * @param handler - Callback receiving { prev, current } state change
236
+ * @returns Unsubscribe function
237
+ */
238
+ onStateChange(handler: StateChangeHandler): Unsubscribe;
239
+
240
+ /**
241
+ * React-style fluent event subscription
242
+ */
243
+ react(handlers: ReactHandlerMap): Unsubscribe;
244
+
245
+ /**
246
+ * Subscribe to agent ready event
247
+ *
248
+ * Called when agent is ready to receive messages.
249
+ * If already ready, handler is called immediately.
250
+ */
251
+ onReady(handler: () => void): Unsubscribe;
252
+
253
+ /**
254
+ * Subscribe to agent destroy event
255
+ *
256
+ * Called when agent is destroyed.
257
+ */
258
+ onDestroy(handler: () => void): Unsubscribe;
259
+
260
+ /**
261
+ * Add middleware to intercept incoming messages (receive side)
262
+ */
263
+ use(middleware: AgentMiddleware): Unsubscribe;
264
+
265
+ /**
266
+ * Add interceptor to intercept outgoing events (event side)
267
+ */
268
+ intercept(interceptor: AgentInterceptor): Unsubscribe;
269
+
270
+ /**
271
+ * Interrupt - User-initiated stop
272
+ *
273
+ * Stops the current operation gracefully.
274
+ * The agent will return to idle state.
275
+ */
276
+ interrupt(): void;
277
+
278
+ /**
279
+ * Destroy - Clean up resources
280
+ */
281
+ destroy(): Promise<void>;
282
+ }
283
+
284
+ // =============================================================================
285
+ // Source & Presenter (EventBus adapters)
286
+ // =============================================================================
287
+
288
+ /**
289
+ * AgentSource interface
290
+ *
291
+ * Subscribes to EventBus for StreamEvents and forwards them to AgentEngine.
292
+ * This is the input adapter: EventBus → AgentEngine
293
+ *
294
+ * ```
295
+ * EventBus ──subscribe──► Source ──handleStreamEvent──► AgentEngine
296
+ * ```
297
+ */
298
+ export interface AgentSource {
299
+ /**
300
+ * Source name (for identification and logging)
301
+ */
302
+ readonly name: string;
303
+
304
+ /**
305
+ * Connect to EventBus and start forwarding StreamEvents
306
+ *
307
+ * @param onEvent - Callback to invoke when StreamEvent is received
308
+ */
309
+ connect(onEvent: (event: StreamEvent) => void): void;
310
+
311
+ /**
312
+ * Disconnect from EventBus
313
+ */
314
+ disconnect(): void;
315
+ }
316
+
317
+ /**
318
+ * AgentPresenter interface
319
+ *
320
+ * Publishes AgentOutput to EventBus.
321
+ * This is the output adapter: AgentEngine → EventBus
322
+ *
323
+ * ```
324
+ * AgentEngine ──present──► Presenter ──emit──► EventBus
325
+ * ```
326
+ */
327
+ export interface AgentPresenter {
328
+ /**
329
+ * Presenter name (for identification and logging)
330
+ */
331
+ readonly name: string;
332
+
333
+ /**
334
+ * Publish an agent output to EventBus
335
+ *
336
+ * @param agentId - The agent ID
337
+ * @param output - The output to publish
338
+ */
339
+ present(agentId: string, output: AgentOutput): void;
340
+ }
341
+
342
+ // =============================================================================
343
+ // Factory Options
344
+ // =============================================================================
345
+
346
+ /**
347
+ * EventBus interface (minimal subset needed by AgentEngine)
348
+ */
349
+ export interface AgentEventBus {
350
+ /**
351
+ * Emit an event to the bus
352
+ */
353
+ emit(event: unknown): void;
354
+
355
+ /**
356
+ * Subscribe to events
357
+ */
358
+ on(type: string, handler: (event: unknown) => void): () => void;
359
+
360
+ /**
361
+ * Subscribe to all events
362
+ */
363
+ onAny(handler: (event: unknown) => void): () => void;
364
+ }
365
+
366
+ /**
367
+ * Options for creating an AgentEngine
368
+ */
369
+ export interface CreateAgentOptions {
370
+ /**
371
+ * Agent ID (optional, auto-generated if not provided)
372
+ */
373
+ agentId?: string;
374
+
375
+ /**
376
+ * EventBus connection
377
+ * AgentEngine uses this to:
378
+ * - emit user_message when receive() is called
379
+ * - Source subscribes to StreamEvent
380
+ * - Presenter emits AgentOutput
381
+ */
382
+ bus: AgentEventBus;
383
+
384
+ /**
385
+ * Source - Subscribes to EventBus, forwards StreamEvent to AgentEngine
386
+ * Optional: default implementation subscribes to StreamEvent types
387
+ */
388
+ source?: AgentSource;
389
+
390
+ /**
391
+ * Presenter - Publishes AgentOutput to EventBus
392
+ * Optional: default implementation emits to bus
393
+ */
394
+ presenter?: AgentPresenter;
395
+ }