@copilotkitnext/runtime 0.0.1

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 (47) hide show
  1. package/.cursor/rules/runtime.always.mdc +9 -0
  2. package/.turbo/turbo-build.log +22 -0
  3. package/.turbo/turbo-check-types.log +4 -0
  4. package/.turbo/turbo-lint.log +56 -0
  5. package/.turbo/turbo-test$colon$coverage.log +149 -0
  6. package/.turbo/turbo-test.log +107 -0
  7. package/LICENSE +11 -0
  8. package/README-RUNNERS.md +78 -0
  9. package/dist/index.d.mts +245 -0
  10. package/dist/index.d.ts +245 -0
  11. package/dist/index.js +1873 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/index.mjs +1841 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/eslint.config.mjs +3 -0
  16. package/package.json +62 -0
  17. package/src/__tests__/get-runtime-info.test.ts +117 -0
  18. package/src/__tests__/handle-run.test.ts +69 -0
  19. package/src/__tests__/handle-transcribe.test.ts +289 -0
  20. package/src/__tests__/in-process-agent-runner-messages.test.ts +599 -0
  21. package/src/__tests__/in-process-agent-runner.test.ts +726 -0
  22. package/src/__tests__/middleware.test.ts +432 -0
  23. package/src/__tests__/routing.test.ts +257 -0
  24. package/src/endpoint.ts +150 -0
  25. package/src/handler.ts +3 -0
  26. package/src/handlers/get-runtime-info.ts +50 -0
  27. package/src/handlers/handle-connect.ts +144 -0
  28. package/src/handlers/handle-run.ts +156 -0
  29. package/src/handlers/handle-transcribe.ts +126 -0
  30. package/src/index.ts +8 -0
  31. package/src/middleware.ts +232 -0
  32. package/src/runner/__tests__/enterprise-runner.test.ts +992 -0
  33. package/src/runner/__tests__/event-compaction.test.ts +253 -0
  34. package/src/runner/__tests__/in-memory-runner.test.ts +483 -0
  35. package/src/runner/__tests__/sqlite-runner.test.ts +975 -0
  36. package/src/runner/agent-runner.ts +27 -0
  37. package/src/runner/enterprise.ts +653 -0
  38. package/src/runner/event-compaction.ts +250 -0
  39. package/src/runner/in-memory.ts +322 -0
  40. package/src/runner/index.ts +0 -0
  41. package/src/runner/sqlite.ts +481 -0
  42. package/src/runtime.ts +53 -0
  43. package/src/transcription-service/transcription-service-openai.ts +29 -0
  44. package/src/transcription-service/transcription-service.ts +11 -0
  45. package/tsconfig.json +13 -0
  46. package/tsup.config.ts +11 -0
  47. package/vitest.config.mjs +15 -0
