@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.
- package/package.json +31 -0
- package/src/agent/AgentStateMachine.ts +151 -0
- package/src/agent/README.md +296 -0
- package/src/agent/__tests__/AgentStateMachine.test.ts +346 -0
- package/src/agent/__tests__/createAgent.test.ts +728 -0
- package/src/agent/__tests__/engine/internal/messageAssemblerProcessor.test.ts +567 -0
- package/src/agent/__tests__/engine/internal/stateEventProcessor.test.ts +315 -0
- package/src/agent/__tests__/engine/internal/turnTrackerProcessor.test.ts +340 -0
- package/src/agent/__tests__/engine/mealy/Mealy.test.ts +370 -0
- package/src/agent/__tests__/engine/mealy/Store.test.ts +123 -0
- package/src/agent/__tests__/engine/mealy/combinators.test.ts +322 -0
- package/src/agent/createAgent.ts +467 -0
- package/src/agent/engine/AgentProcessor.ts +106 -0
- package/src/agent/engine/MealyMachine.ts +184 -0
- package/src/agent/engine/internal/index.ts +35 -0
- package/src/agent/engine/internal/messageAssemblerProcessor.ts +550 -0
- package/src/agent/engine/internal/stateEventProcessor.ts +313 -0
- package/src/agent/engine/internal/turnTrackerProcessor.ts +239 -0
- package/src/agent/engine/mealy/Mealy.ts +308 -0
- package/src/agent/engine/mealy/Processor.ts +70 -0
- package/src/agent/engine/mealy/Sink.ts +56 -0
- package/src/agent/engine/mealy/Source.ts +51 -0
- package/src/agent/engine/mealy/Store.ts +98 -0
- package/src/agent/engine/mealy/combinators.ts +176 -0
- package/src/agent/engine/mealy/index.ts +45 -0
- package/src/agent/index.ts +106 -0
- package/src/agent/types/engine.ts +395 -0
- package/src/agent/types/event.ts +478 -0
- package/src/agent/types/index.ts +197 -0
- package/src/agent/types/message.ts +387 -0
- package/src/common/index.ts +8 -0
- package/src/common/logger/ConsoleLogger.ts +137 -0
- package/src/common/logger/LoggerFactoryImpl.ts +123 -0
- package/src/common/logger/index.ts +26 -0
- package/src/common/logger/types.ts +98 -0
- package/src/container/Container.ts +185 -0
- package/src/container/index.ts +44 -0
- package/src/container/types.ts +71 -0
- package/src/driver/index.ts +42 -0
- package/src/driver/types.ts +363 -0
- package/src/event/EventBus.ts +260 -0
- package/src/event/README.md +237 -0
- package/src/event/__tests__/EventBus.test.ts +251 -0
- package/src/event/index.ts +46 -0
- package/src/event/types/agent.ts +512 -0
- package/src/event/types/base.ts +241 -0
- package/src/event/types/bus.ts +429 -0
- package/src/event/types/command.ts +749 -0
- package/src/event/types/container.ts +471 -0
- package/src/event/types/driver.ts +452 -0
- package/src/event/types/index.ts +26 -0
- package/src/event/types/session.ts +314 -0
- package/src/image/Image.ts +203 -0
- package/src/image/index.ts +36 -0
- package/src/image/types.ts +77 -0
- package/src/index.ts +20 -0
- package/src/mq/OffsetGenerator.ts +48 -0
- package/src/mq/README.md +166 -0
- package/src/mq/__tests__/OffsetGenerator.test.ts +121 -0
- package/src/mq/index.ts +18 -0
- package/src/mq/types.ts +172 -0
- package/src/network/RpcClient.ts +455 -0
- package/src/network/index.ts +76 -0
- package/src/network/jsonrpc.ts +336 -0
- package/src/network/protocol.ts +90 -0
- package/src/network/types.ts +284 -0
- package/src/persistence/index.ts +27 -0
- package/src/persistence/types.ts +226 -0
- package/src/runtime/AgentXRuntime.ts +501 -0
- package/src/runtime/index.ts +56 -0
- package/src/runtime/types.ts +236 -0
- package/src/session/Session.ts +71 -0
- package/src/session/index.ts +25 -0
- package/src/session/types.ts +77 -0
- package/src/workspace/index.ts +27 -0
- package/src/workspace/types.ts +131 -0
- 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
|
+
}
|