@copilotkit/runtime 1.62.2 → 1.62.3

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 (75) hide show
  1. package/dist/package.cjs +1 -1
  2. package/dist/package.mjs +1 -1
  3. package/dist/v2/runtime/core/fetch-handler.cjs +51 -1
  4. package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
  5. package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -1
  6. package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -1
  7. package/dist/v2/runtime/core/fetch-handler.mjs +51 -1
  8. package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
  9. package/dist/v2/runtime/core/fetch-router.cjs +18 -0
  10. package/dist/v2/runtime/core/fetch-router.cjs.map +1 -1
  11. package/dist/v2/runtime/core/fetch-router.mjs +18 -0
  12. package/dist/v2/runtime/core/fetch-router.mjs.map +1 -1
  13. package/dist/v2/runtime/core/hooks.cjs.map +1 -1
  14. package/dist/v2/runtime/core/hooks.d.cts +10 -0
  15. package/dist/v2/runtime/core/hooks.d.cts.map +1 -1
  16. package/dist/v2/runtime/core/hooks.d.mts +10 -0
  17. package/dist/v2/runtime/core/hooks.d.mts.map +1 -1
  18. package/dist/v2/runtime/core/hooks.mjs.map +1 -1
  19. package/dist/v2/runtime/core/runtime.cjs +5 -0
  20. package/dist/v2/runtime/core/runtime.cjs.map +1 -1
  21. package/dist/v2/runtime/core/runtime.d.cts +21 -0
  22. package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
  23. package/dist/v2/runtime/core/runtime.d.mts +21 -0
  24. package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
  25. package/dist/v2/runtime/core/runtime.mjs +5 -0
  26. package/dist/v2/runtime/core/runtime.mjs.map +1 -1
  27. package/dist/v2/runtime/endpoints/single-route-helpers.cjs +1 -0
  28. package/dist/v2/runtime/endpoints/single-route-helpers.cjs.map +1 -1
  29. package/dist/v2/runtime/endpoints/single-route-helpers.mjs +1 -0
  30. package/dist/v2/runtime/endpoints/single-route-helpers.mjs.map +1 -1
  31. package/dist/v2/runtime/handlers/get-runtime-info.cjs +1 -0
  32. package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -1
  33. package/dist/v2/runtime/handlers/get-runtime-info.mjs +1 -0
  34. package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -1
  35. package/dist/v2/runtime/handlers/handle-connect.cjs +2 -1
  36. package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -1
  37. package/dist/v2/runtime/handlers/handle-connect.mjs +2 -1
  38. package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -1
  39. package/dist/v2/runtime/handlers/handle-suggest.cjs +83 -0
  40. package/dist/v2/runtime/handlers/handle-suggest.cjs.map +1 -0
  41. package/dist/v2/runtime/handlers/handle-suggest.mjs +82 -0
  42. package/dist/v2/runtime/handlers/handle-suggest.mjs.map +1 -0
  43. package/dist/v2/runtime/handlers/header-utils.cjs +169 -9
  44. package/dist/v2/runtime/handlers/header-utils.cjs.map +1 -1
  45. package/dist/v2/runtime/handlers/header-utils.d.cts +54 -0
  46. package/dist/v2/runtime/handlers/header-utils.d.cts.map +1 -0
  47. package/dist/v2/runtime/handlers/header-utils.d.mts +54 -0
  48. package/dist/v2/runtime/handlers/header-utils.d.mts.map +1 -0
  49. package/dist/v2/runtime/handlers/header-utils.mjs +168 -9
  50. package/dist/v2/runtime/handlers/header-utils.mjs.map +1 -1
  51. package/dist/v2/runtime/handlers/intelligence/memories.cjs +209 -0
  52. package/dist/v2/runtime/handlers/intelligence/memories.cjs.map +1 -0
  53. package/dist/v2/runtime/handlers/intelligence/memories.mjs +204 -0
  54. package/dist/v2/runtime/handlers/intelligence/memories.mjs.map +1 -0
  55. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +18 -5
  56. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  57. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +18 -5
  58. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  59. package/dist/v2/runtime/handlers/shared/sse-response.cjs +4 -4
  60. package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -1
  61. package/dist/v2/runtime/handlers/shared/sse-response.mjs +4 -4
  62. package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -1
  63. package/dist/v2/runtime/handlers/sse/connect.cjs +2 -2
  64. package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -1
  65. package/dist/v2/runtime/handlers/sse/connect.mjs +3 -3
  66. package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -1
  67. package/dist/v2/runtime/intelligence-platform/client.cjs +71 -2
  68. package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
  69. package/dist/v2/runtime/intelligence-platform/client.d.cts +112 -0
  70. package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
  71. package/dist/v2/runtime/intelligence-platform/client.d.mts +112 -0
  72. package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
  73. package/dist/v2/runtime/intelligence-platform/client.mjs +71 -2
  74. package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
  75. package/package.json +2 -2
package/dist/package.cjs CHANGED
@@ -5,7 +5,7 @@ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
5
5
  var require_package = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
6
6
  module.exports = {
7
7
  "name": "@copilotkit/runtime",
8
- "version": "1.62.2",
8
+ "version": "1.62.3",
9
9
  "private": false,
10
10
  "keywords": [
11
11
  "ai",
package/dist/package.mjs CHANGED
@@ -5,7 +5,7 @@ import { __commonJSMin } from "./_virtual/_rolldown/runtime.mjs";
5
5
  var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
6
6
  module.exports = {
7
7
  "name": "@copilotkit/runtime",
8
- "version": "1.62.2",
8
+ "version": "1.62.3",
9
9
  "private": false,
10
10
  "keywords": [
11
11
  "ai",
@@ -5,12 +5,14 @@ const require_fetch_cors = require('./fetch-cors.cjs');
5
5
  const require_fetch_router = require('./fetch-router.cjs');
6
6
  const require_middleware = require('./middleware.cjs');
7
7
  const require_handle_run = require('../handlers/handle-run.cjs');
8
+ const require_handle_suggest = require('../handlers/handle-suggest.cjs');
8
9
  const require_handle_connect = require('../handlers/handle-connect.cjs');
9
10
  const require_handle_stop = require('../handlers/handle-stop.cjs');
10
11
  const require_get_runtime_info = require('../handlers/get-runtime-info.cjs');
11
12
  const require_handle_transcribe = require('../handlers/handle-transcribe.cjs');
12
13
  const require_handle_debug_events = require('../handlers/handle-debug-events.cjs');
13
14
  const require_threads = require('../handlers/intelligence/threads.cjs');
15
+ const require_memories = require('../handlers/intelligence/memories.cjs');
14
16
  const require_annotate = require('../handlers/intelligence/annotate.cjs');
15
17
  const require_single_route_helpers = require('../endpoints/single-route-helpers.cjs');
16
18
  const require_instance_created = require('../telemetry/instance-created.cjs');
@@ -66,7 +68,7 @@ function createCopilotRuntimeHandler(options) {
66
68
  runtime,
67
69
  route
68
70
  });
69
- if (route.method === "agent/run" || route.method === "agent/connect" || route.method === "transcribe") request = require_single_route_helpers.createJsonRequest(request, methodCall.body);
71
+ if (route.method === "agent/run" || route.method === "agent/suggest" || route.method === "agent/connect" || route.method === "transcribe") request = require_single_route_helpers.createJsonRequest(request, methodCall.body);
70
72
  response = await dispatchRoute(runtime, request, route, { threadEndpointsEnabled: false });
71
73
  } else {
72
74
  const matched = require_fetch_router.matchRoute(path, basePath);
@@ -146,6 +148,11 @@ function dispatchRoute(runtime, request, route, options) {
146
148
  request,
147
149
  agentId: route.agentId
148
150
  });
151
+ case "agent/suggest": return require_handle_suggest.handleSuggestAgent({
152
+ runtime,
153
+ request,
154
+ agentId: route.agentId
155
+ });
149
156
  case "agent/connect": return require_handle_connect.handleConnectAgent({
150
157
  runtime,
151
158
  request,
@@ -174,6 +181,26 @@ function dispatchRoute(runtime, request, route, options) {
174
181
  runtime,
175
182
  request
176
183
  });
184
+ case "memories/list": return request.method.toUpperCase() === "POST" ? require_memories.handleCreateMemory({
185
+ runtime,
186
+ request
187
+ }) : require_memories.handleListMemories({
188
+ runtime,
189
+ request
190
+ });
191
+ case "memories/subscribe": return require_memories.handleSubscribeToMemories({
192
+ runtime,
193
+ request
194
+ });
195
+ case "memories/mutate": return request.method.toUpperCase() === "DELETE" ? require_memories.handleRemoveMemory({
196
+ runtime,
197
+ request,
198
+ memoryId: route.memoryId
199
+ }) : require_memories.handleUpdateMemory({
200
+ runtime,
201
+ request,
202
+ memoryId: route.memoryId
203
+ });
177
204
  case "threads/subscribe": return require_threads.handleSubscribeToThreads({
178
205
  runtime,
179
206
  request
@@ -217,6 +244,10 @@ function dispatchRoute(runtime, request, route, options) {
217
244
  runtime,
218
245
  request
219
246
  }));
247
+ default: throw jsonResponse({
248
+ error: "Not found",
249
+ method: route.method
250
+ }, 404);
220
251
  }
221
252
  }
222
253
  async function resolveSingleRoute(request, basePath, pathname) {
@@ -234,6 +265,12 @@ async function resolveSingleRoute(request, basePath, pathname) {
234
265
  agentId: require_single_route_helpers.expectString(methodCall.params, "agentId")
235
266
  };
236
267
  break;
268
+ case "agent/suggest":
269
+ route = {
270
+ method: "agent/suggest",
271
+ agentId: require_single_route_helpers.expectString(methodCall.params, "agentId")
272
+ };
273
+ break;
237
274
  case "agent/connect":
238
275
  route = {
239
276
  method: "agent/connect",
@@ -253,6 +290,13 @@ async function resolveSingleRoute(request, basePath, pathname) {
253
290
  case "transcribe":
254
291
  route = { method: "transcribe" };
255
292
  break;
293
+ default: {
294
+ const _exhaustive = methodCall.method;
295
+ throw jsonResponse({
296
+ error: "Not found",
297
+ method: _exhaustive
298
+ }, 404);
299
+ }
256
300
  }
257
301
  return {
258
302
  route,
@@ -270,6 +314,12 @@ function validateHttpMethod(httpMethod, route) {
270
314
  case "cpk-debug-events":
271
315
  if (method === "GET") return null;
272
316
  return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "GET" });
317
+ case "memories/list":
318
+ if (method === "GET" || method === "POST") return null;
319
+ return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "GET, POST" });
320
+ case "memories/mutate":
321
+ if (method === "PATCH" || method === "DELETE") return null;
322
+ return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "PATCH, DELETE" });
273
323
  case "threads/update":
