{"version":3,"file":"annotate.cjs","names":["errorResponse","isIntelligenceRuntime","isHandlerResponse","resolveIntelligenceUser","PlatformRequestError"],"sources":["../../../../../src/v2/runtime/handlers/intelligence/annotate.ts"],"sourcesContent":["import { logger } from \"@copilotkit/shared\";\nimport type {\n  CopilotIntelligenceRuntimeLike,\n  CopilotRuntimeLike,\n} from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\n\ninterface AnnotateHandlerParams {\n  runtime: CopilotRuntimeLike;\n  request: Request;\n}\n\ninterface AnnotateBody {\n  /** Discriminator identifying the annotation type (e.g. `\"user_action\"`). */\n  type: string;\n  /** Type-specific payload. Shape varies by `type`. */\n  payload?: unknown;\n  /** The thread the annotation is associated with. */\n  threadId: string;\n  /** Caller-supplied idempotency key. Optional — platform auto-generates one when absent. */\n  clientEventId?: string;\n  /** ISO-8601 client-asserted timestamp. Defaults to server NOW() when absent. */\n  occurredAt?: string;\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 annotate body\");\n    return errorResponse(\"Invalid request body\", 400);\n  }\n}\n\nfunction requireIntelligenceRuntime(\n  runtime: CopilotRuntimeLike,\n): CopilotIntelligenceRuntimeLike | Response {\n  if (!isIntelligenceRuntime(runtime)) {\n    return errorResponse(\n      \"Missing CopilotKitIntelligence configuration. annotate requires a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\",\n      422,\n    );\n  }\n  return runtime;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n  return typeof value === \"string\" && value.length > 0;\n}\n\n/**\n * `POST /annotate` handler.\n *\n * Three-tier flow:\n *   recordAnnotation() (frontend lib; called by useLearnFromUserAction / useLearningContainers)\n *     → POST ${runtimeUrl}/annotate\n *     → this handler resolves the Intel user from BFF auth\n *     → intelligence.annotate(...)\n *     → PUT ${apiUrl}/connector/annotate/:clientEventId\n *\n * The frontend hook may auto-generate a UUID `clientEventId` per call\n * so retries are idempotent end-to-end (the platform collapses to the\n * original row).\n */\nexport async function handleAnnotate({\n  runtime,\n  request,\n}: AnnotateHandlerParams): Promise<Response> {\n  const intelligenceRuntime = requireIntelligenceRuntime(runtime);\n  if (isHandlerResponse(intelligenceRuntime)) return intelligenceRuntime;\n\n  const body = await parseJsonBody(request);\n  if (isHandlerResponse(body)) return body;\n\n  const user = await resolveIntelligenceUser({\n    runtime: intelligenceRuntime,\n    request,\n  });\n  if (isHandlerResponse(user)) return user;\n\n  const parsed = parseAnnotateBody(body);\n  if (isHandlerResponse(parsed)) return parsed;\n\n  try {\n    const result = await intelligenceRuntime.intelligence.annotate({\n      userId: user.id,\n      threadId: parsed.threadId,\n      type: parsed.type,\n      payload: parsed.payload,\n      clientEventId: parsed.clientEventId,\n      occurredAt: parsed.occurredAt,\n    });\n    return new Response(JSON.stringify(result), {\n      status: 200,\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n  } catch (err) {\n    logger.error({ err }, \"annotate: platform call failed\");\n    // Forward the platform's HTTP status when it's a client error\n    // (4xx) so the SDK author sees an actionable response instead of\n    // a generic 502. 5xx and non-platform errors collapse to 502\n    // (\"Bad Gateway\") because the upstream is genuinely at fault.\n    if (\n      err instanceof PlatformRequestError &&\n      err.status >= 400 &&\n      err.status < 500\n    ) {\n      return errorResponse(err.message, err.status);\n    }\n    return errorResponse(\"Failed to annotate\", 502);\n  }\n}\n\nfunction parseAnnotateBody(\n  body: Record<string, unknown>,\n): AnnotateBody | Response {\n  if (!isNonEmptyString(body.threadId)) {\n    return errorResponse(\"Valid threadId is required\", 400);\n  }\n  if (!isNonEmptyString(body.type)) {\n    return errorResponse(\"Valid type is required\", 400);\n  }\n  return {\n    type: body.type,\n    payload: body.payload,\n    threadId: body.threadId,\n    clientEventId: isNonEmptyString(body.clientEventId)\n      ? body.clientEventId\n      : undefined,\n    occurredAt: isNonEmptyString(body.occurredAt) ? body.occurredAt : undefined,\n  };\n}\n"],"mappings":";;;;;;;;;AA4BA,eAAe,cACb,SAC6C;AAC7C,KAAI;AACF,SAAQ,MAAM,QAAQ,MAAM;UACrB,OAAO;AACd,4BAAO,MAAM,EAAE,KAAK,OAAO,EAAE,kCAAkC;AAC/D,SAAOA,oCAAc,wBAAwB,IAAI;;;AAIrD,SAAS,2BACP,SAC2C;AAC3C,KAAI,CAACC,wCAAsB,QAAQ,CACjC,QAAOD,oCACL,+IACA,IACD;AAEH,QAAO;;AAGT,SAAS,iBAAiB,OAAiC;AACzD,QAAO,OAAO,UAAU,YAAY,MAAM,SAAS;;;;;;;;;;;;;;;;AAiBrD,eAAsB,eAAe,EACnC,SACA,WAC2C;CAC3C,MAAM,sBAAsB,2BAA2B,QAAQ;AAC/D,KAAIE,wCAAkB,oBAAoB,CAAE,QAAO;CAEnD,MAAM,OAAO,MAAM,cAAc,QAAQ;AACzC,KAAIA,wCAAkB,KAAK,CAAE,QAAO;CAEpC,MAAM,OAAO,MAAMC,0DAAwB;EACzC,SAAS;EACT;EACD,CAAC;AACF,KAAID,wCAAkB,KAAK,CAAE,QAAO;CAEpC,MAAM,SAAS,kBAAkB,KAAK;AACtC,KAAIA,wCAAkB,OAAO,CAAE,QAAO;AAEtC,KAAI;EACF,MAAM,SAAS,MAAM,oBAAoB,aAAa,SAAS;GAC7D,QAAQ,KAAK;GACb,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,eAAe,OAAO;GACtB,YAAY,OAAO;GACpB,CAAC;AACF,SAAO,IAAI,SAAS,KAAK,UAAU,OAAO,EAAE;GAC1C,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAChD,CAAC;UACK,KAAK;AACZ,4BAAO,MAAM,EAAE,KAAK,EAAE,iCAAiC;AAKvD,MACE,eAAeE,uCACf,IAAI,UAAU,OACd,IAAI,SAAS,IAEb,QAAOJ,oCAAc,IAAI,SAAS,IAAI,OAAO;AAE/C,SAAOA,oCAAc,sBAAsB,IAAI;;;AAInD,SAAS,kBACP,MACyB;AACzB,KAAI,CAAC,iBAAiB,KAAK,SAAS,CAClC,QAAOA,oCAAc,8BAA8B,IAAI;AAEzD,KAAI,CAAC,iBAAiB,KAAK,KAAK,CAC9B,QAAOA,oCAAc,0BAA0B,IAAI;AAErD,QAAO;EACL,MAAM,KAAK;EACX,SAAS,KAAK;EACd,UAAU,KAAK;EACf,eAAe,iBAAiB,KAAK,cAAc,GAC/C,KAAK,gBACL;EACJ,YAAY,iBAAiB,KAAK,WAAW,GAAG,KAAK,aAAa;EACnE"}