UNPKG

@copilotkit/runtime

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

209 lines (207 loc) 9.78 kB
require("reflect-metadata"); const require_runtime = require('../../../../_virtual/_rolldown/runtime.cjs'); const require_runtime$1 = require('../../core/runtime.cjs'); const require_client = require('../../intelligence-platform/client.cjs'); const require_json_response = require('../shared/json-response.cjs'); const require_resolve_intelligence_user = require('../shared/resolve-intelligence-user.cjs'); let _copilotkit_shared = require("@copilotkit/shared"); //#region src/v2/runtime/handlers/intelligence/memories.ts const MISSING_INTELLIGENCE_MESSAGE = "Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options."; /** Allowed `kind` vocabulary the platform's memory endpoints accept. */ const MEMORY_KINDS = new Set([ "topical", "episodic", "operational" ]); /** Allowed `scope` vocabulary the platform's memory endpoints accept. */ const MEMORY_SCOPES = new Set(["user", "project"]); /** * Maps a thrown error to a `Response`. * * For a {@link PlatformRequestError}, forward only client-actionable **4xx** * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422 * unprocessable) so a `useMemories` consumer can branch on them — a flat 500 * would erase that distinction. A platform **5xx** (or any non-4xx / malformed * status) means the runtime is healthy but its dependency failed, so it surfaces * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime * itself broke — and this also avoids a `new Response(..., { status })` * `RangeError` on an out-of-range status. Non-platform throws stay 500. */ function memoryErrorResponse(error, message) { if (error instanceof require_client.PlatformRequestError) { const { status } = error; if (Number.isInteger(status) && status >= 400 && status <= 499) return require_json_response.errorResponse(message, status); return require_json_response.errorResponse(message, 502); } return require_json_response.errorResponse(message, 500); } async function parseJsonBody(request) { try { return await request.json(); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Malformed JSON in memory request body"); return require_json_response.errorResponse("Invalid request body", 400); } } /** * Extracts and validates the create/supersede body fields the platform's * memory endpoints require. Returns a `Response` (400) on invalid input. */ function parseMemoryBody(body) { const { content, kind, scope, sourceThreadIds } = body; if (typeof content !== "string" || typeof kind !== "string") return require_json_response.errorResponse("Memory requires string `content` and `kind`", 400); if (!MEMORY_KINDS.has(kind)) return require_json_response.errorResponse("Memory `kind` must be one of: topical, episodic, operational", 400); if (scope !== void 0 && typeof scope !== "string") return require_json_response.errorResponse("Memory `scope` must be a string when provided", 400); if (typeof scope === "string" && !MEMORY_SCOPES.has(scope)) return require_json_response.errorResponse("Memory `scope` must be one of: user, project", 400); if (sourceThreadIds !== void 0 && (!Array.isArray(sourceThreadIds) || !sourceThreadIds.every((id) => typeof id === "string"))) return require_json_response.errorResponse("Memory `sourceThreadIds` must be an array of strings when provided", 400); return { content, kind, ...typeof scope === "string" ? { scope } : {}, ...Array.isArray(sourceThreadIds) ? { sourceThreadIds } : {} }; } /** * Lists the resolved user's long-term memories via the Intelligence platform. * * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence` * runtime, resolves the user with `identifyUser` (never trusting a * client-supplied id), and proxies to the platform's `GET /api/memories` * with the project API key + resolved user. The `?includeInvalidated=true` * query is forwarded so callers can opt into retired rows. The response is * the platform's `{ memories }` envelope, which the client memory store * consumes directly. */ async function handleListMemories({ runtime, request }) { if (require_runtime$1.isIntelligenceRuntime(runtime)) try { const includeInvalidated = new URL(request.url).searchParams.get("includeInvalidated") === "true"; const user = await require_resolve_intelligence_user.resolveIntelligenceUser({ runtime, request }); if (require_json_response.isHandlerResponse(user)) return user; const data = await runtime.intelligence.listMemories({ userId: user.id, ...includeInvalidated ? { includeInvalidated: true } : {} }); if (data == null || typeof data !== "object" || !Array.isArray(data.memories)) { _copilotkit_shared.logger.error({ data }, "listMemories: platform returned a response without a `memories` array"); return require_json_response.errorResponse("Memory platform returned an invalid list response", 502); } return Response.json(data); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Error listing memories"); return memoryErrorResponse(error, "Failed to list memories"); } return require_json_response.errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422); } /** * Mints memory-realtime join credentials (platform `POST * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser` * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs * the `joinCode` here (unlike threads, where it rides the thread-list response) * because the client builds the `user_meta:memories:<joinCode>` channel topic * from it. */ async function handleSubscribeToMemories({ runtime, request }) { if (require_runtime$1.isIntelligenceRuntime(runtime)) try { const user = await require_resolve_intelligence_user.resolveIntelligenceUser({ runtime, request }); if (require_json_response.isHandlerResponse(user)) return user; const credentials = await runtime.intelligencesubscribeToMemories({ userId: user.id }); return Response.json({ joinToken: credentials.joinToken, joinCode: credentials.joinCode }); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Error subscribing to memories"); return memoryErrorResponse(error, "Failed to subscribe to memories"); } return require_json_response.errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422); } /** * Creates a memory for the resolved user (platform `POST /api/memories`). * Identity comes from `identifyUser`, never the request body. Returns 201 * with the stored memory (the client store applies it server-authoritatively). */ async function handleCreateMemory({ runtime, request }) { if (!require_runtime$1.isIntelligenceRuntime(runtime)) return require_json_response.errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422); try { const body = await parseJsonBody(request); if (require_json_response.isHandlerResponse(body)) return body; const fields = parseMemoryBody(body); if (require_json_response.isHandlerResponse(fields)) return fields; const user = await require_resolve_intelligence_user.resolveIntelligenceUser({ runtime, request }); if (require_json_response.isHandlerResponse(user)) return user; const data = await runtime.intelligence.createMemory({ userId: user.id, ...fields }); return Response.json(data, { status: 201 }); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Error creating memory"); return memoryErrorResponse(error, "Failed to create memory"); } } /** * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and * inserts the new content atomically; the response carries `retiredId`. */ async function handleUpdateMemory({ runtime, request, memoryId }) { if (!require_runtime$1.isIntelligenceRuntime(runtime)) return require_json_response.errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422); try { const body = await parseJsonBody(request); if (require_json_response.isHandlerResponse(body)) return body; const fields = parseMemoryBody(body); if (require_json_response.isHandlerResponse(fields)) return fields; const user = await require_resolve_intelligence_user.resolveIntelligenceUser({ runtime, request }); if (require_json_response.isHandlerResponse(user)) return user; const data = await runtime.intelligence.updateMemory({ userId: user.id, id: memoryId, ...fields }); return Response.json(data); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Error updating memory"); return memoryErrorResponse(error, "Failed to update memory"); } } /** * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy * on the platform side; returns 204. */ async function handleRemoveMemory({ runtime, request, memoryId }) { if (!require_runtime$1.isIntelligenceRuntime(runtime)) return require_json_response.errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422); try { const user = await require_resolve_intelligence_user.resolveIntelligenceUser({ runtime, request }); if (require_json_response.isHandlerResponse(user)) return user; await runtime.intelligence.removeMemory({ userId: user.id, id: memoryId }); return new Response(null, { status: 204 }); } catch (error) { _copilotkit_shared.logger.error({ err: error }, "Error removing memory"); return memoryErrorResponse(error, "Failed to remove memory"); } } //#endregion exports.handleCreateMemory = handleCreateMemory; exports.handleListMemories = handleListMemories; exports.handleRemoveMemory = handleRemoveMemory; exports.handleSubscribeToMemories = handleSubscribeToMemories; exports.handleUpdateMemory = handleUpdateMemory; //# sourceMappingURL=memories.cjs.map