274
324
  if (method === "PATCH" || method === "DELETE") return null;
275
325
  return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "PATCH, DELETE" });
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.cjs","names":["handleCors","runOnRequest","callBeforeRequestMiddleware","runOnBeforeHandler","createJsonRequest","matchRoute","runOnResponse","runOnError","handleRunAgent","handleConnectAgent","handleStopAgent","handleGetRuntimeInfo","handleTranscribe","handleClearThreads","handleListThreads","handleSubscribeToThreads","handleDeleteThread","handleUpdateThread","handleArchiveThread","handleGetThreadMessages","handleGetThreadEvents","handleGetThreadState","handleAnnotate","handleDebugEvents","parseMethodCall","expectString","addCorsHeaders"],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"sourcesContent":["/**\n * Framework-agnostic CopilotKit runtime handler.\n *\n * Returns a pure `(Request) => Promise<Response>` function that can be used\n * directly with Bun, Deno, Cloudflare Workers, Next.js App Router, or any\n * Fetch-native runtime — no framework dependency required.\n *\n * @example\n * ```typescript\n * import { CopilotRuntime, createCopilotRuntimeHandler } from \"@copilotkit/runtime/v2\";\n *\n * const handler = createCopilotRuntimeHandler({\n * runtime: new CopilotRuntime({ agents: { ... } }),\n * basePath: \"/api/copilotkit\",\n * cors: true,\n * });\n *\n * // Bun\n * Bun.serve({ fetch: handler });\n *\n * // Deno\n * Deno.serve(handler);\n *\n * // Cloudflare Workers\n * export default { fetch: handler };\n * ```\n */\n\nimport type { CopilotRuntimeLike } from \"./runtime\";\nimport type { CopilotRuntimeHooks, RouteInfo, HookContext } from \"./hooks\";\nimport {\n runOnRequest,\n runOnBeforeHandler,\n runOnResponse,\n runOnError,\n} from \"./hooks\";\nimport type { CopilotCorsConfig } from \"./fetch-cors\";\nimport { handleCors, addCorsHeaders } from \"./fetch-cors\";\nimport { matchRoute } from \"./fetch-router\";\nimport {\n callBeforeRequestMiddleware,\n callAfterRequestMiddleware,\n} from \"./middleware\";\nimport { handleRunAgent } from \"../handlers/handle-run\";\nimport { handleConnectAgent } from \"../handlers/handle-connect\";\nimport { handleStopAgent } from \"../handlers/handle-stop\";\nimport { handleGetRuntimeInfo } from \"../handlers/get-runtime-info\";\nimport { handleTranscribe } from \"../handlers/handle-transcribe\";\nimport { handleDebugEvents } from \"../handlers/handle-debug-events\";\nimport {\n handleClearThreads,\n handleListThreads,\n handleSubscribeToThreads,\n handleUpdateThread,\n handleArchiveThread,\n handleDeleteThread,\n handleGetThreadMessages,\n handleGetThreadEvents,\n handleGetThreadState,\n} from \"../handlers/handle-threads\";\nimport { handleAnnotate } from \"../handlers/handle-user-actions\";\nimport {\n parseMethodCall,\n createJsonRequest,\n expectString,\n} from \"../endpoints/single-route-helpers\";\nimport type { MethodCall } from \"../endpoints/single-route-helpers\";\nimport { logger } from \"@copilotkit/shared\";\nimport { fireInstanceCreatedTelemetry } from \"../telemetry/instance-created\";\n\n/* ------------------------------------------------------------------------------------------------\n * Public types\n * --------------------------------------------------------------------------------------------- */\n\nexport interface CopilotRuntimeHandlerOptions {\n runtime: CopilotRuntimeLike;\n\n /**\n * Optional base path for routing.\n *\n * When provided: strict prefix stripping. The handler strips this prefix from the\n * URL pathname and matches the remainder against known routes.\n *\n * When omitted: suffix matching. The handler matches known route patterns as\n * suffixes of the URL pathname.\n */\n basePath?: string;\n\n /**\n * Endpoint mode:\n * - \"multi-route\" (default): Routes like POST /agent/:agentId/run, GET /info, etc.\n * - \"single-route\": Single POST endpoint with JSON envelope { method, params, body }\n */\n mode?: \"multi-route\" | \"single-route\";\n\n /**\n * Optional CORS configuration.\n * When not provided, no CORS headers are added (let the framework handle it).\n * Set to true for permissive defaults, or provide an object.\n */\n cors?: boolean | CopilotCorsConfig;\n\n /**\n * Lifecycle hooks for request processing.\n */\n hooks?: CopilotRuntimeHooks;\n}\n\nexport type CopilotRuntimeFetchHandler = (\n request: Request,\n) => Promise<Response>;\n\n/* ------------------------------------------------------------------------------------------------\n * Handler factory\n * --------------------------------------------------------------------------------------------- */\n\nexport function createCopilotRuntimeHandler(\n options: CopilotRuntimeHandlerOptions,\n): CopilotRuntimeFetchHandler {\n const { runtime, basePath, mode = \"multi-route\", cors, hooks } = options;\n\n fireInstanceCreatedTelemetry({ runtime });\n\n const corsConfig = resolveCorsConfig(cors);\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url, \"http://localhost\");\n const path = url.pathname;\n const requestOrigin = request.headers.get(\"origin\");\n\n // Base hook context (route not yet known)\n const baseCtx: HookContext = { request, path, runtime };\n\n let route: RouteInfo | undefined;\n\n try {\n // 1. CORS preflight\n if (corsConfig) {\n const preflight = handleCors(request, corsConfig);\n if (preflight) return preflight;\n }\n\n // 2. onRequest hook\n request = await runOnRequest(hooks, { ...baseCtx, request });\n\n // 3. Legacy beforeRequestMiddleware\n try {\n const maybeModified = await callBeforeRequestMiddleware({\n runtime,\n request,\n path,\n });\n if (maybeModified) {\n request = maybeModified;\n }\n } catch (mwError: unknown) {\n logger.error(\n { err: mwError, url: request.url, path },\n \"Error running before request middleware\",\n );\n if (mwError instanceof Response) {\n return maybeAddCors(mwError, corsConfig, requestOrigin);\n }\n throw mwError;\n }\n\n // 4. Route matching\n let response: Response;\n\n if (mode === \"single-route\") {\n const resolved = await resolveSingleRoute(request, basePath, path);\n route = resolved.route;\n const { methodCall } = resolved;\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n // 6. Wrap body for methods that need it, then dispatch\n if (\n route.method === \"agent/run\" ||\n route.method === \"agent/connect\" ||\n route.method === \"transcribe\"\n ) {\n request = createJsonRequest(request, methodCall.body);\n }\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: false,\n });\n } else {\n // Multi-route: match URL pattern\n const matched = matchRoute(path, basePath);\n if (!matched) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n\n // Validate HTTP method\n const methodError = validateHttpMethod(request.method, matched);\n if (methodError) {\n route = matched;\n throw methodError;\n }\n\n route = matched;\n\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n\n // 6. Handler dispatch\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: true,\n });\n }\n\n // 7. onResponse hook\n response = await runOnResponse(hooks, {\n request,\n response,\n path,\n runtime,\n route,\n });\n\n // 8. CORS headers on response\n response = maybeAddCors(response, corsConfig, requestOrigin);\n\n // 9. Legacy afterRequestMiddleware (non-blocking)\n // Clone the response so middleware can read the body without consuming\n // the original stream that will be sent to the client.\n callAfterRequestMiddleware({\n runtime,\n response: response.clone(),\n path,\n }).catch((error: unknown) => {\n logger.error(\n { err: error, url: request.url, path },\n \"Error running after request middleware\",\n );\n });\n\n return response;\n } catch (error) {\n // Short-circuit with thrown Response\n if (error instanceof Response) {\n const finalResponse = await runOnResponse(hooks, {\n request,\n response: error,\n path,\n runtime,\n route: route ?? { method: \"info\" },\n });\n return maybeAddCors(finalResponse, corsConfig, requestOrigin);\n }\n\n // Run onError hook — wrapped so a throwing hook doesn't escape\n try {\n const errorResponse = await runOnError(hooks, {\n request,\n error,\n path,\n runtime,\n route,\n });\n\n if (errorResponse) {\n return maybeAddCors(errorResponse, corsConfig, requestOrigin);\n }\n } catch (hookError: unknown) {\n logger.error(\n { err: hookError, originalErr: error, url: request.url, path },\n \"onError hook threw\",\n );\n }\n\n logger.error(\n { err: error, url: request.url, path },\n \"Unhandled error in CopilotKit runtime handler\",\n );\n\n return maybeAddCors(\n jsonResponse({ error: \"internal_error\" }, 500),\n corsConfig,\n requestOrigin,\n );\n }\n };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Route dispatch\n * --------------------------------------------------------------------------------------------- */\n\nfunction dispatchRoute(\n runtime: CopilotRuntimeLike,\n request: Request,\n route: RouteInfo,\n options: { threadEndpointsEnabled: boolean },\n): Promise<Response> {\n switch (route.method) {\n case \"agent/run\":\n return handleRunAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/connect\":\n return handleConnectAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/stop\":\n return handleStopAgent({\n runtime,\n request,\n agentId: route.agentId,\n threadId: route.threadId,\n });\n case \"info\":\n return handleGetRuntimeInfo({\n runtime,\n request,\n threadEndpointsEnabled: options.threadEndpointsEnabled,\n });\n case \"transcribe\":\n return handleTranscribe({ runtime, request });\n case \"threads/clear\":\n return Promise.resolve(handleClearThreads({ runtime, request }));\n case \"threads/list\":\n return handleListThreads({ runtime, request });\n case \"threads/subscribe\":\n return handleSubscribeToThreads({ runtime, request });\n case \"threads/update\":\n if (request.method.toUpperCase() === \"DELETE\") {\n return handleDeleteThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n }\n return handleUpdateThread({ runtime, request, threadId: route.threadId });\n case \"threads/archive\":\n return handleArchiveThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/messages\":\n return handleGetThreadMessages({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/events\":\n return handleGetThreadEvents({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/state\":\n return handleGetThreadState({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"annotate\":\n return handleAnnotate({ runtime, request });\n case \"cpk-debug-events\":\n return Promise.resolve(handleDebugEvents({ runtime, request }));\n }\n}\n\ninterface SingleRouteResolution {\n route: RouteInfo;\n methodCall: MethodCall;\n}\n\nasync function resolveSingleRoute(\n request: Request,\n basePath: string | undefined,\n pathname: string,\n): Promise<SingleRouteResolution> {\n if (basePath) {\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n if (!pathname.startsWith(normalizedBase)) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n }\n\n if (request.method !== \"POST\") {\n throw jsonResponse({ error: \"Method not allowed\" }, 405, { Allow: \"POST\" });\n }\n\n const methodCall = await parseMethodCall(request);\n\n let route: RouteInfo;\n switch (methodCall.method) {\n case \"agent/run\":\n route = {\n method: \"agent/run\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/connect\":\n route = {\n method: \"agent/connect\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/stop\":\n route = {\n method: \"agent/stop\",\n agentId: expectString(methodCall.params, \"agentId\"),\n threadId: expectString(methodCall.params, \"threadId\"),\n };\n break;\n case \"info\":\n route = { method: \"info\" };\n break;\n case \"transcribe\":\n route = { method: \"transcribe\" };\n break;\n }\n\n return { route, methodCall };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * HTTP method validation\n * --------------------------------------------------------------------------------------------- */\n\nfunction validateHttpMethod(\n httpMethod: string,\n route: RouteInfo,\n): Response | null {\n const method = httpMethod.toUpperCase();\n\n switch (route.method) {\n case \"info\":\n case \"threads/list\":\n case \"threads/messages\":\n case \"threads/events\":\n case \"threads/state\":\n case \"cpk-debug-events\":\n if (method === \"GET\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET\",\n });\n\n case \"threads/update\":\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n default:\n if (method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"POST\",\n });\n }\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Helpers\n * --------------------------------------------------------------------------------------------- */\n\nfunction resolveCorsConfig(\n cors: boolean | CopilotCorsConfig | undefined,\n): CopilotCorsConfig | null {\n if (!cors) return null;\n if (cors === true) return {};\n return cors;\n}\n\nfunction maybeAddCors(\n response: Response,\n config: CopilotCorsConfig | null,\n requestOrigin: string | null,\n): Response {\n if (!config) return response;\n return addCorsHeaders(response, config, requestOrigin);\n}\n\nfunction jsonResponse(\n body: unknown,\n status: number,\n extraHeaders?: Record<string, string>,\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", ...extraHeaders },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fetch-handler.cjs","names":["handleCors","runOnRequest","callBeforeRequestMiddleware","runOnBeforeHandler","createJsonRequest","matchRoute","runOnResponse","runOnError","handleRunAgent","handleSuggestAgent","handleConnectAgent","handleStopAgent","handleGetRuntimeInfo","handleTranscribe","handleClearThreads","handleListThreads","handleCreateMemory","handleListMemories","handleSubscribeToMemories","handleRemoveMemory","handleUpdateMemory","handleSubscribeToThreads","handleDeleteThread","handleUpdateThread","handleArchiveThread","handleGetThreadMessages","handleGetThreadEvents","handleGetThreadState","handleAnnotate","handleDebugEvents","parseMethodCall","expectString","addCorsHeaders"],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"sourcesContent":["/**\n * Framework-agnostic CopilotKit runtime handler.\n *\n * Returns a pure `(Request) => Promise<Response>` function that can be used\n * directly with Bun, Deno, Cloudflare Workers, Next.js App Router, or any\n * Fetch-native runtime — no framework dependency required.\n *\n * @example\n * ```typescript\n * import { CopilotRuntime, createCopilotRuntimeHandler } from \"@copilotkit/runtime/v2\";\n *\n * const handler = createCopilotRuntimeHandler({\n * runtime: new CopilotRuntime({ agents: { ... } }),\n * basePath: \"/api/copilotkit\",\n * cors: true,\n * });\n *\n * // Bun\n * Bun.serve({ fetch: handler });\n *\n * // Deno\n * Deno.serve(handler);\n *\n * // Cloudflare Workers\n * export default { fetch: handler };\n * ```\n */\n\nimport type { CopilotRuntimeLike } from \"./runtime\";\nimport type { CopilotRuntimeHooks, RouteInfo, HookContext } from \"./hooks\";\nimport {\n runOnRequest,\n runOnBeforeHandler,\n runOnResponse,\n runOnError,\n} from \"./hooks\";\nimport type { CopilotCorsConfig } from \"./fetch-cors\";\nimport { handleCors, addCorsHeaders } from \"./fetch-cors\";\nimport { matchRoute } from \"./fetch-router\";\nimport {\n callBeforeRequestMiddleware,\n callAfterRequestMiddleware,\n} from \"./middleware\";\nimport { handleRunAgent } from \"../handlers/handle-run\";\nimport { handleSuggestAgent } from \"../handlers/handle-suggest\";\nimport { handleConnectAgent } from \"../handlers/handle-connect\";\nimport { handleStopAgent } from \"../handlers/handle-stop\";\nimport { handleGetRuntimeInfo } from \"../handlers/get-runtime-info\";\nimport { handleTranscribe } from \"../handlers/handle-transcribe\";\nimport { handleDebugEvents } from \"../handlers/handle-debug-events\";\nimport {\n handleClearThreads,\n handleListThreads,\n handleSubscribeToThreads,\n handleUpdateThread,\n handleArchiveThread,\n handleDeleteThread,\n handleGetThreadMessages,\n handleGetThreadEvents,\n handleGetThreadState,\n} from \"../handlers/handle-threads\";\nimport {\n handleListMemories,\n handleSubscribeToMemories,\n handleCreateMemory,\n handleUpdateMemory,\n handleRemoveMemory,\n} from \"../handlers/handle-memories\";\nimport { handleAnnotate } from \"../handlers/handle-user-actions\";\nimport {\n parseMethodCall,\n createJsonRequest,\n expectString,\n} from \"../endpoints/single-route-helpers\";\nimport type { MethodCall } from \"../endpoints/single-route-helpers\";\nimport { logger } from \"@copilotkit/shared\";\nimport { fireInstanceCreatedTelemetry } from \"../telemetry/instance-created\";\n\n/* ------------------------------------------------------------------------------------------------\n * Public types\n * --------------------------------------------------------------------------------------------- */\n\nexport interface CopilotRuntimeHandlerOptions {\n runtime: CopilotRuntimeLike;\n\n /**\n * Optional base path for routing.\n *\n * When provided: strict prefix stripping. The handler strips this prefix from the\n * URL pathname and matches the remainder against known routes.\n *\n * When omitted: suffix matching. The handler matches known route patterns as\n * suffixes of the URL pathname.\n */\n basePath?: string;\n\n /**\n * Endpoint mode:\n * - \"multi-route\" (default): Routes like POST /agent/:agentId/run, GET /info, etc.\n * - \"single-route\": Single POST endpoint with JSON envelope { method, params, body }\n */\n mode?: \"multi-route\" | \"single-route\";\n\n /**\n * Optional CORS configuration.\n * When not provided, no CORS headers are added (let the framework handle it).\n * Set to true for permissive defaults, or provide an object.\n */\n cors?: boolean | CopilotCorsConfig;\n\n /**\n * Lifecycle hooks for request processing.\n */\n hooks?: CopilotRuntimeHooks;\n}\n\nexport type CopilotRuntimeFetchHandler = (\n request: Request,\n) => Promise<Response>;\n\n/* ------------------------------------------------------------------------------------------------\n * Handler factory\n * --------------------------------------------------------------------------------------------- */\n\nexport function createCopilotRuntimeHandler(\n options: CopilotRuntimeHandlerOptions,\n): CopilotRuntimeFetchHandler {\n const { runtime, basePath, mode = \"multi-route\", cors, hooks } = options;\n\n fireInstanceCreatedTelemetry({ runtime });\n\n const corsConfig = resolveCorsConfig(cors);\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url, \"http://localhost\");\n const path = url.pathname;\n const requestOrigin = request.headers.get(\"origin\");\n\n // Base hook context (route not yet known)\n const baseCtx: HookContext = { request, path, runtime };\n\n let route: RouteInfo | undefined;\n\n try {\n // 1. CORS preflight\n if (corsConfig) {\n const preflight = handleCors(request, corsConfig);\n if (preflight) return preflight;\n }\n\n // 2. onRequest hook\n request = await runOnRequest(hooks, { ...baseCtx, request });\n\n // 3. Legacy beforeRequestMiddleware\n try {\n const maybeModified = await callBeforeRequestMiddleware({\n runtime,\n request,\n path,\n });\n if (maybeModified) {\n request = maybeModified;\n }\n } catch (mwError: unknown) {\n logger.error(\n { err: mwError, url: request.url, path },\n \"Error running before request middleware\",\n );\n if (mwError instanceof Response) {\n return maybeAddCors(mwError, corsConfig, requestOrigin);\n }\n throw mwError;\n }\n\n // 4. Route matching\n let response: Response;\n\n if (mode === \"single-route\") {\n const resolved = await resolveSingleRoute(request, basePath, path);\n route = resolved.route;\n const { methodCall } = resolved;\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n // 6. Wrap body for methods that need it, then dispatch\n if (\n route.method === \"agent/run\" ||\n route.method === \"agent/suggest\" ||\n route.method === \"agent/connect\" ||\n route.method === \"transcribe\"\n ) {\n request = createJsonRequest(request, methodCall.body);\n }\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: false,\n });\n } else {\n // Multi-route: match URL pattern\n const matched = matchRoute(path, basePath);\n if (!matched) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n\n // Validate HTTP method\n const methodError = validateHttpMethod(request.method, matched);\n if (methodError) {\n route = matched;\n throw methodError;\n }\n\n route = matched;\n\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n\n // 6. Handler dispatch\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: true,\n });\n }\n\n // 7. onResponse hook\n response = await runOnResponse(hooks, {\n request,\n response,\n path,\n runtime,\n route,\n });\n\n // 8. CORS headers on response\n response = maybeAddCors(response, corsConfig, requestOrigin);\n\n // 9. Legacy afterRequestMiddleware (non-blocking)\n // Clone the response so middleware can read the body without consuming\n // the original stream that will be sent to the client.\n callAfterRequestMiddleware({\n runtime,\n response: response.clone(),\n path,\n }).catch((error: unknown) => {\n logger.error(\n { err: error, url: request.url, path },\n \"Error running after request middleware\",\n );\n });\n\n return response;\n } catch (error) {\n // Short-circuit with thrown Response\n if (error instanceof Response) {\n const finalResponse = await runOnResponse(hooks, {\n request,\n response: error,\n path,\n runtime,\n route: route ?? { method: \"info\" },\n });\n return maybeAddCors(finalResponse, corsConfig, requestOrigin);\n }\n\n // Run onError hook — wrapped so a throwing hook doesn't escape\n try {\n const errorResponse = await runOnError(hooks, {\n request,\n error,\n path,\n runtime,\n route,\n });\n\n if (errorResponse) {\n return maybeAddCors(errorResponse, corsConfig, requestOrigin);\n }\n } catch (hookError: unknown) {\n logger.error(\n { err: hookError, originalErr: error, url: request.url, path },\n \"onError hook threw\",\n );\n }\n\n logger.error(\n { err: error, url: request.url, path },\n \"Unhandled error in CopilotKit runtime handler\",\n );\n\n return maybeAddCors(\n jsonResponse({ error: \"internal_error\" }, 500),\n corsConfig,\n requestOrigin,\n );\n }\n };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Route dispatch\n * --------------------------------------------------------------------------------------------- */\n\nfunction dispatchRoute(\n runtime: CopilotRuntimeLike,\n request: Request,\n route: RouteInfo,\n options: { threadEndpointsEnabled: boolean },\n): Promise<Response> {\n switch (route.method) {\n case \"agent/run\":\n return handleRunAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/suggest\":\n return handleSuggestAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/connect\":\n return handleConnectAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/stop\":\n return handleStopAgent({\n runtime,\n request,\n agentId: route.agentId,\n threadId: route.threadId,\n });\n case \"info\":\n return handleGetRuntimeInfo({\n runtime,\n request,\n threadEndpointsEnabled: options.threadEndpointsEnabled,\n });\n case \"transcribe\":\n return handleTranscribe({ runtime, request });\n case \"threads/clear\":\n return Promise.resolve(handleClearThreads({ runtime, request }));\n case \"threads/list\":\n return handleListThreads({ runtime, request });\n case \"memories/list\":\n return request.method.toUpperCase() === \"POST\"\n ? handleCreateMemory({ runtime, request })\n : handleListMemories({ runtime, request });\n case \"memories/subscribe\":\n return handleSubscribeToMemories({ runtime, request });\n case \"memories/mutate\":\n return request.method.toUpperCase() === \"DELETE\"\n ? handleRemoveMemory({ runtime, request, memoryId: route.memoryId })\n : handleUpdateMemory({ runtime, request, memoryId: route.memoryId });\n case \"threads/subscribe\":\n return handleSubscribeToThreads({ runtime, request });\n case \"threads/update\":\n if (request.method.toUpperCase() === \"DELETE\") {\n return handleDeleteThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n }\n return handleUpdateThread({ runtime, request, threadId: route.threadId });\n case \"threads/archive\":\n return handleArchiveThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/messages\":\n return handleGetThreadMessages({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/events\":\n return handleGetThreadEvents({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/state\":\n return handleGetThreadState({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"annotate\":\n return handleAnnotate({ runtime, request });\n case \"cpk-debug-events\":\n return Promise.resolve(handleDebugEvents({ runtime, request }));\n default: {\n // Exhaustiveness guard: a new `RouteInfo` variant added without a case\n // above becomes a compile error here instead of silently returning\n // `undefined` at runtime.\n const _exhaustive: never = route;\n throw jsonResponse(\n { error: \"Not found\", method: (_exhaustive as RouteInfo).method },\n 404,\n );\n }\n }\n}\n\ninterface SingleRouteResolution {\n route: RouteInfo;\n methodCall: MethodCall;\n}\n\nasync function resolveSingleRoute(\n request: Request,\n basePath: string | undefined,\n pathname: string,\n): Promise<SingleRouteResolution> {\n if (basePath) {\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n if (!pathname.startsWith(normalizedBase)) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n }\n\n if (request.method !== \"POST\") {\n throw jsonResponse({ error: \"Method not allowed\" }, 405, { Allow: \"POST\" });\n }\n\n const methodCall = await parseMethodCall(request);\n\n let route: RouteInfo;\n switch (methodCall.method) {\n case \"agent/run\":\n route = {\n method: \"agent/run\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/suggest\":\n route = {\n method: \"agent/suggest\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/connect\":\n route = {\n method: \"agent/connect\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/stop\":\n route = {\n method: \"agent/stop\",\n agentId: expectString(methodCall.params, \"agentId\"),\n threadId: expectString(methodCall.params, \"threadId\"),\n };\n break;\n case \"info\":\n route = { method: \"info\" };\n break;\n case \"transcribe\":\n route = { method: \"transcribe\" };\n break;\n default: {\n // Exhaustiveness guard: a new `METHOD_NAMES`/`EndpointMethod` variant\n // added without a case above becomes a compile error here instead of\n // leaving `route` unassigned at runtime.\n const _exhaustive: never = methodCall.method;\n throw jsonResponse({ error: \"Not found\", method: _exhaustive }, 404);\n }\n }\n\n return { route, methodCall };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * HTTP method validation\n * --------------------------------------------------------------------------------------------- */\n\nfunction validateHttpMethod(\n httpMethod: string,\n route: RouteInfo,\n): Response | null {\n const method = httpMethod.toUpperCase();\n\n switch (route.method) {\n case \"info\":\n case \"threads/list\":\n case \"threads/messages\":\n case \"threads/events\":\n case \"threads/state\":\n case \"cpk-debug-events\":\n if (method === \"GET\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET\",\n });\n\n case \"memories/list\":\n // GET lists the user's memories; POST creates one.\n if (method === \"GET\" || method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET, POST\",\n });\n\n case \"memories/mutate\":\n // PATCH supersedes; DELETE retires.\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n case \"threads/update\":\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n default:\n if (method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"POST\",\n });\n }\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Helpers\n * --------------------------------------------------------------------------------------------- */\n\nfunction resolveCorsConfig(\n cors: boolean | CopilotCorsConfig | undefined,\n): CopilotCorsConfig | null {\n if (!cors) return null;\n if (cors === true) return {};\n return cors;\n}\n\nfunction maybeAddCors(\n response: Response,\n config: CopilotCorsConfig | null,\n requestOrigin: string | null,\n): Response {\n if (!config) return response;\n return addCorsHeaders(response, config, requestOrigin);\n}\n\nfunction jsonResponse(\n body: unknown,\n status: number,\n extraHeaders?: Record<string, string>,\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", ...extraHeaders },\n });\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.d.cts","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"mappings":";;;;;;UA0EiB,4BAAA;EACf,OAAA,EAAS,kBAAA;EAkCT;;;;;AAOF;;;;EA9BE,QAAA;EA+BA;;;;;EAxBA,IAAA;;;;;;EAOA,IAAA,aAAiB,iBAAA;;;;EAKjB,KAAA,GAAQ,mBAAA;AAAA;AAAA,KAGE,0BAAA,IACV,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA,iBAMG,2BAAA,CACd,OAAA,EAAS,4BAAA,GACR,0BAAA"}
1
+ {"version":3,"file":"fetch-handler.d.cts","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"mappings":";;;;;;UAkFiB,4BAAA;EACf,OAAA,EAAS,kBAAA;EAkCT;;;;;AAOF;;;;EA9BE,QAAA;EA+BA;;;;;EAxBA,IAAA;;;;;;EAOA,IAAA,aAAiB,iBAAA;;;;EAKjB,KAAA,GAAQ,mBAAA;AAAA;AAAA,KAGE,0BAAA,IACV,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA,iBAMG,2BAAA,CACd,OAAA,EAAS,4BAAA,GACR,0BAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.d.mts","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"mappings":";;;;;;UA0EiB,4BAAA;EACf,OAAA,EAAS,kBAAA;EAkCT;;;;;AAOF;;;;EA9BE,QAAA;EA+BA;;;;;EAxBA,IAAA;;;;;;EAOA,IAAA,aAAiB,iBAAA;;;;EAKjB,KAAA,GAAQ,mBAAA;AAAA;AAAA,KAGE,0BAAA,IACV,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA,iBAMG,2BAAA,CACd,OAAA,EAAS,4BAAA,GACR,0BAAA"}
1
+ {"version":3,"file":"fetch-handler.d.mts","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"mappings":";;;;;;UAkFiB,4BAAA;EACf,OAAA,EAAS,kBAAA;EAkCT;;;;;AAOF;;;;EA9BE,QAAA;EA+BA;;;;;EAxBA,IAAA;;;;;;EAOA,IAAA,aAAiB,iBAAA;;;;EAKjB,KAAA,GAAQ,mBAAA;AAAA;AAAA,KAGE,0BAAA,IACV,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA,iBAMG,2BAAA,CACd,OAAA,EAAS,4BAAA,GACR,0BAAA"}
@@ -4,12 +4,14 @@ import { addCorsHeaders, handleCors } from "./fetch-cors.mjs";
4
4
  import { matchRoute } from "./fetch-router.mjs";
5
5
  import { callAfterRequestMiddleware, callBeforeRequestMiddleware } from "./middleware.mjs";
6
6
  import { handleRunAgent } from "../handlers/handle-run.mjs";
7
+ import { handleSuggestAgent } from "../handlers/handle-suggest.mjs";
7
8
  import { handleConnectAgent } from "../handlers/handle-connect.mjs";
8
9
  import { handleStopAgent } from "../handlers/handle-stop.mjs";
9
10
  import { handleGetRuntimeInfo } from "../handlers/get-runtime-info.mjs";
10
11
  import { handleTranscribe } from "../handlers/handle-transcribe.mjs";
11
12
  import { handleDebugEvents } from "../handlers/handle-debug-events.mjs";
12
13
  import { handleArchiveThread, handleClearThreads, handleDeleteThread, handleGetThreadEvents, handleGetThreadMessages, handleGetThreadState, handleListThreads, handleSubscribeToThreads, handleUpdateThread } from "../handlers/intelligence/threads.mjs";
14
+ import { handleCreateMemory, handleListMemories, handleRemoveMemory, handleSubscribeToMemories, handleUpdateMemory } from "../handlers/intelligence/memories.mjs";
13
15
  import { handleAnnotate } from "../handlers/intelligence/annotate.mjs";
14
16
  import { createJsonRequest, expectString, parseMethodCall } from "../endpoints/single-route-helpers.mjs";
15
17
  import { fireInstanceCreatedTelemetry } from "../telemetry/instance-created.mjs";
@@ -65,7 +67,7 @@ function createCopilotRuntimeHandler(options) {
65
67
  runtime,
66
68
  route
67
69
  });
