@agentxjs/agent 0.1.6

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/dist/index.cjs ADDED
@@ -0,0 +1,1099 @@
1
+ 'use strict';
2
+
3
+ var common = require('@agentxjs/common');
4
+ var agent = require('@agentxjs/types/agent');
5
+
6
+ // src/engine/mealy/Store.ts
7
+ var MemoryStore = class {
8
+ states = /* @__PURE__ */ new Map();
9
+ get(id) {
10
+ return this.states.get(id);
11
+ }
12
+ set(id, state) {
13
+ this.states.set(id, state);
14
+ }
15
+ delete(id) {
16
+ this.states.delete(id);
17
+ }
18
+ has(id) {
19
+ return this.states.has(id);
20
+ }
21
+ /**
22
+ * Clear all stored states
23
+ */
24
+ clear() {
25
+ this.states.clear();
26
+ }
27
+ /**
28
+ * Get the number of stored states
29
+ */
30
+ get size() {
31
+ return this.states.size;
32
+ }
33
+ /**
34
+ * Get all stored IDs
35
+ */
36
+ keys() {
37
+ return this.states.keys();
38
+ }
39
+ };
40
+ common.createLogger("engine/Mealy");
41
+
42
+ // src/engine/mealy/combinators.ts
43
+ function combineProcessors(processors) {
44
+ return (state, event) => {
45
+ const newState = {};
46
+ const allOutputs = [];
47
+ for (const key in processors) {
48
+ const processor = processors[key];
49
+ const subState = state[key];
50
+ const [newSubState, outputs] = processor(subState, event);
51
+ newState[key] = newSubState;
52
+ allOutputs.push(...outputs);
53
+ }
54
+ return [newState, allOutputs];
55
+ };
56
+ }
57
+ function combineInitialStates(initialStates) {
58
+ return () => {
59
+ const state = {};
60
+ for (const key in initialStates) {
61
+ state[key] = initialStates[key]();
62
+ }
63
+ return state;
64
+ };
65
+ }
66
+ function chainProcessors(...processors) {
67
+ return (state, event) => {
68
+ let currentState = state;
69
+ const finalOutputs = [];
70
+ for (const processor of processors) {
71
+ const [newState, outputs] = processor(currentState, event);
72
+ currentState = newState;
73
+ finalOutputs.push(...outputs);
74
+ }
75
+ return [currentState, finalOutputs];
76
+ };
77
+ }
78
+ function filterProcessor(predicate, processor) {
79
+ return (state, event) => {
80
+ if (predicate(event)) {
81
+ return processor(state, event);
82
+ }
83
+ return [state, []];
84
+ };
85
+ }
86
+ function mapOutput(processor, mapper) {
87
+ return (state, event) => {
88
+ const [newState, outputs] = processor(state, event);
89
+ return [newState, outputs.map(mapper)];
90
+ };
91
+ }
92
+ function withLogging(processor, name, logger6 = console) {
93
+ return (state, event) => {
94
+ logger6.debug(`[${name}] Input:`, { event, state });
95
+ const [newState, outputs] = processor(state, event);
96
+ logger6.debug(`[${name}] Output:`, { newState, outputs });
97
+ return [newState, outputs];
98
+ };
99
+ }
100
+ function identityProcessor() {
101
+ return (state, _event) => {
102
+ return [state, []];
103
+ };
104
+ }
105
+
106
+ // src/engine/internal/messageAssemblerProcessor.ts
107
+ function createInitialMessageAssemblerState() {
108
+ return {
109
+ currentMessageId: null,
110
+ messageStartTime: null,
111
+ pendingContents: {},
112
+ pendingToolCalls: {}
113
+ };
114
+ }
115
+ function generateId() {
116
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
117
+ }
118
+ var messageAssemblerProcessor = (state, input) => {
119
+ switch (input.type) {
120
+ case "message_start":
121
+ return handleMessageStart(state, input);
122
+ case "text_delta":
123
+ return handleTextDelta(state, input);
124
+ case "tool_use_start":
125
+ return handleToolUseStart(state, input);
126
+ case "input_json_delta":
127
+ return handleInputJsonDelta(state, input);
128
+ case "tool_use_stop":
129
+ return handleToolUseStop(state);
130
+ case "tool_result":
131
+ return handleToolResult(state, input);
132
+ case "message_stop":
133
+ return handleMessageStop(state, input);
134
+ case "error_received":
135
+ return handleErrorReceived(state, input);
136
+ default:
137
+ return [state, []];
138
+ }
139
+ };
140
+ function handleMessageStart(state, event) {
141
+ const data = event.data;
142
+ return [
143
+ {
144
+ ...state,
145
+ currentMessageId: data.messageId,
146
+ messageStartTime: event.timestamp,
147
+ pendingContents: {}
148
+ },
149
+ []
150
+ ];
151
+ }
152
+ function handleTextDelta(state, event) {
153
+ const data = event.data;
154
+ const index = 0;
155
+ const existingContent = state.pendingContents[index];
156
+ const pendingContent = existingContent?.type === "text" ? {
157
+ ...existingContent,
158
+ textDeltas: [...existingContent.textDeltas || [], data.text]
159
+ } : {
160
+ type: "text",
161
+ index,
162
+ textDeltas: [data.text]
163
+ };
164
+ return [
165
+ {
166
+ ...state,
167
+ pendingContents: {
168
+ ...state.pendingContents,
169
+ [index]: pendingContent
170
+ }
171
+ },
172
+ []
173
+ ];
174
+ }
175
+ function handleToolUseStart(state, event) {
176
+ const data = event.data;
177
+ const index = 1;
178
+ const pendingContent = {
179
+ type: "tool_use",
180
+ index,
181
+ toolId: data.toolCallId,
182
+ toolName: data.toolName,
183
+ toolInputJson: ""
184
+ };
185
+ return [
186
+ {
187
+ ...state,
188
+ pendingContents: {
189
+ ...state.pendingContents,
190
+ [index]: pendingContent
191
+ }
192
+ },
193
+ []
194
+ ];
195
+ }
196
+ function handleInputJsonDelta(state, event) {
197
+ const data = event.data;
198
+ const index = 1;
199
+ const existingContent = state.pendingContents[index];
200
+ if (!existingContent || existingContent.type !== "tool_use") {
201
+ return [state, []];
202
+ }
203
+ const pendingContent = {
204
+ ...existingContent,
205
+ toolInputJson: (existingContent.toolInputJson || "") + data.partialJson
206
+ };
207
+ return [
208
+ {
209
+ ...state,
210
+ pendingContents: {
211
+ ...state.pendingContents,
212
+ [index]: pendingContent
213
+ }
214
+ },
215
+ []
216
+ ];
217
+ }
218
+ function handleToolUseStop(state, _event) {
219
+ const index = 1;
220
+ const pendingContent = state.pendingContents[index];
221
+ if (!pendingContent || pendingContent.type !== "tool_use") {
222
+ return [state, []];
223
+ }
224
+ const toolId = pendingContent.toolId || "";
225
+ const toolName = pendingContent.toolName || "";
226
+ let toolInput = {};
227
+ try {
228
+ toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
229
+ } catch {
230
+ toolInput = {};
231
+ }
232
+ const toolCall = {
233
+ type: "tool-call",
234
+ id: toolId,
235
+ name: toolName,
236
+ input: toolInput
237
+ };
238
+ const messageId = generateId();
239
+ const timestamp = Date.now();
240
+ const toolCallMessage = {
241
+ id: messageId,
242
+ role: "assistant",
243
+ subtype: "tool-call",
244
+ toolCall,
245
+ timestamp,
246
+ parentId: state.currentMessageId || void 0
247
+ };
248
+ const toolCallMessageEvent = {
249
+ type: "tool_call_message",
250
+ timestamp,
251
+ data: toolCallMessage
252
+ };
253
+ const { [index]: _, ...remainingContents } = state.pendingContents;
254
+ return [
255
+ {
256
+ ...state,
257
+ pendingContents: remainingContents,
258
+ pendingToolCalls: {
259
+ ...state.pendingToolCalls,
260
+ [toolId]: { id: toolId, name: toolName }
261
+ }
262
+ },
263
+ [toolCallMessageEvent]
264
+ ];
265
+ }
266
+ function handleToolResult(state, event) {
267
+ const data = event.data;
268
+ const { toolCallId, result, isError } = data;
269
+ const pendingToolCall = state.pendingToolCalls[toolCallId];
270
+ const toolName = pendingToolCall?.name || "unknown";
271
+ const toolResult = {
272
+ type: "tool-result",
273
+ id: toolCallId,
274
+ name: toolName,
275
+ output: {
276
+ type: isError ? "error-text" : "text",
277
+ value: typeof result === "string" ? result : JSON.stringify(result)
278
+ }
279
+ };
280
+ const messageId = generateId();
281
+ const timestamp = Date.now();
282
+ const toolResultMessage = {
283
+ id: messageId,
284
+ role: "tool",
285
+ subtype: "tool-result",
286
+ toolCallId,
287
+ toolResult,
288
+ timestamp
289
+ };
290
+ const toolResultMessageEvent = {
291
+ type: "tool_result_message",
292
+ timestamp,
293
+ data: toolResultMessage
294
+ };
295
+ const { [toolCallId]: _, ...remainingToolCalls } = state.pendingToolCalls;
296
+ return [
297
+ {
298
+ ...state,
299
+ pendingToolCalls: remainingToolCalls
300
+ },
301
+ [toolResultMessageEvent]
302
+ ];
303
+ }
304
+ function handleMessageStop(state, event) {
305
+ const data = event.data;
306
+ if (!state.currentMessageId) {
307
+ return [state, []];
308
+ }
309
+ const textParts = [];
310
+ const sortedContents = Object.values(state.pendingContents).sort((a, b) => a.index - b.index);
311
+ for (const pending of sortedContents) {
312
+ if (pending.type === "text" && pending.textDeltas) {
313
+ textParts.push(pending.textDeltas.join(""));
314
+ }
315
+ }
316
+ const textContent = textParts.join("");
317
+ const stopReason = data.stopReason;
318
+ if (!textContent || textContent.trim().length === 0) {
319
+ const shouldPreserveToolCalls2 = stopReason === "tool_use";
320
+ return [
321
+ {
322
+ ...createInitialMessageAssemblerState(),
323
+ pendingToolCalls: shouldPreserveToolCalls2 ? state.pendingToolCalls : {}
324
+ },
325
+ []
326
+ ];
327
+ }
328
+ const contentParts = [
329
+ {
330
+ type: "text",
331
+ text: textContent
332
+ }
333
+ ];
334
+ const timestamp = state.messageStartTime || Date.now();
335
+ const assistantMessage = {
336
+ id: state.currentMessageId,
337
+ role: "assistant",
338
+ subtype: "assistant",
339
+ content: contentParts,
340
+ timestamp
341
+ };
342
+ const assistantEvent = {
343
+ type: "assistant_message",
344
+ timestamp,
345
+ data: assistantMessage
346
+ };
347
+ const shouldPreserveToolCalls = stopReason === "tool_use";
348
+ return [
349
+ {
350
+ ...createInitialMessageAssemblerState(),
351
+ pendingToolCalls: shouldPreserveToolCalls ? state.pendingToolCalls : {}
352
+ },
353
+ [assistantEvent]
354
+ ];
355
+ }
356
+ function handleErrorReceived(_state, event) {
357
+ const data = event.data;
358
+ const messageId = generateId();
359
+ const timestamp = Date.now();
360
+ const errorMessage = {
361
+ id: messageId,
362
+ role: "error",
363
+ subtype: "error",
364
+ content: data.message,
365
+ errorCode: data.errorCode,
366
+ timestamp
367
+ };
368
+ const errorMessageEvent = {
369
+ type: "error_message",
370
+ timestamp,
371
+ data: errorMessage
372
+ };
373
+ return [createInitialMessageAssemblerState(), [errorMessageEvent]];
374
+ }
375
+ var messageAssemblerProcessorDef = {
376
+ name: "MessageAssembler",
377
+ description: "Assembles complete messages from stream events",
378
+ initialState: createInitialMessageAssemblerState,
379
+ processor: messageAssemblerProcessor
380
+ };
381
+ var logger2 = common.createLogger("engine/stateEventProcessor");
382
+ function createInitialStateEventProcessorContext() {
383
+ return {};
384
+ }
385
+ var stateEventProcessor = (context, input) => {
386
+ logger2.debug(`[Stream Event] ${input.type}`, {
387
+ context,
388
+ eventData: "data" in input ? input.data : void 0
389
+ });
390
+ switch (input.type) {
391
+ case "message_start":
392
+ return handleMessageStart2(context, input);
393
+ case "message_delta":
394
+ return handleMessageDelta(context);
395
+ case "message_stop":
396
+ return handleMessageStop2(context, input);
397
+ case "text_delta":
398
+ return handleTextDelta2(context);
399
+ case "tool_use_start":
400
+ return handleToolUseStart2(context, input);
401
+ case "tool_use_stop":
402
+ return handleToolUseStop2(context);
403
+ case "error_received":
404
+ return handleErrorReceived2(context, input);
405
+ default:
406
+ logger2.debug(`[Stream Event] ${input.type} (unhandled)`);
407
+ return [context, []];
408
+ }
409
+ };
410
+ function handleMessageStart2(context, event) {
411
+ const data = event.data;
412
+ const conversationStartEvent = {
413
+ type: "conversation_start",
414
+ timestamp: Date.now(),
415
+ data: {
416
+ messageId: data.messageId
417
+ }
418
+ };
419
+ return [context, [conversationStartEvent]];
420
+ }
421
+ function handleMessageDelta(context) {
422
+ return [context, []];
423
+ }
424
+ function handleMessageStop2(context, event) {
425
+ const data = event.data;
426
+ const stopReason = data.stopReason;
427
+ logger2.debug("message_stop received", { stopReason });
428
+ if (stopReason === "tool_use") {
429
+ logger2.debug("Skipping conversation_end (tool_use in progress)");
430
+ return [context, []];
431
+ }
432
+ const conversationEndEvent = {
433
+ type: "conversation_end",
434
+ timestamp: Date.now(),
435
+ data: {
436
+ reason: "completed"
437
+ }
438
+ };
439
+ return [context, [conversationEndEvent]];
440
+ }
441
+ function handleTextDelta2(context) {
442
+ const respondingEvent = {
443
+ type: "conversation_responding",
444
+ timestamp: Date.now(),
445
+ data: {}
446
+ };
447
+ return [context, [respondingEvent]];
448
+ }
449
+ function handleToolUseStart2(context, event) {
450
+ const data = event.data;
451
+ const outputs = [];
452
+ const toolPlannedEvent = {
453
+ type: "tool_planned",
454
+ timestamp: Date.now(),
455
+ data: {
456
+ toolId: data.toolCallId,
457
+ toolName: data.toolName
458
+ }
459
+ };
460
+ outputs.push(toolPlannedEvent);
461
+ const toolExecutingEvent = {
462
+ type: "tool_executing",
463
+ timestamp: Date.now(),
464
+ data: {
465
+ toolId: data.toolCallId,
466
+ toolName: data.toolName,
467
+ input: {}
468
+ }
469
+ };
470
+ outputs.push(toolExecutingEvent);
471
+ return [context, outputs];
472
+ }
473
+ function handleToolUseStop2(context) {
474
+ return [context, []];
475
+ }
476
+ function handleErrorReceived2(context, event) {
477
+ const data = event.data;
478
+ const errorOccurredEvent = {
479
+ type: "error_occurred",
480
+ timestamp: Date.now(),
481
+ data: {
482
+ code: data.errorCode || "unknown_error",
483
+ message: data.message,
484
+ recoverable: true
485
+ }
486
+ };
487
+ return [context, [errorOccurredEvent]];
488
+ }
489
+ var stateEventProcessorDef = {
490
+ name: "StateEventProcessor",
491
+ description: "Transform Stream Events into State Events",
492
+ initialState: createInitialStateEventProcessorContext,
493
+ processor: stateEventProcessor
494
+ };
495
+
496
+ // src/engine/internal/turnTrackerProcessor.ts
497
+ function createInitialTurnTrackerState() {
498
+ return {
499
+ pendingTurn: null,
500
+ costPerInputToken: 3e-6,
501
+ // $3 per 1M tokens
502
+ costPerOutputToken: 15e-6
503
+ // $15 per 1M tokens
504
+ };
505
+ }
506
+ function generateId2() {
507
+ return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
508
+ }
509
+ var turnTrackerProcessor = (state, input) => {
510
+ switch (input.type) {
511
+ case "user_message":
512
+ return handleUserMessage(state, input);
513
+ case "message_stop":
514
+ return handleMessageStop3(state, input);
515
+ case "assistant_message":
516
+ return [state, []];
517
+ default:
518
+ return [state, []];
519
+ }
520
+ };
521
+ function handleUserMessage(state, event) {
522
+ const data = event.data;
523
+ const turnId = generateId2();
524
+ const contentText = typeof data.content === "string" ? data.content : "";
525
+ const pendingTurn = {
526
+ turnId,
527
+ messageId: data.id,
528
+ content: contentText,
529
+ requestedAt: event.timestamp
530
+ };
531
+ const turnRequestEvent = {
532
+ type: "turn_request",
533
+ timestamp: Date.now(),
534
+ data: {
535
+ turnId,
536
+ messageId: data.id,
537
+ content: contentText,
538
+ timestamp: event.timestamp
539
+ }
540
+ };
541
+ return [
542
+ {
543
+ ...state,
544
+ pendingTurn
545
+ },
546
+ [turnRequestEvent]
547
+ ];
548
+ }
549
+ function handleMessageStop3(state, event) {
550
+ if (!state.pendingTurn) {
551
+ return [state, []];
552
+ }
553
+ const data = event.data;
554
+ const stopReason = data.stopReason;
555
+ if (stopReason === "end_turn" || stopReason === "max_tokens" || stopReason === "stop_sequence") {
556
+ return completeTurn(state, event.timestamp);
557
+ }
558
+ return [state, []];
559
+ }
560
+ function completeTurn(state, completedAt) {
561
+ if (!state.pendingTurn) {
562
+ return [state, []];
563
+ }
564
+ const { turnId, messageId, requestedAt } = state.pendingTurn;
565
+ const duration = completedAt - requestedAt;
566
+ const usage = { inputTokens: 0, outputTokens: 0 };
567
+ const turnResponseEvent = {
568
+ type: "turn_response",
569
+ timestamp: Date.now(),
570
+ data: {
571
+ turnId,
572
+ messageId,
573
+ duration,
574
+ usage,
575
+ timestamp: completedAt
576
+ }
577
+ };
578
+ return [
579
+ {
580
+ ...state,
581
+ pendingTurn: null
582
+ },
583
+ [turnResponseEvent]
584
+ ];
585
+ }
586
+ var turnTrackerProcessorDef = {
587
+ name: "TurnTracker",
588
+ description: "Tracks request-response turn pairs",
589
+ initialState: createInitialTurnTrackerState,
590
+ processor: turnTrackerProcessor
591
+ };
592
+
593
+ // src/engine/AgentProcessor.ts
594
+ var agentProcessor = combineProcessors({
595
+ messageAssembler: messageAssemblerProcessor,
596
+ stateEventProcessor,
597
+ turnTracker: turnTrackerProcessor
598
+ });
599
+ var createInitialAgentEngineState = combineInitialStates({
600
+ messageAssembler: createInitialMessageAssemblerState,
601
+ stateEventProcessor: createInitialStateEventProcessorContext,
602
+ turnTracker: createInitialTurnTrackerState
603
+ });
604
+ var logger3 = common.createLogger("engine/MealyMachine");
605
+ var MealyMachine = class {
606
+ store;
607
+ constructor() {
608
+ this.store = new MemoryStore();
609
+ logger3.debug("MealyMachine initialized");
610
+ }
611
+ /**
612
+ * Process a single driveable event and return output events
613
+ *
614
+ * This is the core Mealy Machine operation:
615
+ * process(agentId, event) → outputs[]
616
+ *
617
+ * @param agentId - The agent identifier (for state isolation)
618
+ * @param event - StreamEvent to process
619
+ * @returns Array of output events (state, message, turn events)
620
+ */
621
+ process(agentId, event) {
622
+ const eventType = event.type || "unknown";
623
+ logger3.debug("Processing event", { agentId, eventType });
624
+ const isNewState = !this.store.has(agentId);
625
+ let state = this.store.get(agentId) ?? createInitialAgentEngineState();
626
+ if (isNewState) {
627
+ logger3.debug("Created initial state for agent", { agentId });
628
+ }
629
+ const allOutputs = [];
630
+ allOutputs.push(event);
631
+ const [newState, outputs] = agentProcessor(state, event);
632
+ state = newState;
633
+ for (const output of outputs) {
634
+ allOutputs.push(output);
635
+ const [chainedState, chainedOutputs] = this.processChained(state, output);
636
+ state = chainedState;
637
+ allOutputs.push(...chainedOutputs);
638
+ }
639
+ this.store.set(agentId, state);
640
+ if (outputs.length > 0) {
641
+ logger3.debug("Produced outputs", {
642
+ agentId,
643
+ inputEvent: eventType,
644
+ outputCount: allOutputs.length,
645
+ processorOutputs: outputs.length
646
+ });
647
+ }
648
+ return allOutputs;
649
+ }
650
+ /**
651
+ * Process chained events recursively
652
+ *
653
+ * Some processors produce events that trigger other processors:
654
+ * - MessageAssembler produces MessageEvents
655
+ * - TurnTracker consumes MessageEvents to produce TurnEvents
656
+ */
657
+ processChained(state, event) {
658
+ const [newState, outputs] = agentProcessor(state, event);
659
+ if (outputs.length === 0) {
660
+ return [newState, []];
661
+ }
662
+ const allOutputs = [...outputs];
663
+ let currentState = newState;
664
+ for (const output of outputs) {
665
+ const [chainedState, chainedOutputs] = this.processChained(currentState, output);
666
+ currentState = chainedState;
667
+ allOutputs.push(...chainedOutputs);
668
+ }
669
+ return [currentState, allOutputs];
670
+ }
671
+ /**
672
+ * Clear state for an agent
673
+ *
674
+ * Call this when an agent is destroyed to free memory.
675
+ */
676
+ clearState(agentId) {
677
+ logger3.debug("Clearing state", { agentId });
678
+ this.store.delete(agentId);
679
+ }
680
+ /**
681
+ * Check if state exists for an agent
682
+ */
683
+ hasState(agentId) {
684
+ return this.store.has(agentId);
685
+ }
686
+ };
687
+ function createMealyMachine() {
688
+ return new MealyMachine();
689
+ }
690
+ var logger4 = common.createLogger("agent/AgentStateMachine");
691
+ var AgentStateMachine = class {
692
+ _state = "idle";
693
+ handlers = /* @__PURE__ */ new Set();
694
+ /**
695
+ * Current agent state
696
+ */
697
+ get state() {
698
+ return this._state;
699
+ }
700
+ /**
701
+ * Process an event and update internal state if it's a StateEvent
702
+ *
703
+ * @param event - Event from MealyMachine (could be any AgentOutput)
704
+ */
705
+ process(event) {
706
+ if (!agent.isStateEvent(event)) {
707
+ return;
708
+ }
709
+ const prev = this._state;
710
+ const next = this.mapEventToState(event);
711
+ if (next !== null && prev !== next) {
712
+ this._state = next;
713
+ logger4.debug("State transition", {
714
+ eventType: event.type,
715
+ from: prev,
716
+ to: next
717
+ });
718
+ this.notifyHandlers({ prev, current: next });
719
+ }
720
+ }
721
+ /**
722
+ * Subscribe to state changes
723
+ *
724
+ * @param handler - Callback receiving { prev, current } state change
725
+ * @returns Unsubscribe function
726
+ */
727
+ onStateChange(handler) {
728
+ this.handlers.add(handler);
729
+ return () => {
730
+ this.handlers.delete(handler);
731
+ };
732
+ }
733
+ /**
734
+ * Reset state machine (used on destroy)
735
+ */
736
+ reset() {
737
+ const prev = this._state;
738
+ this._state = "idle";
739
+ if (prev !== "idle") {
740
+ this.notifyHandlers({ prev, current: "idle" });
741
+ }
742
+ this.handlers.clear();
743
+ }
744
+ /**
745
+ * Map StateEvent type to AgentState
746
+ *
747
+ * @param event - StateEvent from MealyMachine
748
+ * @returns New AgentState or null if no transition needed
749
+ */
750
+ mapEventToState(event) {
751
+ switch (event.type) {
752
+ // Conversation lifecycle
753
+ case "conversation_start":
754
+ return "thinking";
755
+ case "conversation_thinking":
756
+ return "thinking";
757
+ case "conversation_responding":
758
+ return "responding";
759
+ case "conversation_end":
760
+ return "idle";
761
+ case "conversation_interrupted":
762
+ return "idle";
763
+ // Tool lifecycle
764
+ case "tool_planned":
765
+ return "planning_tool";
766
+ case "tool_executing":
767
+ return "awaiting_tool_result";
768
+ case "tool_completed":
769
+ return "responding";
770
+ case "tool_failed":
771
+ return "responding";
772
+ // Error
773
+ case "error_occurred":
774
+ return "error";
775
+ default:
776
+ return null;
777
+ }
778
+ }
779
+ /**
780
+ * Notify all registered handlers of state change
781
+ */
782
+ notifyHandlers(change) {
783
+ for (const handler of this.handlers) {
784
+ try {
785
+ handler(change);
786
+ } catch (error) {
787
+ logger4.error("State change handler error", {
788
+ from: change.prev,
789
+ to: change.current,
790
+ error
791
+ });
792
+ }
793
+ }
794
+ }
795
+ };
796
+ var logger5 = common.createLogger("agent/SimpleAgent");
797
+ function generateAgentId() {
798
+ return `agent_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
799
+ }
800
+ var SimpleMessageQueue = class {
801
+ queue = [];
802
+ get length() {
803
+ return this.queue.length;
804
+ }
805
+ get isEmpty() {
806
+ return this.queue.length === 0;
807
+ }
808
+ enqueue(message) {
809
+ this.queue.push(message);
810
+ }
811
+ dequeue() {
812
+ return this.queue.shift();
813
+ }
814
+ clear() {
815
+ this.queue = [];
816
+ }
817
+ };
818
+ var SimpleAgent = class {
819
+ agentId;
820
+ createdAt;
821
+ messageQueue;
822
+ _messageQueue = new SimpleMessageQueue();
823
+ driver;
824
+ presenter;
825
+ machine;
826
+ stateMachine;
827
+ handlers = /* @__PURE__ */ new Set();
828
+ typeHandlers = /* @__PURE__ */ new Map();
829
+ readyHandlers = /* @__PURE__ */ new Set();
830
+ destroyHandlers = /* @__PURE__ */ new Set();
831
+ middlewares = [];
832
+ interceptors = [];
833
+ isProcessing = false;
834
+ constructor(options) {
835
+ this.agentId = generateAgentId();
836
+ this.createdAt = Date.now();
837
+ this.messageQueue = this._messageQueue;
838
+ this.driver = options.driver;
839
+ this.presenter = options.presenter;
840
+ this.machine = new MealyMachine();
841
+ this.stateMachine = new AgentStateMachine();
842
+ }
843
+ get state() {
844
+ return this.stateMachine.state;
845
+ }
846
+ async receive(message) {
847
+ console.log(
848
+ "[SimpleAgent.receive] CALLED with message:",
849
+ typeof message === "string" ? message : message.content
850
+ );
851
+ const userMessage = typeof message === "string" ? {
852
+ id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
853
+ role: "user",
854
+ subtype: "user",
855
+ content: message,
856
+ timestamp: Date.now()
857
+ } : message;
858
+ this._messageQueue.enqueue(userMessage);
859
+ console.log("[SimpleAgent.receive] Message queued, isProcessing:", this.isProcessing);
860
+ if (this.isProcessing) {
861
+ return new Promise((resolve, reject) => {
862
+ userMessage._resolve = resolve;
863
+ userMessage._reject = reject;
864
+ });
865
+ }
866
+ console.log("[SimpleAgent.receive] Starting processQueue");
867
+ await this.processQueue();
868
+ }
869
+ async processQueue() {
870
+ if (this.isProcessing) return;
871
+ this.isProcessing = true;
872
+ console.log("[SimpleAgent.processQueue] Starting, queue size:", this._messageQueue.length);
873
+ while (!this._messageQueue.isEmpty) {
874
+ const message = this._messageQueue.dequeue();
875
+ if (!message) break;
876
+ console.log("[SimpleAgent.processQueue] Processing message:", message.id);
877
+ try {
878
+ await this.processMessage(message);
879
+ if (message._resolve) {
880
+ message._resolve();
881
+ }
882
+ } catch (error) {
883
+ if (message._reject) {
884
+ message._reject(error);
885
+ }
886
+ throw error;
887
+ }
888
+ }
889
+ this.isProcessing = false;
890
+ console.log("[SimpleAgent.processQueue] Finished");
891
+ }
892
+ async processMessage(message) {
893
+ console.log("[SimpleAgent.processMessage] START, message:", message.id);
894
+ let processedMessage = message;
895
+ for (const middleware of this.middlewares) {
896
+ let nextCalled = false;
897
+ await middleware(processedMessage, async (msg) => {
898
+ nextCalled = true;
899
+ processedMessage = msg;
900
+ });
901
+ if (!nextCalled) {
902
+ console.log("[SimpleAgent.processMessage] Middleware blocked message");
903
+ return;
904
+ }
905
+ }
906
+ console.log("[SimpleAgent.processMessage] Getting driver stream...");
907
+ const driverStream = this.driver.receive(processedMessage);
908
+ console.log("[SimpleAgent.processMessage] Driver stream:", driverStream);
909
+ try {
910
+ console.log("[SimpleAgent.processMessage] Starting for-await loop...");
911
+ for await (const streamEvent of driverStream) {
912
+ this.handleStreamEvent(streamEvent);
913
+ }
914
+ console.log("[SimpleAgent.processMessage] For-await loop completed");
915
+ } catch (error) {
916
+ console.log("[SimpleAgent.processMessage] ERROR:", error);
917
+ throw error;
918
+ }
919
+ console.log("[SimpleAgent.processMessage] END");
920
+ }
921
+ /**
922
+ * Handle a stream event from the driver (push-based API)
923
+ *
924
+ * This method processes a single StreamEvent through the MealyMachine
925
+ * and emits all resulting outputs to presenter and handlers.
926
+ */
927
+ handleStreamEvent(event) {
928
+ logger5.info("handleStreamEvent", { type: event.type });
929
+ const outputs = this.machine.process(this.agentId, event);
930
+ logger5.info("MealyMachine outputs", {
931
+ count: outputs.length,
932
+ types: outputs.map((o) => o.type)
933
+ });
934
+ for (const output of outputs) {
935
+ this.stateMachine.process(output);
936
+ this.emitOutput(output);
937
+ }
938
+ }
939
+ emitOutput(output) {
940
+ let currentOutput = output;
941
+ const runInterceptor = (index, out) => {
942
+ if (index >= this.interceptors.length) {
943
+ currentOutput = out;
944
+ return;
945
+ }
946
+ this.interceptors[index](out, (nextOut) => {
947
+ runInterceptor(index + 1, nextOut);
948
+ });
949
+ };
950
+ runInterceptor(0, output);
951
+ if (!currentOutput) return;
952
+ this.presenter.present(this.agentId, currentOutput);
953
+ for (const handler of this.handlers) {
954
+ try {
955
+ handler(currentOutput);
956
+ } catch (e) {
957
+ console.error("Event handler error:", e);
958
+ }
959
+ }
960
+ const typeSet = this.typeHandlers.get(currentOutput.type);
961
+ if (typeSet) {
962
+ for (const handler of typeSet) {
963
+ try {
964
+ handler(currentOutput);
965
+ } catch (e) {
966
+ console.error("Event handler error:", e);
967
+ }
968
+ }
969
+ }
970
+ }
971
+ on(typeOrHandler, handler) {
972
+ if (typeof typeOrHandler === "function") {
973
+ this.handlers.add(typeOrHandler);
974
+ return () => this.handlers.delete(typeOrHandler);
975
+ }
976
+ if (typeof typeOrHandler === "object" && !Array.isArray(typeOrHandler)) {
977
+ const unsubscribes = [];
978
+ for (const [type, h2] of Object.entries(typeOrHandler)) {
979
+ if (h2) {
980
+ unsubscribes.push(this.on(type, h2));
981
+ }
982
+ }
983
+ return () => unsubscribes.forEach((u) => u());
984
+ }
985
+ const types = Array.isArray(typeOrHandler) ? typeOrHandler : [typeOrHandler];
986
+ const h = handler;
987
+ for (const type of types) {
988
+ if (!this.typeHandlers.has(type)) {
989
+ this.typeHandlers.set(type, /* @__PURE__ */ new Set());
990
+ }
991
+ this.typeHandlers.get(type).add(h);
992
+ }
993
+ return () => {
994
+ for (const type of types) {
995
+ this.typeHandlers.get(type)?.delete(h);
996
+ }
997
+ };
998
+ }
999
+ onStateChange(handler) {
1000
+ return this.stateMachine.onStateChange(handler);
1001
+ }
1002
+ react(handlers) {
1003
+ const eventHandlerMap = {};
1004
+ for (const [key, handler] of Object.entries(handlers)) {
1005
+ if (handler && key.startsWith("on")) {
1006
+ const eventType = key.slice(2).replace(/([A-Z])/g, "_$1").toLowerCase().slice(1);
1007
+ eventHandlerMap[eventType] = handler;
1008
+ }
1009
+ }
1010
+ return this.on(eventHandlerMap);
1011
+ }
1012
+ onReady(handler) {
1013
+ try {
1014
+ handler();
1015
+ } catch (e) {
1016
+ console.error("onReady handler error:", e);
1017
+ }
1018
+ this.readyHandlers.add(handler);
1019
+ return () => this.readyHandlers.delete(handler);
1020
+ }
1021
+ onDestroy(handler) {
1022
+ this.destroyHandlers.add(handler);
1023
+ return () => this.destroyHandlers.delete(handler);
1024
+ }
1025
+ use(middleware) {
1026
+ this.middlewares.push(middleware);
1027
+ return () => {
1028
+ const index = this.middlewares.indexOf(middleware);
1029
+ if (index >= 0) {
1030
+ this.middlewares.splice(index, 1);
1031
+ }
1032
+ };
1033
+ }
1034
+ intercept(interceptor) {
1035
+ this.interceptors.push(interceptor);
1036
+ return () => {
1037
+ const index = this.interceptors.indexOf(interceptor);
1038
+ if (index >= 0) {
1039
+ this.interceptors.splice(index, 1);
1040
+ }
1041
+ };
1042
+ }
1043
+ interrupt() {
1044
+ if (this.state === "idle") {
1045
+ return;
1046
+ }
1047
+ this.driver.interrupt();
1048
+ }
1049
+ async destroy() {
1050
+ if (this.state !== "idle") {
1051
+ this.interrupt();
1052
+ }
1053
+ for (const handler of this.destroyHandlers) {
1054
+ try {
1055
+ handler();
1056
+ } catch (e) {
1057
+ console.error("onDestroy handler error:", e);
1058
+ }
1059
+ }
1060
+ this.machine.clearState(this.agentId);
1061
+ this.stateMachine.reset();
1062
+ this._messageQueue.clear();
1063
+ this.handlers.clear();
1064
+ this.typeHandlers.clear();
1065
+ this.readyHandlers.clear();
1066
+ this.destroyHandlers.clear();
1067
+ this.middlewares.length = 0;
1068
+ this.interceptors.length = 0;
1069
+ }
1070
+ };
1071
+ function createAgent(options) {
1072
+ return new SimpleAgent(options);
1073
+ }
1074
+
1075
+ exports.AgentStateMachine = AgentStateMachine;
1076
+ exports.MealyMachine = MealyMachine;
1077
+ exports.MemoryStore = MemoryStore;
1078
+ exports.agentProcessor = agentProcessor;
1079
+ exports.chainProcessors = chainProcessors;
1080
+ exports.combineInitialStates = combineInitialStates;
1081
+ exports.combineProcessors = combineProcessors;
1082
+ exports.createAgent = createAgent;
1083
+ exports.createInitialAgentEngineState = createInitialAgentEngineState;
1084
+ exports.createInitialMessageAssemblerState = createInitialMessageAssemblerState;
1085
+ exports.createInitialStateEventProcessorContext = createInitialStateEventProcessorContext;
1086
+ exports.createInitialTurnTrackerState = createInitialTurnTrackerState;
1087
+ exports.createMealyMachine = createMealyMachine;
1088
+ exports.filterProcessor = filterProcessor;
1089
+ exports.identityProcessor = identityProcessor;
1090
+ exports.mapOutput = mapOutput;
1091
+ exports.messageAssemblerProcessor = messageAssemblerProcessor;
1092
+ exports.messageAssemblerProcessorDef = messageAssemblerProcessorDef;
1093
+ exports.stateEventProcessor = stateEventProcessor;
1094
+ exports.stateEventProcessorDef = stateEventProcessorDef;
1095
+ exports.turnTrackerProcessor = turnTrackerProcessor;
1096
+ exports.turnTrackerProcessorDef = turnTrackerProcessorDef;
1097
+ exports.withLogging = withLogging;
1098
+ //# sourceMappingURL=index.cjs.map
1099
+ //# sourceMappingURL=index.cjs.map