@@ -0,0 +1,253 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { compactEvents } from "../event-compaction";
3
+ import { BaseEvent, EventType } from "@ag-ui/client";
4
+
5
+ describe("Event Compaction", () => {
6
+ describe("Text Message Compaction", () => {
7
+ it("should compact multiple text message content events into one", () => {
8
+ const events: BaseEvent[] = [
9
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "user" },
10
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Hello" },
11
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: " " },
12
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "world" },
13
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg1" },
14
+ ];
15
+
16
+ const compacted = compactEvents(events);
17
+
18
+ expect(compacted).toHaveLength(3);
19
+ expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
20
+ expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
21
+ expect((compacted[1] as any).delta).toBe("Hello world");
22
+ expect(compacted[2].type).toBe(EventType.TEXT_MESSAGE_END);
23
+ });
24
+
25
+ it("should move interleaved events to after text message events", () => {
26
+ const events: BaseEvent[] = [
27
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "assistant" },
28
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Processing" },
29
+ { type: EventType.CUSTOM, id: "custom1", name: "thinking" },
30
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "..." },
31
+ { type: EventType.CUSTOM, id: "custom2", name: "done-thinking" },
32
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg1" },
33
+ ];
34
+
35
+ const compacted = compactEvents(events);
36
+
37
+ expect(compacted).toHaveLength(5);
38
+ // Text message events should come first
39
+ expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
40
+ expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
41
+ expect((compacted[1] as any).delta).toBe("Processing...");
42
+ expect(compacted[2].type).toBe(EventType.TEXT_MESSAGE_END);
43
+ // Other events should come after
44
+ expect(compacted[3].type).toBe(EventType.CUSTOM);
45
+ expect((compacted[3] as any).id).toBe("custom1");
46
+ expect(compacted[4].type).toBe(EventType.CUSTOM);
47
+ expect((compacted[4] as any).id).toBe("custom2");
48
+ });
49
+
50
+ it("should handle multiple messages independently", () => {
51
+ const events: BaseEvent[] = [
52
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "user" },
53
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Hi" },
54
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg1" },
55
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg2", role: "assistant" },
56
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg2", delta: "Hello" },
57
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg2", delta: " there" },
58
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg2" },
59
+ ];
60
+
61
+ const compacted = compactEvents(events);
62
+
63
+ expect(compacted).toHaveLength(6);
64
+ // First message
65
+ expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
66
+ expect((compacted[0] as any).messageId).toBe("msg1");
67
+ expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
68
+ expect((compacted[1] as any).delta).toBe("Hi");
69
+ expect(compacted[2].type).toBe(EventType.TEXT_MESSAGE_END);
70
+ // Second message
71
+ expect(compacted[3].type).toBe(EventType.TEXT_MESSAGE_START);
72
+ expect((compacted[3] as any).messageId).toBe("msg2");
73
+ expect(compacted[4].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
74
+ expect((compacted[4] as any).delta).toBe("Hello there");
75
+ expect(compacted[5].type).toBe(EventType.TEXT_MESSAGE_END);
76
+ });
77
+
78
+ it("should handle incomplete messages", () => {
79
+ const events: BaseEvent[] = [
80
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "user" },
81
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Incomplete" },
82
+ // No END event
83
+ ];
84
+
85
+ const compacted = compactEvents(events);
86
+
87
+ expect(compacted).toHaveLength(2);
88
+ expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
89
+ expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
90
+ expect((compacted[1] as any).delta).toBe("Incomplete");
91
+ });
92
+
93
+ it("should pass through non-text-message events unchanged", () => {
94
+ const events: BaseEvent[] = [
95
+ { type: EventType.CUSTOM, id: "custom1", name: "event1" },
96
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search" },
97
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
98
+ ];
99
+
100
+ const compacted = compactEvents(events);
101
+
102
+ expect(compacted).toEqual(events);
103
+ });
104
+
105
+ it("should handle empty content deltas", () => {
106
+ const events: BaseEvent[] = [
107
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "user" },
108
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "" },
109
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Hello" },
110
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "" },
111
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg1" },
112
+ ];
113
+
114
+ const compacted = compactEvents(events);
115
+
116
+ expect(compacted).toHaveLength(3);
117
+ expect((compacted[1] as any).delta).toBe("Hello");
118
+ });
119
+ });
120
+
121
+ describe("Tool Call Compaction", () => {
122
+ it("should compact multiple tool call args events into one", () => {
123
+ const events: BaseEvent[] = [
124
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search", parentMessageId: "msg1" },
125
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"query": "' },
126
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: 'weather' },
127
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: ' today"' },
128
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '}' },
129
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
130
+ ];
131
+
132
+ const compacted = compactEvents(events);
133
+
134
+ expect(compacted).toHaveLength(3);
135
+ expect(compacted[0].type).toBe(EventType.TOOL_CALL_START);
136
+ expect(compacted[1].type).toBe(EventType.TOOL_CALL_ARGS);
137
+ expect((compacted[1] as any).delta).toBe('{"query": "weather today"}');
138
+ expect(compacted[2].type).toBe(EventType.TOOL_CALL_END);
139
+ });
140
+
141
+ it("should move interleaved events to after tool call events", () => {
142
+ const events: BaseEvent[] = [
143
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "calculate", parentMessageId: "msg1" },
144
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"a": ' },
145
+ { type: EventType.CUSTOM, id: "custom1", name: "processing" },
146
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '10, "b": 20}' },
147
+ { type: EventType.CUSTOM, id: "custom2", name: "calculating" },
148
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
149
+ ];
150
+
151
+ const compacted = compactEvents(events);
152
+
153
+ expect(compacted).toHaveLength(5);
154
+ // Tool call events should come first
155
+ expect(compacted[0].type).toBe(EventType.TOOL_CALL_START);
156
+ expect(compacted[1].type).toBe(EventType.TOOL_CALL_ARGS);
157
+ expect((compacted[1] as any).delta).toBe('{"a": 10, "b": 20}');
158
+ expect(compacted[2].type).toBe(EventType.TOOL_CALL_END);
159
+ // Other events should come after
160
+ expect(compacted[3].type).toBe(EventType.CUSTOM);
161
+ expect((compacted[3] as any).id).toBe("custom1");
162
+ expect(compacted[4].type).toBe(EventType.CUSTOM);
163
+ expect((compacted[4] as any).id).toBe("custom2");
164
+ });
165
+
166
+ it("should handle multiple tool calls independently", () => {
167
+ const events: BaseEvent[] = [
168
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search", parentMessageId: "msg1" },
169
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"query": "test"}' },
170
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
171
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool2", toolCallName: "calculate", parentMessageId: "msg1" },
172
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool2", delta: '{"a": ' },
173
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool2", delta: '5}' },
174
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool2" },
175
+ ];
176
+
177
+ const compacted = compactEvents(events);
178
+
179
+ expect(compacted).toHaveLength(6);
180
+ // First tool call
181
+ expect(compacted[0].type).toBe(EventType.TOOL_CALL_START);
182
+ expect((compacted[0] as any).toolCallId).toBe("tool1");
183
+ expect(compacted[1].type).toBe(EventType.TOOL_CALL_ARGS);
184
+ expect((compacted[1] as any).delta).toBe('{"query": "test"}');
185
+ expect(compacted[2].type).toBe(EventType.TOOL_CALL_END);
186
+ // Second tool call
187
+ expect(compacted[3].type).toBe(EventType.TOOL_CALL_START);
188
+ expect((compacted[3] as any).toolCallId).toBe("tool2");
189
+ expect(compacted[4].type).toBe(EventType.TOOL_CALL_ARGS);
190
+ expect((compacted[4] as any).delta).toBe('{"a": 5}');
191
+ expect(compacted[5].type).toBe(EventType.TOOL_CALL_END);
192
+ });
193
+
194
+ it("should handle incomplete tool calls", () => {
195
+ const events: BaseEvent[] = [
196
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search", parentMessageId: "msg1" },
197
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"incomplete": ' },
198
+ // No END event
199
+ ];
200
+
201
+ const compacted = compactEvents(events);
202
+
203
+ expect(compacted).toHaveLength(2);
204
+ expect(compacted[0].type).toBe(EventType.TOOL_CALL_START);
205
+ expect(compacted[1].type).toBe(EventType.TOOL_CALL_ARGS);
206
+ expect((compacted[1] as any).delta).toBe('{"incomplete": ');
207
+ });
208
+
209
+ it("should handle empty args deltas", () => {
210
+ const events: BaseEvent[] = [
211
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search", parentMessageId: "msg1" },
212
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: "" },
213
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"test": true}' },
214
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: "" },
215
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
216
+ ];
217
+
218
+ const compacted = compactEvents(events);
219
+
220
+ expect(compacted).toHaveLength(3);
221
+ expect((compacted[1] as any).delta).toBe('{"test": true}');
222
+ });
223
+ });
224
+
225
+ describe("Mixed Compaction", () => {
226
+ it("should handle text messages and tool calls together", () => {
227
+ const events: BaseEvent[] = [
228
+ { type: EventType.TEXT_MESSAGE_START, messageId: "msg1", role: "assistant" },
229
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "Let me " },
230
+ { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg1", delta: "search for that" },
231
+ { type: EventType.TEXT_MESSAGE_END, messageId: "msg1" },
232
+ { type: EventType.TOOL_CALL_START, toolCallId: "tool1", toolCallName: "search", parentMessageId: "msg1" },
233
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: '{"q": "' },
234
+ { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool1", delta: 'test"}' },
235
+ { type: EventType.TOOL_CALL_END, toolCallId: "tool1" },
236
+ ];
237
+
238
+ const compacted = compactEvents(events);
239
+
240
+ expect(compacted).toHaveLength(6);
241
+ // Text message
242
+ expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
243
+ expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
244
+ expect((compacted[1] as any).delta).toBe("Let me search for that");
245
+ expect(compacted[2].type).toBe(EventType.TEXT_MESSAGE_END);
246
+ // Tool call
247
+ expect(compacted[3].type).toBe(EventType.TOOL_CALL_START);
248
+ expect(compacted[4].type).toBe(EventType.TOOL_CALL_ARGS);
249
+ expect((compacted[4] as any).delta).toBe('{"q": "test"}');
250
+ expect(compacted[5].type).toBe(EventType.TOOL_CALL_END);
251
+ });
252
+ });
253
+ });