{"version":3,"sources":["../../src/protocol/derivative-questions.ts"],"sourcesContent":["/**\n * Builder-side client for the Personal Server derivative question API.\n *\n * @remarks\n * A question is a standing prompt over the owner's source scopes. The\n * Personal Server answers it locally (the raw sources never leave the\n * machine except through its inference call) and writes the answer into the\n * derived scope as an ordinary derivative record, with lineage pointing at\n * the sources. The builder then reads the derived scope with its normal read\n * grant. Every source change re-runs the question, so a builder registers it\n * once and keeps reading a scope that stays up to date.\n *\n * One grant carries the whole pipeline, and it needs all three of:\n *\n * - a bare read entry for every source scope (the answer exposes them, so\n *   the server refuses the registration otherwise:\n *   `DERIVATIVE_SOURCE_NOT_GRANTED`),\n * - a bare read entry for the derived scope (to read the answer back),\n * - `write:<derivedScope>` (the credential the question routes authorize\n *   against).\n *\n * Authentication is the Write API's, with no new credential: the write\n * session bearer from {@link openWriteSession} plus a fresh, single-use\n * `X-Vana-Write-Signature` Web3Signed proof over every request, carrying the\n * grant id as a signed claim. These helpers own that: they open one session\n * per `{ signer, Personal Server, grant }`, reuse it across calls, sign a new\n * proof per request, and re-open the session once when a call comes back a\n * 401 the session is responsible for (the Personal Server keeps sessions in\n * memory and forgets them when it restarts; a 401 about the PROOF is\n * surfaced as it is, since a new session would not change it).\n *\n * Two rules govern the proof on these routes, and both are the server's\n * (`personal-server-ts` d91124d and later):\n *\n * - the signed `uri` claim covers the query string, not just the path,\n *   because `?derivedScope=` is what the list route authorizes against;\n * - every call carries a fresh `nonce` claim, which becomes the server's\n *   replay key. Without one the whole proof is the key, so two identical\n *   polls signed inside the same second are refused as a replay.\n *\n * @category Protocol\n */\n\nimport { z } from \"zod\";\nimport { buildWeb3SignedHeader } from \"../auth/web3-signed-builder\";\nimport {\n  DerivativeComputeUnavailableError,\n  DerivativeCycleError,\n  DerivativeDerivedScopeRequiredError,\n  DerivativeQuestionFailedError,\n  DerivativeQuestionInvalidError,\n  DerivativeQuestionNotFoundError,\n  DerivativeQuestionRejectedError,\n  DerivativeQuestionTimeoutError,\n  DerivativeSourceNotGrantedError,\n  WriteConflictError,\n  WriteForbiddenError,\n  WriteRequestError,\n  WriteUnauthorizedError,\n  type PersonalServerWriteError,\n} from \"../errors\";\nimport { assertDerivedScopeNaming } from \"./lineage\";\nimport {\n  readPersonalServerErrorBody,\n  type PersonalServerErrorBody,\n} from \"./personal-server-error-body\";\nimport {\n  readPersonalServerData,\n  type ReadPersonalServerDataParams,\n} from \"./personal-server-data\";\nimport type { DataFileEnvelope } from \"./data-file\";\nimport {\n  openWriteSession,\n  WRITE_SIGNATURE_HEADER,\n  type WriteSession,\n} from \"./personal-server-write\";\nimport {\n  errorMessage,\n  freshProofNonce,\n  normalizeBaseUrl,\n  proofKeyFor,\n  resolveFetch,\n  sendWithFreshProof,\n  sleep,\n  type WriteTransportRetryOptions,\n} from \"./write-request\";\nimport {\n  resolveWriteSigner,\n  type ResolveWriteSignerOptions,\n  type WriteSignerSource,\n} from \"./write-signer\";\n\n/** Path the question routes are mounted at. */\nexport const DERIVATIVE_QUESTIONS_PATH = \"/v1/derivatives/questions\";\n/** The most source scopes one question may read. */\nexport const MAX_QUESTION_SOURCE_SCOPES = 16;\n/** The longest question text the Personal Server accepts. */\nexport const MAX_QUESTION_CHARS = 8_000;\n/** The longest model id the Personal Server accepts. */\nexport const MAX_QUESTION_MODEL_CHARS = 128;\n/** Model ids as providers spell them (`z-ai/glm-5.2`, `gpt-4o-mini`, ...). */\nconst MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;\n/** How long {@link waitForQuestion} polls before giving up. */\nexport const DEFAULT_QUESTION_TIMEOUT_MS = 120_000;\n/** How long {@link waitForQuestion} waits between polls. */\nexport const DEFAULT_QUESTION_POLL_INTERVAL_MS = 2_000;\n/** Re-open a session this long before its token expires. */\nconst SESSION_REFRESH_SKEW_MS = 30_000;\n\n/** Every state a question can be in. */\nexport const QUESTION_STATUSES = [\n  \"pending\",\n  \"ready\",\n  \"failed\",\n  \"stale\",\n] as const;\n\n/**\n * `pending` (never computed) -> `ready` | `failed`; a source change or an\n * explicit recompute puts a computed question back to `stale`, which\n * settles as `ready` or `failed` again.\n */\n/**\n * Every failure class a question can carry. A closed vocabulary, because the\n * status route serves it to a reader of the derived scope: it never carries a\n * scope name, the question or provider detail.\n *\n * - `inference_unavailable` — the provider or relay failed. The only\n *   transient class: the Personal Server retries it on its own.\n * - `source_missing` — a source scope is deleted or holds no local data.\n * - `grant_invalid` — the registering builder's grant no longer covers what\n *   the question reads.\n * - `internal` — anything else, including a permanent provider 4xx.\n */\nexport const DERIVATIVE_ERROR_CODES = [\n  \"inference_unavailable\",\n  \"source_missing\",\n  \"grant_invalid\",\n  \"internal\",\n] as const;\n\n/** @see {@link DERIVATIVE_ERROR_CODES} */\nexport const DerivativeErrorCodeSchema = z.enum(DERIVATIVE_ERROR_CODES);\n\n/** @see {@link DERIVATIVE_ERROR_CODES} */\nexport type DerivativeErrorCode = z.infer<typeof DerivativeErrorCodeSchema>;\n\nexport const QuestionStatusSchema = z.enum(QUESTION_STATUSES);\n\n/** @see {@link QuestionStatusSchema} */\nexport type QuestionStatus = z.infer<typeof QuestionStatusSchema>;\n\n/** Who registered the question: the owner, or a builder under a grant. */\nexport const QuestionRegisteredBySchema = z.union([\n  z.object({ kind: z.literal(\"owner\") }),\n  z.object({\n    kind: z.literal(\"builder\"),\n    builder: z.string(),\n    grantId: z.string(),\n  }),\n]);\n\n/** @see {@link QuestionRegisteredBySchema} */\nexport type QuestionRegisteredBy = z.infer<typeof QuestionRegisteredBySchema>;\n\n// The server always sends these; `nullish` keeps a Personal Server that\n// omits one readable rather than failing the whole call on a missing field.\nconst nullableString = z\n  .string()\n  .nullish()\n  .transform((value) => value ?? null);\n\n/**\n * A question registration as the Personal Server reports it (the answer of\n * register, get and list).\n */\nexport const DerivativeQuestionSchema = z.object({\n  questionId: z.string().min(1),\n  derivedScope: z.string().min(1),\n  sourceScopes: z.array(z.string()),\n  question: z.string(),\n  /** The model override, or `null` for the server's default. */\n  model: nullableString,\n  registeredBy: QuestionRegisteredBySchema,\n  status: QuestionStatusSchema,\n  /** A short reason, set only while `status` is `failed`. */\n  error: nullableString,\n  /**\n   * The coarse failure class behind `error`, set only while `status` is\n   * `failed`. `null` from a Personal Server that predates the class\n   * (`personal-server-ts` before the status route).\n   */\n  errorCode: DerivativeErrorCodeSchema.nullish().transform(\n    (value) => value ?? null,\n  ),\n  createdAt: z.string(),\n  updatedAt: nullableString,\n  /** When the last compute finished, or `null` while `pending`. */\n  lastComputedAt: nullableString,\n  /** Local version of the derived record the last compute wrote. */\n  derivedVersion: z\n    .number()\n    .nullish()\n    .transform((value) => value ?? null),\n  derivedCollectedAt: nullableString,\n});\n\n/** @see {@link DerivativeQuestionSchema} */\nexport type DerivativeQuestion = z.infer<typeof DerivativeQuestionSchema>;\n\nconst QuestionListSchema = z.object({\n  questions: z.array(DerivativeQuestionSchema),\n});\n\n/**\n * The 202 answer of a recompute request: the same registration view every\n * other question route answers, so a client needs one schema.\n *\n * @remarks\n * Older Personal Servers answered only\n * `{ questionId, derivedScope, status }` here. The full view is a superset\n * of those three fields, so code reading them is unaffected, but the answer\n * of a server before `personal-server-ts` d91124d no longer parses.\n */\nexport const QuestionRecomputeResultSchema = DerivativeQuestionSchema;\n\n/** @see {@link QuestionRecomputeResultSchema} */\nexport type QuestionRecomputeResult = DerivativeQuestion;\n\n/** The answer of a delete request. */\nexport const QuestionDeleteResultSchema = z.object({\n  questionId: z.string().min(1),\n  deleted: z.literal(true),\n});\n\n/** @see {@link QuestionDeleteResultSchema} */\nexport type QuestionDeleteResult = z.infer<typeof QuestionDeleteResultSchema>;\n\n/**\n * Connection, credential and transport shared by every question call.\n *\n * @remarks\n * The write session is opened on demand and reused for every later call\n * made with the same `signer` object, Personal Server, audience, grant and\n * `fetch`; a 401 re-opens it once and replays the call.\n */\nexport interface DerivativeQuestionAuthParams extends ResolveWriteSignerOptions {\n  /** Personal Server origin, e.g. `https://ps.example.com`. */\n  personalServerUrl: string;\n  /** Builder key: a viem `LocalAccount`, `WalletClient`, or `{ signMessage }`. */\n  signer: WriteSignerSource;\n  /**\n   * The grant the call runs under. It must carry `write:<derivedScope>`, a\n   * bare read entry for the derived scope, and a bare read entry for every\n   * source scope.\n   */\n  grantId: string;\n  /** Web3Signed audience; defaults to `personalServerUrl`. */\n  audience?: string;\n  /** `fetch` to use; defaults to `globalThis.fetch`. */\n  fetch?: typeof fetch;\n  /** Extra request headers. */\n  headers?: HeadersInit;\n  retry?: WriteTransportRetryOptions;\n  /** Aborts the request (and, for {@link waitForQuestion}, the polling). */\n  signal?: AbortSignal;\n}\n\nexport interface RegisterQuestionParams extends DerivativeQuestionAuthParams {\n  /**\n   * The scope the answer is written into. Must not share its first\n   * dot-segment with any source scope, so put derivatives in the app's own\n   * namespace.\n   */\n  derivedScope: string;\n  /**\n   * The scopes the question reads: 1 to\n   * {@link MAX_QUESTION_SOURCE_SCOPES} distinct scopes, none of them the\n   * derived scope. They do not have to hold data yet: the question computes\n   * once they do.\n   */\n  sourceScopes: readonly string[];\n  /** The prompt, 1 to {@link MAX_QUESTION_CHARS} characters. */\n  question: string;\n  /** Model id override; omitted = the Personal Server's default model. */\n  model?: string;\n}\n\nexport interface GetQuestionParams extends DerivativeQuestionAuthParams {\n  questionId: string;\n}\n\nexport interface ListQuestionsParams extends DerivativeQuestionAuthParams {\n  /**\n   * The derived scope to list. A builder must name one (it may only see its\n   * own questions on a scope it may write); the unfiltered list is the\n   * owner's.\n   */\n  derivedScope: string;\n}\n\nexport interface RecomputeQuestionParams extends DerivativeQuestionAuthParams {\n  questionId: string;\n}\n\nexport interface DeleteQuestionParams extends DerivativeQuestionAuthParams {\n  questionId: string;\n}\n\nexport interface WaitForQuestionParams extends DerivativeQuestionAuthParams {\n  questionId: string;\n  /** Give up after this long (default {@link DEFAULT_QUESTION_TIMEOUT_MS}). */\n  timeoutMs?: number;\n  /** Wait between polls (default {@link DEFAULT_QUESTION_POLL_INTERVAL_MS}). */\n  pollIntervalMs?: number;\n}\n\nexport interface AskPersonalServerParams extends RegisterQuestionParams {\n  timeoutMs?: number;\n  pollIntervalMs?: number;\n}\n\n/** {@link askPersonalServer}'s answer. */\nexport interface AskPersonalServerResult {\n  /** The settled registration (`status` is `ready`). */\n  registration: DerivativeQuestion;\n  /** The derived record the Personal Server wrote and the builder just read. */\n  record: DataFileEnvelope;\n}\n\n/**\n * Open write sessions, keyed by the signer object so a session is never\n * shared between builder keys and nothing is retained once the caller drops\n * its signer.\n */\nconst sessionsBySigner = new WeakMap<object, Map<string, WriteSession>>();\n\nfunction sessionCacheKey(\n  personalServerUrl: string,\n  audience: string,\n  grantId: string,\n  fetchFn: typeof fetch,\n): string {\n  // The token is only valid on the server that minted it, and `fetch` is\n  // what decides which server that is (a test double, a proxy, the global).\n  return (\n    JSON.stringify([personalServerUrl, audience, grantId]) + fetchIdOf(fetchFn)\n  );\n}\n\nconst fetchIds = new WeakMap<object, number>();\nlet nextFetchId = 0;\n\nfunction fetchIdOf(fetchFn: typeof fetch): string {\n  let id = fetchIds.get(fetchFn);\n  if (id === undefined) {\n    id = ++nextFetchId;\n    fetchIds.set(fetchFn, id);\n  }\n  return `#${id}`;\n}\n\ninterface ResolvedQuestionRequest {\n  baseUrl: string;\n  audience: string;\n  fetchFn: typeof fetch;\n  cacheKey: string;\n  signerKey: object;\n}\n\nfunction resolveRequest(\n  params: DerivativeQuestionAuthParams,\n): ResolvedQuestionRequest {\n  if (\n    typeof params.personalServerUrl !== \"string\" ||\n    params.personalServerUrl.length === 0\n  ) {\n    throw new WriteRequestError(\"personalServerUrl is required\");\n  }\n  // Checked before anything is signed or sent: without a grant the Personal\n  // Server has nothing to authorize the call against.\n  if (typeof params.grantId !== \"string\" || params.grantId.length === 0) {\n    throw new WriteRequestError(\n      \"grantId is required; a question call runs under the grant carrying write:<derivedScope>\",\n    );\n  }\n  if (params.signer === null || typeof params.signer !== \"object\") {\n    throw new WriteRequestError(\n      \"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object\",\n    );\n  }\n  const fetchFn = resolveFetch(params.fetch);\n  const baseUrl = normalizeBaseUrl(params.personalServerUrl);\n  const audience = params.audience ?? baseUrl;\n  return {\n    baseUrl,\n    audience,\n    fetchFn,\n    cacheKey: sessionCacheKey(baseUrl, audience, params.grantId, fetchFn),\n    signerKey: params.signer,\n  };\n}\n\n/**\n * The session to use: the cached one while it is comfortably live, else a\n * fresh handshake. `force` drops the cached one first (the 401 path).\n */\nasync function resolveSession(\n  params: DerivativeQuestionAuthParams,\n  resolved: ResolvedQuestionRequest,\n  force: boolean,\n): Promise<WriteSession> {\n  let cache = sessionsBySigner.get(resolved.signerKey);\n  if (cache === undefined) {\n    cache = new Map();\n    sessionsBySigner.set(resolved.signerKey, cache);\n  }\n  const cached = cache.get(resolved.cacheKey);\n  if (\n    !force &&\n    cached !== undefined &&\n    cached.expiresAt > Date.now() + SESSION_REFRESH_SKEW_MS\n  ) {\n    return cached;\n  }\n  if (force) cache.delete(resolved.cacheKey);\n  const session = await openWriteSession({\n    personalServerUrl: resolved.baseUrl,\n    signer: params.signer,\n    grantId: params.grantId,\n    account: params.account,\n    audience: resolved.audience,\n    fetch: resolved.fetchFn,\n    headers: params.headers,\n    retry: params.retry,\n  });\n  cache.set(resolved.cacheKey, session);\n  return session;\n}\n\n/**\n * The 401s a re-handshake cannot fix. They are failures of the per-request\n * PROOF, not of the session, so the same call signed under a brand new\n * session fails exactly the same way: replaying it would burn a second\n * proof, add a pointless handshake, and report the wrong problem. Every\n * other 401 is treated as the session the Personal Server forgot.\n */\nconst PROOF_FAILURE_CODES = new Set([\n  \"WRITE_ATTRIBUTION_REQUIRED\",\n  \"WRITE_ATTRIBUTION_INVALID\",\n  \"WRITE_ATTRIBUTION_SIGNER_MISMATCH\",\n  \"WRITE_ATTRIBUTION_GRANT_MISMATCH\",\n  \"WRITE_ATTRIBUTION_REPLAY\",\n]);\n\nfunction isStaleSession(errorCode: string | null): boolean {\n  return errorCode === null || !PROOF_FAILURE_CODES.has(errorCode);\n}\n\n/**\n * Map a non-2xx question answer onto the SDK's typed errors. `body` is the\n * already-read error body, for the caller that had to peek at it (a response\n * body can only be read once).\n */\nasync function questionErrorFromResponse(\n  response: Response,\n  body?: PersonalServerErrorBody,\n): Promise<PersonalServerWriteError> {\n  const { errorCode, message, details } =\n    body ?? (await readPersonalServerErrorBody(response));\n  const text =\n    message ??\n    `Derivative question request failed: ${response.status} ${response.statusText}`;\n  switch (errorCode) {\n    case \"DERIVATIVE_SOURCE_NOT_GRANTED\":\n      return new DerivativeSourceNotGrantedError(text, errorCode, details);\n    case \"DERIVATIVE_CYCLE\":\n      return new DerivativeCycleError(text, errorCode, details);\n    case \"DERIVATIVE_COMPUTE_UNAVAILABLE\":\n      return new DerivativeComputeUnavailableError(text, errorCode, details);\n    case \"DERIVATIVE_QUESTION_INVALID\":\n    case \"LINEAGE_SCOPE_UNDER_SOURCE_PREFIX\":\n      return new DerivativeQuestionInvalidError(\n        text,\n        response.status,\n        errorCode,\n        details,\n      );\n    case \"DERIVATIVE_QUESTION_NOT_FOUND\":\n      return new DerivativeQuestionNotFoundError(text, errorCode, details);\n    case \"DERIVATIVE_DERIVED_SCOPE_REQUIRED\":\n      return new DerivativeDerivedScopeRequiredError(text, errorCode, details);\n    default:\n      break;\n  }\n  switch (response.status) {\n    case 401:\n      return new WriteUnauthorizedError(text, errorCode, details);\n    case 403:\n      return new WriteForbiddenError(text, errorCode, details);\n    case 404:\n      return new DerivativeQuestionNotFoundError(text, errorCode, details);\n    case 409:\n      return new WriteConflictError(text, errorCode, details);\n    default:\n      return new DerivativeQuestionRejectedError(\n        text,\n        response.status,\n        errorCode,\n        details,\n      );\n  }\n}\n\n/**\n * The typed error for a non-2xx answer of any `/v1/derivatives` route.\n *\n * @remarks\n * Shared with the reader-facing status client so both surfaces map the same\n * `errorCode` to the same error class. Not part of the package's public API.\n *\n * @internal\n */\nexport const personalServerErrorFromQuestionResponse =\n  questionErrorFromResponse;\n\ninterface QuestionRequestSpec {\n  method: \"GET\" | \"POST\" | \"DELETE\";\n  /**\n   * The whole request target, path AND query string. The Personal Server\n   * verifies the proof against it (the query decides the authorization on\n   * the list route), so it is built once and used for both the signed `uri`\n   * claim and the `fetch` URL, where the two cannot drift apart.\n   */\n  target: string;\n  /** JSON body; sent (and signed) as compact JSON. */\n  body?: Record<string, unknown>;\n  label: string;\n}\n\nasync function sendOnce(\n  params: DerivativeQuestionAuthParams,\n  resolved: ResolvedQuestionRequest,\n  session: WriteSession,\n  spec: QuestionRequestSpec,\n  bodyBytes: Uint8Array | undefined,\n): Promise<Response> {\n  return sendWithFreshProof(\n    spec.label,\n    resolved.fetchFn,\n    params.retry,\n    proofKeyFor({\n      aud: session.audience,\n      method: spec.method,\n      uri: spec.target,\n      grantId: session.grantId,\n      signedBytes: bodyBytes,\n    }),\n    async (iat) => {\n      const headers = new Headers(params.headers);\n      headers.set(\"Accept\", \"application/json\");\n      headers.set(\"Authorization\", `Bearer ${session.accessToken}`);\n      if (bodyBytes !== undefined) {\n        headers.set(\"Content-Type\", \"application/json\");\n      }\n      headers.set(\n        WRITE_SIGNATURE_HEADER,\n        await buildWeb3SignedHeader({\n          signMessage: session.signer.signMessage,\n          aud: session.audience,\n          // The proof commits to the whole request target, query included:\n          // `?derivedScope=` is what the list route authorizes against, and a\n          // proof that did not cover it would authorize any other scope.\n          uri: spec.target,\n          method: spec.method,\n          body: bodyBytes,\n          grantId: session.grantId,\n          // Fresh per attempt, so a retry after a thrown `fetch` is never the\n          // proof the server may already have consumed, and so two identical\n          // polls inside one second stay distinct.\n          nonce: freshProofNonce(),\n          iat,\n        }),\n      );\n      return {\n        url: `${resolved.baseUrl}${spec.target}`,\n        init: {\n          method: spec.method,\n          headers,\n          ...(bodyBytes === undefined\n            ? {}\n            : { body: bodyBytes as unknown as BodyInit }),\n          ...(params.signal ? { signal: params.signal } : {}),\n        },\n      };\n    },\n  );\n}\n\n/**\n * Run one question call under a reused write session: fresh proof, and one\n * re-handshake when the Personal Server no longer knows the session.\n */\nasync function sendQuestionRequest<T>(\n  params: DerivativeQuestionAuthParams,\n  spec: QuestionRequestSpec,\n  schema: z.ZodType<T>,\n): Promise<T> {\n  const resolved = resolveRequest(params);\n  // Compact JSON is the contract: the server re-serializes what it parsed\n  // and refuses anything else with WRITE_BODY_NOT_CANONICAL.\n  const bodyBytes =\n    spec.body === undefined\n      ? undefined\n      : new TextEncoder().encode(JSON.stringify(spec.body));\n\n  let session = await resolveSession(params, resolved, false);\n  let response = await sendOnce(params, resolved, session, spec, bodyBytes);\n  // Read once, kept for the throw below: a body cannot be read twice.\n  let errorBody: PersonalServerErrorBody | undefined;\n  if (response.status === 401) {\n    errorBody = await readPersonalServerErrorBody(response);\n    if (isStaleSession(errorBody.errorCode)) {\n      // The Personal Server keeps write sessions in memory: a restart (or an\n      // expiry the client did not see) invalidates the bearer, not the grant.\n      // Open a new session once and replay the call with a fresh proof.\n      session = await resolveSession(params, resolved, true);\n      response = await sendOnce(params, resolved, session, spec, bodyBytes);\n      errorBody = undefined;\n    }\n  }\n\n  if (!response.ok) {\n    throw await questionErrorFromResponse(response, errorBody);\n  }\n  let body: unknown;\n  try {\n    body = await response.json();\n  } catch (err) {\n    throw new DerivativeQuestionRejectedError(\n      `${spec.label} response is not JSON`,\n      response.status,\n      null,\n      { cause: errorMessage(err) },\n    );\n  }\n  const parsed = schema.safeParse(body);\n  if (!parsed.success) {\n    throw new DerivativeQuestionRejectedError(\n      `${spec.label} response is not a derivative question answer`,\n      response.status,\n      null,\n      { issues: parsed.error.issues },\n    );\n  }\n  return parsed.data;\n}\n\n/** The request target for one question id: no query, so the bare path. */\nfunction assertQuestionId(questionId: string): string {\n  if (typeof questionId !== \"string\" || questionId.length === 0) {\n    throw new WriteRequestError(\"questionId is required\");\n  }\n  return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;\n}\n\n/**\n * Validate a registration the way the Personal Server does, so a builder\n * gets a typed error before a proof is signed rather than a 400 after.\n */\nfunction registrationBody(params: RegisterQuestionParams): {\n  derivedScope: string;\n  sourceScopes: string[];\n  question: string;\n  model?: string;\n} {\n  const { derivedScope, question } = params;\n  if (typeof derivedScope !== \"string\" || derivedScope.length === 0) {\n    throw new WriteRequestError(\"derivedScope is required\");\n  }\n  if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {\n    throw new WriteRequestError(\n      \"sourceScopes must be a non-empty array of scopes\",\n    );\n  }\n  if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {\n    throw new WriteRequestError(\n      `sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,\n      { max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length },\n    );\n  }\n  const sourceScopes: string[] = [];\n  for (const scope of params.sourceScopes) {\n    if (typeof scope !== \"string\" || scope.length === 0) {\n      throw new WriteRequestError(\"sourceScopes entries must be scope strings\");\n    }\n    if (sourceScopes.includes(scope)) {\n      throw new WriteRequestError(\"sourceScopes must not repeat a scope\", {\n        duplicate: scope,\n      });\n    }\n    if (scope === derivedScope) {\n      throw new WriteRequestError(\n        \"derivedScope cannot be one of its own sources\",\n        { scope },\n      );\n    }\n    sourceScopes.push(scope);\n  }\n  if (typeof question !== \"string\" || question.trim() === \"\") {\n    throw new WriteRequestError(\"question must be a non-empty string\");\n  }\n  if (question.length > MAX_QUESTION_CHARS) {\n    throw new WriteRequestError(\n      `question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,\n      { max: MAX_QUESTION_CHARS, length: question.length },\n    );\n  }\n  if (params.model !== undefined) {\n    if (\n      typeof params.model !== \"string\" ||\n      params.model.length > MAX_QUESTION_MODEL_CHARS ||\n      !MODEL_ID_PATTERN.test(params.model)\n    ) {\n      throw new WriteRequestError(\"model must be a provider model id\", {\n        model: params.model,\n      });\n    }\n  }\n  // The lineage naming rule, applied before signing: the server would refuse\n  // the registration with LINEAGE_SCOPE_UNDER_SOURCE_PREFIX.\n  assertDerivedScopeNaming(derivedScope, sourceScopes);\n  return {\n    derivedScope,\n    sourceScopes,\n    question,\n    ...(params.model === undefined ? {} : { model: params.model }),\n  };\n}\n\n/**\n * Register a standing question over the owner's source scopes.\n *\n * @remarks\n * Sends `POST /v1/derivatives/questions`. The registration comes back\n * `pending` and the first compute is scheduled immediately; poll it with\n * {@link waitForQuestion}, then read `derivedScope`.\n *\n * @example\n * ```typescript\n * const registered = await registerQuestion({\n *   personalServerUrl: \"https://ps.example.com\",\n *   signer,\n *   grantId,\n *   derivedScope: \"coach.weekly\",\n *   sourceScopes: [\"oura.sleep\", \"chatgpt.conversations\"],\n *   question: \"How did my sleep relate to my mood this week?\",\n * });\n * ```\n * @returns The registration, `status: \"pending\"`.\n * @throws {WriteRequestError} Before sending: a missing grant, a bad scope\n *   list, an over-long question, a derived scope under a source's namespace.\n * @throws {DerivativeSourceNotGrantedError} 403: a source scope is not\n *   read-granted to the builder (`details.scopes`).\n * @throws {DerivativeCycleError} 409: the question would make the derived\n *   scope a transitive source of itself.\n * @throws {DerivativeQuestionInvalidError} 400 from the server.\n * @throws {DerivativeComputeUnavailableError} 503: no compute layer.\n * @throws {WriteForbiddenError} 403: the grant does not authorize writing\n *   the derived scope.\n */\nexport async function registerQuestion(\n  params: RegisterQuestionParams,\n): Promise<DerivativeQuestion> {\n  const body = registrationBody(params);\n  return sendQuestionRequest(\n    params,\n    {\n      method: \"POST\",\n      target: DERIVATIVE_QUESTIONS_PATH,\n      body,\n      label: \"Register derivative question\",\n    },\n    DerivativeQuestionSchema,\n  );\n}\n\n/**\n * Read one question's current state.\n *\n * @remarks\n * Sends `GET /v1/derivatives/questions/:id`. A builder only sees questions\n * it registered itself; anything else is a 404.\n *\n * @returns The registration, including `status`, `lastComputedAt`,\n *   `derivedVersion` and (when it failed) `error`.\n * @throws {DerivativeQuestionNotFoundError} 404: unknown id, or not this\n *   builder's question.\n */\nexport async function getQuestion(\n  params: GetQuestionParams,\n): Promise<DerivativeQuestion> {\n  const target = assertQuestionId(params.questionId);\n  return sendQuestionRequest(\n    params,\n    { method: \"GET\", target, label: \"Read derivative question\" },\n    DerivativeQuestionSchema,\n  );\n}\n\n/**\n * List the questions this builder registered on a derived scope.\n *\n * @remarks\n * Sends `GET /v1/derivatives/questions?derivedScope=...`. The scope is\n * required for a builder: it is what the call is authorized against, which\n * is exactly why the signed proof commits to the query string as well as the\n * path. The target is built once and used for both, so the signature and the\n * request can never name different scopes.\n *\n * @returns The registrations, newest state included.\n * @throws {DerivativeDerivedScopeRequiredError} 400\n *   `DERIVATIVE_DERIVED_SCOPE_REQUIRED` when the server saw no\n *   `?derivedScope=` (the SDK refuses an empty one before sending).\n */\nexport async function listQuestions(\n  params: ListQuestionsParams,\n): Promise<DerivativeQuestion[]> {\n  if (\n    typeof params.derivedScope !== \"string\" ||\n    params.derivedScope.length === 0\n  ) {\n    throw new WriteRequestError(\n      \"derivedScope is required; a builder may only list its own questions on a scope it may write\",\n    );\n  }\n  const target = `${DERIVATIVE_QUESTIONS_PATH}?derivedScope=${encodeURIComponent(params.derivedScope)}`;\n  const { questions } = await sendQuestionRequest(\n    params,\n    {\n      method: \"GET\",\n      target,\n      label: \"List derivative questions\",\n    },\n    QuestionListSchema,\n  );\n  return questions;\n}\n\n/**\n * Ask the Personal Server to recompute a question now.\n *\n * @remarks\n * Sends `POST /v1/derivatives/questions/:id/recompute`, which answers 202\n * and schedules the compute immediately instead of after the usual quiet\n * period. Use it to retry a `failed` question; a source change recomputes on\n * its own.\n *\n * @returns The full registration view, with the status the question was put\n *   into (`pending` when it had never computed, else `stale`). Servers\n *   before `personal-server-ts` d91124d answered only\n *   `{ questionId, derivedScope, status }` here, which no longer parses.\n */\nexport async function recomputeQuestion(\n  params: RecomputeQuestionParams,\n): Promise<QuestionRecomputeResult> {\n  const target = `${assertQuestionId(params.questionId)}/recompute`;\n  return sendQuestionRequest(\n    params,\n    { method: \"POST\", target, label: \"Recompute derivative question\" },\n    QuestionRecomputeResultSchema,\n  );\n}\n\n/**\n * Delete a question registration.\n *\n * @remarks\n * Sends `DELETE /v1/derivatives/questions/:id`. The question stops\n * recomputing; the derived records it already wrote are left alone (delete\n * those through the data-point deletion path).\n *\n * @returns `{ questionId, deleted: true }`.\n */\nexport async function deleteQuestion(\n  params: DeleteQuestionParams,\n): Promise<QuestionDeleteResult> {\n  const target = assertQuestionId(params.questionId);\n  return sendQuestionRequest(\n    params,\n    { method: \"DELETE\", target, label: \"Delete derivative question\" },\n    QuestionDeleteResultSchema,\n  );\n}\n\n/** `true` once the question has settled: nothing more to wait for. */\nfunction isSettled(status: QuestionStatus): boolean {\n  return status === \"ready\" || status === \"failed\";\n}\n\nfunction abortError(signal: AbortSignal): Error {\n  const reason: unknown = signal.reason;\n  if (reason instanceof Error) return reason;\n  const error = new Error(\"The operation was aborted\");\n  error.name = \"AbortError\";\n  return error;\n}\n\n/**\n * Poll a question until it settles.\n *\n * @remarks\n * Calls {@link getQuestion} every `pollIntervalMs` until `status` is `ready`\n * or `failed` and returns that state; a `failed` question is returned, not\n * thrown, so the caller can read `error` and decide whether to\n * {@link recomputeQuestion}. All polls share the one write session and each\n * signs its own proof.\n *\n * @example\n * ```typescript\n * const settled = await waitForQuestion({\n *   personalServerUrl,\n *   signer,\n *   grantId,\n *   questionId: registered.questionId,\n *   timeoutMs: 60_000,\n * });\n * if (settled.status === \"ready\") {\n *   // read derivedScope\n * }\n * ```\n * @returns The settled registration (`ready` or `failed`).\n * @throws {DerivativeQuestionTimeoutError} The question had not settled\n *   within `timeoutMs`; it keeps computing on the server.\n * @throws Whatever {@link getQuestion} throws, and the `signal`'s abort\n *   reason when the caller aborts.\n */\nexport async function waitForQuestion(\n  params: WaitForQuestionParams,\n): Promise<DerivativeQuestion> {\n  const timeoutMs = Math.max(\n    0,\n    params.timeoutMs ?? DEFAULT_QUESTION_TIMEOUT_MS,\n  );\n  const pollIntervalMs = Math.max(\n    0,\n    params.pollIntervalMs ?? DEFAULT_QUESTION_POLL_INTERVAL_MS,\n  );\n  const deadline = Date.now() + timeoutMs;\n  for (;;) {\n    if (params.signal?.aborted) throw abortError(params.signal);\n    const latest = await getQuestion(params);\n    if (isSettled(latest.status)) return latest;\n    const remaining = deadline - Date.now();\n    if (remaining <= 0) {\n      throw new DerivativeQuestionTimeoutError(\n        `Derivative question ${latest.questionId} was still ${latest.status} after ${timeoutMs}ms`,\n        {\n          questionId: latest.questionId,\n          derivedScope: latest.derivedScope,\n          status: latest.status,\n          timeoutMs,\n        },\n      );\n    }\n    await sleep(Math.min(pollIntervalMs, remaining));\n  }\n}\n\n/**\n * Register a question, wait for it, and read the answer: the whole builder\n * loop in one call.\n *\n * @remarks\n * {@link registerQuestion} + {@link waitForQuestion} +\n * {@link readPersonalServerData} on the derived scope, which is why the\n * grant needs a bare read entry for `derivedScope` on top of\n * `write:<derivedScope>` and the source reads. The read is the plain\n * Web3Signed one; when the grant is priced, settle the 402 yourself with the\n * escrow-aware read from `@opendatalabs/vana-sdk/server` and use\n * {@link registerQuestion} and {@link waitForQuestion} directly.\n *\n * A question registered this way keeps recomputing after the call returns:\n * every later change to a source scope refreshes the derived record, and the\n * builder can read it again without registering anything.\n *\n * @example\n * ```typescript\n * const { registration, record } = await askPersonalServer({\n *   personalServerUrl: \"https://ps.example.com\",\n *   signer,\n *   grantId,\n *   derivedScope: \"coach.weekly\",\n *   sourceScopes: [\"oura.sleep\"],\n *   question: \"How did my sleep trend this week?\",\n * });\n * console.log(record.data.answer, registration.questionId);\n * ```\n * @returns The settled registration and the derived record.\n * @throws {DerivativeQuestionFailedError} The question settled as `failed`\n *   (`details.error` is the server's reason).\n * @throws Everything {@link registerQuestion}, {@link waitForQuestion} and\n *   the read path throw.\n */\nexport async function askPersonalServer(\n  params: AskPersonalServerParams,\n): Promise<AskPersonalServerResult> {\n  const registered = await registerQuestion(params);\n  const registration = await waitForQuestion({\n    ...params,\n    questionId: registered.questionId,\n  });\n  if (registration.status !== \"ready\") {\n    throw new DerivativeQuestionFailedError(\n      `Derivative question ${registration.questionId} failed: ${registration.error ?? \"no reason given\"}`,\n      {\n        questionId: registration.questionId,\n        derivedScope: registration.derivedScope,\n        error: registration.error,\n      },\n    );\n  }\n  const signer = resolveWriteSigner(params.signer, {\n    account: params.account,\n  });\n  const readParams: ReadPersonalServerDataParams = {\n    personalServerUrl: normalizeBaseUrl(params.personalServerUrl),\n    scope: params.derivedScope,\n    grantId: params.grantId,\n    signMessage: signer.signMessage,\n    ...(params.audience === undefined ? {} : { audience: params.audience }),\n    ...(params.headers === undefined ? {} : { headers: params.headers }),\n    ...(params.fetch === undefined ? {} : { fetch: params.fetch }),\n  };\n  const record = await readPersonalServerData(readParams);\n  return { registration, record };\n}\n"],"mappings":"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","names":[]}