{"version":3,"file":"memories.mjs","names":[],"sources":["../../../../../src/v2/runtime/handlers/intelligence/memories.ts"],"sourcesContent":["import type { CopilotRuntimeLike } from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { logger } from \"@copilotkit/shared\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\n\ninterface MemoriesHandlerParams {\n  runtime: CopilotRuntimeLike;\n  request: Request;\n}\n\ninterface MemoryMutationParams extends MemoriesHandlerParams {\n  memoryId: string;\n}\n\nconst MISSING_INTELLIGENCE_MESSAGE =\n  \"Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\";\n\n/** Allowed `kind` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n  \"topical\",\n  \"episodic\",\n  \"operational\",\n]);\n/** Allowed `scope` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Maps a thrown error to a `Response`.\n *\n * For a {@link PlatformRequestError}, forward only client-actionable **4xx**\n * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422\n * unprocessable) so a `useMemories` consumer can branch on them — a flat 500\n * would erase that distinction. A platform **5xx** (or any non-4xx / malformed\n * status) means the runtime is healthy but its dependency failed, so it surfaces\n * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime\n * itself broke — and this also avoids a `new Response(..., { status })`\n * `RangeError` on an out-of-range status. Non-platform throws stay 500.\n */\nfunction memoryErrorResponse(error: unknown, message: string): Response {\n  if (error instanceof PlatformRequestError) {\n    const { status } = error;\n    if (Number.isInteger(status) && status >= 400 && status <= 499) {\n      return errorResponse(message, status);\n    }\n    return errorResponse(message, 502);\n  }\n  return errorResponse(message, 500);\n}\n\nasync function parseJsonBody(\n  request: Request,\n): Promise<Record<string, unknown> | Response> {\n  try {\n    return (await request.json()) as Record<string, unknown>;\n  } catch (error) {\n    logger.error({ err: error }, \"Malformed JSON in memory request body\");\n    return errorResponse(\"Invalid request body\", 400);\n  }\n}\n\n/**\n * Extracts and validates the create/supersede body fields the platform's\n * memory endpoints require. Returns a `Response` (400) on invalid input.\n */\nfunction parseMemoryBody(body: Record<string, unknown>):\n  | {\n      content: string;\n      kind: string;\n      scope?: string;\n      sourceThreadIds?: string[];\n    }\n  | Response {\n  const { content, kind, scope, sourceThreadIds } = body;\n  if (typeof content !== \"string\" || typeof kind !== \"string\") {\n    return errorResponse(\"Memory requires string `content` and `kind`\", 400);\n  }\n  // `kind` must be one of the platform's known kinds. Reject an out-of-vocabulary\n  // value here rather than forwarding it for the platform to reject.\n  if (!MEMORY_KINDS.has(kind)) {\n    return errorResponse(\n      \"Memory `kind` must be one of: topical, episodic, operational\",\n      400,\n    );\n  }\n  // `scope` is optional: when omitted the platform applies its default\n  // (`\"user\"`). Only reject a present-but-wrong-typed scope.\n  if (scope !== undefined && typeof scope !== \"string\") {\n    return errorResponse(\"Memory `scope` must be a string when provided\", 400);\n  }\n  // When `scope` is present, it must be one of the known scopes.\n  if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n    return errorResponse(\"Memory `scope` must be one of: user, project\", 400);\n  }\n  // `sourceThreadIds` is optional, but when present it must be a string array.\n  // Validate every element so non-string ids are not forwarded to the platform.\n  if (\n    sourceThreadIds !== undefined &&\n    (!Array.isArray(sourceThreadIds) ||\n      !sourceThreadIds.every((id) => typeof id === \"string\"))\n  ) {\n    return errorResponse(\n      \"Memory `sourceThreadIds` must be an array of strings when provided\",\n      400,\n    );\n  }\n  return {\n    content,\n    kind,\n    ...(typeof scope === \"string\" ? { scope } : {}),\n    ...(Array.isArray(sourceThreadIds)\n      ? { sourceThreadIds: sourceThreadIds as string[] }\n      : {}),\n    // `sourceThreadIds` elements are validated as strings above; the cast is safe.\n  };\n}\n\n/**\n * Validates the recall body: `query` required non-empty string (trimmed);\n * `limit` optional finite positive integer; `scope` optional and in the known\n * scopes. Returns a 400 Response on invalid input. The returned `query` is the\n * trimmed value so a whitespace-padded query is never forwarded to the platform.\n */\nfunction parseRecallBody(\n  body: Record<string, unknown>,\n): { query: string; limit?: number; scope?: string } | Response {\n  const { query, limit, scope } = body;\n  // Trim before the emptiness check so whitespace-only queries (e.g. \"   \")\n  // are rejected rather than forwarded as a useless query to the platform.\n  const trimmedQuery = typeof query === \"string\" ? query.trim() : query;\n  if (typeof trimmedQuery !== \"string\" || trimmedQuery.length === 0) {\n    return errorResponse(\"Recall requires a non-empty string `query`\", 400);\n  }\n  // When provided, `limit` must be a finite positive integer. `Number.isInteger`\n  // already rejects NaN, Infinity, and fractions (NaN/Infinity would otherwise\n  // JSON-serialize to `null` and silently corrupt the forwarded request);\n  // the `> 0` guard rejects zero and negatives.\n  if (\n    limit !== undefined &&\n    !(typeof limit === \"number\" && Number.isInteger(limit) && limit > 0)\n  ) {\n    return errorResponse(\"Recall `limit` must be a positive integer\", 400);\n  }\n  if (scope !== undefined && typeof scope !== \"string\") {\n    return errorResponse(\"Recall `scope` must be a string when provided\", 400);\n  }\n  if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n    return errorResponse(\"Recall `scope` must be one of: user, project\", 400);\n  }\n  return {\n    query: trimmedQuery,\n    ...(typeof limit === \"number\" ? { limit } : {}),\n    ...(typeof scope === \"string\" ? { scope } : {}),\n  };\n}\n\n/**\n * Lists the resolved user's long-term memories via the Intelligence platform.\n *\n * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence`\n * runtime, resolves the user with `identifyUser` (never trusting a\n * client-supplied id), and proxies to the platform's `GET /api/memories`\n * with the project API key + resolved user. The `?includeInvalidated=true`\n * query is forwarded so callers can opt into retired rows. The response is\n * the platform's `{ memories }` envelope, which the client memory store\n * consumes directly.\n */\nexport async function handleListMemories({\n  runtime,\n  request,\n}: MemoriesHandlerParams): Promise<Response> {\n  if (isIntelligenceRuntime(runtime)) {\n    try {\n      const url = new URL(request.url);\n      const includeInvalidated =\n        url.searchParams.get(\"includeInvalidated\") === \"true\";\n\n      const user = await resolveIntelligenceUser({ runtime, request });\n      if (isHandlerResponse(user)) return user;\n\n      const data = await runtime.intelligence.listMemories({\n        userId: user.id,\n        ...(includeInvalidated ? { includeInvalidated: true } : {}),\n      });\n\n      // The client memory store consumes the `{ memories: [...] }` envelope\n      // directly. Assert the shape before forwarding so a platform contract\n      // violation surfaces as a clear 502 (the runtime is healthy but its\n      // dependency returned the wrong shape) instead of a 200 the client will\n      // choke on.\n      if (\n        data == null ||\n        typeof data !== \"object\" ||\n        !Array.isArray((data as { memories?: unknown }).memories)\n      ) {\n        logger.error(\n          { data },\n          \"listMemories: platform returned a response without a `memories` array\",\n        );\n        return errorResponse(\n          \"Memory platform returned an invalid list response\",\n          502,\n        );\n      }\n\n      return Response.json(data);\n    } catch (error) {\n      logger.error({ err: error }, \"Error listing memories\");\n      return memoryErrorResponse(error, \"Failed to list memories\");\n    }\n  }\n\n  return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Semantically recalls the resolved user's memories via the platform (`POST\n * /api/memories/recall`, hybrid RAG). Mirrors {@link handleListMemories}:\n * requires a `CopilotKitIntelligence` runtime, resolves the user with\n * `identifyUser` (never a client-supplied id), proxies with the project API\n * key + resolved user. Body `{ query, limit?, scope? }`; response `{ memories }`,\n * each optionally carrying `score`.\n */\nexport async function handleRecallMemories({\n  runtime,\n  request,\n}: MemoriesHandlerParams): Promise<Response> {\n  if (!isIntelligenceRuntime(runtime)) {\n    return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n  }\n  try {\n    const body = await parseJsonBody(request);\n    if (isHandlerResponse(body)) return body;\n    const fields = parseRecallBody(body);\n    if (isHandlerResponse(fields)) return fields;\n\n    const user = await resolveIntelligenceUser({ runtime, request });\n    if (isHandlerResponse(user)) return user;\n\n    const data = await runtime.intelligence.recallMemories({\n      userId: user.id,\n      ...fields,\n    });\n\n    if (\n      data == null ||\n      typeof data !== \"object\" ||\n      !Array.isArray((data as { memories?: unknown }).memories)\n    ) {\n      logger.error(\n        { data },\n        \"recallMemories: platform returned a response without a `memories` array\",\n      );\n      return errorResponse(\n        \"Memory platform returned an invalid recall response\",\n        502,\n      );\n    }\n    return Response.json(data);\n  } catch (error) {\n    logger.error({ err: error }, \"Error recalling memories\");\n    return memoryErrorResponse(error, \"Failed to recall memories\");\n  }\n}\n\n/**\n * Mints memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires\n * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser`\n * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs\n * the `joinCode` here (unlike threads, where it rides the thread-list response)\n * because the client builds the `user_meta:memories:<joinCode>` channel topic\n * from it.\n *\n * When the platform also resolves a project scope, the response additionally\n * carries `projectJoinToken` / `projectJoinCode`, which the client uses to open\n * a second `project_meta:memories:<projectJoinCode>` channel. These are\n * optional: absent project scope → both fields are omitted (silent-degrade\n * contract; the client opens only the user channel).\n */\nexport async function handleSubscribeToMemories({\n  runtime,\n  request,\n}: MemoriesHandlerParams): Promise<Response> {\n  if (isIntelligenceRuntime(runtime)) {\n    try {\n      const user = await resolveIntelligenceUser({ runtime, request });\n      if (isHandlerResponse(user)) return user;\n\n      const credentials = await runtime.intelligence.ɵsubscribeToMemories({\n        userId: user.id,\n      });\n\n      return Response.json({\n        joinToken: credentials.joinToken,\n        joinCode: credentials.joinCode,\n        // Project-scoped credentials ride along only when the platform minted\n        // them; omit both when absent (silent-degrade contract).\n        ...(credentials.projectJoinToken !== undefined\n          ? { projectJoinToken: credentials.projectJoinToken }\n          : {}),\n        ...(credentials.projectJoinCode !== undefined\n          ? { projectJoinCode: credentials.projectJoinCode }\n          : {}),\n      });\n    } catch (error) {\n      logger.error({ err: error }, \"Error subscribing to memories\");\n      return memoryErrorResponse(error, \"Failed to subscribe to memories\");\n    }\n  }\n\n  return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Creates a memory for the resolved user (platform `POST /api/memories`).\n * Identity comes from `identifyUser`, never the request body. Returns 201\n * with the stored memory (the client store applies it server-authoritatively).\n */\nexport async function handleCreateMemory({\n  runtime,\n  request,\n}: MemoriesHandlerParams): Promise<Response> {\n  if (!isIntelligenceRuntime(runtime)) {\n    return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n  }\n  try {\n    const body = await parseJsonBody(request);\n    if (isHandlerResponse(body)) return body;\n    const fields = parseMemoryBody(body);\n    if (isHandlerResponse(fields)) return fields;\n\n    const user = await resolveIntelligenceUser({ runtime, request });\n    if (isHandlerResponse(user)) return user;\n\n    const data = await runtime.intelligence.createMemory({\n      userId: user.id,\n      ...fields,\n    });\n    return Response.json(data, { status: 201 });\n  } catch (error) {\n    logger.error({ err: error }, \"Error creating memory\");\n    return memoryErrorResponse(error, \"Failed to create memory\");\n  }\n}\n\n/**\n * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and\n * inserts the new content atomically; the response carries `retiredId`.\n */\nexport async function handleUpdateMemory({\n  runtime,\n  request,\n  memoryId,\n}: MemoryMutationParams): Promise<Response> {\n  if (!isIntelligenceRuntime(runtime)) {\n    return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n  }\n  try {\n    const body = await parseJsonBody(request);\n    if (isHandlerResponse(body)) return body;\n    const fields = parseMemoryBody(body);\n    if (isHandlerResponse(fields)) return fields;\n\n    const user = await resolveIntelligenceUser({ runtime, request });\n    if (isHandlerResponse(user)) return user;\n\n    const data = await runtime.intelligence.updateMemory({\n      userId: user.id,\n      id: memoryId,\n      ...fields,\n    });\n    return Response.json(data);\n  } catch (error) {\n    logger.error({ err: error }, \"Error updating memory\");\n    return memoryErrorResponse(error, \"Failed to update memory\");\n  }\n}\n\n/**\n * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy\n * on the platform side; returns 204.\n */\nexport async function handleRemoveMemory({\n  runtime,\n  request,\n  memoryId,\n}: MemoryMutationParams): Promise<Response> {\n  if (!isIntelligenceRuntime(runtime)) {\n    return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n  }\n  try {\n    const user = await resolveIntelligenceUser({ runtime, request });\n    if (isHandlerResponse(user)) return user;\n\n    await runtime.intelligence.removeMemory({ userId: user.id, id: memoryId });\n    return new Response(null, { status: 204 });\n  } catch (error) {\n    logger.error({ err: error }, \"Error removing memory\");\n    return memoryErrorResponse(error, \"Failed to remove memory\");\n  }\n}\n"],"mappings":";;;;;;;;AAgBA,MAAM,+BACJ;;AAGF,MAAM,eAAoC,IAAI,IAAI;CAChD;CACA;CACA;CACD,CAAC;;AAEF,MAAM,gBAAqC,IAAI,IAAI,CAAC,QAAQ,UAAU,CAAC;;;;;;;;;;;;;AAcvE,SAAS,oBAAoB,OAAgB,SAA2B;AACtE,KAAI,iBAAiB,sBAAsB;EACzC,MAAM,EAAE,WAAW;AACnB,MAAI,OAAO,UAAU,OAAO,IAAI,UAAU,OAAO,UAAU,IACzD,QAAO,cAAc,SAAS,OAAO;AAEvC,SAAO,cAAc,SAAS,IAAI;;AAEpC,QAAO,cAAc,SAAS,IAAI;;AAGpC,eAAe,cACb,SAC6C;AAC7C,KAAI;AACF,SAAQ,MAAM,QAAQ,MAAM;UACrB,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,wCAAwC;AACrE,SAAO,cAAc,wBAAwB,IAAI;;;;;;;AAQrD,SAAS,gBAAgB,MAOZ;CACX,MAAM,EAAE,SAAS,MAAM,OAAO,oBAAoB;AAClD,KAAI,OAAO,YAAY,YAAY,OAAO,SAAS,SACjD,QAAO,cAAc,+CAA+C,IAAI;AAI1E,KAAI,CAAC,aAAa,IAAI,KAAK,CACzB,QAAO,cACL,gEACA,IACD;AAIH,KAAI,UAAU,UAAa,OAAO,UAAU,SAC1C,QAAO,cAAc,iDAAiD,IAAI;AAG5E,KAAI,OAAO,UAAU,YAAY,CAAC,cAAc,IAAI,MAAM,CACxD,QAAO,cAAc,gDAAgD,IAAI;AAI3E,KACE,oBAAoB,WACnB,CAAC,MAAM,QAAQ,gBAAgB,IAC9B,CAAC,gBAAgB,OAAO,OAAO,OAAO,OAAO,SAAS,EAExD,QAAO,cACL,sEACA,IACD;AAEH,QAAO;EACL;EACA;EACA,GAAI,OAAO,UAAU,WAAW,EAAE,OAAO,GAAG,EAAE;EAC9C,GAAI,MAAM,QAAQ,gBAAgB,GAC9B,EAAmB,iBAA6B,GAChD,EAAE;EAEP;;;;;;;;AASH,SAAS,gBACP,MAC8D;CAC9D,MAAM,EAAE,OAAO,OAAO,UAAU;CAGhC,MAAM,eAAe,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG;AAChE,KAAI,OAAO,iBAAiB,YAAY,aAAa,WAAW,EAC9D,QAAO,cAAc,8CAA8C,IAAI;AAMzE,KACE,UAAU,UACV,EAAE,OAAO,UAAU,YAAY,OAAO,UAAU,MAAM,IAAI,QAAQ,GAElE,QAAO,cAAc,6CAA6C,IAAI;AAExE,KAAI,UAAU,UAAa,OAAO,UAAU,SAC1C,QAAO,cAAc,iDAAiD,IAAI;AAE5E,KAAI,OAAO,UAAU,YAAY,CAAC,cAAc,IAAI,MAAM,CACxD,QAAO,cAAc,gDAAgD,IAAI;AAE3E,QAAO;EACL,OAAO;EACP,GAAI,OAAO,UAAU,WAAW,EAAE,OAAO,GAAG,EAAE;EAC9C,GAAI,OAAO,UAAU,WAAW,EAAE,OAAO,GAAG,EAAE;EAC/C;;;;;;;;;;;;;AAcH,eAAsB,mBAAmB,EACvC,SACA,WAC2C;AAC3C,KAAI,sBAAsB,QAAQ,CAChC,KAAI;EAEF,MAAM,qBADM,IAAI,IAAI,QAAQ,IAAI,CAE1B,aAAa,IAAI,qBAAqB,KAAK;EAEjD,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;EAEpC,MAAM,OAAO,MAAM,QAAQ,aAAa,aAAa;GACnD,QAAQ,KAAK;GACb,GAAI,qBAAqB,EAAE,oBAAoB,MAAM,GAAG,EAAE;GAC3D,CAAC;AAOF,MACE,QAAQ,QACR,OAAO,SAAS,YAChB,CAAC,MAAM,QAAS,KAAgC,SAAS,EACzD;AACA,UAAO,MACL,EAAE,MAAM,EACR,wEACD;AACD,UAAO,cACL,qDACA,IACD;;AAGH,SAAO,SAAS,KAAK,KAAK;UACnB,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,yBAAyB;AACtD,SAAO,oBAAoB,OAAO,0BAA0B;;AAIhE,QAAO,cAAc,8BAA8B,IAAI;;;;;;;;;;AAWzD,eAAsB,qBAAqB,EACzC,SACA,WAC2C;AAC3C,KAAI,CAAC,sBAAsB,QAAQ,CACjC,QAAO,cAAc,8BAA8B,IAAI;AAEzD,KAAI;EACF,MAAM,OAAO,MAAM,cAAc,QAAQ;AACzC,MAAI,kBAAkB,KAAK,CAAE,QAAO;EACpC,MAAM,SAAS,gBAAgB,KAAK;AACpC,MAAI,kBAAkB,OAAO,CAAE,QAAO;EAEtC,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;EAEpC,MAAM,OAAO,MAAM,QAAQ,aAAa,eAAe;GACrD,QAAQ,KAAK;GACb,GAAG;GACJ,CAAC;AAEF,MACE,QAAQ,QACR,OAAO,SAAS,YAChB,CAAC,MAAM,QAAS,KAAgC,SAAS,EACzD;AACA,UAAO,MACL,EAAE,MAAM,EACR,0EACD;AACD,UAAO,cACL,uDACA,IACD;;AAEH,SAAO,SAAS,KAAK,KAAK;UACnB,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,2BAA2B;AACxD,SAAO,oBAAoB,OAAO,4BAA4B;;;;;;;;;;;;;;;;;;AAmBlE,eAAsB,0BAA0B,EAC9C,SACA,WAC2C;AAC3C,KAAI,sBAAsB,QAAQ,CAChC,KAAI;EACF,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;EAEpC,MAAM,cAAc,MAAM,QAAQ,aAAa,qBAAqB,EAClE,QAAQ,KAAK,IACd,CAAC;AAEF,SAAO,SAAS,KAAK;GACnB,WAAW,YAAY;GACvB,UAAU,YAAY;GAGtB,GAAI,YAAY,qBAAqB,SACjC,EAAE,kBAAkB,YAAY,kBAAkB,GAClD,EAAE;GACN,GAAI,YAAY,oBAAoB,SAChC,EAAE,iBAAiB,YAAY,iBAAiB,GAChD,EAAE;GACP,CAAC;UACK,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,gCAAgC;AAC7D,SAAO,oBAAoB,OAAO,kCAAkC;;AAIxE,QAAO,cAAc,8BAA8B,IAAI;;;;;;;AAQzD,eAAsB,mBAAmB,EACvC,SACA,WAC2C;AAC3C,KAAI,CAAC,sBAAsB,QAAQ,CACjC,QAAO,cAAc,8BAA8B,IAAI;AAEzD,KAAI;EACF,MAAM,OAAO,MAAM,cAAc,QAAQ;AACzC,MAAI,kBAAkB,KAAK,CAAE,QAAO;EACpC,MAAM,SAAS,gBAAgB,KAAK;AACpC,MAAI,kBAAkB,OAAO,CAAE,QAAO;EAEtC,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;EAEpC,MAAM,OAAO,MAAM,QAAQ,aAAa,aAAa;GACnD,QAAQ,KAAK;GACb,GAAG;GACJ,CAAC;AACF,SAAO,SAAS,KAAK,MAAM,EAAE,QAAQ,KAAK,CAAC;UACpC,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,wBAAwB;AACrD,SAAO,oBAAoB,OAAO,0BAA0B;;;;;;;AAQhE,eAAsB,mBAAmB,EACvC,SACA,SACA,YAC0C;AAC1C,KAAI,CAAC,sBAAsB,QAAQ,CACjC,QAAO,cAAc,8BAA8B,IAAI;AAEzD,KAAI;EACF,MAAM,OAAO,MAAM,cAAc,QAAQ;AACzC,MAAI,kBAAkB,KAAK,CAAE,QAAO;EACpC,MAAM,SAAS,gBAAgB,KAAK;AACpC,MAAI,kBAAkB,OAAO,CAAE,QAAO;EAEtC,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;EAEpC,MAAM,OAAO,MAAM,QAAQ,aAAa,aAAa;GACnD,QAAQ,KAAK;GACb,IAAI;GACJ,GAAG;GACJ,CAAC;AACF,SAAO,SAAS,KAAK,KAAK;UACnB,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,wBAAwB;AACrD,SAAO,oBAAoB,OAAO,0BAA0B;;;;;;;AAQhE,eAAsB,mBAAmB,EACvC,SACA,SACA,YAC0C;AAC1C,KAAI,CAAC,sBAAsB,QAAQ,CACjC,QAAO,cAAc,8BAA8B,IAAI;AAEzD,KAAI;EACF,MAAM,OAAO,MAAM,wBAAwB;GAAE;GAAS;GAAS,CAAC;AAChE,MAAI,kBAAkB,KAAK,CAAE,QAAO;AAEpC,QAAM,QAAQ,aAAa,aAAa;GAAE,QAAQ,KAAK;GAAI,IAAI;GAAU,CAAC;AAC1E,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;UACnC,OAAO;AACd,SAAO,MAAM,EAAE,KAAK,OAAO,EAAE,wBAAwB;AACrD,SAAO,oBAAoB,OAAO,0BAA0B"}