68
- if (route.method === "agent/run" || route.method === "agent/connect" || route.method === "transcribe") request = createJsonRequest(request, methodCall.body);
70
+ if (route.method === "agent/run" || route.method === "agent/suggest" || route.method === "agent/connect" || route.method === "transcribe") request = createJsonRequest(request, methodCall.body);
69
71
  response = await dispatchRoute(runtime, request, route, { threadEndpointsEnabled: false });
70
72
  } else {
71
73
  const matched = matchRoute(path, basePath);
@@ -145,6 +147,11 @@ function dispatchRoute(runtime, request, route, options) {
145
147
  request,
146
148
  agentId: route.agentId
147
149
  });
150
+ case "agent/suggest": return handleSuggestAgent({
151
+ runtime,
152
+ request,
153
+ agentId: route.agentId
154
+ });
148
155
  case "agent/connect": return handleConnectAgent({
149
156
  runtime,
150
157
  request,
@@ -173,6 +180,26 @@ function dispatchRoute(runtime, request, route, options) {
173
180
  runtime,
174
181
  request
175
182
  });
183
+ case "memories/list": return request.method.toUpperCase() === "POST" ? handleCreateMemory({
184
+ runtime,
185
+ request
186
+ }) : handleListMemories({
187
+ runtime,
188
+ request
189
+ });
190
+ case "memories/subscribe": return handleSubscribeToMemories({
191
+ runtime,
192
+ request
193
+ });
194
+ case "memories/mutate": return request.method.toUpperCase() === "DELETE" ? handleRemoveMemory({
195
+ runtime,
196
+ request,
197
+ memoryId: route.memoryId
198
+ }) : handleUpdateMemory({
199
+ runtime,
200
+ request,
201
+ memoryId: route.memoryId
202
+ });
176
203
  case "threads/subscribe": return handleSubscribeToThreads({
177
204
  runtime,
178
205
  request
@@ -216,6 +243,10 @@ function dispatchRoute(runtime, request, route, options) {
216
243
  runtime,
217
244
  request
218
245
  }));
246
+ default: throw jsonResponse({
247
+ error: "Not found",
248
+ method: route.method
249
+ }, 404);
219
250
  }
