@copilotkitnext/runtime 0.0.2 → 0.0.4

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 (40) hide show
  1. package/dist/index.js +1 -14
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +1 -14
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +4 -4
  6. package/.turbo/turbo-build.log +0 -23
  7. package/.turbo/turbo-check-types.log +0 -4
  8. package/.turbo/turbo-lint.log +0 -56
  9. package/.turbo/turbo-test$colon$coverage.log +0 -149
  10. package/.turbo/turbo-test.log +0 -107
  11. package/src/__tests__/get-runtime-info.test.ts +0 -117
  12. package/src/__tests__/handle-run.test.ts +0 -69
  13. package/src/__tests__/handle-transcribe.test.ts +0 -289
  14. package/src/__tests__/in-process-agent-runner-messages.test.ts +0 -599
  15. package/src/__tests__/in-process-agent-runner.test.ts +0 -726
  16. package/src/__tests__/middleware.test.ts +0 -432
  17. package/src/__tests__/routing.test.ts +0 -257
  18. package/src/endpoint.ts +0 -150
  19. package/src/handler.ts +0 -3
  20. package/src/handlers/get-runtime-info.ts +0 -50
  21. package/src/handlers/handle-connect.ts +0 -144
  22. package/src/handlers/handle-run.ts +0 -156
  23. package/src/handlers/handle-transcribe.ts +0 -126
  24. package/src/index.ts +0 -8
  25. package/src/middleware.ts +0 -232
  26. package/src/runner/__tests__/enterprise-runner.test.ts +0 -992
  27. package/src/runner/__tests__/event-compaction.test.ts +0 -253
  28. package/src/runner/__tests__/in-memory-runner.test.ts +0 -483
  29. package/src/runner/__tests__/sqlite-runner.test.ts +0 -975
  30. package/src/runner/agent-runner.ts +0 -27
  31. package/src/runner/enterprise.ts +0 -653
  32. package/src/runner/event-compaction.ts +0 -250
  33. package/src/runner/in-memory.ts +0 -341
  34. package/src/runner/index.ts +0 -0
  35. package/src/runner/sqlite.ts +0 -481
  36. package/src/runtime.ts +0 -53
  37. package/src/transcription-service/transcription-service-openai.ts +0 -29
  38. package/src/transcription-service/transcription-service.ts +0 -11
  39. package/tsconfig.json +0 -13
  40. package/tsup.config.ts +0 -11
