{"version":3,"file":"shared.mjs","sources":["../../../../src/tools/memory/shared.ts"],"sourcesContent":["/**\n * Shared Zod schemas + helpers for the memory tool family.\n *\n * The tool schemas deliberately do NOT expose `agent_id` or `user_id`. Scope\n * is captured in a closure at tool construction time by {@link buildMemoryTools},\n * so even a hallucinated tool call with extra fields cannot influence it.\n */\nimport { z } from 'zod';\nimport {\n  DEFAULT_MAX_INJECTED_CHARS,\n  MEMORY_PATH_PREFIX,\n} from '@/memory/constants';\nimport type {\n  MemoryAppendInput,\n  MemoryBackend,\n  MemoryEntry,\n  MemoryScope,\n} from '@/memory/types';\n\nexport const MemorySearchSchema = z.object({\n  query: z.string().describe('Natural-language query to search memory for'),\n  maxResults: z\n    .number()\n    .int()\n    .min(1)\n    .max(50)\n    .optional()\n    .describe('Maximum number of results to return (default 10)'),\n  minScore: z\n    .number()\n    .min(0)\n    .max(1)\n    .optional()\n    .describe('Minimum hybrid score (0..1) below which results are dropped'),\n});\n\nexport const MemoryGetSchema = z.object({\n  path: z\n    .string()\n    .describe(\n      'Memory path, e.g. \"memory/decisions.md\". Must start with \"memory/\"'\n    ),\n  from: z\n    .number()\n    .int()\n    .min(1)\n    .optional()\n    .describe('Starting line number (1-indexed)'),\n  lines: z\n    .number()\n    .int()\n    .min(1)\n    .optional()\n    .describe('Number of lines to read starting at `from`'),\n});\n\nexport const MemoryAppendSchema = z.object({\n  path: z\n    .string()\n    .describe(\n      'Memory path to append to (e.g. \"memory/decisions.md\"). Must start with \"memory/\"'\n    ),\n  content: z\n    .string()\n    .min(1)\n    .describe(\n      \"Note content in the agent's own voice. Markdown allowed. Each call appends an immutable entry.\"\n    ),\n});\n\nexport type MemorySearchArgs = z.infer<typeof MemorySearchSchema>;\nexport type MemoryGetArgs = z.infer<typeof MemoryGetSchema>;\nexport type MemoryAppendArgs = z.infer<typeof MemoryAppendSchema>;\n\n/** Shape returned by `memory_search` — serialised as the tool result string. */\nexport interface MemorySearchToolResult {\n  results: Array<\n    Pick<MemoryEntry, 'id' | 'path' | 'content' | 'score' | 'createdAt'> & {\n      citation?: string;\n    }\n  >;\n  disabled?: boolean;\n  unavailable?: boolean;\n  error?: string;\n  warning?: string;\n  action?: string;\n}\n\n/** Shape returned by `memory_get`. */\nexport interface MemoryGetToolResult {\n  path: string;\n  text: string;\n  disabled?: boolean;\n  error?: string;\n}\n\nexport function buildMemorySearchUnavailableResult(\n  error: string | undefined\n): MemorySearchToolResult {\n  const reason =\n    (error ?? 'memory search unavailable').trim() ||\n    'memory search unavailable';\n  const isQuota = /insufficient_quota|quota|429/i.test(reason);\n  return {\n    results: [],\n    disabled: true,\n    unavailable: true,\n    error: reason,\n    warning: isQuota\n      ? 'Memory search is unavailable because the embedding provider quota is exhausted.'\n      : 'Memory search is unavailable due to an embedding/provider error.',\n    action: isQuota\n      ? 'Top up or switch embedding provider, then retry memory_search.'\n      : 'Check embedding provider configuration and retry memory_search.',\n  };\n}\n\n/**\n * Clamp a ranked result list to a total character budget.\n * Ported from upstream `tools.citations.ts::clampResultsByInjectedChars`.\n */\nexport function clampResultsByInjectedChars<T extends { content: string }>(\n  results: T[],\n  maxInjectedChars: number = DEFAULT_MAX_INJECTED_CHARS\n): T[] {\n  const out: T[] = [];\n  let total = 0;\n  for (const result of results) {\n    const size = result.content.length ?? 0;\n    if (total + size > maxInjectedChars && out.length > 0) break;\n    out.push(result);\n    total += size;\n  }\n  return out;\n}\n\nexport interface MemoryToolBinding {\n  backend: MemoryBackend;\n  scope: MemoryScope;\n  maxInjectedChars?: number;\n  /** Phase 2 — per-call search options propagated into backend.search. */\n  searchOptions?: {\n    mmr?: { enabled?: boolean; lambda?: number };\n    temporalDecay?: { enabled?: boolean; halfLifeDays?: number };\n    citations?: 'on' | 'off' | 'auto';\n  };\n  /** Phase 2 — optional best-effort recall recorder. */\n  recallTracker?: {\n    record(params: {\n      agentId: string;\n      query: string;\n      hits: Array<{ id: string; path: string; score: number }>;\n    }): Promise<void>;\n  };\n}\n\nexport function assertAppendAllowed(path: string): void {\n  if (!path || !path.startsWith(MEMORY_PATH_PREFIX)) {\n    throw new Error(\n      `memory_append path must start with \"${MEMORY_PATH_PREFIX}\"`\n    );\n  }\n}\n\n/** Normalise an append call into the backend input shape. */\nexport function toAppendInput(args: MemoryAppendArgs): MemoryAppendInput {\n  assertAppendAllowed(args.path);\n  return { path: args.path, content: args.content };\n}\n"],"names":[],"mappings":"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"}