220
251
  }
221
252
  async function resolveSingleRoute(request, basePath, pathname) {
@@ -233,6 +264,12 @@ async function resolveSingleRoute(request, basePath, pathname) {
233
264
  agentId: expectString(methodCall.params, "agentId")
234
265
  };
235
266
  break;
267
+ case "agent/suggest":
268
+ route = {
269
+ method: "agent/suggest",
270
+ agentId: expectString(methodCall.params, "agentId")
271
+ };
272
+ break;
236
273
  case "agent/connect":
237
274
  route = {
238
275
  method: "agent/connect",
@@ -252,6 +289,13 @@ async function resolveSingleRoute(request, basePath, pathname) {
252
289
  case "transcribe":
253
290
  route = { method: "transcribe" };
254
291
  break;
292
+ default: {
293
+ const _exhaustive = methodCall.method;
294
+ throw jsonResponse({
295
+ error: "Not found",
296
+ method: _exhaustive
297
+ }, 404);
298
+ }
255
299
  }
256
300
  return {
257
301
  route,
@@ -269,6 +313,12 @@ function validateHttpMethod(httpMethod, route) {
269
313
  case "cpk-debug-events":
270
314
  if (method === "GET") return null;
271
315
  return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "GET" });
316
+ case "memories/list":
317
+ if (method === "GET" || method === "POST") return null;
318
+ return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "GET, POST" });
319
+ case "memories/mutate":
320
+ if (method === "PATCH" || method === "DELETE") return null;
321
+ return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "PATCH, DELETE" });
272
322
  case "threads/update":
