@copilotkit/runtime 1.56.5 → 1.57.0
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/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/runtime/core/fetch-handler.cjs +16 -0
- package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.mjs +17 -1
- package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.cjs +18 -1
- package/dist/v2/runtime/core/fetch-router.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.mjs +18 -1
- package/dist/v2/runtime/core/fetch-router.mjs.map +1 -1
- package/dist/v2/runtime/core/hooks.cjs.map +1 -1
- package/dist/v2/runtime/core/hooks.d.cts +8 -0
- package/dist/v2/runtime/core/hooks.d.cts.map +1 -1
- package/dist/v2/runtime/core/hooks.d.mts +8 -0
- package/dist/v2/runtime/core/hooks.d.mts.map +1 -1
- package/dist/v2/runtime/core/hooks.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.cjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/threads.cjs +124 -12
- package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/threads.mjs +122 -13
- package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +1 -1
- package/dist/v2/runtime/index.d.cts +1 -1
- package/dist/v2/runtime/index.d.mts +1 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs +30 -0
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +66 -0
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +66 -0
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +30 -0
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.cjs +94 -22
- package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.cts +65 -2
- package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.mts +65 -2
- package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.mjs +94 -22
- package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
- package/dist/v2/runtime/runner/index.d.cts +1 -1
- package/dist/v2/runtime/runner/index.d.mts +1 -1
- package/package.json +2 -2
- package/src/v2/runtime/__tests__/fetch-handler-validation.test.ts +68 -0
- package/src/v2/runtime/__tests__/fetch-router.test.ts +46 -0
- package/src/v2/runtime/__tests__/handle-run.test.ts +97 -1
- package/src/v2/runtime/__tests__/handle-threads.test.ts +493 -13
- package/src/v2/runtime/core/fetch-handler.ts +19 -0
- package/src/v2/runtime/core/fetch-router.ts +33 -1
- package/src/v2/runtime/core/hooks.ts +3 -0
- package/src/v2/runtime/handlers/handle-run.ts +4 -0
- package/src/v2/runtime/handlers/handle-threads.ts +3 -0
- package/src/v2/runtime/handlers/intelligence/threads.ts +200 -41
- package/src/v2/runtime/intelligence-platform/client.ts +76 -0
- package/src/v2/runtime/runner/__tests__/in-memory-runner.test.ts +417 -3
- package/src/v2/runtime/runner/in-memory.ts +137 -51
|
@@ -35,6 +35,10 @@ export async function handleRunAgent({
|
|
|
35
35
|
return agent;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Ensure the clone carries the registry key so InMemoryAgentRunner can
|
|
39
|
+
// tag historic runs with the correct agentId for filtering.
|
|
40
|
+
agent.agentId = agentId;
|
|
41
|
+
|
|
38
42
|
configureAgentForRequest({ runtime, request, agentId, agent });
|
|
39
43
|
|
|
40
44
|
if (
|
|
@@ -7,6 +7,7 @@ import { logger } from "@copilotkit/shared";
|
|
|
7
7
|
import { errorResponse, isHandlerResponse } from "../shared/json-response";
|
|
8
8
|
import { isValidIdentifier } from "../shared/intelligence-utils";
|
|
9
9
|
import { resolveIntelligenceUser } from "../shared/resolve-intelligence-user";
|
|
10
|
+
import { InMemoryAgentRunner } from "../../runner/in-memory";
|
|
10
11
|
|
|
11
12
|
interface ThreadsHandlerParams {
|
|
12
13
|
runtime: CopilotRuntimeLike;
|
|
@@ -73,40 +74,70 @@ export async function handleListThreads({
|
|
|
73
74
|
runtime,
|
|
74
75
|
request,
|
|
75
76
|
}: ThreadsHandlerParams): Promise<Response> {
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
77
|
+
// Intelligence platform path
|
|
78
|
+
if (isIntelligenceRuntime(runtime)) {
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(request.url);
|
|
81
|
+
const agentId = url.searchParams.get("agentId");
|
|
82
|
+
const includeArchived =
|
|
83
|
+
url.searchParams.get("includeArchived") === "true";
|
|
84
|
+
const limitParam = url.searchParams.get("limit");
|
|
85
|
+
const cursor = url.searchParams.get("cursor");
|
|
86
|
+
const user = await resolveIntelligenceUser({ runtime, request });
|
|
87
|
+
if (isHandlerResponse(user)) return user;
|
|
88
|
+
|
|
89
|
+
if (!isValidIdentifier(agentId)) {
|
|
90
|
+
return errorResponse("Valid agentId query param is required", 400);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const data = await runtime.intelligence.listThreads({
|
|
94
|
+
userId: user.id,
|
|
95
|
+
agentId,
|
|
96
|
+
...(includeArchived ? { includeArchived: true } : {}),
|
|
97
|
+
...(limitParam ? { limit: Number(limitParam) } : {}),
|
|
98
|
+
...(cursor ? { cursor } : {}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return Response.json(data);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
logger.error({ err: error }, "Error listing threads");
|
|
104
|
+
return errorResponse("Failed to list threads", 500);
|
|
105
|
+
}
|
|
79
106
|
}
|
|
80
107
|
|
|
81
|
-
|
|
108
|
+
// Local in-memory fallback — useful for local development without Intelligence
|
|
109
|
+
if (runtime.runner instanceof InMemoryAgentRunner) {
|
|
82
110
|
const url = new URL(request.url);
|
|
83
111
|
const agentId = url.searchParams.get("agentId");
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const user = await resolveIntelligenceUser({
|
|
88
|
-
runtime: intelligenceRuntime,
|
|
89
|
-
request,
|
|
90
|
-
});
|
|
91
|
-
if (isHandlerResponse(user)) return user;
|
|
92
|
-
|
|
93
|
-
if (!isValidIdentifier(agentId)) {
|
|
94
|
-
return errorResponse("Valid agentId query param is required", 400);
|
|
112
|
+
let threads = runtime.runner.listThreads();
|
|
113
|
+
if (agentId) {
|
|
114
|
+
threads = threads.filter((t) => t.agentId === agentId);
|
|
95
115
|
}
|
|
116
|
+
return Response.json({ threads, nextCursor: null });
|
|
117
|
+
}
|
|
96
118
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
...(cursor ? { cursor } : {}),
|
|
103
|
-
});
|
|
119
|
+
return errorResponse(
|
|
120
|
+
"Missing CopilotKitIntelligence configuration. Thread operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.",
|
|
121
|
+
422,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
104
124
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Clears all in-memory thread history for the local-dev InMemory fallback.
|
|
127
|
+
*
|
|
128
|
+
* The local-dev fallback exposes this so consumers (e.g. the demo's Clear
|
|
129
|
+
* button) can wipe in-memory thread history without restarting the runtime.
|
|
130
|
+
* Intentionally a no-op when the Intelligence platform is configured: real
|
|
131
|
+
* thread history lives in the database and must not be wiped by a
|
|
132
|
+
* client-side page load.
|
|
133
|
+
*/
|
|
134
|
+
export function handleClearThreads({
|
|
135
|
+
runtime,
|
|
136
|
+
}: ThreadsHandlerParams): Response {
|
|
137
|
+
if (runtime.runner instanceof InMemoryAgentRunner) {
|
|
138
|
+
runtime.runner.clearThreads();
|
|
109
139
|
}
|
|
140
|
+
return new Response(null, { status: 204 });
|
|
110
141
|
}
|
|
111
142
|
|
|
112
143
|
export async function handleUpdateThread({
|
|
@@ -237,25 +268,153 @@ export async function handleGetThreadMessages({
|
|
|
237
268
|
request,
|
|
238
269
|
threadId,
|
|
239
270
|
}: ThreadMutationParams): Promise<Response> {
|
|
240
|
-
|
|
241
|
-
if (
|
|
242
|
-
|
|
271
|
+
// Intelligence platform path
|
|
272
|
+
if (isIntelligenceRuntime(runtime)) {
|
|
273
|
+
try {
|
|
274
|
+
const user = await resolveIntelligenceUser({ runtime, request });
|
|
275
|
+
if (isHandlerResponse(user)) return user;
|
|
276
|
+
|
|
277
|
+
const data = await runtime.intelligence.getThreadMessages({ threadId });
|
|
278
|
+
return Response.json(data);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
logger.error({ err: error, threadId }, "Error fetching thread messages");
|
|
281
|
+
return errorResponse("Failed to fetch thread messages", 500);
|
|
282
|
+
}
|
|
243
283
|
}
|
|
244
284
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
285
|
+
// Local in-memory fallback — useful for local development without Intelligence
|
|
286
|
+
if (runtime.runner instanceof InMemoryAgentRunner) {
|
|
287
|
+
const messages = runtime.runner.getThreadMessages(threadId);
|
|
288
|
+
// Map ag-ui Message objects to the same shape the Intelligence platform
|
|
289
|
+
// returns. Switching on the discriminant `role` lets each branch read
|
|
290
|
+
// the narrowed message arm directly, instead of laundering through
|
|
291
|
+
// `Record<string, unknown>` and chained `as` casts.
|
|
292
|
+
const mapped = messages.map((msg) => {
|
|
293
|
+
switch (msg.role) {
|
|
294
|
+
case "assistant": {
|
|
295
|
+
const toolCalls = msg.toolCalls ?? [];
|
|
296
|
+
return {
|
|
297
|
+
id: msg.id,
|
|
298
|
+
role: msg.role,
|
|
299
|
+
...(msg.content !== undefined ? { content: msg.content } : {}),
|
|
300
|
+
...(toolCalls.length > 0
|
|
301
|
+
? {
|
|
302
|
+
toolCalls: toolCalls.map((tc) => ({
|
|
303
|
+
id: tc.id,
|
|
304
|
+
name: tc.function.name,
|
|
305
|
+
args: tc.function.arguments,
|
|
306
|
+
})),
|
|
307
|
+
}
|
|
308
|
+
: {}),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
case "tool":
|
|
312
|
+
return {
|
|
313
|
+
id: msg.id,
|
|
314
|
+
role: msg.role,
|
|
315
|
+
content: msg.content,
|
|
316
|
+
toolCallId: msg.toolCallId,
|
|
317
|
+
};
|
|
318
|
+
default:
|
|
319
|
+
return {
|
|
320
|
+
id: msg.id,
|
|
321
|
+
role: msg.role,
|
|
322
|
+
...("content" in msg && msg.content !== undefined
|
|
323
|
+
? { content: msg.content }
|
|
324
|
+
: {}),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
249
327
|
});
|
|
250
|
-
|
|
328
|
+
return Response.json({ messages: mapped });
|
|
329
|
+
}
|
|
251
330
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
331
|
+
return errorResponse(
|
|
332
|
+
"Missing CopilotKitIntelligence configuration. Thread operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.",
|
|
333
|
+
422,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
255
336
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
337
|
+
export async function handleGetThreadEvents({
|
|
338
|
+
runtime,
|
|
339
|
+
request,
|
|
340
|
+
threadId,
|
|
341
|
+
}: ThreadMutationParams): Promise<Response> {
|
|
342
|
+
// Intelligence platform path. Delegates to the platform's `_inspect`
|
|
343
|
+
// endpoint (Intelligence PR #144). Auth still flows through the standard
|
|
344
|
+
// identifyUser → API key path; threadId scoping happens server-side.
|
|
345
|
+
if (isIntelligenceRuntime(runtime)) {
|
|
346
|
+
try {
|
|
347
|
+
const user = await resolveIntelligenceUser({ runtime, request });
|
|
348
|
+
if (isHandlerResponse(user)) return user;
|
|
349
|
+
|
|
350
|
+
const data = await runtime.intelligence.getThreadEvents({ threadId });
|
|
351
|
+
// Strip platform-internal fields (`decodeErrorRowIds`, `truncated`)
|
|
352
|
+
// before returning to the inspector — those describe persistence-side
|
|
353
|
+
// concerns the inspector currently has no UI for. The shape becomes
|
|
354
|
+
// `{ events }`, matching the in-memory branch below.
|
|
355
|
+
return Response.json({ events: data.events });
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger.error({ err: error, threadId }, "Error fetching thread events");
|
|
358
|
+
return errorResponse("Failed to fetch thread events", 500);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Local in-memory fallback
|
|
363
|
+
if (runtime.runner instanceof InMemoryAgentRunner) {
|
|
364
|
+
try {
|
|
365
|
+
const events = runtime.runner.getThreadEvents(threadId);
|
|
366
|
+
return Response.json({ events });
|
|
367
|
+
} catch (error) {
|
|
368
|
+
logger.error({ err: error, threadId }, "Error fetching thread events");
|
|
369
|
+
return errorResponse("Failed to fetch thread events", 500);
|
|
370
|
+
}
|
|
260
371
|
}
|
|
372
|
+
|
|
373
|
+
return errorResponse(
|
|
374
|
+
"Missing CopilotKitIntelligence configuration. Thread operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.",
|
|
375
|
+
422,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export async function handleGetThreadState({
|
|
380
|
+
runtime,
|
|
381
|
+
request,
|
|
382
|
+
threadId,
|
|
383
|
+
}: ThreadMutationParams): Promise<Response> {
|
|
384
|
+
// Intelligence platform path. Delegates to the platform's `_inspect`
|
|
385
|
+
// state endpoint, which folds STATE_DELTA events onto the latest
|
|
386
|
+
// STATE_SNAPSHOT to return the thread's current state.
|
|
387
|
+
if (isIntelligenceRuntime(runtime)) {
|
|
388
|
+
try {
|
|
389
|
+
const user = await resolveIntelligenceUser({ runtime, request });
|
|
390
|
+
if (isHandlerResponse(user)) return user;
|
|
391
|
+
|
|
392
|
+
const data = await runtime.intelligence.getThreadState({ threadId });
|
|
393
|
+
// Flatten the discriminated `ThreadStateResult` to the wire shape the
|
|
394
|
+
// inspector consumes (`{ state: <value> | null }`). Missing snapshot
|
|
395
|
+
// and decode-error both surface as `null`; the inspector renders an
|
|
396
|
+
// empty state branch for null and the platform's decode-error case is
|
|
397
|
+
// already logged platform-side.
|
|
398
|
+
const state = data.kind === "snapshot" ? data.state : null;
|
|
399
|
+
return Response.json({ state });
|
|
400
|
+
} catch (error) {
|
|
401
|
+
logger.error({ err: error, threadId }, "Error fetching thread state");
|
|
402
|
+
return errorResponse("Failed to fetch thread state", 500);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (runtime.runner instanceof InMemoryAgentRunner) {
|
|
407
|
+
try {
|
|
408
|
+
const state = runtime.runner.getThreadState(threadId);
|
|
409
|
+
return Response.json({ state });
|
|
410
|
+
} catch (error) {
|
|
411
|
+
logger.error({ err: error, threadId }, "Error fetching thread state");
|
|
412
|
+
return errorResponse("Failed to fetch thread state", 500);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return errorResponse(
|
|
417
|
+
"Missing CopilotKitIntelligence configuration. Thread operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.",
|
|
418
|
+
422,
|
|
419
|
+
);
|
|
261
420
|
}
|
|
@@ -198,6 +198,40 @@ export interface ThreadMessagesResponse {
|
|
|
198
198
|
messages: ThreadMessage[];
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Persisted AG-UI event for the inspector's debugging views. The platform
|
|
203
|
+
* stores raw events keyed by run; the `_inspect` route returns them in
|
|
204
|
+
* replay order (oldest first) across every run that targeted the thread.
|
|
205
|
+
*/
|
|
206
|
+
export interface ThreadInspectEvent {
|
|
207
|
+
type: string;
|
|
208
|
+
[key: string]: unknown;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Response from {@link CopilotKitIntelligence.getThreadEvents}. Mirrors the
|
|
213
|
+
* `ThreadEventsResult` shape returned by the platform's
|
|
214
|
+
* `GET /api/_inspect/threads/:id/events` endpoint.
|
|
215
|
+
*/
|
|
216
|
+
export interface ThreadEventsResponse {
|
|
217
|
+
events: ThreadInspectEvent[];
|
|
218
|
+
/** Row IDs the platform failed to decode (raw column corrupted). */
|
|
219
|
+
decodeErrorRowIds: string[];
|
|
220
|
+
/** True when the platform hit its per-thread event cap. */
|
|
221
|
+
truncated: boolean;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Response from {@link CopilotKitIntelligence.getThreadState}. Mirrors the
|
|
226
|
+
* discriminated `ThreadStateResult` returned by the platform's
|
|
227
|
+
* `GET /api/_inspect/threads/:id/state` endpoint, which folds RFC 6902
|
|
228
|
+
* STATE_DELTA events on top of the latest STATE_SNAPSHOT.
|
|
229
|
+
*/
|
|
230
|
+
export type ThreadStateResponse =
|
|
231
|
+
| { kind: "no-snapshot" }
|
|
232
|
+
| { kind: "snapshot-decode-error" }
|
|
233
|
+
| { kind: "snapshot"; state: unknown; skippedDeltas: number };
|
|
234
|
+
|
|
201
235
|
export interface AcquireThreadLockRequest {
|
|
202
236
|
threadId: string;
|
|
203
237
|
runId: string;
|
|
@@ -556,6 +590,48 @@ export class CopilotKitIntelligence {
|
|
|
556
590
|
);
|
|
557
591
|
}
|
|
558
592
|
|
|
593
|
+
/**
|
|
594
|
+
* Fetch the persisted AG-UI event stream for a thread.
|
|
595
|
+
*
|
|
596
|
+
* Backed by the platform's `GET /api/_inspect/threads/:id/events`
|
|
597
|
+
* introspection endpoint (see Intelligence PR #144). Events are returned
|
|
598
|
+
* in replay order across every run that targeted the thread. The
|
|
599
|
+
* `_inspect/` prefix flags this as debug-only — production code paths
|
|
600
|
+
* must not depend on it.
|
|
601
|
+
*
|
|
602
|
+
* @throws {@link PlatformRequestError} on non-2xx responses.
|
|
603
|
+
*/
|
|
604
|
+
async getThreadEvents(params: {
|
|
605
|
+
threadId: string;
|
|
606
|
+
}): Promise<ThreadEventsResponse> {
|
|
607
|
+
return this.#request<ThreadEventsResponse>(
|
|
608
|
+
"GET",
|
|
609
|
+
`/api/_inspect/threads/${encodeURIComponent(params.threadId)}/events`,
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Fetch the current agent state for a thread.
|
|
615
|
+
*
|
|
616
|
+
* Backed by the platform's `GET /api/_inspect/threads/:id/state`
|
|
617
|
+
* introspection endpoint (see Intelligence PR #144). The platform folds
|
|
618
|
+
* RFC 6902 STATE_DELTA events on top of the latest STATE_SNAPSHOT, so
|
|
619
|
+
* the returned state reflects the thread's current state — not just the
|
|
620
|
+
* last snapshot. The discriminated response distinguishes "no snapshot
|
|
621
|
+
* persisted yet" from "snapshot present" so consumers can render the
|
|
622
|
+
* correct empty state.
|
|
623
|
+
*
|
|
624
|
+
* @throws {@link PlatformRequestError} on non-2xx responses.
|
|
625
|
+
*/
|
|
626
|
+
async getThreadState(params: {
|
|
627
|
+
threadId: string;
|
|
628
|
+
}): Promise<ThreadStateResponse> {
|
|
629
|
+
return this.#request<ThreadStateResponse>(
|
|
630
|
+
"GET",
|
|
631
|
+
`/api/_inspect/threads/${encodeURIComponent(params.threadId)}/state`,
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
|
|
559
635
|
/**
|
|
560
636
|
* Mark a thread as archived.
|
|
561
637
|
*
|