remem-mcp 0.7.3 → 0.7.6

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.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/proxy/server.ts","../src/proxy/capture.ts","../src/proxy/inject.ts","../src/proxy/session.ts"],"sourcesContent":["/**\n * Memory Proxy — HTTP proxy that injects memory into LLM requests.\n *\n * Adapted from TencentDB Agent Memory's Memory Proxy concept (MIT, Tencent 2026).\n * https://github.com/TencentCloud/TencentDB-Agent-Memory\n *\n * Instead of requiring MCP hooks, the agent points its base URL to this proxy.\n * The proxy intercepts /v1/chat/completions (OpenAI) and /v1/messages (Anthropic),\n * injects memory into the system prompt, and forwards to the upstream LLM.\n *\n * This enables zero-code integration with any agent that calls OpenAI/Anthropic APIs.\n */\n\nimport {\n createServer,\n request as httpRequestHttp,\n type IncomingMessage,\n type ServerResponse,\n} from \"node:http\";\nimport { request as httpRequest } from \"node:https\";\nimport { URL } from \"node:url\";\nimport { LocalEmbedder } from \"../embedding/local.js\";\nimport { SQLiteBackend } from \"../storage/sqlite.js\";\nimport { captureConversation, captureConversationAnthropic } from \"./capture.js\";\nimport { injectMemory } from \"./inject.js\";\nimport { SessionStore } from \"./session.js\";\n\nexport interface ProxyConfig {\n port: number;\n upstreamUrl: string;\n upstreamApiKey?: string;\n dbPath: string;\n /** Whether to auto-capture conversations. Default: true. */\n autoCapture: boolean;\n /** Whether to inject memory into system prompt. Default: true. */\n injectMemory: boolean;\n}\n\n/** Default proxy config from environment variables. */\nexport function loadProxyConfig(): ProxyConfig {\n return {\n port: parseInt(process.env.REMEM_PROXY_PORT ?? \"8765\", 10),\n upstreamUrl: process.env.REMEM_UPSTREAM_URL ?? \"https://api.openai.com\",\n upstreamApiKey: process.env.REMEM_UPSTREAM_API_KEY ?? process.env.OPENAI_API_KEY,\n dbPath: process.env.REMEM_DB_PATH ?? \"\",\n autoCapture: process.env.REMEM_PROXY_CAPTURE !== \"false\",\n injectMemory: process.env.REMEM_PROXY_INJECT !== \"false\",\n };\n}\n\n/** Start the Memory Proxy server. */\nexport async function startProxyServer(config: ProxyConfig): Promise<void> {\n if (!config.dbPath) {\n throw new Error(\"REMEM_DB_PATH is required for proxy mode\");\n }\n\n const storage = new SQLiteBackend(config.dbPath);\n const embedder = new LocalEmbedder();\n const sessions = new SessionStore();\n\n const server = createServer(async (req, res) => {\n try {\n const url = new URL(req.url ?? \"/\", `http://localhost:${config.port}`);\n\n // Health check\n if (url.pathname === \"/health\" && req.method === \"GET\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", proxy: true, upstream: config.upstreamUrl }));\n return;\n }\n\n // Session init — user selects team/agent/task\n if (url.pathname === \"/session/init\" && req.method === \"POST\") {\n const body = await readBody(req);\n const { teamId, agentId, taskId, userId } = JSON.parse(body);\n const sessionId = sessions.create({ teamId, agentId, taskId, userId });\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ sessionId }));\n return;\n }\n\n // OpenAI protocol: POST /v1/chat/completions\n if (url.pathname === \"/v1/chat/completions\" && req.method === \"POST\") {\n await handleOpenAIRequest(req, res, config, storage, embedder, sessions);\n return;\n }\n\n // Anthropic protocol: POST /v1/messages\n if (url.pathname === \"/v1/messages\" && req.method === \"POST\") {\n await handleAnthropicRequest(req, res, config, storage, embedder, sessions);\n return;\n }\n\n // Pass-through for other endpoints (e.g., /v1/models)\n await passthrough(req, res, config);\n } catch (err) {\n console.error(\"[remem-mcp proxy] Error:\", err);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Proxy internal error\", detail: String(err) }));\n }\n });\n\n server.listen(config.port, () => {\n console.log(`[remem-mcp proxy] Listening on http://localhost:${config.port}`);\n console.log(`[remem-mcp proxy] Upstream: ${config.upstreamUrl}`);\n console.log(`[remem-mcp proxy] Endpoints:`);\n console.log(` POST /v1/chat/completions (OpenAI protocol)`);\n console.log(` POST /v1/messages (Anthropic protocol)`);\n console.log(` POST /session/init (bind team/agent/task)`);\n console.log(` GET /health (health check)`);\n });\n}\n\n/** Handle OpenAI /v1/chat/completions request. */\nasync function handleOpenAIRequest(\n req: IncomingMessage,\n res: ServerResponse,\n config: ProxyConfig,\n storage: SQLiteBackend,\n embedder: LocalEmbedder,\n sessions: SessionStore,\n): Promise<void> {\n const body = await readBody(req);\n const parsed = JSON.parse(body);\n\n // Inject memory into system prompt\n if (config.injectMemory) {\n const lastUserMessage = getLastUserMessage(parsed.messages ?? []);\n const sessionBinding = sessions.getFromHeaders(req.headers);\n console.error(\n `[proxy] inject: userMsg=\"${lastUserMessage?.slice(0, 50)}\" binding=${JSON.stringify(sessionBinding)}`,\n );\n if (lastUserMessage) {\n try {\n const injected = await injectMemory(\n parsed.messages ?? [],\n lastUserMessage,\n storage,\n embedder,\n sessionBinding,\n );\n const hasMemory = injected.some((m: { content: string }) => m.content.includes(\"<remem-mcp>\"));\n console.error(`[proxy] inject result: hasMemory=${hasMemory}, messages=${injected.length}`);\n parsed.messages = injected;\n } catch (e) {\n console.error(`[proxy] inject error:`, e);\n }\n }\n }\n\n // Forward to upstream\n const upstreamResp = await forwardRequest(\n config.upstreamUrl,\n \"/v1/chat/completions\",\n \"POST\",\n JSON.stringify(parsed),\n config.upstreamApiKey,\n req.headers,\n );\n\n // Auto-capture the conversation\n if (config.autoCapture) {\n const responseText = extractOpenAIResponse(upstreamResp.body);\n if (responseText) {\n captureConversation(\n parsed.messages ?? [],\n responseText,\n storage,\n sessions.getFromHeaders(req.headers),\n ).catch((e: unknown) => console.error(\"[remem-mcp proxy] Capture error:\", e));\n }\n }\n\n // Return response to client\n res.writeHead(upstreamResp.statusCode, upstreamResp.headers);\n res.end(upstreamResp.body);\n}\n\n/** Handle Anthropic /v1/messages request. */\nasync function handleAnthropicRequest(\n req: IncomingMessage,\n res: ServerResponse,\n config: ProxyConfig,\n storage: SQLiteBackend,\n embedder: LocalEmbedder,\n sessions: SessionStore,\n): Promise<void> {\n const body = await readBody(req);\n const parsed = JSON.parse(body);\n\n // Inject memory into system prompt\n if (config.injectMemory) {\n const lastUserMessage = getLastUserMessageAnthropic(parsed.messages ?? []);\n const sessionBinding = sessions.getFromHeaders(req.headers);\n if (lastUserMessage) {\n const systemPrompt = typeof parsed.system === \"string\" ? parsed.system : \"\";\n const injected = await injectMemoryAnthropic(\n systemPrompt,\n lastUserMessage,\n storage,\n embedder,\n sessionBinding,\n );\n parsed.system = injected;\n }\n }\n\n // Forward to upstream\n const upstreamResp = await forwardRequest(\n config.upstreamUrl,\n \"/v1/messages\",\n \"POST\",\n JSON.stringify(parsed),\n config.upstreamApiKey,\n req.headers,\n );\n\n // Auto-capture\n if (config.autoCapture) {\n const responseText = extractAnthropicResponse(upstreamResp.body);\n if (responseText) {\n captureConversationAnthropic(\n parsed.messages ?? [],\n responseText,\n storage,\n sessions.getFromHeaders(req.headers),\n ).catch((e: unknown) => console.error(\"[remem-mcp proxy] Capture error:\", e));\n }\n }\n\n res.writeHead(upstreamResp.statusCode, upstreamResp.headers);\n res.end(upstreamResp.body);\n}\n\n/** Pass-through for unsupported endpoints. */\nasync function passthrough(\n req: IncomingMessage,\n res: ServerResponse,\n config: ProxyConfig,\n): Promise<void> {\n const url = new URL(req.url ?? \"/\", `http://localhost:${config.port}`);\n const upstreamResp = await forwardRequest(\n config.upstreamUrl,\n url.pathname + url.search,\n req.method ?? \"GET\",\n await readBody(req),\n config.upstreamApiKey,\n req.headers,\n );\n res.writeHead(upstreamResp.statusCode, upstreamResp.headers);\n res.end(upstreamResp.body);\n}\n\n/** Read the full request body as a string. */\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (c) => chunks.push(c));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n req.on(\"error\", reject);\n });\n}\n\n/** Get the last user message from OpenAI-format messages. */\nfunction getLastUserMessage(messages: Array<{ role: string; content: string }>): string | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n return typeof messages[i].content === \"string\"\n ? messages[i].content\n : JSON.stringify(messages[i].content);\n }\n }\n return null;\n}\n\n/** Get the last user message from Anthropic-format messages. */\nfunction getLastUserMessageAnthropic(\n messages: Array<{ role: string; content: unknown }>,\n): string | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n const content = messages[i].content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const textBlock = content.find((b: { type: string; text?: string }) => b.type === \"text\");\n if (textBlock?.text) return textBlock.text;\n }\n }\n }\n return null;\n}\n\n/** Extract text from OpenAI chat completion response. */\nfunction extractOpenAIResponse(body: string): string | null {\n try {\n const parsed = JSON.parse(body);\n return parsed.choices?.[0]?.message?.content ?? null;\n } catch {\n return null;\n }\n}\n\n/** Extract text from Anthropic messages response. */\nfunction extractAnthropicResponse(body: string): string | null {\n try {\n const parsed = JSON.parse(body);\n const textBlocks = parsed.content?.filter((b: { type: string }) => b.type === \"text\") ?? [];\n return textBlocks.map((b: { text: string }) => b.text).join(\"\\n\") || null;\n } catch {\n return null;\n }\n}\n\n/** Forward a request to the upstream server. */\nasync function forwardRequest(\n upstreamUrl: string,\n path: string,\n method: string,\n body: string,\n apiKey?: string,\n headers?: Record<string, string | string[] | undefined>,\n): Promise<{ statusCode: number; headers: Record<string, string>; body: string }> {\n const url = new URL(path, upstreamUrl);\n const isHttps = url.protocol === \"https:\";\n const requestFn = isHttps ? httpRequest : httpRequestHttp;\n\n const forwardHeaders: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(body).toString(),\n };\n\n // Copy relevant headers from original request\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n const lower = key.toLowerCase();\n if (\n lower === \"authorization\" ||\n lower === \"x-api-key\" ||\n lower === \"anthropic-version\" ||\n lower === \"openai-organization\" ||\n lower === \"accept\" ||\n lower === \"accept-encoding\"\n ) {\n if (typeof value === \"string\") {\n forwardHeaders[key] = value;\n }\n }\n }\n }\n\n // Override with configured API key if provided\n if (apiKey) {\n if (path.startsWith(\"/v1/messages\")) {\n forwardHeaders[\"x-api-key\"] = apiKey;\n } else {\n forwardHeaders[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n }\n\n return new Promise((resolve, reject) => {\n const proxyReq = requestFn(url, { method, headers: forwardHeaders }, (proxyRes) => {\n const chunks: Buffer[] = [];\n proxyRes.on(\"data\", (c) => chunks.push(c));\n proxyRes.on(\"end\", () => {\n const respHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(proxyRes.headers)) {\n if (typeof v === \"string\") respHeaders[k] = v;\n }\n resolve({\n statusCode: proxyRes.statusCode ?? 200,\n headers: respHeaders,\n body: Buffer.concat(chunks).toString(\"utf-8\"),\n });\n });\n proxyRes.on(\"error\", reject);\n });\n proxyReq.on(\"error\", reject);\n proxyReq.write(body);\n proxyReq.end();\n });\n}\n\n/** Inject memory into Anthropic-format system prompt. */\nasync function injectMemoryAnthropic(\n systemPrompt: string,\n userMessage: string,\n storage: SQLiteBackend,\n embedder: LocalEmbedder,\n sessionBinding: { teamId?: string; agentId?: string; userId?: string; taskId?: string },\n): Promise<string> {\n const memoryBlock = await injectMemory([], userMessage, storage, embedder, sessionBinding);\n // For Anthropic, we append the memory to the system prompt\n const memoryText = extractMemoryBlock(memoryBlock);\n if (!memoryText) return systemPrompt;\n return `${systemPrompt}\\n\\n${memoryText}`;\n}\n\n/** Extract the memory block text from injected messages. */\nfunction extractMemoryBlock(messages: Array<{ role: string; content: string }>): string | null {\n for (const msg of messages) {\n if (msg.role === \"system\" && msg.content.includes(\"<remem-mcp>\")) {\n return msg.content;\n }\n }\n return null;\n}\n","/**\n * Auto-capture — captures conversations after the upstream LLM responds.\n *\n * Reuses the same capture logic as the session transcript capture in hook-handlers.ts.\n */\n\nimport type { SQLiteBackend } from \"../storage/sqlite.js\";\nimport { generateId } from \"../utils/ulid.js\";\n\ninterface SessionBinding {\n teamId?: string;\n agentId?: string;\n userId?: string;\n taskId?: string;\n}\n\ninterface Message {\n role: string;\n content: string;\n}\n\n/**\n * Capture an OpenAI-format conversation (user messages + assistant response).\n */\nexport async function captureConversation(\n messages: Message[],\n assistantResponse: string,\n storage: SQLiteBackend,\n binding: SessionBinding,\n): Promise<void> {\n // Build a conversation summary\n const userMessages = messages.filter((m) => m.role === \"user\");\n if (userMessages.length === 0) return;\n\n const lastUser = userMessages[userMessages.length - 1];\n const content = `User: ${lastUser.content.slice(0, 500)}\\n\\nAssistant: ${assistantResponse.slice(0, 2000)}`;\n\n const id = generateId();\n const now = Date.now();\n\n await storage.put({\n id,\n sessionKey: `proxy-${binding.teamId ?? \"default\"}`,\n agentId: binding.agentId ?? \"proxy\",\n type: \"conversation\",\n content,\n tags: [\"proxy\", \"conversation\"],\n createdAt: now,\n metadata: {\n source: \"proxy\",\n teamId: binding.teamId,\n agentId: binding.agentId,\n userId: binding.userId,\n taskId: binding.taskId,\n },\n teamId: binding.teamId,\n userId: binding.userId,\n taskId: binding.taskId,\n });\n}\n\n/**\n * Capture an Anthropic-format conversation.\n */\nexport async function captureConversationAnthropic(\n messages: Array<{ role: string; content: unknown }>,\n assistantResponse: string,\n storage: SQLiteBackend,\n binding: SessionBinding,\n): Promise<void> {\n // Convert Anthropic format to simple messages\n const simpleMessages: Message[] = messages.map((m) => ({\n role: m.role,\n content:\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content\n .filter((b: { type: string; text?: string }) => b.type === \"text\" && b.text)\n .map((b: { text: string }) => b.text)\n .join(\"\\n\")\n : \"\",\n }));\n\n await captureConversation(simpleMessages, assistantResponse, storage, binding);\n}\n","/**\n * Memory injection — queries recall + scenarios + persona + skills\n * and injects them into the system prompt.\n *\n * Reuses the same recall logic as the hook-recall handler.\n */\n\nimport type { LocalEmbedder } from \"../embedding/local.js\";\nimport type { SQLiteBackend } from \"../storage/sqlite.js\";\n\ninterface SessionBinding {\n teamId?: string;\n agentId?: string;\n userId?: string;\n taskId?: string;\n}\n\ninterface Message {\n role: string;\n content: string;\n}\n\n/**\n * Inject memory into OpenAI-format messages.\n * - Queries recall with the last user message\n * - Prepends a system message with the memory block\n */\nexport async function injectMemory(\n messages: Message[],\n userMessage: string,\n storage: SQLiteBackend,\n embedder: LocalEmbedder,\n binding: SessionBinding,\n): Promise<Message[]> {\n // Generate embedding for the query\n let queryEmbedding: number[] | null = null;\n try {\n queryEmbedding = await embedder.embed(userMessage);\n console.error(`[proxy inject] embedding: ${queryEmbedding?.length ?? 0} dims`);\n } catch (e) {\n console.error(`[proxy inject] embed error: ${e}`);\n }\n\n // Query recall (hybrid search)\n let results: Array<{\n id: string;\n content: string;\n type: string;\n tags: string[];\n score: number;\n }> = [];\n try {\n const searchResults = await storage.search(userMessage, queryEmbedding, {\n sessionKey: \"\",\n limit: 5,\n offset: 0,\n mode: \"hybrid\",\n filters: {\n teamId: binding.teamId,\n agentId: binding.agentId,\n userId: binding.userId,\n },\n });\n results = searchResults.map((r) => ({\n id: r.entry.id,\n content: r.entry.content,\n type: r.entry.type,\n tags: r.entry.tags,\n score: r.score,\n }));\n console.error(`[proxy inject] search: ${results.length} results`);\n } catch (e) {\n console.error(`[proxy inject] search error: ${e}`);\n }\n\n // Query L1 atoms for the top captures\n const atoms: string[] = [];\n for (const result of results.slice(0, 3)) {\n try {\n const captureAtoms = await storage.listAtoms({ captureId: result.id, limit: 3 });\n for (const atom of captureAtoms) {\n atoms.push(atom.fact);\n }\n } catch {\n // best-effort\n }\n }\n\n // Query L2 scenarios\n let scenarios: string[] = [];\n if (binding.teamId) {\n try {\n const allScenarios = await storage.listScenarios({\n teamId: binding.teamId,\n agentId: binding.agentId,\n limit: 2,\n });\n scenarios = allScenarios.map((s) => s.summary);\n } catch {\n // best-effort\n }\n }\n\n // Query L3 persona\n let persona: string | null = null;\n if (binding.teamId && binding.agentId && binding.userId) {\n try {\n const p = await storage.readPersona(binding.teamId, binding.agentId, binding.userId);\n persona = p?.content ?? null;\n } catch {\n // best-effort\n }\n }\n\n // Query skills\n let skills: string[] = [];\n if (binding.teamId && binding.agentId) {\n try {\n const matchedSkills = await storage.searchSkills(\n binding.teamId,\n binding.agentId,\n userMessage,\n 2,\n );\n skills = matchedSkills.map((s) => `**${s.name}**: ${s.description ?? \"\"}`);\n } catch {\n // best-effort\n }\n }\n\n // [F1: Canvas injection] Query canvas for this session if offload is enabled\n let canvasBlock: string | null = null;\n const offloadOn =\n process.env.REMEM_OFFLOAD_ENABLED === \"true\" ||\n process.env.REMEM_OFFLOAD_ENABLED === \"1\" ||\n process.env.REMEM_FLOW === \"full\";\n if (offloadOn) {\n try {\n // For proxy mode, use team_id as session key (no cwd available)\n const sessionKey = `proxy-${binding.teamId ?? \"default\"}`;\n const canvasRow = (storage as any).db\n .prepare(\n \"SELECT mermaid_text, node_count FROM canvases WHERE session_key = ? ORDER BY updated_at DESC LIMIT 1\",\n )\n .get(sessionKey) as { mermaid_text: string | null; node_count: number } | undefined;\n if (canvasRow && canvasRow.mermaid_text && canvasRow.node_count > 0) {\n canvasBlock = `### Task Canvas (${canvasRow.node_count} steps)\\n\\`\\`\\`mermaid\\n${canvasRow.mermaid_text}\\n\\`\\`\\``;\n }\n } catch {\n // best-effort\n }\n }\n\n // Build the memory block\n const memoryBlock = buildMemoryBlock(results, atoms, scenarios, persona, skills, canvasBlock);\n if (!memoryBlock) return messages;\n\n // Find the system message and append, or prepend a new one\n const systemIdx = messages.findIndex((m) => m.role === \"system\");\n if (systemIdx >= 0) {\n const newMessages = [...messages];\n newMessages[systemIdx] = {\n ...messages[systemIdx],\n content: `${messages[systemIdx].content}\\n\\n${memoryBlock}`,\n };\n return newMessages;\n }\n\n return [{ role: \"system\", content: memoryBlock }, ...messages];\n}\n\n/** Build the <remem-mcp> memory block for injection. */\nfunction buildMemoryBlock(\n results: Array<{ content: string; type: string; tags: string[] }>,\n atoms: string[],\n scenarios: string[],\n persona: string | null,\n skills: string[],\n canvasBlock: string | null,\n): string | null {\n const sections: string[] = [];\n\n if (atoms.length > 0) {\n sections.push(`### Relevant Facts\\n${atoms.map((a) => `- ${a}`).join(\"\\n\")}`);\n }\n\n if (results.length > 0) {\n const captures = results.slice(0, 3).map((r) => `- [${r.type}] ${r.content.slice(0, 200)}`);\n sections.push(`### Past Memories\\n${captures.join(\"\\n\")}`);\n }\n\n if (scenarios.length > 0) {\n sections.push(`### Scenarios\\n${scenarios.map((s) => `- ${s}`).join(\"\\n\")}`);\n }\n\n if (persona) {\n sections.push(`### User Profile\\n${persona}`);\n }\n\n if (skills.length > 0) {\n sections.push(`### Relevant Skills\\n${skills.map((s) => `- ${s}`).join(\"\\n\")}`);\n }\n\n if (canvasBlock) {\n sections.push(canvasBlock);\n }\n\n if (sections.length === 0) return null;\n\n return `<remem-mcp>\\n${sections.join(\"\\n\\n\")}\\n</remem-mcp>`;\n}\n","/**\n * Session store — tracks team/agent/task bindings for proxy sessions.\n *\n * Adapted from TencentDB Agent Memory's sessionInit concept (MIT, Tencent 2026).\n * The proxy binds each session to a team/agent/task so memory queries are scoped.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\ninterface SessionBinding {\n teamId?: string;\n agentId?: string;\n taskId?: string;\n userId?: string;\n}\n\n/**\n * In-memory session store.\n * For production, this should be persisted to Redis or SQLite.\n */\nexport class SessionStore {\n private sessions = new Map<string, SessionBinding>();\n\n /** Create a new session with the given binding. */\n create(binding: SessionBinding): string {\n const sessionId = randomUUID();\n this.sessions.set(sessionId, binding);\n return sessionId;\n }\n\n /** Get the binding for a session. */\n get(sessionId: string): SessionBinding | null {\n return this.sessions.get(sessionId) ?? null;\n }\n\n /** Get the binding from request headers (x-remem-session or x-tdai-user-key). */\n getFromHeaders(headers: Record<string, string | string[] | undefined>): SessionBinding {\n const sessionId = headers[\"x-remem-session\"] as string | undefined;\n if (sessionId) {\n const binding = this.sessions.get(sessionId);\n if (binding) return binding;\n }\n\n // Fall back to header-based binding\n return {\n teamId: headers[\"x-remem-team\"] as string | undefined,\n agentId: headers[\"x-remem-agent\"] as string | undefined,\n taskId: headers[\"x-remem-task\"] as string | undefined,\n userId: headers[\"x-remem-user\"] as string | undefined,\n };\n }\n\n /** Delete a session. */\n delete(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /** Clear all sessions. */\n clear(): void {\n this.sessions.clear();\n }\n}\n"],"mappings":"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","names":[]}