273
323
  if (method === "PATCH" || method === "DELETE") return null;
274
324
  return jsonResponse({ error: "Method not allowed" }, 405, { Allow: "PATCH, DELETE" });
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.mjs","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"sourcesContent":["/**\n * Framework-agnostic CopilotKit runtime handler.\n *\n * Returns a pure `(Request) => Promise<Response>` function that can be used\n * directly with Bun, Deno, Cloudflare Workers, Next.js App Router, or any\n * Fetch-native runtime — no framework dependency required.\n *\n * @example\n * ```typescript\n * import { CopilotRuntime, createCopilotRuntimeHandler } from \"@copilotkit/runtime/v2\";\n *\n * const handler = createCopilotRuntimeHandler({\n * runtime: new CopilotRuntime({ agents: { ... } }),\n * basePath: \"/api/copilotkit\",\n * cors: true,\n * });\n *\n * // Bun\n * Bun.serve({ fetch: handler });\n *\n * // Deno\n * Deno.serve(handler);\n *\n * // Cloudflare Workers\n * export default { fetch: handler };\n * ```\n */\n\nimport type { CopilotRuntimeLike } from \"./runtime\";\nimport type { CopilotRuntimeHooks, RouteInfo, HookContext } from \"./hooks\";\nimport {\n runOnRequest,\n runOnBeforeHandler,\n runOnResponse,\n runOnError,\n} from \"./hooks\";\nimport type { CopilotCorsConfig } from \"./fetch-cors\";\nimport { handleCors, addCorsHeaders } from \"./fetch-cors\";\nimport { matchRoute } from \"./fetch-router\";\nimport {\n callBeforeRequestMiddleware,\n callAfterRequestMiddleware,\n} from \"./middleware\";\nimport { handleRunAgent } from \"../handlers/handle-run\";\nimport { handleConnectAgent } from \"../handlers/handle-connect\";\nimport { handleStopAgent } from \"../handlers/handle-stop\";\nimport { handleGetRuntimeInfo } from \"../handlers/get-runtime-info\";\nimport { handleTranscribe } from \"../handlers/handle-transcribe\";\nimport { handleDebugEvents } from \"../handlers/handle-debug-events\";\nimport {\n handleClearThreads,\n handleListThreads,\n handleSubscribeToThreads,\n handleUpdateThread,\n handleArchiveThread,\n handleDeleteThread,\n handleGetThreadMessages,\n handleGetThreadEvents,\n handleGetThreadState,\n} from \"../handlers/handle-threads\";\nimport { handleAnnotate } from \"../handlers/handle-user-actions\";\nimport {\n parseMethodCall,\n createJsonRequest,\n expectString,\n} from \"../endpoints/single-route-helpers\";\nimport type { MethodCall } from \"../endpoints/single-route-helpers\";\nimport { logger } from \"@copilotkit/shared\";\nimport { fireInstanceCreatedTelemetry } from \"../telemetry/instance-created\";\n\n/* ------------------------------------------------------------------------------------------------\n * Public types\n * --------------------------------------------------------------------------------------------- */\n\nexport interface CopilotRuntimeHandlerOptions {\n runtime: CopilotRuntimeLike;\n\n /**\n * Optional base path for routing.\n *\n * When provided: strict prefix stripping. The handler strips this prefix from the\n * URL pathname and matches the remainder against known routes.\n *\n * When omitted: suffix matching. The handler matches known route patterns as\n * suffixes of the URL pathname.\n */\n basePath?: string;\n\n /**\n * Endpoint mode:\n * - \"multi-route\" (default): Routes like POST /agent/:agentId/run, GET /info, etc.\n * - \"single-route\": Single POST endpoint with JSON envelope { method, params, body }\n */\n mode?: \"multi-route\" | \"single-route\";\n\n /**\n * Optional CORS configuration.\n * When not provided, no CORS headers are added (let the framework handle it).\n * Set to true for permissive defaults, or provide an object.\n */\n cors?: boolean | CopilotCorsConfig;\n\n /**\n * Lifecycle hooks for request processing.\n */\n hooks?: CopilotRuntimeHooks;\n}\n\nexport type CopilotRuntimeFetchHandler = (\n request: Request,\n) => Promise<Response>;\n\n/* ------------------------------------------------------------------------------------------------\n * Handler factory\n * --------------------------------------------------------------------------------------------- */\n\nexport function createCopilotRuntimeHandler(\n options: CopilotRuntimeHandlerOptions,\n): CopilotRuntimeFetchHandler {\n const { runtime, basePath, mode = \"multi-route\", cors, hooks } = options;\n\n fireInstanceCreatedTelemetry({ runtime });\n\n const corsConfig = resolveCorsConfig(cors);\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url, \"http://localhost\");\n const path = url.pathname;\n const requestOrigin = request.headers.get(\"origin\");\n\n // Base hook context (route not yet known)\n const baseCtx: HookContext = { request, path, runtime };\n\n let route: RouteInfo | undefined;\n\n try {\n // 1. CORS preflight\n if (corsConfig) {\n const preflight = handleCors(request, corsConfig);\n if (preflight) return preflight;\n }\n\n // 2. onRequest hook\n request = await runOnRequest(hooks, { ...baseCtx, request });\n\n // 3. Legacy beforeRequestMiddleware\n try {\n const maybeModified = await callBeforeRequestMiddleware({\n runtime,\n request,\n path,\n });\n if (maybeModified) {\n request = maybeModified;\n }\n } catch (mwError: unknown) {\n logger.error(\n { err: mwError, url: request.url, path },\n \"Error running before request middleware\",\n );\n if (mwError instanceof Response) {\n return maybeAddCors(mwError, corsConfig, requestOrigin);\n }\n throw mwError;\n }\n\n // 4. Route matching\n let response: Response;\n\n if (mode === \"single-route\") {\n const resolved = await resolveSingleRoute(request, basePath, path);\n route = resolved.route;\n const { methodCall } = resolved;\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n // 6. Wrap body for methods that need it, then dispatch\n if (\n route.method === \"agent/run\" ||\n route.method === \"agent/connect\" ||\n route.method === \"transcribe\"\n ) {\n request = createJsonRequest(request, methodCall.body);\n }\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: false,\n });\n } else {\n // Multi-route: match URL pattern\n const matched = matchRoute(path, basePath);\n if (!matched) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n\n // Validate HTTP method\n const methodError = validateHttpMethod(request.method, matched);\n if (methodError) {\n route = matched;\n throw methodError;\n }\n\n route = matched;\n\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n\n // 6. Handler dispatch\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: true,\n });\n }\n\n // 7. onResponse hook\n response = await runOnResponse(hooks, {\n request,\n response,\n path,\n runtime,\n route,\n });\n\n // 8. CORS headers on response\n response = maybeAddCors(response, corsConfig, requestOrigin);\n\n // 9. Legacy afterRequestMiddleware (non-blocking)\n // Clone the response so middleware can read the body without consuming\n // the original stream that will be sent to the client.\n callAfterRequestMiddleware({\n runtime,\n response: response.clone(),\n path,\n }).catch((error: unknown) => {\n logger.error(\n { err: error, url: request.url, path },\n \"Error running after request middleware\",\n );\n });\n\n return response;\n } catch (error) {\n // Short-circuit with thrown Response\n if (error instanceof Response) {\n const finalResponse = await runOnResponse(hooks, {\n request,\n response: error,\n path,\n runtime,\n route: route ?? { method: \"info\" },\n });\n return maybeAddCors(finalResponse, corsConfig, requestOrigin);\n }\n\n // Run onError hook — wrapped so a throwing hook doesn't escape\n try {\n const errorResponse = await runOnError(hooks, {\n request,\n error,\n path,\n runtime,\n route,\n });\n\n if (errorResponse) {\n return maybeAddCors(errorResponse, corsConfig, requestOrigin);\n }\n } catch (hookError: unknown) {\n logger.error(\n { err: hookError, originalErr: error, url: request.url, path },\n \"onError hook threw\",\n );\n }\n\n logger.error(\n { err: error, url: request.url, path },\n \"Unhandled error in CopilotKit runtime handler\",\n );\n\n return maybeAddCors(\n jsonResponse({ error: \"internal_error\" }, 500),\n corsConfig,\n requestOrigin,\n );\n }\n };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Route dispatch\n * --------------------------------------------------------------------------------------------- */\n\nfunction dispatchRoute(\n runtime: CopilotRuntimeLike,\n request: Request,\n route: RouteInfo,\n options: { threadEndpointsEnabled: boolean },\n): Promise<Response> {\n switch (route.method) {\n case \"agent/run\":\n return handleRunAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/connect\":\n return handleConnectAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/stop\":\n return handleStopAgent({\n runtime,\n request,\n agentId: route.agentId,\n threadId: route.threadId,\n });\n case \"info\":\n return handleGetRuntimeInfo({\n runtime,\n request,\n threadEndpointsEnabled: options.threadEndpointsEnabled,\n });\n case \"transcribe\":\n return handleTranscribe({ runtime, request });\n case \"threads/clear\":\n return Promise.resolve(handleClearThreads({ runtime, request }));\n case \"threads/list\":\n return handleListThreads({ runtime, request });\n case \"threads/subscribe\":\n return handleSubscribeToThreads({ runtime, request });\n case \"threads/update\":\n if (request.method.toUpperCase() === \"DELETE\") {\n return handleDeleteThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n }\n return handleUpdateThread({ runtime, request, threadId: route.threadId });\n case \"threads/archive\":\n return handleArchiveThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/messages\":\n return handleGetThreadMessages({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/events\":\n return handleGetThreadEvents({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/state\":\n return handleGetThreadState({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"annotate\":\n return handleAnnotate({ runtime, request });\n case \"cpk-debug-events\":\n return Promise.resolve(handleDebugEvents({ runtime, request }));\n }\n}\n\ninterface SingleRouteResolution {\n route: RouteInfo;\n methodCall: MethodCall;\n}\n\nasync function resolveSingleRoute(\n request: Request,\n basePath: string | undefined,\n pathname: string,\n): Promise<SingleRouteResolution> {\n if (basePath) {\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n if (!pathname.startsWith(normalizedBase)) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n }\n\n if (request.method !== \"POST\") {\n throw jsonResponse({ error: \"Method not allowed\" }, 405, { Allow: \"POST\" });\n }\n\n const methodCall = await parseMethodCall(request);\n\n let route: RouteInfo;\n switch (methodCall.method) {\n case \"agent/run\":\n route = {\n method: \"agent/run\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/connect\":\n route = {\n method: \"agent/connect\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/stop\":\n route = {\n method: \"agent/stop\",\n agentId: expectString(methodCall.params, \"agentId\"),\n threadId: expectString(methodCall.params, \"threadId\"),\n };\n break;\n case \"info\":\n route = { method: \"info\" };\n break;\n case \"transcribe\":\n route = { method: \"transcribe\" };\n break;\n }\n\n return { route, methodCall };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * HTTP method validation\n * --------------------------------------------------------------------------------------------- */\n\nfunction validateHttpMethod(\n httpMethod: string,\n route: RouteInfo,\n): Response | null {\n const method = httpMethod.toUpperCase();\n\n switch (route.method) {\n case \"info\":\n case \"threads/list\":\n case \"threads/messages\":\n case \"threads/events\":\n case \"threads/state\":\n case \"cpk-debug-events\":\n if (method === \"GET\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET\",\n });\n\n case \"threads/update\":\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n default:\n if (method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"POST\",\n });\n }\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Helpers\n * --------------------------------------------------------------------------------------------- */\n\nfunction resolveCorsConfig(\n cors: boolean | CopilotCorsConfig | undefined,\n): CopilotCorsConfig | null {\n if (!cors) return null;\n if (cors === true) return {};\n return cors;\n}\n\nfunction maybeAddCors(\n response: Response,\n config: CopilotCorsConfig | null,\n requestOrigin: string | null,\n): Response {\n if (!config) return response;\n return addCorsHeaders(response, config, requestOrigin);\n}\n\nfunction jsonResponse(\n body: unknown,\n status: number,\n extraHeaders?: Record<string, string>,\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", ...extraHeaders },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fetch-handler.mjs","names":[],"sources":["../../../../src/v2/runtime/core/fetch-handler.ts"],"sourcesContent":["/**\n * Framework-agnostic CopilotKit runtime handler.\n *\n * Returns a pure `(Request) => Promise<Response>` function that can be used\n * directly with Bun, Deno, Cloudflare Workers, Next.js App Router, or any\n * Fetch-native runtime — no framework dependency required.\n *\n * @example\n * ```typescript\n * import { CopilotRuntime, createCopilotRuntimeHandler } from \"@copilotkit/runtime/v2\";\n *\n * const handler = createCopilotRuntimeHandler({\n * runtime: new CopilotRuntime({ agents: { ... } }),\n * basePath: \"/api/copilotkit\",\n * cors: true,\n * });\n *\n * // Bun\n * Bun.serve({ fetch: handler });\n *\n * // Deno\n * Deno.serve(handler);\n *\n * // Cloudflare Workers\n * export default { fetch: handler };\n * ```\n */\n\nimport type { CopilotRuntimeLike } from \"./runtime\";\nimport type { CopilotRuntimeHooks, RouteInfo, HookContext } from \"./hooks\";\nimport {\n runOnRequest,\n runOnBeforeHandler,\n runOnResponse,\n runOnError,\n} from \"./hooks\";\nimport type { CopilotCorsConfig } from \"./fetch-cors\";\nimport { handleCors, addCorsHeaders } from \"./fetch-cors\";\nimport { matchRoute } from \"./fetch-router\";\nimport {\n callBeforeRequestMiddleware,\n callAfterRequestMiddleware,\n} from \"./middleware\";\nimport { handleRunAgent } from \"../handlers/handle-run\";\nimport { handleSuggestAgent } from \"../handlers/handle-suggest\";\nimport { handleConnectAgent } from \"../handlers/handle-connect\";\nimport { handleStopAgent } from \"../handlers/handle-stop\";\nimport { handleGetRuntimeInfo } from \"../handlers/get-runtime-info\";\nimport { handleTranscribe } from \"../handlers/handle-transcribe\";\nimport { handleDebugEvents } from \"../handlers/handle-debug-events\";\nimport {\n handleClearThreads,\n handleListThreads,\n handleSubscribeToThreads,\n handleUpdateThread,\n handleArchiveThread,\n handleDeleteThread,\n handleGetThreadMessages,\n handleGetThreadEvents,\n handleGetThreadState,\n} from \"../handlers/handle-threads\";\nimport {\n handleListMemories,\n handleSubscribeToMemories,\n handleCreateMemory,\n handleUpdateMemory,\n handleRemoveMemory,\n} from \"../handlers/handle-memories\";\nimport { handleAnnotate } from \"../handlers/handle-user-actions\";\nimport {\n parseMethodCall,\n createJsonRequest,\n expectString,\n} from \"../endpoints/single-route-helpers\";\nimport type { MethodCall } from \"../endpoints/single-route-helpers\";\nimport { logger } from \"@copilotkit/shared\";\nimport { fireInstanceCreatedTelemetry } from \"../telemetry/instance-created\";\n\n/* ------------------------------------------------------------------------------------------------\n * Public types\n * --------------------------------------------------------------------------------------------- */\n\nexport interface CopilotRuntimeHandlerOptions {\n runtime: CopilotRuntimeLike;\n\n /**\n * Optional base path for routing.\n *\n * When provided: strict prefix stripping. The handler strips this prefix from the\n * URL pathname and matches the remainder against known routes.\n *\n * When omitted: suffix matching. The handler matches known route patterns as\n * suffixes of the URL pathname.\n */\n basePath?: string;\n\n /**\n * Endpoint mode:\n * - \"multi-route\" (default): Routes like POST /agent/:agentId/run, GET /info, etc.\n * - \"single-route\": Single POST endpoint with JSON envelope { method, params, body }\n */\n mode?: \"multi-route\" | \"single-route\";\n\n /**\n * Optional CORS configuration.\n * When not provided, no CORS headers are added (let the framework handle it).\n * Set to true for permissive defaults, or provide an object.\n */\n cors?: boolean | CopilotCorsConfig;\n\n /**\n * Lifecycle hooks for request processing.\n */\n hooks?: CopilotRuntimeHooks;\n}\n\nexport type CopilotRuntimeFetchHandler = (\n request: Request,\n) => Promise<Response>;\n\n/* ------------------------------------------------------------------------------------------------\n * Handler factory\n * --------------------------------------------------------------------------------------------- */\n\nexport function createCopilotRuntimeHandler(\n options: CopilotRuntimeHandlerOptions,\n): CopilotRuntimeFetchHandler {\n const { runtime, basePath, mode = \"multi-route\", cors, hooks } = options;\n\n fireInstanceCreatedTelemetry({ runtime });\n\n const corsConfig = resolveCorsConfig(cors);\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url, \"http://localhost\");\n const path = url.pathname;\n const requestOrigin = request.headers.get(\"origin\");\n\n // Base hook context (route not yet known)\n const baseCtx: HookContext = { request, path, runtime };\n\n let route: RouteInfo | undefined;\n\n try {\n // 1. CORS preflight\n if (corsConfig) {\n const preflight = handleCors(request, corsConfig);\n if (preflight) return preflight;\n }\n\n // 2. onRequest hook\n request = await runOnRequest(hooks, { ...baseCtx, request });\n\n // 3. Legacy beforeRequestMiddleware\n try {\n const maybeModified = await callBeforeRequestMiddleware({\n runtime,\n request,\n path,\n });\n if (maybeModified) {\n request = maybeModified;\n }\n } catch (mwError: unknown) {\n logger.error(\n { err: mwError, url: request.url, path },\n \"Error running before request middleware\",\n );\n if (mwError instanceof Response) {\n return maybeAddCors(mwError, corsConfig, requestOrigin);\n }\n throw mwError;\n }\n\n // 4. Route matching\n let response: Response;\n\n if (mode === \"single-route\") {\n const resolved = await resolveSingleRoute(request, basePath, path);\n route = resolved.route;\n const { methodCall } = resolved;\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n // 6. Wrap body for methods that need it, then dispatch\n if (\n route.method === \"agent/run\" ||\n route.method === \"agent/suggest\" ||\n route.method === \"agent/connect\" ||\n route.method === \"transcribe\"\n ) {\n request = createJsonRequest(request, methodCall.body);\n }\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: false,\n });\n } else {\n // Multi-route: match URL pattern\n const matched = matchRoute(path, basePath);\n if (!matched) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n\n // Validate HTTP method\n const methodError = validateHttpMethod(request.method, matched);\n if (methodError) {\n route = matched;\n throw methodError;\n }\n\n route = matched;\n\n // 5. onBeforeHandler hook\n request = await runOnBeforeHandler(hooks, {\n request,\n path,\n runtime,\n route,\n });\n\n // 6. Handler dispatch\n response = await dispatchRoute(runtime, request, route, {\n threadEndpointsEnabled: true,\n });\n }\n\n // 7. onResponse hook\n response = await runOnResponse(hooks, {\n request,\n response,\n path,\n runtime,\n route,\n });\n\n // 8. CORS headers on response\n response = maybeAddCors(response, corsConfig, requestOrigin);\n\n // 9. Legacy afterRequestMiddleware (non-blocking)\n // Clone the response so middleware can read the body without consuming\n // the original stream that will be sent to the client.\n callAfterRequestMiddleware({\n runtime,\n response: response.clone(),\n path,\n }).catch((error: unknown) => {\n logger.error(\n { err: error, url: request.url, path },\n \"Error running after request middleware\",\n );\n });\n\n return response;\n } catch (error) {\n // Short-circuit with thrown Response\n if (error instanceof Response) {\n const finalResponse = await runOnResponse(hooks, {\n request,\n response: error,\n path,\n runtime,\n route: route ?? { method: \"info\" },\n });\n return maybeAddCors(finalResponse, corsConfig, requestOrigin);\n }\n\n // Run onError hook — wrapped so a throwing hook doesn't escape\n try {\n const errorResponse = await runOnError(hooks, {\n request,\n error,\n path,\n runtime,\n route,\n });\n\n if (errorResponse) {\n return maybeAddCors(errorResponse, corsConfig, requestOrigin);\n }\n } catch (hookError: unknown) {\n logger.error(\n { err: hookError, originalErr: error, url: request.url, path },\n \"onError hook threw\",\n );\n }\n\n logger.error(\n { err: error, url: request.url, path },\n \"Unhandled error in CopilotKit runtime handler\",\n );\n\n return maybeAddCors(\n jsonResponse({ error: \"internal_error\" }, 500),\n corsConfig,\n requestOrigin,\n );\n }\n };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Route dispatch\n * --------------------------------------------------------------------------------------------- */\n\nfunction dispatchRoute(\n runtime: CopilotRuntimeLike,\n request: Request,\n route: RouteInfo,\n options: { threadEndpointsEnabled: boolean },\n): Promise<Response> {\n switch (route.method) {\n case \"agent/run\":\n return handleRunAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/suggest\":\n return handleSuggestAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/connect\":\n return handleConnectAgent({\n runtime,\n request,\n agentId: route.agentId,\n });\n case \"agent/stop\":\n return handleStopAgent({\n runtime,\n request,\n agentId: route.agentId,\n threadId: route.threadId,\n });\n case \"info\":\n return handleGetRuntimeInfo({\n runtime,\n request,\n threadEndpointsEnabled: options.threadEndpointsEnabled,\n });\n case \"transcribe\":\n return handleTranscribe({ runtime, request });\n case \"threads/clear\":\n return Promise.resolve(handleClearThreads({ runtime, request }));\n case \"threads/list\":\n return handleListThreads({ runtime, request });\n case \"memories/list\":\n return request.method.toUpperCase() === \"POST\"\n ? handleCreateMemory({ runtime, request })\n : handleListMemories({ runtime, request });\n case \"memories/subscribe\":\n return handleSubscribeToMemories({ runtime, request });\n case \"memories/mutate\":\n return request.method.toUpperCase() === \"DELETE\"\n ? handleRemoveMemory({ runtime, request, memoryId: route.memoryId })\n : handleUpdateMemory({ runtime, request, memoryId: route.memoryId });\n case \"threads/subscribe\":\n return handleSubscribeToThreads({ runtime, request });\n case \"threads/update\":\n if (request.method.toUpperCase() === \"DELETE\") {\n return handleDeleteThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n }\n return handleUpdateThread({ runtime, request, threadId: route.threadId });\n case \"threads/archive\":\n return handleArchiveThread({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/messages\":\n return handleGetThreadMessages({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/events\":\n return handleGetThreadEvents({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"threads/state\":\n return handleGetThreadState({\n runtime,\n request,\n threadId: route.threadId,\n });\n case \"annotate\":\n return handleAnnotate({ runtime, request });\n case \"cpk-debug-events\":\n return Promise.resolve(handleDebugEvents({ runtime, request }));\n default: {\n // Exhaustiveness guard: a new `RouteInfo` variant added without a case\n // above becomes a compile error here instead of silently returning\n // `undefined` at runtime.\n const _exhaustive: never = route;\n throw jsonResponse(\n { error: \"Not found\", method: (_exhaustive as RouteInfo).method },\n 404,\n );\n }\n }\n}\n\ninterface SingleRouteResolution {\n route: RouteInfo;\n methodCall: MethodCall;\n}\n\nasync function resolveSingleRoute(\n request: Request,\n basePath: string | undefined,\n pathname: string,\n): Promise<SingleRouteResolution> {\n if (basePath) {\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n if (!pathname.startsWith(normalizedBase)) {\n throw jsonResponse({ error: \"Not found\" }, 404);\n }\n }\n\n if (request.method !== \"POST\") {\n throw jsonResponse({ error: \"Method not allowed\" }, 405, { Allow: \"POST\" });\n }\n\n const methodCall = await parseMethodCall(request);\n\n let route: RouteInfo;\n switch (methodCall.method) {\n case \"agent/run\":\n route = {\n method: \"agent/run\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/suggest\":\n route = {\n method: \"agent/suggest\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/connect\":\n route = {\n method: \"agent/connect\",\n agentId: expectString(methodCall.params, \"agentId\"),\n };\n break;\n case \"agent/stop\":\n route = {\n method: \"agent/stop\",\n agentId: expectString(methodCall.params, \"agentId\"),\n threadId: expectString(methodCall.params, \"threadId\"),\n };\n break;\n case \"info\":\n route = { method: \"info\" };\n break;\n case \"transcribe\":\n route = { method: \"transcribe\" };\n break;\n default: {\n // Exhaustiveness guard: a new `METHOD_NAMES`/`EndpointMethod` variant\n // added without a case above becomes a compile error here instead of\n // leaving `route` unassigned at runtime.\n const _exhaustive: never = methodCall.method;\n throw jsonResponse({ error: \"Not found\", method: _exhaustive }, 404);\n }\n }\n\n return { route, methodCall };\n}\n\n/* ------------------------------------------------------------------------------------------------\n * HTTP method validation\n * --------------------------------------------------------------------------------------------- */\n\nfunction validateHttpMethod(\n httpMethod: string,\n route: RouteInfo,\n): Response | null {\n const method = httpMethod.toUpperCase();\n\n switch (route.method) {\n case \"info\":\n case \"threads/list\":\n case \"threads/messages\":\n case \"threads/events\":\n case \"threads/state\":\n case \"cpk-debug-events\":\n if (method === \"GET\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET\",\n });\n\n case \"memories/list\":\n // GET lists the user's memories; POST creates one.\n if (method === \"GET\" || method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"GET, POST\",\n });\n\n case \"memories/mutate\":\n // PATCH supersedes; DELETE retires.\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n case \"threads/update\":\n if (method === \"PATCH\" || method === \"DELETE\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"PATCH, DELETE\",\n });\n\n default:\n if (method === \"POST\") return null;\n return jsonResponse({ error: \"Method not allowed\" }, 405, {\n Allow: \"POST\",\n });\n }\n}\n\n/* ------------------------------------------------------------------------------------------------\n * Helpers\n * --------------------------------------------------------------------------------------------- */\n\nfunction resolveCorsConfig(\n cors: boolean | CopilotCorsConfig | undefined,\n): CopilotCorsConfig | null {\n if (!cors) return null;\n if (cors === true) return {};\n return cors;\n}\n\nfunction maybeAddCors(\n response: Response,\n config: CopilotCorsConfig | null,\n requestOrigin: string | null,\n): Response {\n if (!config) return response;\n return addCorsHeaders(response, config, requestOrigin);\n}\n\nfunction jsonResponse(\n body: unknown,\n status: number,\n extraHeaders?: Record<string, string>,\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", ...extraHeaders },\n });\n}\n"],"mappings":"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"}
@@ -43,6 +43,14 @@ function matchSegments(path) {
43
43
  agentId
44
44
  };