@@ -1,599 +0,0 @@
1
- import { describe, it, expect, beforeEach } from "vitest";
2
- import { InMemoryAgentRunner } from "../runner/in-memory";
3
- import {
4
- AbstractAgent,
5
- BaseEvent,
6
- RunAgentInput,
7
- Message,
8
- RunStartedEvent,
9
- EventType,
10
- } from "@ag-ui/client";
11
- import { EMPTY, firstValueFrom, Observable } from "rxjs";
12
- import { toArray } from "rxjs/operators";
13
-
14
- // Type helpers for event filtering
15
- type EventWithType = BaseEvent & { type: string };
16
- type EventWithId = BaseEvent & { id: string };
17
- type EventWithMessageId = BaseEvent & { messageId: string };
18
- type EventWithMessageIdAndDelta = BaseEvent & {
19
- messageId: string;
20
- delta: string;
21
- };
22
-
23
- // Mock agent that can handle messages and callbacks
24
- class MessageAwareAgent extends AbstractAgent {
25
- private events: BaseEvent[] = [];
26
- public receivedMessages: Message[] = [];
27
- public onNewMessageCalled = 0;
28
- public onRunStartedCalled = 0;
29
-
30
- constructor(events: BaseEvent[] = []) {
31
- super();
32
- this.events = events;
33
- }
34
-
35
- protected run(input: RunAgentInput): Observable<BaseEvent> {
36
- return EMPTY;
37
- }
38
-
39
- async runAgent(
40
- input: RunAgentInput,
41
- options: {
42
- onEvent: (event: { event: BaseEvent }) => void;
43
- onNewMessage?: (args: { message: Message }) => void;
44
- onRunStartedEvent?: (args: { event: BaseEvent }) => void;
45
- }
46
- // @ts-expect-error
47
- ): Promise<RunAgentResult> {
48
- // Call onRunStartedEvent if provided
49
- if (options.onRunStartedEvent) {
50
- this.onRunStartedCalled++;
51
- const runStartedEvent = {
52
- type: EventType.RUN_STARTED,
53
- threadId: input.threadId,
54
- runId: input.runId,
55
- } as RunStartedEvent;
56
- options.onRunStartedEvent({ event: runStartedEvent });
57
- }
58
-
59
- // Emit the agent's own events
60
- for (const event of this.events) {
61
- options.onEvent({ event });
62
- }
63
-
64
- // Return a promise as expected
65
- return Promise.resolve();
66
- }
67
- }
68
-
69
- describe("InMemoryAgentRunner - Message Injection", () => {
70
- let runner: InMemoryAgentRunner;
71
-
72
- beforeEach(() => {
73
- runner = new InMemoryAgentRunner();
74
- });
75
-
76
- describe("Message Injection on Run", () => {
77
- it("should inject user messages as events when running an agent", async () => {
78
- const threadId = "test-thread-messages-1";
79
- const userMessage: Message = {
80
- id: "user-msg-1",
81
- role: "user",
82
- content: "Hello, agent!",
83
- };
84
-
85
- const agentEvents: BaseEvent[] = [
86
- {
87
- type: EventType.CUSTOM,
88
- id: "agent-response-1",
89
- timestamp: Date.now(),
90
- name: "agent-response",
91
- value: { text: "Hello, user!" },
92
- } as BaseEvent,
93
- ];
94
-
95
- const agent = new MessageAwareAgent(agentEvents);
96
- const input: RunAgentInput = {
97
- messages: [userMessage],
98
- state: {},
99
- threadId,
100
- runId: "run-1",
101
- tools: [],
102
- context: [],
103
- };
104
-
105
- // Run the agent
106
- const runObservable = runner.run({ threadId, agent, input });
107
- const runEvents = await firstValueFrom(runObservable.pipe(toArray()));
108
-
109
- // run() should only return agent events, not injected messages
110
- expect(runEvents).toHaveLength(1);
111
- expect((runEvents[0] as EventWithId).id).toBe("agent-response-1");
112
-
113
- // connect() should have all events including injected messages
114
- const connectObservable = runner.connect({ threadId });
115
- const allEvents = await firstValueFrom(connectObservable.pipe(toArray()));
116
-
117
- // Should have: user message events (Start, Content, End) + agent event = 4 events
118
- expect(allEvents.length).toBe(4);
119
-
120
- // Find the injected user message events
121
- const textStartEvents = allEvents.filter(
122
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_START
123
- );
124
- const textContentEvents = allEvents.filter(
125
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_CONTENT
126
- );
127
- const textEndEvents = allEvents.filter(
128
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_END
129
- );
130
-
131
- expect(textStartEvents).toHaveLength(1);
132
- expect(textStartEvents[0]).toMatchObject({
133
- type: EventType.TEXT_MESSAGE_START,
134
- messageId: "user-msg-1",
135
- });
136
-
137
- expect(textContentEvents).toHaveLength(1);
138
- expect(textContentEvents[0]).toMatchObject({
139
- type: EventType.TEXT_MESSAGE_CONTENT,
140
- messageId: "user-msg-1",
141
- delta: "Hello, agent!",
142
- });
143
-
144
- expect(textEndEvents).toHaveLength(1);
145
- expect(textEndEvents[0]).toMatchObject({
146
- type: EventType.TEXT_MESSAGE_END,
147
- messageId: "user-msg-1",
148
- });
149
-
150
- // Verify the agent callbacks
151
- expect(agent.onNewMessageCalled).toBe(0); // onNewMessage is not called by the test agent
152
- expect(agent.onRunStartedCalled).toBe(1);
153
- });
154
-
155
- it("should inject assistant messages as proper TextMessage events", async () => {
156
- const threadId = "test-thread-messages-2";
157
- const assistantMessage: Message = {
158
- id: "assistant-msg-1",
159
- role: "assistant",
160
- content: "I can help you with that!",
161
- };
162
-
163
- const agent = new MessageAwareAgent([]);
164
- const input: RunAgentInput = {
165
- messages: [assistantMessage],
166
- state: {},
167
- threadId,
168
- runId: "run-2",
169
- tools: [],
170
- context: [],
171
- };
172
-
173
- // Run the agent
174
- await firstValueFrom(
175
- runner.run({ threadId, agent, input }).pipe(toArray())
176
- );
177
-
178
- // Check events via connect
179
- const allEvents = await firstValueFrom(
180
- runner.connect({ threadId }).pipe(toArray())
181
- );
182
-
183
- // Find the injected message events
184
- const textStartEvents = allEvents.filter(
185
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_START
186
- );
187
- const textContentEvents = allEvents.filter(
188
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_CONTENT
189
- );
190
- const textEndEvents = allEvents.filter(
191
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_END
192
- );
193
-
194
- expect(textStartEvents).toHaveLength(1);
195
- expect(textStartEvents[0]).toMatchObject({
196
- type: EventType.TEXT_MESSAGE_START,
197
- messageId: "assistant-msg-1",
198
- role: "assistant",
199
- });
200
-
201
- expect(textContentEvents).toHaveLength(1);
202
- expect(textContentEvents[0]).toMatchObject({
203
- type: EventType.TEXT_MESSAGE_CONTENT,
204
- messageId: "assistant-msg-1",
205
- delta: "I can help you with that!",
206
- });
207
-
208
- expect(textEndEvents).toHaveLength(1);
209
- expect(textEndEvents[0]).toMatchObject({
210
- type: EventType.TEXT_MESSAGE_END,
211
- messageId: "assistant-msg-1",
212
- });
213
- });
214
-
215
- it("should inject tool call messages as proper ToolCall events", async () => {
216
- const threadId = "test-thread-messages-3";
217
- const toolCallMessage: Message = {
218
- id: "assistant-msg-2",
219
- role: "assistant",
220
- content: "",
221
- toolCalls: [
222
- {
223
- id: "tool-call-1",
224
- type: "function",
225
- function: {
226
- name: "get_weather",
227
- arguments: '{"location": "New York"}',
228
- },
229
- },
230
- ],
231
- };
232
-
233
- const agent = new MessageAwareAgent([]);
234
- const input: RunAgentInput = {
235
- messages: [toolCallMessage],
236
- state: {},
237
- threadId,
238
- runId: "run-3",
239
- tools: [],
240
- context: [],
241
- };
242
-
243
- // Run the agent
244
- await firstValueFrom(
245
- runner.run({ threadId, agent, input }).pipe(toArray())
246
- );
247
-
248
- // Check events via connect
249
- const allEvents = await firstValueFrom(
250
- runner.connect({ threadId }).pipe(toArray())
251
- );
252
-
253
- // Find the injected tool call events
254
- const toolStartEvents = allEvents.filter(
255
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_START
256
- );
257
- const toolArgsEvents = allEvents.filter(
258
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_ARGS
259
- );
260
- const toolEndEvents = allEvents.filter(
261
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_END
262
- );
263
-
264
- expect(toolStartEvents).toHaveLength(1);
265
- expect(toolStartEvents[0]).toMatchObject({
266
- type: EventType.TOOL_CALL_START,
267
- toolCallId: "tool-call-1",
268
- toolCallName: "get_weather",
269
- parentMessageId: "assistant-msg-2",
270
- });
271
-
272
- expect(toolArgsEvents).toHaveLength(1);
273
- expect(toolArgsEvents[0]).toMatchObject({
274
- type: EventType.TOOL_CALL_ARGS,
275
- toolCallId: "tool-call-1",
276
- delta: '{"location": "New York"}',
277
- });
278
-
279
- expect(toolEndEvents).toHaveLength(1);
280
- expect(toolEndEvents[0]).toMatchObject({
281
- type: EventType.TOOL_CALL_END,
282
- toolCallId: "tool-call-1",
283
- });
284
- });
285
-
286
- it("should inject developer and system messages as TextMessage events", async () => {
287
- const threadId = "test-thread-messages-dev-sys";
288
- const developerMessage: Message = {
289
- id: "dev-msg-1",
290
- role: "developer",
291
- content: "You are a helpful assistant.",
292
- };
293
- const systemMessage: Message = {
294
- id: "sys-msg-1",
295
- role: "system",
296
- content: "System prompt: Be concise.",
297
- };
298
-
299
- const agent = new MessageAwareAgent([]);
300
- const input: RunAgentInput = {
301
- messages: [developerMessage, systemMessage],
302
- state: {},
303
- threadId,
304
- runId: "run-dev-sys",
305
- tools: [],
306
- context: [],
307
- };
308
-
309
- // Run the agent
310
- await firstValueFrom(
311
- runner.run({ threadId, agent, input }).pipe(toArray())
312
- );
313
-
314
- // Check events via connect
315
- const allEvents = await firstValueFrom(
316
- runner.connect({ threadId }).pipe(toArray())
317
- );
318
-
319
- // Find the injected message events
320
- const textStartEvents = allEvents.filter(
321
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_START
322
- );
323
- const textContentEvents = allEvents.filter(
324
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_CONTENT
325
- );
326
- const textEndEvents = allEvents.filter(
327
- (e) => (e as EventWithType).type === EventType.TEXT_MESSAGE_END
328
- );
329
-
330
- // Should have 2 sets of text message events (one for each message)
331
- expect(textStartEvents).toHaveLength(2);
332
- expect(textContentEvents).toHaveLength(2);
333
- expect(textEndEvents).toHaveLength(2);
334
-
335
- // Verify developer message events
336
- expect(
337
- textStartEvents.some(
338
- (e) => (e as EventWithMessageId).messageId === "dev-msg-1"
339
- )
340
- ).toBe(true);
341
- expect(
342
- textContentEvents.some((e) => {
343
- const evt = e as EventWithMessageIdAndDelta;
344
- return (
345
- evt.messageId === "dev-msg-1" &&
346
- evt.delta === "You are a helpful assistant."
347
- );
348
- })
349
- ).toBe(true);
350
-
351
- // Verify system message events
352
- expect(
353
- textStartEvents.some(
354
- (e) => (e as EventWithMessageId).messageId === "sys-msg-1"
355
- )
356
- ).toBe(true);
357
- expect(
358
- textContentEvents.some((e) => {
359
- const evt = e as EventWithMessageIdAndDelta;
360
- return (
361
- evt.messageId === "sys-msg-1" &&
362
- evt.delta === "System prompt: Be concise."
363
- );
364
- })
365
- ).toBe(true);
366
- });
367
-
368
- it("should inject tool result messages as ToolCallResult events", async () => {
369
- const threadId = "test-thread-messages-4";
370
- const toolResultMessage: Message = {
371
- id: "tool-result-1",
372
- role: "tool",
373
- content: "72°F and sunny",
374
- toolCallId: "tool-call-1",
375
- };
376
-
377
- const agent = new MessageAwareAgent([]);
378
- const input: RunAgentInput = {
379
- messages: [toolResultMessage],
380
- state: {},
381
- threadId,
382
- runId: "run-4",
383
- tools: [],
384
- context: [],
385
- };
386
-
387
- // Run the agent
388
- await firstValueFrom(
389
- runner.run({ threadId, agent, input }).pipe(toArray())
390
- );
391
-
392
- // Check events via connect
393
- const allEvents = await firstValueFrom(
394
- runner.connect({ threadId }).pipe(toArray())
395
- );
396
-
397
- // Find the injected tool result events
398
- const toolResultEvents = allEvents.filter(
399
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_RESULT
400
- );
401
-
402
- expect(toolResultEvents).toHaveLength(1);
403
- expect(toolResultEvents[0]).toMatchObject({
404
- type: EventType.TOOL_CALL_RESULT,
405
- messageId: "tool-result-1",
406
- toolCallId: "tool-call-1",
407
- content: "72°F and sunny",
408
- role: "tool",
409
- });
410
- });
411
- });
412
-
413
- describe("Consecutive Runs with Different Messages", () => {
414
- it("should accumulate messages across multiple runs", async () => {
415
- const threadId = "test-thread-consecutive-1";
416
-
417
- // First run with a user message
418
- const userMessage1: Message = {
419
- id: "user-msg-1",
420
- role: "user",
421
- content: "What's the weather?",
422
- };
423
-
424
- const agent1 = new MessageAwareAgent([
425
- {
426
- type: EventType.CUSTOM,
427
- id: "agent-1-response",
428
- timestamp: Date.now(),
429
- name: "agent-response",
430
- value: { text: "Let me check..." },
431
- } as BaseEvent,
432
- ]);
433
-
434
- const input1: RunAgentInput = {
435
- messages: [userMessage1],
436
- state: {},
437
- threadId,
438
- runId: "run-1",
439
- tools: [],
440
- context: [],
441
- };
442
-
443
- await firstValueFrom(
444
- runner.run({ threadId, agent: agent1, input: input1 }).pipe(toArray())
445
- );
446
-
447
- // Second run with assistant and tool messages
448
- const assistantMessage: Message = {
449
- id: "assistant-msg-1",
450
- role: "assistant",
451
- content: "",
452
- toolCalls: [
453
- {
454
- id: "tool-call-1",
455
- type: "function",
456
- function: {
457
- name: "get_weather",
458
- arguments: '{"location": "current"}',
459
- },
460
- },
461
- ],
462
- };
463
-
464
- const toolResultMessage: Message = {
465
- id: "tool-result-1",
466
- role: "tool",
467
- content: "72°F and sunny in New York",
468
- toolCallId: "tool-call-1",
469
- };
470
-
471
- const agent2 = new MessageAwareAgent([
472
- {
473
- type: EventType.CUSTOM,
474
- id: "agent-2-response",
475
- timestamp: Date.now(),
476
- name: "agent-response",
477
- value: { text: "It's 72°F and sunny!" },
478
- } as BaseEvent,
479
- ]);
480
-
481
- const input2: RunAgentInput = {
482
- messages: [userMessage1, assistantMessage, toolResultMessage],
483
- state: {},
484
- threadId,
485
- runId: "run-2",
486
- tools: [],
487
- context: [],
488
- };
489
-
490
- await firstValueFrom(
491
- runner.run({ threadId, agent: agent2, input: input2 }).pipe(toArray())
492
- );
493
-
494
- // Connect should have all events from both runs
495
- const allEvents = await firstValueFrom(
496
- runner.connect({ threadId }).pipe(toArray())
497
- );
498
-
499
- // Should have events from both runs plus injected message events
500
- expect(allEvents.length).toBeGreaterThan(4);
501
-
502
- // Verify we have both agent responses
503
- const agentResponses = allEvents.filter(
504
- (e) => e.type === EventType.CUSTOM
505
- );
506
- expect(
507
- agentResponses.some((e) => (e as EventWithId).id === "agent-1-response")
508
- ).toBe(true);
509
- expect(
510
- agentResponses.some((e) => (e as EventWithId).id === "agent-2-response")
511
- ).toBe(true);
512
-
513
- // Verify we have the tool call events
514
- const toolCallStarts = allEvents.filter(
515
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_START
516
- );
517
- expect(toolCallStarts).toHaveLength(1);
518
-
519
- // Verify we have the tool result event
520
- const toolResults = allEvents.filter(
521
- (e) => (e as EventWithType).type === EventType.TOOL_CALL_RESULT
522
- );
523
- expect(toolResults).toHaveLength(1);
524
- });
525
-
526
- it("should track seen message IDs and not duplicate messages", async () => {
527
- const threadId = "test-thread-duplicate-1";
528
-
529
- const sharedMessage: Message = {
530
- id: "shared-msg-1",
531
- role: "assistant",
532
- content: "This message appears in both runs",
533
- };
534
-
535
- const newMessage: Message = {
536
- id: "new-msg-1",
537
- role: "assistant",
538
- content: "This is a new message",
539
- };
540
-
541
- // First run with shared message
542
- const agent1 = new MessageAwareAgent([]);
543
- const input1: RunAgentInput = {
544
- messages: [sharedMessage],
545
- state: {},
546
- threadId,
547
- runId: "run-1",
548
- tools: [],
549
- context: [],
550
- };
551
-
552
- await firstValueFrom(
553
- runner.run({ threadId, agent: agent1, input: input1 }).pipe(toArray())
554
- );
555
-
556
- // Second run with shared message and new message
557
- const agent2 = new MessageAwareAgent([]);
558
- const input2: RunAgentInput = {
559
- messages: [sharedMessage, newMessage],
560
- state: {},
561
- threadId,
562
- runId: "run-2",
563
- tools: [],
564
- context: [],
565
- };
566
-
567
- await firstValueFrom(
568
- runner.run({ threadId, agent: agent2, input: input2 }).pipe(toArray())
569
- );
570
-
571
- // Connect should have events without duplicates
572
- const allEvents = await firstValueFrom(
573
- runner.connect({ threadId }).pipe(toArray())
574
- );
575
-
576
- // Count TextMessageStart events for our messages
577
- const textStartEvents = allEvents.filter((e) => {
578
- const evt = e as EventWithType & { messageId?: string };
579
- return (
580
- evt.type === EventType.TEXT_MESSAGE_START &&
581
- (evt.messageId === "shared-msg-1" || evt.messageId === "new-msg-1")
582
- );
583
- });
584
-
585
- // Should have exactly 2 TextMessageStart events (one for each unique message)
586
- expect(textStartEvents).toHaveLength(2);
587
- expect(
588
- textStartEvents.some(
589
- (e) => (e as EventWithMessageId).messageId === "shared-msg-1"
590
- )
591
- ).toBe(true);
592
- expect(
593
- textStartEvents.some(
594
- (e) => (e as EventWithMessageId).messageId === "new-msg-1"
595
- )
596
- ).toBe(true);
597
- });
598
- });
599
- });