{"version":3,"file":"retrievable-CXTAUuuv.mjs","names":["#id","#content","#trustTier","#source","#kind","#score","#createdAt","#updatedAt","#inline","#artifactConstructor"],"sources":["../src/lib/classes/retrievable.ts"],"sourcesContent":["import { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { SpooledArtifact } from './spooled_artifact'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { ENCODE_METHOD, DECODE_METHOD } from '../utils/encoder_symbols'\nimport { E_INVALID_INITIAL_RETRIEVABLE_VALUE } from '../exceptions/runtime'\nimport { artifactConstructorResolverSchema } from '../contracts/spooled_artifact_constructor'\nimport type { DateTime } from 'luxon'\nimport type { TokenEncoding } from './tokenizable'\nimport type { AdkEncodableSnapshot } from './encodable'\nimport type { ArtifactConstructorResolver } from './tool'\n\n/**\n * Trust-tier discriminator declared by the retrieval middleware at construction time. Drives\n * which envelope the LLM battery wraps the record in.\n *\n * @remarks\n * Vocabulary deliberately mirrors the published security-research taxonomy (\"first-party /\n * third-party\" per *Hidden-in-Plain-Text* WWW '26 and *When AI Meets the Web* IEEE S&P 2026)\n * and explicitly avoids the words \"user\" or \"system\" so the names cannot leak into the model's\n * OpenAI-Model-Spec role-tier authority resolution.\n *\n * - `'first-party'` — deployer-vetted corpora (signed internal docs, policy KBs, curated\n *   reference material). Rendered as a `<retrieved_corpus>` parent with per-record nonce-keyed\n *   `<retrieved>` children. The label \"first-party\" never appears in the envelope itself.\n * - `'third-party-public'` — open-web scrapes, search results, public APIs. Rendered through\n *   the untrusted-content envelope with `kind: 'retrieved-third-party-public'`.\n * - `'third-party-private'` — user uploads, pasted attachments, partner APIs. Rendered through\n *   the untrusted-content envelope with `kind: 'retrieved-third-party-private'`.\n */\nexport type RetrievableTrustTier = 'first-party' | 'third-party-public' | 'third-party-private'\n\n/**\n * Plain input object supplied to {@link Retrievable} at construction time.\n *\n * @remarks\n * Validated against `rawRetrievableSchema` before the `Retrievable` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawRetrievable {\n  /**\n   * Stable unique identifier for this retrieved record. Used as the closing-tag nonce in the\n   * rendered envelope, so it must be unguessable from the payload.\n   */\n  id: string\n  /**\n   * The retrieved content. A plain `string` or {@link @nhtio/adk!Tokenizable} for small inline text, or a\n   * {@link @nhtio/adk!SpooledArtifact} when the extracted text is large and lives in a consumer\n   * {@link @nhtio/adk/common!ByteStore} (persist it via {@link @nhtio/adk!DispatchContext.storeRetrievableBytes}, wrap\n   * the returned reader in a `SpooledArtifact`, and pass it here). Reader-backed content keeps the\n   * body out of the permanent heap, but token estimation and render still materialise it\n   * transiently (see {@link Retrievable.estimateTokens}).\n   */\n  content: string | Tokenizable | SpooledArtifact\n  /**\n   * Trust tier declared by the retrieval middleware at construction time. Required — there is\n   * NO default. The decision must be conscious. See {@link RetrievableTrustTier}.\n   */\n  trustTier: RetrievableTrustTier\n  /** Optional provenance string: URL, document path, knowledge-base id, etc. */\n  source?: string\n  /** Optional semantic label: 'policy' | 'reference' | 'web-page' | 'pdf' | etc. */\n  kind?: string\n  /** Optional relevance / similarity score in `[0, 1]` from the retrieval middleware. */\n  score?: number\n  /** When the source record was created (publication date, upload date, etc.). */\n  createdAt: string | number | Date | DateTime\n  /** When the source record was last modified. */\n  updatedAt: string | number | Date | DateTime\n  /** Whether to render this record inline rather than as a retrievable handle; defaults to `false`. */\n  inline?: boolean\n  /** Resolver for the spooled-artifact constructor used when plain content is auto-spooled; defaults to `undefined` (the base artifact). */\n  artifactConstructor?: ArtifactConstructorResolver\n}\n\n/**\n * A fully-resolved {@link RawRetrievable} where all fields have been validated and temporal\n * values normalised to Luxon `DateTime` instances.\n */\ninterface ResolvedRetrievable {\n  id: string\n  content: Tokenizable | SpooledArtifact\n  trustTier: RetrievableTrustTier\n  source?: string\n  kind?: string\n  score?: number\n  createdAt: DateTime\n  updatedAt: DateTime\n  inline: boolean\n  artifactConstructor?: ArtifactConstructorResolver\n}\n\n/**\n * Validator schema used to validate a {@link RawRetrievable} before constructing a\n * {@link Retrievable}.\n *\n * @remarks\n * - `id` — required non-empty string.\n * - `content` — required {@link @nhtio/adk!Tokenizable.schema}.\n * - `trustTier` — required, one of `'first-party'`, `'third-party-public'`,\n *   `'third-party-private'`. Unknown / missing values reject.\n * - `source` / `kind` — optional strings.\n * - `score` — optional number in `[0, 1]`.\n * - `createdAt` / `updatedAt` — required datetime-parseable values.\n *\n * Throws {@link @nhtio/adk/exceptions!E_INVALID_INITIAL_RETRIEVABLE_VALUE} (via the {@link Retrievable} constructor)\n * when validation fails.\n */\nconst contentSchema = validator.alternatives(\n  validator.string(),\n  validator.custom((value, helpers) => {\n    if (Tokenizable.isTokenizable(value) || SpooledArtifact.isSpooledArtifact(value)) {\n      return value\n    }\n    return helpers.error('any.invalid')\n  })\n)\n\nconst rawRetrievableSchema = validator.object<RawRetrievable>({\n  id: validator.string().required(),\n  content: contentSchema.required(),\n  trustTier: validator\n    .string()\n    .valid('first-party', 'third-party-public', 'third-party-private')\n    .required(),\n  source: validator.string().optional(),\n  kind: validator.string().optional(),\n  score: validator.number().min(0).max(1).optional(),\n  createdAt: validator.datetime().required(),\n  updatedAt: validator.datetime().required(),\n  inline: validator.boolean().default(false),\n  artifactConstructor: artifactConstructorResolverSchema().optional(),\n})\n\n/**\n * An immutable, validated retrieved record (RAG content) held by the agent.\n *\n * @remarks\n * Peer of {@link @nhtio/adk!Memory} / `Message` / `Thought` / `ToolCall`. Carries an explicit `trustTier`\n * that LLM batteries branch on to choose the rendering envelope. The retrieval middleware that\n * produced the record is the only party that knows its provenance — batteries MUST NOT\n * auto-classify or infer the tier from `source`.\n */\nexport class Retrievable {\n  /**\n   * Validator schema that accepts a {@link RawRetrievable} object.\n   *\n   * @remarks\n   * Reusable fragment for any schema that needs to validate or nest a retrievable record.\n   */\n  public static schema = rawRetrievableSchema\n\n  /**\n   * Returns `true` if `value` is a {@link Retrievable} instance.\n   *\n   * @remarks\n   * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.\n   */\n  public static isRetrievable(value: unknown): value is Retrievable {\n    return isInstanceOf(value, 'Retrievable', Retrievable)\n  }\n\n  /** Stable unique identifier for this retrieved record. */\n  declare readonly id: string\n  /**\n   * The retrieved content: a {@link @nhtio/adk!Tokenizable} (inline text) or a\n   * {@link @nhtio/adk!SpooledArtifact} (reader-backed, large text living in a consumer store). Use\n   * {@link Retrievable.estimateTokens} for budgeting and {@link Retrievable.contentString} to\n   * materialise the body at render time.\n   */\n  declare readonly content: Tokenizable | SpooledArtifact\n  /** Trust tier declared by the retrieval middleware. */\n  declare readonly trustTier: RetrievableTrustTier\n  /** Optional provenance string. */\n  declare readonly source: string | undefined\n  /** Optional semantic label. */\n  declare readonly kind: string | undefined\n  /** Optional relevance / similarity score in `[0, 1]`. */\n  declare readonly score: number | undefined\n  /** When the source record was created. */\n  declare readonly createdAt: DateTime\n  /** When the source record was last modified. */\n  declare readonly updatedAt: DateTime\n  /** Whether this record is rendered inline; defaults to `false` (handle mode for spooled content). */\n  declare readonly inline: boolean\n  /** Producer-declared resolver for the artifact subclass used during auto-spooling, if any. */\n  declare readonly artifactConstructor: ArtifactConstructorResolver | undefined\n  /** Whether a non-inline spooled artifact lacks cached size metadata. */\n  declare readonly sizeUnknown: boolean\n\n  #id: string\n  #content: Tokenizable | SpooledArtifact\n  #trustTier: RetrievableTrustTier\n  #source: string | undefined\n  #kind: string | undefined\n  #score: number | undefined\n  #createdAt: DateTime\n  #updatedAt: DateTime\n  #inline: boolean\n  #artifactConstructor: ArtifactConstructorResolver | undefined\n\n  /**\n   * @param raw - The raw retrievable input validated against `rawRetrievableSchema`.\n   * @throws {@link @nhtio/adk/exceptions!E_INVALID_INITIAL_RETRIEVABLE_VALUE} when `raw` does not satisfy the schema.\n   */\n  constructor(raw: RawRetrievable) {\n    let resolved: ResolvedRetrievable\n    try {\n      resolved = validateOrThrow<ResolvedRetrievable>(rawRetrievableSchema, raw, true)\n    } catch (err) {\n      throw new E_INVALID_INITIAL_RETRIEVABLE_VALUE({\n        cause: isError(err) ? err : undefined,\n      })\n    }\n    this.#id = resolved.id\n    this.#content =\n      Tokenizable.isTokenizable(resolved.content) ||\n      SpooledArtifact.isSpooledArtifact(resolved.content)\n        ? resolved.content\n        : new Tokenizable(resolved.content)\n    this.#trustTier = resolved.trustTier\n    this.#source = resolved.source\n    this.#kind = resolved.kind\n    this.#score = resolved.score\n    this.#createdAt = resolved.createdAt\n    this.#updatedAt = resolved.updatedAt\n    this.#inline = resolved.inline\n    this.#artifactConstructor = resolved.artifactConstructor\n\n    Object.defineProperties(this, {\n      id: {\n        get: () => this.#id,\n        enumerable: true,\n        configurable: false,\n      },\n      content: {\n        get: () => this.#content,\n        enumerable: true,\n        configurable: false,\n      },\n      trustTier: {\n        get: () => this.#trustTier,\n        enumerable: true,\n        configurable: false,\n      },\n      source: {\n        get: () => this.#source,\n        enumerable: true,\n        configurable: false,\n      },\n      kind: {\n        get: () => this.#kind,\n        enumerable: true,\n        configurable: false,\n      },\n      score: {\n        get: () => this.#score,\n        enumerable: true,\n        configurable: false,\n      },\n      createdAt: {\n        get: () => this.#createdAt,\n        enumerable: true,\n        configurable: false,\n      },\n      updatedAt: {\n        get: () => this.#updatedAt,\n        enumerable: true,\n        configurable: false,\n      },\n      inline: {\n        get: () => this.#inline,\n        enumerable: true,\n        configurable: false,\n      },\n      artifactConstructor: {\n        get: () => this.#artifactConstructor,\n        enumerable: true,\n        configurable: false,\n      },\n      sizeUnknown: {\n        get: () =>\n          SpooledArtifact.isSpooledArtifact(this.#content) &&\n          !this.#inline &&\n          !this.#content.hasSizeHints(),\n        enumerable: true,\n        configurable: false,\n      },\n    })\n  }\n\n  /**\n   * Estimates the token count of the content under `encoding`.\n   *\n   * @remarks\n   * Delegates to the content's own `estimateTokens`: synchronous for a {@link @nhtio/adk!Tokenizable}\n   * (returns `number`), asynchronous for a {@link @nhtio/adk!SpooledArtifact} (returns\n   * `Promise<number>`, reading the bytes from the backing store on demand). Both shapes satisfy the\n   * adapter's token-budget path, which already awaits estimates.\n   *\n   * Note: the `SpooledArtifact` branch materialises the full decoded string transiently to count\n   * tokens — reader-backing keeps the body off the *permanent* heap, but does not eliminate the\n   * transient allocation at budgeting time.\n   *\n   * @param encoding - The encoding identifier to use for counting.\n   * @returns The estimated token count.\n   */\n  estimateTokens(encoding: TokenEncoding): number | Promise<number> {\n    if (\n      SpooledArtifact.isSpooledArtifact(this.#content) &&\n      !this.#inline &&\n      this.#content.hasSizeHints()\n    ) {\n      return this.#content.estimateHandleTokens(this.#id, encoding)\n    }\n    return this.#content.estimateTokens(encoding)\n  }\n\n  /**\n   * Returns the content body as a single string.\n   *\n   * @remarks\n   * For a {@link @nhtio/adk!Tokenizable} this is synchronous in effect (resolved immediately); for a\n   * {@link @nhtio/adk!SpooledArtifact} it reads the full body from the backing store via\n   * {@link @nhtio/adk!SpooledArtifact.asString}. Always returns a `Promise` so callers have one\n   * code path; render helpers `await` it at the point the trust-tier envelope is built.\n   *\n   * @returns The full content body as a string.\n   */\n  async contentString(): Promise<string> {\n    return SpooledArtifact.isSpooledArtifact(this.#content)\n      ? this.#content.asString()\n      : this.#content.toString()\n  }\n\n  /**\n   * Serialise this Retrievable into an `@nhtio/encoder` snapshot.\n   *\n   * @remarks\n   * Emits a {@link RawRetrievable}-shaped object; `content` is the live {@link @nhtio/adk!Tokenizable} or\n   * {@link @nhtio/adk!SpooledArtifact} (the encoder recurses — a reader-backed artifact round-trips as a\n   * handle, throwing {@link @nhtio/adk!E_READER_NOT_DESCRIBABLE} if its reader cannot describe itself).\n   * Round-trips via {@link Retrievable.[DECODE_METHOD]}, which re-validates through the constructor.\n   *\n   * @returns A {@link RawRetrievable}-shaped snapshot.\n   */\n  [ENCODE_METHOD](): AdkEncodableSnapshot {\n    return {\n      id: this.#id,\n      content: this.#content,\n      trustTier: this.#trustTier,\n      source: this.#source,\n      kind: this.#kind,\n      score: this.#score,\n      createdAt: this.#createdAt,\n      updatedAt: this.#updatedAt,\n      inline: this.#inline,\n      artifactConstructor: this.#artifactConstructor,\n    }\n  }\n\n  /**\n   * Reconstruct a {@link Retrievable} from a {@link Retrievable.[ENCODE_METHOD]} snapshot.\n   *\n   * @param data - The snapshot produced by {@link Retrievable.[ENCODE_METHOD]}.\n   * @returns A fully-validated {@link Retrievable}.\n   */\n  static [DECODE_METHOD](data: AdkEncodableSnapshot): Retrievable {\n    return new Retrievable(data as RawRetrievable)\n  }\n}\n"],"mappings":"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"}