45
45
  }
46
+ if (len >= 3 && segments[len - 3] === "agent" && segments[len - 1] === "suggest") {
47
+ const agentId = safeDecodeURIComponent(segments[len - 2]);
48
+ if (!agentId) return null;
49
+ return {
50
+ method: "agent/suggest",
51
+ agentId
52
+ };
53
+ }
46
54
  if (len >= 3 && segments[len - 3] === "agent" && segments[len - 1] === "connect") {
47
55
  const agentId = safeDecodeURIComponent(segments[len - 2]);
48
56
  if (!agentId) return null;
@@ -104,6 +112,16 @@ function matchSegments(path) {
104
112
  };
105
113
  }
106
114
  if (len >= 1 && segments[len - 1] === "threads") return { method: "threads/list" };
115
+ if (len >= 2 && segments[len - 2] === "memories" && segments[len - 1] === "subscribe") return { method: "memories/subscribe" };
116
+ if (len >= 2 && segments[len - 2] === "memories" && segments[len - 1] !== "subscribe") {
117
+ const memoryId = safeDecodeURIComponent(segments[len - 1]);
118
+ if (!memoryId) return null;
119
+ return {
120
+ method: "memories/mutate",
121
+ memoryId
122
+ };
123
+ }
124
+ if (len >= 1 && segments[len - 1] === "memories") return { method: "memories/list" };
107
125
  if (len >= 1 && segments[len - 1] === "annotate") return { method: "annotate" };
