@copilotkitnext/runtime 0.0.14 → 0.0.16

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.js CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,23 +15,14 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
31
21
  var index_exports = {};
32
22
  __export(index_exports, {
23
+ AgentRunner: () => AgentRunner,
33
24
  CopilotRuntime: () => CopilotRuntime,
34
- EnterpriseAgentRunner: () => EnterpriseAgentRunner,
35
25
  InMemoryAgentRunner: () => InMemoryAgentRunner,
36
- SqliteAgentRunner: () => SqliteAgentRunner,
37
26
  VERSION: () => VERSION,
38
27
  createCopilotEndpoint: () => createCopilotEndpoint
39
28
  });
@@ -42,7 +31,7 @@ module.exports = __toCommonJS(index_exports);
42
31
  // package.json
43
32
  var package_default = {
44
33
  name: "@copilotkitnext/runtime",
45
- version: "0.0.14",
34
+ version: "0.0.16",
46
35
  description: "Server-side runtime package for CopilotKit2",
47
36
  main: "dist/index.js",
48
37
  types: "dist/index.d.ts",
@@ -70,35 +59,25 @@ var package_default = {
70
59
  devDependencies: {
71
60
  "@copilotkitnext/eslint-config": "workspace:*",
72
61
  "@copilotkitnext/typescript-config": "workspace:*",
73
- "@types/better-sqlite3": "^7.6.13",
74
62
  "@types/node": "^22.15.3",
75
- "better-sqlite3": "^12.2.0",
76
63
  eslint: "^9.30.0",
77
- "ioredis-mock": "^8.9.0",
78
64
  openai: "^5.9.0",
79
65
  tsup: "^8.5.0",
80
66
  typescript: "5.8.2",
81
67
  vitest: "^3.0.5"
82
68
  },
83
69
  dependencies: {
84
- "@ag-ui/client": "0.0.40-alpha.3",
85
- "@ag-ui/core": "0.0.40-alpha.3",
86
- "@ag-ui/encoder": "0.0.40-alpha.3",
70
+ "@ag-ui/client": "0.0.40-alpha.6",
71
+ "@ag-ui/core": "0.0.40-alpha.6",
72
+ "@ag-ui/encoder": "0.0.40-alpha.6",
87
73
  "@copilotkitnext/shared": "workspace:*",
88
74
  hono: "^4.6.13",
89
- ioredis: "^5.7.0",
90
- kysely: "^0.28.5",
91
75
  rxjs: "7.8.1"
92
76
  },
93
77
  peerDependencies: {
94
- "better-sqlite3": "^12.2.0",
95
78
  openai: "^5.9.0"
96
79
  },
97
- peerDependenciesMeta: {
98
- "better-sqlite3": {
99
- optional: true
100
- }
101
- },
80
+ peerDependenciesMeta: {},
102
81
  engines: {
103
82
  node: ">=18"
104
83
  }
@@ -110,158 +89,7 @@ var AgentRunner = class {
110
89
 
111
90
  // src/runner/in-memory.ts
112
91
  var import_rxjs = require("rxjs");
113
- var import_client2 = require("@ag-ui/client");
114
-
115
- // src/runner/event-compaction.ts
116
92
  var import_client = require("@ag-ui/client");
117
- function compactEvents(events) {
118
- const compacted = [];
119
- const pendingTextMessages = /* @__PURE__ */ new Map();
120
- const pendingToolCalls = /* @__PURE__ */ new Map();
121
- for (const event of events) {
122
- if (event.type === import_client.EventType.TEXT_MESSAGE_START) {
123
- const startEvent = event;
124
- const messageId = startEvent.messageId;
125
- if (!pendingTextMessages.has(messageId)) {
126
- pendingTextMessages.set(messageId, {
127
- contents: [],
128
- otherEvents: []
129
- });
130
- }
131
- const pending = pendingTextMessages.get(messageId);
132
- pending.start = startEvent;
133
- } else if (event.type === import_client.EventType.TEXT_MESSAGE_CONTENT) {
134
- const contentEvent = event;
135
- const messageId = contentEvent.messageId;
136
- if (!pendingTextMessages.has(messageId)) {
137
- pendingTextMessages.set(messageId, {
138
- contents: [],
139
- otherEvents: []
140
- });
141
- }
142
- const pending = pendingTextMessages.get(messageId);
143
- pending.contents.push(contentEvent);
144
- } else if (event.type === import_client.EventType.TEXT_MESSAGE_END) {
145
- const endEvent = event;
146
- const messageId = endEvent.messageId;
147
- if (!pendingTextMessages.has(messageId)) {
148
- pendingTextMessages.set(messageId, {
149
- contents: [],
150
- otherEvents: []
151
- });
152
- }
153
- const pending = pendingTextMessages.get(messageId);
154
- pending.end = endEvent;
155
- flushTextMessage(messageId, pending, compacted);
156
- pendingTextMessages.delete(messageId);
157
- } else if (event.type === import_client.EventType.TOOL_CALL_START) {
158
- const startEvent = event;
159
- const toolCallId = startEvent.toolCallId;
160
- if (!pendingToolCalls.has(toolCallId)) {
161
- pendingToolCalls.set(toolCallId, {
162
- args: [],
163
- otherEvents: []
164
- });
165
- }
166
- const pending = pendingToolCalls.get(toolCallId);
167
- pending.start = startEvent;
168
- } else if (event.type === import_client.EventType.TOOL_CALL_ARGS) {
169
- const argsEvent = event;
170
- const toolCallId = argsEvent.toolCallId;
171
- if (!pendingToolCalls.has(toolCallId)) {
172
- pendingToolCalls.set(toolCallId, {
173
- args: [],
174
- otherEvents: []
175
- });
176
- }
177
- const pending = pendingToolCalls.get(toolCallId);
178
- pending.args.push(argsEvent);
179
- } else if (event.type === import_client.EventType.TOOL_CALL_END) {
180
- const endEvent = event;
181
- const toolCallId = endEvent.toolCallId;
182
- if (!pendingToolCalls.has(toolCallId)) {
183
- pendingToolCalls.set(toolCallId, {
184
- args: [],
185
- otherEvents: []
186
- });
187
- }
188
- const pending = pendingToolCalls.get(toolCallId);
189
- pending.end = endEvent;
190
- flushToolCall(toolCallId, pending, compacted);
191
- pendingToolCalls.delete(toolCallId);
192
- } else {
193
- let addedToBuffer = false;
194
- for (const [messageId, pending] of pendingTextMessages) {
195
- if (pending.start && !pending.end) {
196
- pending.otherEvents.push(event);
197
- addedToBuffer = true;
198
- break;
199
- }
200
- }
201
- if (!addedToBuffer) {
202
- for (const [toolCallId, pending] of pendingToolCalls) {
203
- if (pending.start && !pending.end) {
204
- pending.otherEvents.push(event);
205
- addedToBuffer = true;
206
- break;
207
- }
208
- }
209
- }
210
- if (!addedToBuffer) {
211
- compacted.push(event);
212
- }
213
- }
214
- }
215
- for (const [messageId, pending] of pendingTextMessages) {
216
- flushTextMessage(messageId, pending, compacted);
217
- }
218
- for (const [toolCallId, pending] of pendingToolCalls) {
219
- flushToolCall(toolCallId, pending, compacted);
220
- }
221
- return compacted;
222
- }
223
- function flushTextMessage(messageId, pending, compacted) {
224
- if (pending.start) {
225
- compacted.push(pending.start);
226
- }
227
- if (pending.contents.length > 0) {
228
- const concatenatedDelta = pending.contents.map((c) => c.delta).join("");
229
- const compactedContent = {
230
- type: import_client.EventType.TEXT_MESSAGE_CONTENT,
231
- messageId,
232
- delta: concatenatedDelta
233
- };
234
- compacted.push(compactedContent);
235
- }
236
- if (pending.end) {
237
- compacted.push(pending.end);
238
- }
239
- for (const otherEvent of pending.otherEvents) {
240
- compacted.push(otherEvent);
241
- }
242
- }
243
- function flushToolCall(toolCallId, pending, compacted) {
244
- if (pending.start) {
245
- compacted.push(pending.start);
246
- }
247
- if (pending.args.length > 0) {
248
- const concatenatedArgs = pending.args.map((a) => a.delta).join("");
249
- const compactedArgs = {
250
- type: import_client.EventType.TOOL_CALL_ARGS,
251
- toolCallId,
252
- delta: concatenatedArgs
253
- };
254
- compacted.push(compactedArgs);
255
- }
256
- if (pending.end) {
257
- compacted.push(pending.end);
258
- }
259
- for (const otherEvent of pending.otherEvents) {
260
- compacted.push(otherEvent);
261
- }
262
- }
263
-
264
- // src/runner/in-memory.ts
265
93
  var InMemoryEventStore = class {
266
94
  constructor(threadId) {
267
95
  this.threadId = threadId;
@@ -279,61 +107,6 @@ var InMemoryEventStore = class {
279
107
  };
280
108
  var GLOBAL_STORE = /* @__PURE__ */ new Map();
281
109
  var InMemoryAgentRunner = class extends AgentRunner {
282
- convertMessageToEvents(message) {
283
- const events = [];
284
- if ((message.role === "assistant" || message.role === "user" || message.role === "developer" || message.role === "system") && message.content) {
285
- const textStartEvent = {
286
- type: import_client2.EventType.TEXT_MESSAGE_START,
287
- messageId: message.id,
288
- role: message.role
289
- };
290
- events.push(textStartEvent);
291
- const textContentEvent = {
292
- type: import_client2.EventType.TEXT_MESSAGE_CONTENT,
293
- messageId: message.id,
294
- delta: message.content
295
- };
296
- events.push(textContentEvent);
297
- const textEndEvent = {
298
- type: import_client2.EventType.TEXT_MESSAGE_END,
299
- messageId: message.id
300
- };
301
- events.push(textEndEvent);
302
- }
303
- if (message.role === "assistant" && message.toolCalls) {
304
- for (const toolCall of message.toolCalls) {
305
- const toolStartEvent = {
306
- type: import_client2.EventType.TOOL_CALL_START,
307
- toolCallId: toolCall.id,
308
- toolCallName: toolCall.function.name,
309
- parentMessageId: message.id
310
- };
311
- events.push(toolStartEvent);
312
- const toolArgsEvent = {
313
- type: import_client2.EventType.TOOL_CALL_ARGS,
314
- toolCallId: toolCall.id,
315
- delta: toolCall.function.arguments
316
- };
317
- events.push(toolArgsEvent);
318
- const toolEndEvent = {
319
- type: import_client2.EventType.TOOL_CALL_END,
320
- toolCallId: toolCall.id
321
- };
322
- events.push(toolEndEvent);
323
- }
324
- }
325
- if (message.role === "tool" && message.toolCallId) {
326
- const toolResultEvent = {
327
- type: import_client2.EventType.TOOL_CALL_RESULT,
328
- messageId: message.id,
329
- toolCallId: message.toolCallId,
330
- content: message.content,
331
- role: "tool"
332
- };
333
- events.push(toolResultEvent);
334
- }
335
- return events;
336
- }
337
110
  run(request) {
338
111
  let existingStore = GLOBAL_STORE.get(request.threadId);
339
112
  if (!existingStore) {
@@ -354,6 +127,13 @@ var InMemoryAgentRunner = class extends AgentRunner {
354
127
  if ("messageId" in event && typeof event.messageId === "string") {
355
128
  historicMessageIds.add(event.messageId);
356
129
  }
130
+ if (event.type === import_client.EventType.RUN_STARTED) {
131
+ const runStarted = event;
132
+ const messages = runStarted.input?.messages ?? [];
133
+ for (const message of messages) {
134
+ historicMessageIds.add(message.id);
135
+ }
136
+ }
357
137
  }
358
138
  }
359
139
  const nextSubject = new import_rxjs.ReplaySubject(Infinity);
@@ -367,9 +147,26 @@ var InMemoryAgentRunner = class extends AgentRunner {
367
147
  try {
368
148
  await request.agent.runAgent(request.input, {
369
149
  onEvent: ({ event }) => {
370
- runSubject.next(event);
371
- nextSubject.next(event);
372
- currentRunEvents.push(event);
150
+ let processedEvent = event;
151
+ if (event.type === import_client.EventType.RUN_STARTED) {
152
+ const runStartedEvent = event;
153
+ if (!runStartedEvent.input) {
154
+ const sanitizedMessages = request.input.messages ? request.input.messages.filter(
155
+ (message) => !historicMessageIds.has(message.id)
156
+ ) : void 0;
157
+ const updatedInput = {
158
+ ...request.input,
159
+ ...sanitizedMessages !== void 0 ? { messages: sanitizedMessages } : {}
160
+ };
161
+ processedEvent = {
162
+ ...runStartedEvent,
163
+ input: updatedInput
164
+ };
165
+ }
166
+ }
167
+ runSubject.next(processedEvent);
168
+ nextSubject.next(processedEvent);
169
+ currentRunEvents.push(processedEvent);
373
170
  },
374
171
  onNewMessage: ({ message }) => {
375
172
  if (!seenMessageIds.has(message.id)) {
@@ -381,21 +178,13 @@ var InMemoryAgentRunner = class extends AgentRunner {
381
178
  for (const message of request.input.messages) {
382
179
  if (!seenMessageIds.has(message.id)) {
383
180
  seenMessageIds.add(message.id);
384
- const events = this.convertMessageToEvents(message);
385
- const isNewMessage = !historicMessageIds.has(message.id);
386
- for (const event of events) {
387
- nextSubject.next(event);
388
- if (isNewMessage) {
389
- currentRunEvents.push(event);
390
- }
391
- }
392
181
  }
393
182
  }
394
183
  }
395
184
  }
396
185
  });
397
186
  if (store.currentRunId) {
398
- const compactedEvents = compactEvents(currentRunEvents);
187
+ const compactedEvents = (0, import_client.compactEvents)(currentRunEvents);
399
188
  store.historicRuns.push({
400
189
  threadId: request.threadId,
401
190
  runId: store.currentRunId,
@@ -410,7 +199,7 @@ var InMemoryAgentRunner = class extends AgentRunner {
410
199
  nextSubject.complete();
411
200
  } catch {
412
201
  if (store.currentRunId && currentRunEvents.length > 0) {
413
- const compactedEvents = compactEvents(currentRunEvents);
202
+ const compactedEvents = (0, import_client.compactEvents)(currentRunEvents);
414
203
  store.historicRuns.push({
415
204
  threadId: request.threadId,
416
205
  runId: store.currentRunId,
@@ -447,7 +236,7 @@ var InMemoryAgentRunner = class extends AgentRunner {
447
236
  for (const run of store.historicRuns) {
448
237
  allHistoricEvents.push(...run.events);
449
238
  }
450
- const compactedEvents = compactEvents(allHistoricEvents);
239
+ const compactedEvents = (0, import_client.compactEvents)(allHistoricEvents);
451
240
  const emittedMessageIds = /* @__PURE__ */ new Set();
452
241
  for (const event of compactedEvents) {
453
242
  connectionSubject.next(event);
@@ -509,7 +298,7 @@ var import_hono = require("hono");
509
298
  var import_cors = require("hono/cors");
510
299
 
511
300
  // src/handlers/handle-run.ts
512
- var import_client3 = require("@ag-ui/client");
301
+ var import_client2 = require("@ag-ui/client");
513
302
  var import_encoder = require("@ag-ui/encoder");
514
303
  async function handleRunAgent({
515
304
  runtime,
@@ -556,7 +345,7 @@ async function handleRunAgent({
556
345
  let input;
557
346
  try {
558
347
  const requestBody = await request.json();
559
- input = import_client3.RunAgentInputSchema.parse(requestBody);
348
+ input = import_client2.RunAgentInputSchema.parse(requestBody);
560
349
  } catch {
561
350
  return new Response(
562
351
  JSON.stringify({
@@ -938,7 +727,7 @@ async function callAfterRequestMiddleware({
938
727
  }
939
728
 
940
729
  // src/handlers/handle-connect.ts
941
- var import_client4 = require("@ag-ui/client");
730
+ var import_client3 = require("@ag-ui/client");
942
731
  var import_encoder2 = require("@ag-ui/encoder");
943
732
  async function handleConnectAgent({
944
733
  runtime,
@@ -967,7 +756,7 @@ async function handleConnectAgent({
967
756
  let input;
968
757
  try {
969
758
  const requestBody = await request.json();
970
- input = import_client4.RunAgentInputSchema.parse(requestBody);
759
+ input = import_client3.RunAgentInputSchema.parse(requestBody);
971
760
  } catch {
972
761
  return new Response(
973
762
  JSON.stringify({
@@ -1175,723 +964,11 @@ function createCopilotEndpoint({
1175
964
  return c.json({ error: "Not found" }, 404);
1176
965
  });
1177
966
  }
1178
-
1179
- // src/runner/sqlite.ts
1180
- var import_rxjs2 = require("rxjs");
1181
- var import_client5 = require("@ag-ui/client");
1182
- var import_better_sqlite3 = __toESM(require("better-sqlite3"));
1183
- var SCHEMA_VERSION = 1;
1184
- var ACTIVE_CONNECTIONS = /* @__PURE__ */ new Map();
1185
- var SqliteAgentRunner = class extends AgentRunner {
1186
- db;
1187
- constructor(options = {}) {
1188
- super();
1189
- const dbPath = options.dbPath ?? ":memory:";
1190
- if (!import_better_sqlite3.default) {
1191
- throw new Error(
1192
- "better-sqlite3 is required for SqliteAgentRunner but was not found.\nPlease install it in your project:\n npm install better-sqlite3\n or\n pnpm add better-sqlite3\n or\n yarn add better-sqlite3\n\nIf you don't need persistence, use InMemoryAgentRunner instead."
1193
- );
1194
- }
1195
- this.db = new import_better_sqlite3.default(dbPath);
1196
- this.initializeSchema();
1197
- }
1198
- convertMessageToEvents(message) {
1199
- const events = [];
1200
- if ((message.role === "assistant" || message.role === "user" || message.role === "developer" || message.role === "system") && message.content) {
1201
- const textStartEvent = {
1202
- type: import_client5.EventType.TEXT_MESSAGE_START,
1203
- messageId: message.id,
1204
- role: message.role
1205
- };
1206
- events.push(textStartEvent);
1207
- const textContentEvent = {
1208
- type: import_client5.EventType.TEXT_MESSAGE_CONTENT,
1209
- messageId: message.id,
1210
- delta: message.content
1211
- };
1212
- events.push(textContentEvent);
1213
- const textEndEvent = {
1214
- type: import_client5.EventType.TEXT_MESSAGE_END,
1215
- messageId: message.id
1216
- };
1217
- events.push(textEndEvent);
1218
- }
1219
- if (message.role === "assistant" && message.toolCalls) {
1220
- for (const toolCall of message.toolCalls) {
1221
- const toolStartEvent = {
1222
- type: import_client5.EventType.TOOL_CALL_START,
1223
- toolCallId: toolCall.id,
1224
- toolCallName: toolCall.function.name,
1225
- parentMessageId: message.id
1226
- };
1227
- events.push(toolStartEvent);
1228
- const toolArgsEvent = {
1229
- type: import_client5.EventType.TOOL_CALL_ARGS,
1230
- toolCallId: toolCall.id,
1231
- delta: toolCall.function.arguments
1232
- };
1233
- events.push(toolArgsEvent);
1234
- const toolEndEvent = {
1235
- type: import_client5.EventType.TOOL_CALL_END,
1236
- toolCallId: toolCall.id
1237
- };
1238
- events.push(toolEndEvent);
1239
- }
1240
- }
1241
- if (message.role === "tool" && message.toolCallId) {
1242
- const toolResultEvent = {
1243
- type: import_client5.EventType.TOOL_CALL_RESULT,
1244
- messageId: message.id,
1245
- toolCallId: message.toolCallId,
1246
- content: message.content,
1247
- role: "tool"
1248
- };
1249
- events.push(toolResultEvent);
1250
- }
1251
- return events;
1252
- }
1253
- initializeSchema() {
1254
- this.db.exec(`
1255
- CREATE TABLE IF NOT EXISTS agent_runs (
1256
- id INTEGER PRIMARY KEY AUTOINCREMENT,
1257
- thread_id TEXT NOT NULL,
1258
- run_id TEXT NOT NULL UNIQUE,
1259
- parent_run_id TEXT,
1260
- events TEXT NOT NULL,
1261
- input TEXT NOT NULL,
1262
- created_at INTEGER NOT NULL,
1263
- version INTEGER NOT NULL
1264
- )
1265
- `);
1266
- this.db.exec(`
1267
- CREATE TABLE IF NOT EXISTS run_state (
1268
- thread_id TEXT PRIMARY KEY,
1269
- is_running INTEGER DEFAULT 0,
1270
- current_run_id TEXT,
1271
- updated_at INTEGER NOT NULL
1272
- )
1273
- `);
1274
- this.db.exec(`
1275
- CREATE INDEX IF NOT EXISTS idx_thread_id ON agent_runs(thread_id);
1276
- CREATE INDEX IF NOT EXISTS idx_parent_run_id ON agent_runs(parent_run_id);
1277
- `);
1278
- this.db.exec(`
1279
- CREATE TABLE IF NOT EXISTS schema_version (
1280
- version INTEGER PRIMARY KEY,
1281
- applied_at INTEGER NOT NULL
1282
- )
1283
- `);
1284
- const currentVersion = this.db.prepare("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1").get();
1285
- if (!currentVersion || currentVersion.version < SCHEMA_VERSION) {
1286
- this.db.prepare("INSERT OR REPLACE INTO schema_version (version, applied_at) VALUES (?, ?)").run(SCHEMA_VERSION, Date.now());
1287
- }
1288
- }
1289
- storeRun(threadId, runId, events, input, parentRunId) {
1290
- const compactedEvents = compactEvents(events);
1291
- const stmt = this.db.prepare(`
1292
- INSERT INTO agent_runs (thread_id, run_id, parent_run_id, events, input, created_at, version)
1293
- VALUES (?, ?, ?, ?, ?, ?, ?)
1294
- `);
1295
- stmt.run(
1296
- threadId,
1297
- runId,
1298
- parentRunId ?? null,
1299
- JSON.stringify(compactedEvents),
1300
- // Store only this run's compacted events
1301
- JSON.stringify(input),
1302
- Date.now(),
1303
- SCHEMA_VERSION
1304
- );
1305
- }
1306
- getHistoricRuns(threadId) {
1307
- const stmt = this.db.prepare(`
1308
- WITH RECURSIVE run_chain AS (
1309
- -- Base case: find the root runs (those without parent)
1310
- SELECT * FROM agent_runs
1311
- WHERE thread_id = ? AND parent_run_id IS NULL
1312
-
1313
- UNION ALL
1314
-
1315
- -- Recursive case: find children of current level
1316
- SELECT ar.* FROM agent_runs ar
1317
- INNER JOIN run_chain rc ON ar.parent_run_id = rc.run_id
1318
- WHERE ar.thread_id = ?
1319
- )
1320
- SELECT * FROM run_chain
1321
- ORDER BY created_at ASC
1322
- `);
1323
- const rows = stmt.all(threadId, threadId);
1324
- return rows.map((row) => ({
1325
- id: row.id,
1326
- thread_id: row.thread_id,
1327
- run_id: row.run_id,
1328
- parent_run_id: row.parent_run_id,
1329
- events: JSON.parse(row.events),
1330
- input: JSON.parse(row.input),
1331
- created_at: row.created_at,
1332
- version: row.version
1333
- }));
1334
- }
1335
- getLatestRunId(threadId) {
1336
- const stmt = this.db.prepare(`
1337
- SELECT run_id FROM agent_runs
1338
- WHERE thread_id = ?
1339
- ORDER BY created_at DESC
1340
- LIMIT 1
1341
- `);
1342
- const result = stmt.get(threadId);
1343
- return result?.run_id ?? null;
1344
- }
1345
- setRunState(threadId, isRunning, runId) {
1346
- const stmt = this.db.prepare(`
1347
- INSERT OR REPLACE INTO run_state (thread_id, is_running, current_run_id, updated_at)
1348
- VALUES (?, ?, ?, ?)
1349
- `);
1350
- stmt.run(threadId, isRunning ? 1 : 0, runId ?? null, Date.now());
1351
- }
1352
- getRunState(threadId) {
1353
- const stmt = this.db.prepare(`
1354
- SELECT is_running, current_run_id FROM run_state WHERE thread_id = ?
1355
- `);
1356
- const result = stmt.get(threadId);
1357
- return {
1358
- isRunning: result?.is_running === 1,
1359
- currentRunId: result?.current_run_id ?? null
1360
- };
1361
- }
1362
- run(request) {
1363
- const runState = this.getRunState(request.threadId);
1364
- if (runState.isRunning) {
1365
- throw new Error("Thread already running");
1366
- }
1367
- this.setRunState(request.threadId, true, request.input.runId);
1368
- const seenMessageIds = /* @__PURE__ */ new Set();
1369
- const currentRunEvents = [];
1370
- const historicRuns = this.getHistoricRuns(request.threadId);
1371
- const historicMessageIds = /* @__PURE__ */ new Set();
1372
- for (const run of historicRuns) {
1373
- for (const event of run.events) {
1374
- if ("messageId" in event && typeof event.messageId === "string") {
1375
- historicMessageIds.add(event.messageId);
1376
- }
1377
- }
1378
- }
1379
- const nextSubject = new import_rxjs2.ReplaySubject(Infinity);
1380
- const prevSubject = ACTIVE_CONNECTIONS.get(request.threadId);
1381
- ACTIVE_CONNECTIONS.set(request.threadId, nextSubject);
1382
- const runSubject = new import_rxjs2.ReplaySubject(Infinity);
1383
- const runAgent = async () => {
1384
- const parentRunId = this.getLatestRunId(request.threadId);
1385
- try {
1386
- await request.agent.runAgent(request.input, {
1387
- onEvent: ({ event }) => {
1388
- runSubject.next(event);
1389
- nextSubject.next(event);
1390
- currentRunEvents.push(event);
1391
- },
1392
- onNewMessage: ({ message }) => {
1393
- if (!seenMessageIds.has(message.id)) {
1394
- seenMessageIds.add(message.id);
1395
- }
1396
- },
1397
- onRunStartedEvent: () => {
1398
- if (request.input.messages) {
1399
- for (const message of request.input.messages) {
1400
- if (!seenMessageIds.has(message.id)) {
1401
- seenMessageIds.add(message.id);
1402
- const events = this.convertMessageToEvents(message);
1403
- const isNewMessage = !historicMessageIds.has(message.id);
1404
- for (const event of events) {
1405
- nextSubject.next(event);
1406
- if (isNewMessage) {
1407
- currentRunEvents.push(event);
1408
- }
1409
- }
1410
- }
1411
- }
1412
- }
1413
- }
1414
- });
1415
- this.storeRun(
1416
- request.threadId,
1417
- request.input.runId,
1418
- currentRunEvents,
1419
- request.input,
1420
- parentRunId
1421
- );
1422
- this.setRunState(request.threadId, false);
1423
- runSubject.complete();
1424
- nextSubject.complete();
1425
- } catch {
1426
- if (currentRunEvents.length > 0) {
1427
- this.storeRun(
1428
- request.threadId,
1429
- request.input.runId,
1430
- currentRunEvents,
1431
- request.input,
1432
- parentRunId
1433
- );
1434
- }
1435
- this.setRunState(request.threadId, false);
1436
- runSubject.complete();
1437
- nextSubject.complete();
1438
- }
1439
- };
1440
- if (prevSubject) {
1441
- prevSubject.subscribe({
1442
- next: (e) => nextSubject.next(e),
1443
- error: (err) => nextSubject.error(err),
1444
- complete: () => {
1445
- }
1446
- });
1447
- }
1448
- runAgent();
1449
- return runSubject.asObservable();
1450
- }
1451
- connect(request) {
1452
- const connectionSubject = new import_rxjs2.ReplaySubject(Infinity);
1453
- const historicRuns = this.getHistoricRuns(request.threadId);
1454
- const allHistoricEvents = [];
1455
- for (const run of historicRuns) {
1456
- allHistoricEvents.push(...run.events);
1457
- }
1458
- const compactedEvents = compactEvents(allHistoricEvents);
1459
- const emittedMessageIds = /* @__PURE__ */ new Set();
1460
- for (const event of compactedEvents) {
1461
- connectionSubject.next(event);
1462
- if ("messageId" in event && typeof event.messageId === "string") {
1463
- emittedMessageIds.add(event.messageId);
1464
- }
1465
- }
1466
- const activeSubject = ACTIVE_CONNECTIONS.get(request.threadId);
1467
- const runState = this.getRunState(request.threadId);
1468
- if (activeSubject && runState.isRunning) {
1469
- activeSubject.subscribe({
1470
- next: (event) => {
1471
- if ("messageId" in event && typeof event.messageId === "string" && emittedMessageIds.has(event.messageId)) {
1472
- return;
1473
- }
1474
- connectionSubject.next(event);
1475
- },
1476
- complete: () => connectionSubject.complete(),
1477
- error: (err) => connectionSubject.error(err)
1478
- });
1479
- } else {
1480
- connectionSubject.complete();
1481
- }
1482
- return connectionSubject.asObservable();
1483
- }
1484
- isRunning(request) {
1485
- const runState = this.getRunState(request.threadId);
1486
- return Promise.resolve(runState.isRunning);
1487
- }
1488
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1489
- stop(_request) {
1490
- throw new Error("Method not implemented.");
1491
- }
1492
- /**
1493
- * Close the database connection (for cleanup)
1494
- */
1495
- close() {
1496
- if (this.db) {
1497
- this.db.close();
1498
- }
1499
- }
1500
- };
1501
-
1502
- // src/runner/enterprise.ts
1503
- var import_rxjs3 = require("rxjs");
1504
- var import_client6 = require("@ag-ui/client");
1505
- var SCHEMA_VERSION2 = 1;
1506
- var redisKeys = {
1507
- stream: (threadId, runId) => `stream:${threadId}:${runId}`,
1508
- active: (threadId) => `active:${threadId}`,
1509
- lock: (threadId) => `lock:${threadId}`
1510
- };
1511
- var EnterpriseAgentRunner = class extends AgentRunner {
1512
- db;
1513
- redis;
1514
- redisSub;
1515
- serverId;
1516
- streamRetentionMs;
1517
- streamActiveTTLMs;
1518
- lockTTLMs;
1519
- constructor(options) {
1520
- super();
1521
- this.db = options.kysely;
1522
- this.redis = options.redis;
1523
- this.redisSub = options.redisSub || options.redis.duplicate();
1524
- this.serverId = options.serverId || this.generateServerId();
1525
- this.streamRetentionMs = options.streamRetentionMs ?? 36e5;
1526
- this.streamActiveTTLMs = options.streamActiveTTLMs ?? 3e5;
1527
- this.lockTTLMs = options.lockTTLMs ?? 3e5;
1528
- this.initializeSchema();
1529
- }
1530
- run(request) {
1531
- const runSubject = new import_rxjs3.ReplaySubject(Infinity);
1532
- const executeRun = async () => {
1533
- const { threadId, input, agent } = request;
1534
- const runId = input.runId;
1535
- const streamKey = redisKeys.stream(threadId, runId);
1536
- const activeRunId = await this.redis.get(redisKeys.active(threadId));
1537
- if (activeRunId) {
1538
- throw new Error("Thread already running");
1539
- }
1540
- const lockAcquired = await this.redis.set(
1541
- redisKeys.lock(threadId),
1542
- this.serverId,
1543
- "PX",
1544
- this.lockTTLMs,
1545
- "NX"
1546
- );
1547
- if (!lockAcquired) {
1548
- throw new Error("Thread already running");
1549
- }
1550
- await this.redis.setex(
1551
- redisKeys.active(threadId),
1552
- Math.floor(this.lockTTLMs / 1e3),
1553
- runId
1554
- );
1555
- await this.setRunState(threadId, true, runId);
1556
- const currentRunEvents = [];
1557
- const seenMessageIds = /* @__PURE__ */ new Set();
1558
- const historicRuns = await this.getHistoricRuns(threadId);
1559
- const historicMessageIds = /* @__PURE__ */ new Set();
1560
- for (const run of historicRuns) {
1561
- const events = JSON.parse(run.events);
1562
- for (const event of events) {
1563
- if ("messageId" in event && typeof event.messageId === "string") {
1564
- historicMessageIds.add(event.messageId);
1565
- }
1566
- }
1567
- }
1568
- const parentRunId = historicRuns[historicRuns.length - 1]?.run_id ?? null;
1569
- try {
1570
- await agent.runAgent(input, {
1571
- onEvent: async ({ event }) => {
1572
- runSubject.next(event);
1573
- currentRunEvents.push(event);
1574
- await this.redis.xadd(
1575
- streamKey,
1576
- "MAXLEN",
1577
- "~",
1578
- "10000",
1579
- "*",
1580
- "type",
1581
- event.type,
1582
- "data",
1583
- JSON.stringify(event)
1584
- );
1585
- await this.redis.pexpire(streamKey, this.streamActiveTTLMs);
1586
- if (event.type === import_client6.EventType.RUN_FINISHED || event.type === import_client6.EventType.RUN_ERROR) {
1587
- await this.redis.pexpire(streamKey, this.streamRetentionMs);
1588
- }
1589
- },
1590
- onNewMessage: ({ message }) => {
1591
- if (!seenMessageIds.has(message.id)) {
1592
- seenMessageIds.add(message.id);
1593
- }
1594
- },
1595
- onRunStartedEvent: async () => {
1596
- if (input.messages) {
1597
- for (const message of input.messages) {
1598
- if (!seenMessageIds.has(message.id)) {
1599
- seenMessageIds.add(message.id);
1600
- const events = this.convertMessageToEvents(message);
1601
- const isNewMessage = !historicMessageIds.has(message.id);
1602
- for (const event of events) {
1603
- await this.redis.xadd(
1604
- streamKey,
1605
- "MAXLEN",
1606
- "~",
1607
- "10000",
1608
- "*",
1609
- "type",
1610
- event.type,
1611
- "data",
1612
- JSON.stringify(event)
1613
- );
1614
- if (isNewMessage) {
1615
- currentRunEvents.push(event);
1616
- }
1617
- }
1618
- }
1619
- }
1620
- }
1621
- await this.redis.pexpire(streamKey, this.streamActiveTTLMs);
1622
- }
1623
- });
1624
- const compactedEvents = compactEvents(currentRunEvents);
1625
- await this.storeRun(threadId, runId, compactedEvents, input, parentRunId);
1626
- } finally {
1627
- await this.setRunState(threadId, false);
1628
- await this.redis.del(redisKeys.active(threadId));
1629
- await this.redis.del(redisKeys.lock(threadId));
1630
- const exists = await this.redis.exists(streamKey);
1631
- if (exists) {
1632
- await this.redis.pexpire(streamKey, this.streamRetentionMs);
1633
- }
1634
- runSubject.complete();
1635
- }
1636
- };
1637
- executeRun().catch((error) => {
1638
- runSubject.error(error);
1639
- });
1640
- return runSubject.asObservable();
1641
- }
1642
- connect(request) {
1643
- const connectionSubject = new import_rxjs3.ReplaySubject(Infinity);
1644
- const streamConnection = async () => {
1645
- const { threadId } = request;
1646
- const historicRuns = await this.getHistoricRuns(threadId);
1647
- const allHistoricEvents = [];
1648
- for (const run of historicRuns) {
1649
- const events = JSON.parse(run.events);
1650
- allHistoricEvents.push(...events);
1651
- }
1652
- const compactedEvents = compactEvents(allHistoricEvents);
1653
- const emittedMessageIds = /* @__PURE__ */ new Set();
1654
- for (const event of compactedEvents) {
1655
- connectionSubject.next(event);
1656
- if ("messageId" in event && typeof event.messageId === "string") {
1657
- emittedMessageIds.add(event.messageId);
1658
- }
1659
- }
1660
- const activeRunId = await this.redis.get(redisKeys.active(threadId));
1661
- if (activeRunId) {
1662
- const streamKey = redisKeys.stream(threadId, activeRunId);
1663
- let lastId = "0-0";
1664
- let consecutiveEmptyReads = 0;
1665
- while (true) {
1666
- try {
1667
- const result = await this.redis.call(
1668
- "XREAD",
1669
- "BLOCK",
1670
- "5000",
1671
- "COUNT",
1672
- "100",
1673
- "STREAMS",
1674
- streamKey,
1675
- lastId
1676
- );
1677
- if (!result || result.length === 0) {
1678
- consecutiveEmptyReads++;
1679
- const exists = await this.redis.exists(streamKey);
1680
- if (!exists) {
1681
- break;
1682
- }
1683
- const stillActive = await this.redis.get(redisKeys.active(threadId));
1684
- if (stillActive !== activeRunId) {
1685
- break;
1686
- }
1687
- if (consecutiveEmptyReads > 3) {
1688
- break;
1689
- }
1690
- continue;
1691
- }
1692
- consecutiveEmptyReads = 0;
1693
- const [, messages] = result[0] || [null, []];
1694
- for (const [id, fields] of messages || []) {
1695
- lastId = id;
1696
- let eventData = null;
1697
- let eventType = null;
1698
- for (let i = 0; i < fields.length; i += 2) {
1699
- if (fields[i] === "data") {
1700
- eventData = fields[i + 1] ?? null;
1701
- } else if (fields[i] === "type") {
1702
- eventType = fields[i + 1] ?? null;
1703
- }
1704
- }
1705
- if (eventData) {
1706
- const event = JSON.parse(eventData);
1707
- if ("messageId" in event && typeof event.messageId === "string" && emittedMessageIds.has(event.messageId)) {
1708
- continue;
1709
- }
1710
- connectionSubject.next(event);
1711
- if (eventType === import_client6.EventType.RUN_FINISHED || eventType === import_client6.EventType.RUN_ERROR) {
1712
- connectionSubject.complete();
1713
- return;
1714
- }
1715
- }
1716
- }
1717
- } catch {
1718
- break;
1719
- }
1720
- }
1721
- }
1722
- connectionSubject.complete();
1723
- };
1724
- streamConnection().catch(() => connectionSubject.complete());
1725
- return connectionSubject.asObservable();
1726
- }
1727
- async isRunning(request) {
1728
- const { threadId } = request;
1729
- const activeRunId = await this.redis.get(redisKeys.active(threadId));
1730
- if (activeRunId) return true;
1731
- const lockExists = await this.redis.exists(redisKeys.lock(threadId));
1732
- if (lockExists) return true;
1733
- const state = await this.db.selectFrom("run_state").where("thread_id", "=", threadId).selectAll().executeTakeFirst();
1734
- return state?.is_running === 1;
1735
- }
1736
- async stop(request) {
1737
- const { threadId } = request;
1738
- const activeRunId = await this.redis.get(redisKeys.active(threadId));
1739
- if (!activeRunId) {
1740
- return false;
1741
- }
1742
- const streamKey = redisKeys.stream(threadId, activeRunId);
1743
- await this.redis.xadd(
1744
- streamKey,
1745
- "*",
1746
- "type",
1747
- import_client6.EventType.RUN_ERROR,
1748
- "data",
1749
- JSON.stringify({
1750
- type: import_client6.EventType.RUN_ERROR,
1751
- error: "Run stopped by user"
1752
- })
1753
- );
1754
- await this.redis.pexpire(streamKey, this.streamRetentionMs);
1755
- await this.setRunState(threadId, false);
1756
- await this.redis.del(redisKeys.active(threadId));
1757
- await this.redis.del(redisKeys.lock(threadId));
1758
- return true;
1759
- }
1760
- // Helper methods
1761
- convertMessageToEvents(message) {
1762
- const events = [];
1763
- if ((message.role === "assistant" || message.role === "user" || message.role === "developer" || message.role === "system") && message.content) {
1764
- const textStartEvent = {
1765
- type: import_client6.EventType.TEXT_MESSAGE_START,
1766
- messageId: message.id,
1767
- role: message.role
1768
- };
1769
- events.push(textStartEvent);
1770
- const textContentEvent = {
1771
- type: import_client6.EventType.TEXT_MESSAGE_CONTENT,
1772
- messageId: message.id,
1773
- delta: message.content
1774
- };
1775
- events.push(textContentEvent);
1776
- const textEndEvent = {
1777
- type: import_client6.EventType.TEXT_MESSAGE_END,
1778
- messageId: message.id
1779
- };
1780
- events.push(textEndEvent);
1781
- }
1782
- if (message.role === "assistant" && message.toolCalls) {
1783
- for (const toolCall of message.toolCalls) {
1784
- const toolStartEvent = {
1785
- type: import_client6.EventType.TOOL_CALL_START,
1786
- toolCallId: toolCall.id,
1787
- toolCallName: toolCall.function.name,
1788
- parentMessageId: message.id
1789
- };
1790
- events.push(toolStartEvent);
1791
- const toolArgsEvent = {
1792
- type: import_client6.EventType.TOOL_CALL_ARGS,
1793
- toolCallId: toolCall.id,
1794
- delta: toolCall.function.arguments
1795
- };
1796
- events.push(toolArgsEvent);
1797
- const toolEndEvent = {
1798
- type: import_client6.EventType.TOOL_CALL_END,
1799
- toolCallId: toolCall.id
1800
- };
1801
- events.push(toolEndEvent);
1802
- }
1803
- }
1804
- if (message.role === "tool" && message.toolCallId) {
1805
- const toolResultEvent = {
1806
- type: import_client6.EventType.TOOL_CALL_RESULT,
1807
- messageId: message.id,
1808
- toolCallId: message.toolCallId,
1809
- content: message.content,
1810
- role: "tool"
1811
- };
1812
- events.push(toolResultEvent);
1813
- }
1814
- return events;
1815
- }
1816
- async initializeSchema() {
1817
- try {
1818
- await this.db.schema.createTable("agent_runs").ifNotExists().addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()).addColumn("thread_id", "text", (col) => col.notNull()).addColumn("run_id", "text", (col) => col.notNull().unique()).addColumn("parent_run_id", "text").addColumn("events", "text", (col) => col.notNull()).addColumn("input", "text", (col) => col.notNull()).addColumn("created_at", "integer", (col) => col.notNull()).addColumn("version", "integer", (col) => col.notNull()).execute().catch(() => {
1819
- });
1820
- await this.db.schema.createTable("run_state").ifNotExists().addColumn("thread_id", "text", (col) => col.primaryKey()).addColumn("is_running", "integer", (col) => col.defaultTo(0)).addColumn("current_run_id", "text").addColumn("server_id", "text").addColumn("updated_at", "integer", (col) => col.notNull()).execute().catch(() => {
1821
- });
1822
- await this.db.schema.createTable("schema_version").ifNotExists().addColumn("version", "integer", (col) => col.primaryKey()).addColumn("applied_at", "integer", (col) => col.notNull()).execute().catch(() => {
1823
- });
1824
- await this.db.schema.createIndex("idx_thread_id").ifNotExists().on("agent_runs").column("thread_id").execute().catch(() => {
1825
- });
1826
- await this.db.schema.createIndex("idx_parent_run_id").ifNotExists().on("agent_runs").column("parent_run_id").execute().catch(() => {
1827
- });
1828
- const currentVersion = await this.db.selectFrom("schema_version").orderBy("version", "desc").limit(1).selectAll().executeTakeFirst();
1829
- if (!currentVersion || currentVersion.version < SCHEMA_VERSION2) {
1830
- await this.db.insertInto("schema_version").values({
1831
- version: SCHEMA_VERSION2,
1832
- applied_at: Date.now()
1833
- }).onConflict(
1834
- (oc) => oc.column("version").doUpdateSet({ applied_at: Date.now() })
1835
- ).execute();
1836
- }
1837
- } catch {
1838
- }
1839
- }
1840
- async storeRun(threadId, runId, events, input, parentRunId) {
1841
- await this.db.insertInto("agent_runs").values({
1842
- thread_id: threadId,
1843
- run_id: runId,
1844
- parent_run_id: parentRunId,
1845
- events: JSON.stringify(events),
1846
- input: JSON.stringify(input),
1847
- created_at: Date.now(),
1848
- version: SCHEMA_VERSION2
1849
- }).execute();
1850
- }
1851
- async getHistoricRuns(threadId) {
1852
- const rows = await this.db.selectFrom("agent_runs").where("thread_id", "=", threadId).orderBy("created_at", "asc").selectAll().execute();
1853
- return rows.map((row) => ({
1854
- id: Number(row.id),
1855
- thread_id: row.thread_id,
1856
- run_id: row.run_id,
1857
- parent_run_id: row.parent_run_id,
1858
- events: row.events,
1859
- input: row.input,
1860
- created_at: row.created_at,
1861
- version: row.version
1862
- }));
1863
- }
1864
- async setRunState(threadId, isRunning, runId) {
1865
- await this.db.insertInto("run_state").values({
1866
- thread_id: threadId,
1867
- is_running: isRunning ? 1 : 0,
1868
- current_run_id: runId ?? null,
1869
- server_id: this.serverId,
1870
- updated_at: Date.now()
1871
- }).onConflict(
1872
- (oc) => oc.column("thread_id").doUpdateSet({
1873
- is_running: isRunning ? 1 : 0,
1874
- current_run_id: runId ?? null,
1875
- server_id: this.serverId,
1876
- updated_at: Date.now()
1877
- })
1878
- ).execute();
1879
- }
1880
- async close() {
1881
- await this.db.destroy();
1882
- this.redis.disconnect();
1883
- this.redisSub.disconnect();
1884
- }
1885
- generateServerId() {
1886
- return `server-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1887
- }
1888
- };
1889
967
  // Annotate the CommonJS export names for ESM import in node:
1890
968
  0 && (module.exports = {
969
+ AgentRunner,
1891
970
  CopilotRuntime,
1892
- EnterpriseAgentRunner,
1893
971
  InMemoryAgentRunner,
1894
- SqliteAgentRunner,
1895
972
  VERSION,
1896
973
  createCopilotEndpoint
1897
974
  });