108
126
  return null;
109
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-router.cjs","names":[],"sources":["../../../../src/v2/runtime/core/fetch-router.ts"],"sourcesContent":["/**\n * Lightweight URL router for framework-agnostic CopilotKit runtime handler.\n *\n * Two strategies:\n * - With `basePath`: strict prefix strip → match remainder\n * - Without `basePath`: suffix matching on known patterns\n *\n * Single-route mode: delegates to `parseMethodCall` for JSON envelope dispatch.\n */\n\nimport type { RouteInfo } from \"./hooks\";\n\n/**\n * Match a request URL against known CopilotKit route patterns.\n *\n * @param pathname - The URL pathname to match\n * @param basePath - Optional base path prefix to strip first\n * @returns RouteInfo if matched, null otherwise\n */\nexport function matchRoute(\n pathname: string,\n basePath?: string,\n): RouteInfo | null {\n let remainder: string;\n\n if (basePath) {\n // Normalize: ensure basePath doesn't end with /\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n\n // Special case: basePath === \"/\" matches everything\n if (normalizedBase === \"/\") {\n remainder = pathname;\n } else {\n if (!pathname.startsWith(normalizedBase)) return null;\n\n // The character after basePath must be \"/\" or end of string\n const afterBase = pathname.slice(normalizedBase.length);\n if (afterBase.length > 0 && !afterBase.startsWith(\"/\")) return null;\n\n remainder = afterBase || \"/\";\n }\n } else {\n // Suffix matching: find known patterns at the end of the pathname\n remainder = pathname;\n }\n\n return matchSegments(remainder);\n}\n\nfunction safeDecodeURIComponent(value: string): string | null {\n try {\n return decodeURIComponent(value);\n } catch {\n return null;\n }\n}\n\nfunction matchSegments(path: string): RouteInfo | null {\n const segments = path.split(\"/\").filter(Boolean);\n const len = segments.length;\n\n // Try suffix matching — scan from the end for known patterns\n\n // /info (1 segment)\n if (len >= 1 && segments[len - 1] === \"info\") {\n return { method: \"info\" };\n }\n\n // /transcribe (1 segment)\n if (len >= 1 && segments[len - 1] === \"transcribe\") {\n return { method: \"transcribe\" };\n }\n\n // /cpk-debug-events (1 segment)\n // Reserved route name: the `cpk-` prefix makes collision with a\n // user-named agent essentially impossible (the router only treats\n // `agent/:agentId/...` patterns as agent lookups, so a bare\n // `cpk-debug-events` segment would never fall through to one —\n // the prefix is the real guard, not this branch's position).\n // Handler returns 404 in production.\n if (len >= 1 && segments[len - 1] === \"cpk-debug-events\") {\n return { method: \"cpk-debug-events\" };\n }\n\n // /agent/:agentId/run (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"agent\" &&\n segments[len - 1] === \"run\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 2]!);\n if (!agentId) return null;\n return { method: \"agent/run\", agentId };\n }\n\n // /agent/:agentId/connect (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"agent\" &&\n segments[len - 1] === \"connect\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 2]!);\n if (!agentId) return null;\n return { method: \"agent/connect\", agentId };\n }\n\n // /agent/:agentId/stop/:threadId (4 segments)\n if (\n len >= 4 &&\n segments[len - 4] === \"agent\" &&\n segments[len - 2] === \"stop\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 3]!);\n const threadId = safeDecodeURIComponent(segments[len - 1]!);\n if (!agentId || !threadId) return null;\n return { method: \"agent/stop\", agentId, threadId };\n }\n\n // /threads/subscribe (2 segments)\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] === \"subscribe\"\n ) {\n return { method: \"threads/subscribe\" };\n }\n\n // /threads/:threadId/messages (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"messages\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/messages\", threadId };\n }\n\n // /threads/:threadId/events (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"events\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/events\", threadId };\n }\n\n // /threads/:threadId/state (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"state\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/state\", threadId };\n }\n\n // /threads/:threadId/archive (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"archive\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/archive\", threadId };\n }\n\n // /threads/clear (2 segments) — wipe in-memory thread history\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] === \"clear\"\n ) {\n return { method: \"threads/clear\" };\n }\n\n // /threads/:threadId (2 segments) — update or delete\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] !== \"subscribe\" &&\n segments[len - 1] !== \"clear\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 1]!);\n if (!threadId) return null;\n // Disambiguated by HTTP method in the handler\n return { method: \"threads/update\", threadId };\n }\n\n // /threads (1 segment) — list\n if (len >= 1 && segments[len - 1] === \"threads\") {\n return { method: \"threads/list\" };\n }\n\n // /annotate (1 segment) — annotate a thread event\n if (len >= 1 && segments[len - 1] === \"annotate\") {\n return { method: \"annotate\" };\n }\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fetch-router.cjs","names":[],"sources":["../../../../src/v2/runtime/core/fetch-router.ts"],"sourcesContent":["/**\n * Lightweight URL router for framework-agnostic CopilotKit runtime handler.\n *\n * Two strategies:\n * - With `basePath`: strict prefix strip → match remainder\n * - Without `basePath`: suffix matching on known patterns\n *\n * Single-route mode: delegates to `parseMethodCall` for JSON envelope dispatch.\n */\n\nimport type { RouteInfo } from \"./hooks\";\n\n/**\n * Match a request URL against known CopilotKit route patterns.\n *\n * @param pathname - The URL pathname to match\n * @param basePath - Optional base path prefix to strip first\n * @returns RouteInfo if matched, null otherwise\n */\nexport function matchRoute(\n pathname: string,\n basePath?: string,\n): RouteInfo | null {\n let remainder: string;\n\n if (basePath) {\n // Normalize: ensure basePath doesn't end with /\n const normalizedBase =\n basePath.length > 1 && basePath.endsWith(\"/\")\n ? basePath.slice(0, -1)\n : basePath;\n\n // Special case: basePath === \"/\" matches everything\n if (normalizedBase === \"/\") {\n remainder = pathname;\n } else {\n if (!pathname.startsWith(normalizedBase)) return null;\n\n // The character after basePath must be \"/\" or end of string\n const afterBase = pathname.slice(normalizedBase.length);\n if (afterBase.length > 0 && !afterBase.startsWith(\"/\")) return null;\n\n remainder = afterBase || \"/\";\n }\n } else {\n // Suffix matching: find known patterns at the end of the pathname\n remainder = pathname;\n }\n\n return matchSegments(remainder);\n}\n\nfunction safeDecodeURIComponent(value: string): string | null {\n try {\n return decodeURIComponent(value);\n } catch {\n return null;\n }\n}\n\nfunction matchSegments(path: string): RouteInfo | null {\n const segments = path.split(\"/\").filter(Boolean);\n const len = segments.length;\n\n // Try suffix matching — scan from the end for known patterns\n\n // /info (1 segment)\n if (len >= 1 && segments[len - 1] === \"info\") {\n return { method: \"info\" };\n }\n\n // /transcribe (1 segment)\n if (len >= 1 && segments[len - 1] === \"transcribe\") {\n return { method: \"transcribe\" };\n }\n\n // /cpk-debug-events (1 segment)\n // Reserved route name: the `cpk-` prefix makes collision with a\n // user-named agent essentially impossible (the router only treats\n // `agent/:agentId/...` patterns as agent lookups, so a bare\n // `cpk-debug-events` segment would never fall through to one —\n // the prefix is the real guard, not this branch's position).\n // Handler returns 404 in production.\n if (len >= 1 && segments[len - 1] === \"cpk-debug-events\") {\n return { method: \"cpk-debug-events\" };\n }\n\n // /agent/:agentId/run (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"agent\" &&\n segments[len - 1] === \"run\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 2]!);\n if (!agentId) return null;\n return { method: \"agent/run\", agentId };\n }\n\n // /agent/:agentId/suggest (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"agent\" &&\n segments[len - 1] === \"suggest\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 2]!);\n if (!agentId) return null;\n return { method: \"agent/suggest\", agentId };\n }\n\n // /agent/:agentId/connect (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"agent\" &&\n segments[len - 1] === \"connect\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 2]!);\n if (!agentId) return null;\n return { method: \"agent/connect\", agentId };\n }\n\n // /agent/:agentId/stop/:threadId (4 segments)\n if (\n len >= 4 &&\n segments[len - 4] === \"agent\" &&\n segments[len - 2] === \"stop\"\n ) {\n const agentId = safeDecodeURIComponent(segments[len - 3]!);\n const threadId = safeDecodeURIComponent(segments[len - 1]!);\n if (!agentId || !threadId) return null;\n return { method: \"agent/stop\", agentId, threadId };\n }\n\n // /threads/subscribe (2 segments)\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] === \"subscribe\"\n ) {\n return { method: \"threads/subscribe\" };\n }\n\n // /threads/:threadId/messages (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"messages\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/messages\", threadId };\n }\n\n // /threads/:threadId/events (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"events\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/events\", threadId };\n }\n\n // /threads/:threadId/state (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"state\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/state\", threadId };\n }\n\n // /threads/:threadId/archive (3 segments)\n if (\n len >= 3 &&\n segments[len - 3] === \"threads\" &&\n segments[len - 1] === \"archive\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 2]!);\n if (!threadId) return null;\n return { method: \"threads/archive\", threadId };\n }\n\n // /threads/clear (2 segments) — wipe in-memory thread history\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] === \"clear\"\n ) {\n return { method: \"threads/clear\" };\n }\n\n // /threads/:threadId (2 segments) — update or delete\n if (\n len >= 2 &&\n segments[len - 2] === \"threads\" &&\n segments[len - 1] !== \"subscribe\" &&\n segments[len - 1] !== \"clear\"\n ) {\n const threadId = safeDecodeURIComponent(segments[len - 1]!);\n if (!threadId) return null;\n // Disambiguated by HTTP method in the handler\n return { method: \"threads/update\", threadId };\n }\n\n // /threads (1 segment) — list\n if (len >= 1 && segments[len - 1] === \"threads\") {\n return { method: \"threads/list\" };\n }\n\n // /memories/subscribe (2 segments) — mint memory-realtime join credentials.\n if (\n len >= 2 &&\n segments[len - 2] === \"memories\" &&\n segments[len - 1] === \"subscribe\"\n ) {\n return { method: \"memories/subscribe\" };\n }\n\n // /memories/:id (2 segments) — supersede (PATCH) or retire (DELETE).\n // Disambiguated by HTTP method in the handler.\n if (\n len >= 2 &&\n segments[len - 2] === \"memories\" &&\n segments[len - 1] !== \"subscribe\"\n ) {\n const memoryId = safeDecodeURIComponent(segments[len - 1]!);\n if (!memoryId) return null;\n return { method: \"memories/mutate\", memoryId };\n }\n\n // /memories (1 segment) — GET lists; POST creates.\n if (len >= 1 && segments[len - 1] === \"memories\") {\n return { method: \"memories/list\" };\n }\n\n // /annotate (1 segment) — annotate a thread event\n if (len >= 1 && segments[len - 1] === \"annotate\") {\n return { method: \"annotate\" };\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -42,6 +42,14 @@ function matchSegments(path) {
42
42
  agentId
43
43
  };
44
44
  }
45
+ if (len >= 3 && segments[len - 3] === "agent" && segments[len - 1] === "suggest") {
46
+ const agentId = safeDecodeURIComponent(segments[len - 2]);
47
+ if (!agentId) return null;
48
+ return {
49
+ method: "agent/suggest",
50
+ agentId
51
+ };
52
+ }
45
53
  if (len >= 3 && segments[len - 3] === "agent" && segments[len - 1] === "connect") {
46
54
  const agentId = safeDecodeURIComponent(segments[len - 2]);
47
55
  if (!agentId) return null;
@@ -103,6 +111,16 @@ function matchSegments(path) {
103
111
  };
104
112
  }
105
113
  if (len >= 1 && segments[len - 1] === "threads") return { method: "threads/list" };
114
+ if (len >= 2 && segments[len - 2] === "memories" && segments[len - 1] === "subscribe") return { method: "memories/subscribe" };
115
+ if (len >= 2 && segments[len - 2] === "memories" && segments[len - 1] !== "subscribe") {
116
+ const memoryId = safeDecodeURIComponent(segments[len - 1]);
117
+ if (!memoryId) return null;
118
+ return {
119
+ method: "memories/mutate",
120
+ memoryId
121
+ };
122
+ }
123
+ if (len >= 1 && segments[len - 1] === "memories") return { method: "memories/list" };
106
124
  if (len >= 1 && segments[len - 1] === "annotate") return { method: "annotate" };
107
125
  return null;
108
126
  }