{"version":3,"sources":["../../src/api.ts","../../src/cache.ts","../../src/skeleton.ts","../../src/index.ts","../../src/react/index.ts"],"names":["useState","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Adapter over the global `Summarizer` API. Feature-detected; on browsers\n * without it, every entry point returns `null` so callers can stay declarative.\n *\n * Spec: https://developer.chrome.com/docs/ai/summarizer-api\n */\n\nexport interface SummarizerInstance {\n  summarize(text: string): Promise<string>;\n  summarizeStreaming?(text: string): AsyncIterable<string>;\n  destroy?(): void;\n}\n\nexport interface DownloadProgressEvent extends Event {\n  readonly loaded: number;\n}\n\nexport interface CreateMonitor {\n  addEventListener(\n    type: \"downloadprogress\",\n    listener: (event: DownloadProgressEvent) => void,\n  ): void;\n}\n\nexport interface SummarizerCreateOptions {\n  type?: \"tldr\" | \"key-points\" | \"teaser\" | \"headline\";\n  format?: \"markdown\" | \"plain-text\";\n  length?: \"short\" | \"medium\" | \"long\";\n  preference?: \"auto\" | \"speed\" | \"capability\";\n  sharedContext?: string;\n  expectedInputLanguages?: string[];\n  expectedContextLanguages?: string[];\n  outputLanguage?: string;\n  /** Observe model-download progress when creation requires one. */\n  monitor?: (m: CreateMonitor) => void;\n}\n\nexport type SummarizerAvailability =\n  | \"unavailable\"\n  | \"downloadable\"\n  | \"downloading\"\n  | \"available\";\n\n/**\n * Subset of `SummarizerCreateOptions` that the spec accepts when probing\n * availability. Pass the relevant creation shape so the result applies to the\n * configuration you intend to create.\n */\nexport interface SummarizerAvailabilityOptions {\n  type?: SummarizerCreateOptions[\"type\"];\n  format?: SummarizerCreateOptions[\"format\"];\n  length?: SummarizerCreateOptions[\"length\"];\n  preference?: SummarizerCreateOptions[\"preference\"];\n  expectedInputLanguages?: string[];\n  expectedContextLanguages?: string[];\n  outputLanguage?: string;\n}\n\nexport interface SummarizerApi {\n  availability(\n    options?: SummarizerAvailabilityOptions,\n  ): Promise<SummarizerAvailability>;\n  create(options?: SummarizerCreateOptions): Promise<SummarizerInstance>;\n}\n\n/** Internal: read the native global. Not exported from the package. */\nexport const getSummarizerApi = (): SummarizerApi | null => {\n  if (typeof globalThis === \"undefined\") return null;\n  return (\n    (globalThis as unknown as { Summarizer?: SummarizerApi }).Summarizer ?? null\n  );\n};\n\n/** Whether the current environment exposes the Summarizer API. */\nexport const isAvailable = (): boolean => getSummarizerApi() !== null;\n\nexport const checkAvailability = async (\n  options?: SummarizerAvailabilityOptions,\n): Promise<SummarizerAvailability | null> => {\n  const api = getSummarizerApi();\n  if (!api?.availability) return null;\n  try {\n    return await api.availability(options);\n  } catch {\n    return null;\n  }\n};\n\nconst DEFAULT_MAX_CACHED_SESSIONS = 8;\n\ninterface CacheConfig {\n  max: number;\n}\n\nconst cacheConfig: CacheConfig = { max: DEFAULT_MAX_CACHED_SESSIONS };\n\ninterface SessionEntry {\n  key: string;\n  session: Promise<SummarizerInstance>;\n  /** Active prepare leases. Leased entries never evict. */\n  leaseCount: number;\n  /** Operations currently running inference on this session. */\n  inFlightCount: number;\n  /** Still reachable through `sessionCache`. */\n  inMap: boolean;\n  /** Destruction already scheduled; guards double-destroy. */\n  destroyed: boolean;\n}\n\n// Map iteration order is insertion order, which lets us use it as an LRU:\n// on hit we re-insert to bump recency, and on overflow we evict the\n// oldest (first) entry.\nconst sessionCache = new Map<string, SessionEntry>();\n\nconst isPinned = (entry: SessionEntry): boolean =>\n  entry.leaseCount > 0 || entry.inFlightCount > 0;\n\nconst normalizeCacheMax = (max: number): number =>\n  Number.isFinite(max) ? Math.max(0, Math.floor(max)) : 0;\n\nexport interface ConfigureSummarizerCacheOptions {\n  /** Soft cap on cached summarizer sessions. Default: `8`. */\n  max?: number;\n}\n\n/**\n * Bound the internal summarizer session cache. Excess entries are evicted in\n * LRU order (their `destroy?()` is invoked when present). Lowering `max`\n * immediately evicts down to the new ceiling.\n */\nexport const configureSummarizerCache = (\n  options: ConfigureSummarizerCacheOptions = {},\n): void => {\n  if (options.max !== undefined) {\n    cacheConfig.max = normalizeCacheMax(options.max);\n  }\n  trim();\n};\n\nconst destroySession = (session: Promise<SummarizerInstance>): void => {\n  session\n    .then((instance) => {\n      try {\n        instance.destroy?.();\n      } catch {\n        // best-effort; the spec doesn't require destroy to be infallible.\n      }\n    })\n    .catch(() => {\n      // session never resolved (e.g. create() rejected); nothing to destroy.\n    });\n};\n\nconst detachEntry = (entry: SessionEntry): void => {\n  if (!entry.inMap) return;\n  entry.inMap = false;\n  sessionCache.delete(entry.key);\n};\n\n/**\n * Destroy a detached entry once nothing pins it. Pinned entries are settled\n * again when their last lease releases or their last in-flight call ends.\n */\nconst settleEntry = (entry: SessionEntry): void => {\n  if (entry.inMap || entry.destroyed || isPinned(entry)) return;\n  entry.destroyed = true;\n  destroySession(entry.session);\n};\n\nconst trim = (): void => {\n  if (sessionCache.size <= cacheConfig.max) return;\n  for (const entry of [...sessionCache.values()]) {\n    if (sessionCache.size <= cacheConfig.max) return;\n    // Leased or in-flight entries never evict, so the cache may temporarily\n    // exceed `max` while they stay pinned.\n    if (isPinned(entry)) continue;\n    detachEntry(entry);\n    settleEntry(entry);\n  }\n};\n\n/**\n * Drop every cached summarizer session. Sessions live for the tab lifetime by\n * default; call this to free them eagerly when navigating away from a feature\n * that won't be revisited. Sessions pinned by a lease or an in-flight call\n * leave the cache now and are destroyed once the last pin drops.\n */\nexport const clearSummarizerSessions = (): void => {\n  for (const entry of [...sessionCache.values()]) {\n    detachEntry(entry);\n    settleEntry(entry);\n  }\n};\n\n/**\n * Drop the cached summarizer whose create-options match `options`.\n */\nexport const clearSummarizerSession = (\n  options: SummarizerCreateOptions,\n): void => {\n  const entry = sessionCache.get(JSON.stringify(options));\n  if (!entry) return;\n  detachEntry(entry);\n  settleEntry(entry);\n};\n\n/**\n * Get or create the cache entry for the given options. Sessions live for the\n * tab lifetime so navigating between same-config pages skips the ~1-3s cold\n * start. On `create()` failure the cache slot is purged so the next call\n * retries instead of returning a poisoned promise.\n */\nconst getOrCreateEntry = (\n  api: SummarizerApi,\n  options: SummarizerCreateOptions,\n): SessionEntry => {\n  const key = JSON.stringify(options);\n  const existing = sessionCache.get(key);\n  if (existing) {\n    // Bump recency: delete + reinsert so this entry moves to the end of the\n    // LRU order.\n    sessionCache.delete(key);\n    sessionCache.set(key, existing);\n    return existing;\n  }\n  const entry: SessionEntry = {\n    key,\n    session: api.create(options).catch((err) => {\n      detachEntry(entry);\n      throw err;\n    }),\n    leaseCount: 0,\n    inFlightCount: 0,\n    inMap: true,\n    destroyed: false,\n  };\n  // A prepare-only caller may never observe the session promise; keep the\n  // stored branch handled so failed creation cannot surface as an unhandled\n  // rejection.\n  entry.session.catch(() => {});\n  sessionCache.set(key, entry);\n  return entry;\n};\n\nexport interface AcquiredSummarizer {\n  session: Promise<SummarizerInstance>;\n  /** Release the in-flight pin. Idempotent. */\n  done(): void;\n}\n\n/**\n * Get or create a `Summarizer` session and pin it for one operation. The pin\n * defers destruction (final lease release, clear, eviction) until `done()`\n * runs, so in-flight inference can never lose its session.\n */\nexport const acquireSummarizer = (\n  api: SummarizerApi,\n  options: SummarizerCreateOptions,\n): AcquiredSummarizer => {\n  const entry = getOrCreateEntry(api, options);\n  // Pin before trimming so a fresh entry can never evict itself when every\n  // other entry is pinned.\n  entry.inFlightCount += 1;\n  trim();\n  let released = false;\n  return {\n    session: entry.session,\n    done: () => {\n      if (released) return;\n      released = true;\n      entry.inFlightCount -= 1;\n      settleEntry(entry);\n      // The dropped pin may leave the cache over its cap; re-trim now\n      // instead of waiting for the next create or configure call.\n      trim();\n    },\n  };\n};\n\nexport interface SummarizerSessionLease {\n  /** Settles with the underlying `create()` outcome. */\n  ready: Promise<void>;\n  /** Idempotent. The final release detaches and destroys once safe. */\n  release(): void;\n}\n\n/**\n * Start (or join) session creation for the given options and hold a lease on\n * the entry. Leases pin the entry against LRU eviction. The final release\n * removes the entry from the cache and destroys the session as soon as no\n * in-flight call uses it; released-before-ready sessions are destroyed when\n * creation later succeeds.\n */\nexport const leaseSummarizer = (\n  api: SummarizerApi,\n  options: SummarizerCreateOptions,\n): SummarizerSessionLease => {\n  const entry = getOrCreateEntry(api, options);\n  // Pin before trimming so a fresh entry can never evict itself when every\n  // other entry is pinned.\n  entry.leaseCount += 1;\n  trim();\n  let released = false;\n  const ready = entry.session.then(() => undefined);\n  // Keep unobserved leases from surfacing unhandled rejections.\n  ready.catch(() => {});\n  return {\n    ready,\n    release: () => {\n      if (released) return;\n      released = true;\n      entry.leaseCount -= 1;\n      if (entry.leaseCount > 0) return;\n      detachEntry(entry);\n      settleEntry(entry);\n    },\n  };\n};\n\n/** Test-only escape hatch; drop every cached session. */\nexport const __clearSessionCacheForTests = (): void => {\n  sessionCache.clear();\n  cacheConfig.max = DEFAULT_MAX_CACHED_SESSIONS;\n};\n","/**\n * `sessionStorage`-backed cache so a successful summary renders instantly on\n * revisit, skipping the model entirely. The cache is best-effort: storage\n * disabled / quota exceeded falls through silently; the summary still\n * renders.\n */\n\nexport interface SummaryCache {\n  get(key: string): string | null;\n  set(key: string, value: string): void;\n}\n\n/**\n * Public-facing `cache` option. Pass `\"session\"` / `\"local\"` for storage\n * shortcuts, or any `{ get, set }`-shaped object for a custom backend.\n */\nexport type CacheOption = \"session\" | \"local\" | SummaryCache;\n\n/**\n * Default time-to-live for entries written by the built-in `\"session\"` /\n * `\"local\"` storage shortcuts: one hour. On-device model output changes as\n * the browser updates the model, so built-in entries expire instead of\n * persisting indefinitely. Override per call with `cacheTtl`. Custom\n * `{ get, set }` caches own their expiry policy.\n */\nexport const DEFAULT_CACHE_TTL_MS = 60 * 60 * 1000;\n\n/** Version tag for the storage envelope written by the built-in shortcuts. */\nconst ENVELOPE_VERSION = 1;\n\ninterface CacheEnvelope {\n  v: number;\n  value: string;\n  expiresAt: number;\n}\n\n/**\n * Parse a stored entry into a versioned envelope. Legacy raw strings,\n * malformed JSON, unsupported versions, and invalid timestamps all return\n * `null` so the caller treats them as misses.\n */\nconst parseEnvelope = (raw: string): CacheEnvelope | null => {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    return null;\n  }\n  if (typeof parsed !== \"object\" || parsed === null) return null;\n  const envelope = parsed as Partial<CacheEnvelope>;\n  if (envelope.v !== ENVELOPE_VERSION) return null;\n  if (typeof envelope.value !== \"string\") return null;\n  if (\n    typeof envelope.expiresAt !== \"number\" ||\n    !Number.isFinite(envelope.expiresAt)\n  )\n    return null;\n  return envelope as CacheEnvelope;\n};\n\nconst normalizeTtl = (ttlMs: number | undefined): number =>\n  typeof ttlMs === \"number\" && Number.isFinite(ttlMs) && ttlMs > 0\n    ? ttlMs\n    : DEFAULT_CACHE_TTL_MS;\n\ninterface DefaultCacheOptions {\n  /** Storage backend. Default: `globalThis.sessionStorage`. */\n  storage?: Storage;\n  /** Prefix for cache keys. Default: `\"summarizer:\"`. */\n  prefix?: string;\n  /** Entry time-to-live in milliseconds. Default: `DEFAULT_CACHE_TTL_MS`. */\n  ttlMs?: number;\n}\n\nexport const createSessionStorageCache = (\n  options: DefaultCacheOptions = {},\n): SummaryCache => {\n  const prefix = options.prefix ?? \"summarizer:\";\n  const storage =\n    options.storage ??\n    (typeof globalThis !== \"undefined\"\n      ? (globalThis as { sessionStorage?: Storage }).sessionStorage\n      : undefined);\n  const ttlMs = normalizeTtl(options.ttlMs);\n\n  return {\n    get(key) {\n      if (!storage) return null;\n      let raw: string | null;\n      try {\n        raw = storage.getItem(prefix + key);\n      } catch {\n        return null;\n      }\n      if (raw === null) return null;\n      const envelope = parseEnvelope(raw);\n      if (envelope && Date.now() < envelope.expiresAt) return envelope.value;\n      // Legacy raw strings, malformed envelopes, and expired entries are\n      // misses; drop them so the next successful run replaces the slot.\n      try {\n        storage.removeItem(prefix + key);\n      } catch {\n        // best-effort cleanup only.\n      }\n      return null;\n    },\n    set(key, value) {\n      if (!storage) return;\n      try {\n        storage.setItem(\n          prefix + key,\n          JSON.stringify({\n            v: ENVELOPE_VERSION,\n            value,\n            expiresAt: Date.now() + ttlMs,\n          }),\n        );\n      } catch {\n        // quota / disabled storage; best-effort only.\n      }\n    },\n  };\n};\n\n/**\n * Resolve the public `cache` option into a concrete `{ get, set }` backend.\n * `undefined` → no caching. `\"session\"` / `\"local\"` → wrap the matching\n * web-storage backend (no-op fallback if unavailable) with a TTL envelope.\n * Object → passthrough; `ttlMs` does not apply to custom backends.\n */\nexport const resolveCache = (\n  value: CacheOption | undefined,\n  ttlMs?: number,\n): SummaryCache | undefined => {\n  if (value === undefined) return undefined;\n  if (value === \"session\") {\n    return createSessionStorageCache({ ttlMs });\n  }\n  if (value === \"local\") {\n    const storage =\n      typeof globalThis !== \"undefined\"\n        ? (globalThis as { localStorage?: Storage }).localStorage\n        : undefined;\n    return createSessionStorageCache({ storage, ttlMs });\n  }\n  return value;\n};\n\n/**\n * Build a default cache key from the route, input, and summary options that\n * affect the output. A legacy string input still returns the compact\n * `pathname:lang` key. Pass a custom string to `summarize()`'s `cacheKey`\n * option for finer-grained invalidation.\n */\ninterface DefaultCacheKeyInput {\n  text: string;\n  language: string;\n  languageHints?: boolean;\n  type?: string;\n  length?: string;\n  format?: string;\n  preference?: string;\n  sharedContext?: string;\n}\n\nconst currentPathname = (): string => {\n  let pathname = \"\";\n  if (typeof globalThis === \"undefined\") {\n    pathname = \"\";\n  } else {\n    const loc = (globalThis as { location?: Location }).location;\n    pathname = loc?.pathname ?? \"\";\n  }\n  return pathname;\n};\n\nexport const defaultCacheKey = (\n  input: string | DefaultCacheKeyInput,\n): string => {\n  const pathname = currentPathname();\n  if (typeof input === \"string\")\n    return pathname ? `${pathname}:${input}` : input;\n  return JSON.stringify([\n    pathname,\n    input.text.trim(),\n    input.language,\n    input.languageHints === true,\n    input.type ?? \"\",\n    input.length ?? \"\",\n    input.format ?? \"\",\n    input.preference ?? \"\",\n    input.sharedContext ?? \"\",\n  ]);\n};\n","/** Internal output normalization for `summarize()`. */\n\n/** Strip wrapping quotes / whitespace and collapse internal whitespace. */\nexport const cleanSummary = (raw: string): string =>\n  raw\n    .replace(/^[\"“”'`\\s]+|[\"“”'`\\s]+$/g, \"\")\n    .replace(/\\s+/g, \" \")\n    .trim();\n","/**\n * @web-ai-sdk/summarizer; building block for the Web's Built-in Summarizer API.\n *\n * Vanilla TypeScript / DOM core. The React adapter at `@web-ai-sdk/summarizer/react` is a\n * thin hook around this module.\n *\n * Spec: https://developer.chrome.com/docs/ai/summarizer-api\n */\n\nimport {\n  acquireSummarizer,\n  type ConfigureSummarizerCacheOptions,\n  type CreateMonitor,\n  checkAvailability,\n  clearSummarizerSession,\n  clearSummarizerSessions,\n  configureSummarizerCache,\n  getSummarizerApi,\n  isAvailable,\n  leaseSummarizer,\n  type SummarizerApi,\n  type SummarizerAvailability,\n  type SummarizerAvailabilityOptions,\n  type SummarizerCreateOptions,\n  type SummarizerInstance,\n} from \"./api.js\";\nimport {\n  type CacheOption,\n  DEFAULT_CACHE_TTL_MS,\n  defaultCacheKey,\n  resolveCache,\n  type SummaryCache,\n} from \"./cache.js\";\nimport { cleanSummary } from \"./skeleton.js\";\n\nexport type {\n  CacheOption,\n  ConfigureSummarizerCacheOptions,\n  CreateMonitor,\n  SummarizerApi,\n  SummarizerAvailability,\n  SummarizerAvailabilityOptions,\n  SummarizerCreateOptions,\n  SummarizerInstance,\n  SummaryCache,\n};\nexport {\n  checkAvailability,\n  clearSummarizerSession,\n  clearSummarizerSessions,\n  configureSummarizerCache,\n  DEFAULT_CACHE_TTL_MS,\n  isAvailable,\n};\n\nexport interface SummarizeOptions {\n  /** Text to summarize. Empty / whitespace input resolves to `{ output: null }`. */\n  input: string;\n  /** BCP-47 language for input + output hints. Falls back to omitting hints if unsupported. */\n  language: string;\n  /** Languages the model supports for input/output hints. Default: `[\"en\", \"es\", \"ja\"]`. */\n  supportedLanguages?: readonly string[];\n  /** Summary shape. Default: `\"tldr\"`. */\n  type?: \"tldr\" | \"key-points\" | \"teaser\" | \"headline\";\n  /** Length preset. Default: `\"medium\"`. */\n  length?: \"short\" | \"medium\" | \"long\";\n  /** Output format. Default: `\"plain-text\"`. */\n  format?: \"plain-text\" | \"markdown\";\n  /**\n   * Performance preference hint. `\"speed\"` biases toward a faster, lighter\n   * model; `\"capability\"` toward a more comprehensive one; `\"auto\"` lets the\n   * browser balance the two. The browser may override the hint when a\n   * functional requirement (e.g. the requested language) needs a more capable\n   * model. Default: `\"auto\"` (matches the platform default).\n   */\n  preference?: \"auto\" | \"speed\" | \"capability\";\n  /** Native `sharedContext` string (a hint about who/what the summary is for). */\n  sharedContext?: string;\n  /** Observe model-download progress when creation requires one. */\n  monitor?: (m: CreateMonitor) => void;\n  /**\n   * Result cache. Off by default; every call hits the model. Pass\n   * `\"session\"` / `\"local\"` for the matching web-storage shortcut, or any\n   * `{ get, set }`-shaped object for a custom backend.\n   */\n  cache?: CacheOption;\n  /** Cache key. Default: JSON string of route, input, and summary options. */\n  cacheKey?: string;\n  /**\n   * Time-to-live in milliseconds for entries written by the built-in\n   * `\"session\"` / `\"local\"` storage shortcuts. Default: one hour\n   * (`DEFAULT_CACHE_TTL_MS`). Ignored for custom `{ get, set }` caches, which\n   * own their expiry policy.\n   */\n  cacheTtl?: number;\n  /**\n   * Force a fresh summary. Skips the cache read, runs the model, and\n   * replaces the cached value after a successful run. Applies to built-in\n   * and custom caches.\n   */\n  cacheRefresh?: boolean;\n  /**\n   * Streaming update callback (cleaned text, monotonically growing).\n   * Receives the **cumulative** buffer, not deltas.\n   */\n  onUpdate?: (text: string) => void;\n  /** Abort signal. */\n  signal?: AbortSignal;\n}\n\nexport interface SummarizeResult {\n  /** Final summary text (cleaned), or `null` if the input was empty. */\n  output: string | null;\n  /** Whether the result came from the cache (no model call). */\n  cached: boolean;\n}\n\nconst NORMALIZE_LANG = (lang: string): string =>\n  lang.split(\"-\")[0]?.toLowerCase() ?? lang.toLowerCase();\n\nconst DEFAULT_SUPPORTED_LANGUAGES = [\"en\", \"es\", \"ja\"] as const;\n\nexport class SummarizerUnavailableError extends Error {\n  override readonly name = \"SummarizerUnavailableError\";\n}\n\n/**\n * Session-affecting subset of `SummarizeOptions`. `prepareSummarizer` and\n * `summarize` derive the same native create options from these fields, so a\n * prepared session is reused by the matching call.\n * `monitor` observes creation only; it never affects the cache key.\n */\nexport type PrepareSummarizerOptions = Pick<\n  SummarizeOptions,\n  | \"language\"\n  | \"supportedLanguages\"\n  | \"type\"\n  | \"length\"\n  | \"format\"\n  | \"preference\"\n  | \"sharedContext\"\n  | \"monitor\"\n>;\n\ninterface SessionConfig {\n  lang: string;\n  languageHints: boolean;\n  createOptions: SummarizerCreateOptions;\n}\n\n/**\n * Single source of the option-to-session mapping. The session cache key derives from\n * the stable fields of `createOptions` (`monitor` never fragments reuse),\n * so `summarize` and `prepareSummarizer` must both go\n * through this derivation.\n */\nconst resolveSessionConfig = (\n  options: PrepareSummarizerOptions,\n): SessionConfig => {\n  const lang = NORMALIZE_LANG(options.language);\n  const supported = new Set(\n    (options.supportedLanguages ?? DEFAULT_SUPPORTED_LANGUAGES).map(\n      NORMALIZE_LANG,\n    ),\n  );\n  const languageHints = supported.has(lang);\n\n  const langOptions: Pick<\n    SummarizerCreateOptions,\n    \"expectedInputLanguages\" | \"expectedContextLanguages\" | \"outputLanguage\"\n  > = languageHints\n    ? {\n        expectedInputLanguages: [lang],\n        expectedContextLanguages: [lang],\n        outputLanguage: lang,\n      }\n    : {};\n\n  const createOptions: SummarizerCreateOptions = {\n    type: options.type ?? \"tldr\",\n    format: options.format ?? \"plain-text\",\n    length: options.length ?? \"medium\",\n    preference: options.preference ?? \"auto\",\n    sharedContext: options.sharedContext ?? \"\",\n    ...langOptions,\n    ...(options.monitor ? { monitor: options.monitor } : {}),\n  };\n\n  return { lang, languageHints, createOptions };\n};\n\nexport interface SummarizerLease {\n  /**\n   * Resolves when the native session is created. Rejects with\n   * `SummarizerUnavailableError` when the API is missing or creation fails.\n   */\n  ready: Promise<void>;\n  /**\n   * Idempotent. The final release destroys the session once no other lease\n   * or in-flight call uses it.\n   */\n  release(): void;\n}\n\n/**\n * Start native session creation as soon as user intent is clear, before the\n * input exists. The matching `summarize` call reuses the prepared session\n * without a second create. Never throws synchronously; unavailability and\n * creation failures reject `ready`. Failed preparations leave the cache so a\n * later call can retry.\n */\nexport const prepareSummarizer = (\n  options: PrepareSummarizerOptions,\n): SummarizerLease => {\n  const api = getSummarizerApi();\n  if (!api?.create) {\n    const ready = Promise.reject(\n      new SummarizerUnavailableError(\n        \"Summarizer API is not available in this environment.\",\n      ),\n    );\n    // Keep unobserved leases from surfacing unhandled rejections.\n    ready.catch(() => {});\n    return { ready, release: () => {} };\n  }\n  const { createOptions } = resolveSessionConfig(options);\n  const lease = leaseSummarizer(api, createOptions);\n  const ready = lease.ready.catch((err) => {\n    const message = (err as Error)?.message ?? String(err);\n    throw new SummarizerUnavailableError(\n      `Summarizer.create() failed: ${message}`,\n    );\n  });\n  ready.catch(() => {});\n  return { ready, release: lease.release };\n};\n\n/**\n * Generate a summary. Uses streaming when the underlying instance supports\n * it, one-shot otherwise. Returns `{ output: null }` for empty input.\n * Throws `SummarizerUnavailableError` when the API isn't present in the\n * environment.\n *\n * Output is normalized via an internal cleaner (wrapping quotes/whitespace\n * stripped, internal whitespace collapsed). Anything beyond that — e.g.\n * trimming terminal punctuation for headline-style use cases — is the\n * consumer's concern.\n */\nexport const summarize = async (\n  options: SummarizeOptions,\n): Promise<SummarizeResult> => {\n  const api = getSummarizerApi();\n  if (!api?.create) {\n    throw new SummarizerUnavailableError(\n      \"Summarizer API is not available in this environment.\",\n    );\n  }\n\n  const text = options.input.trim();\n  if (!text) return { output: null, cached: false };\n\n  const { lang, languageHints, createOptions } = resolveSessionConfig(options);\n  const cache = resolveCache(options.cache, options.cacheTtl);\n  const cacheKey =\n    options.cacheKey ??\n    defaultCacheKey({\n      text,\n      language: lang,\n      languageHints,\n      type: options.type,\n      length: options.length,\n      format: options.format,\n      preference: options.preference,\n      sharedContext: options.sharedContext,\n    });\n  if (cache && !options.cacheRefresh) {\n    const cached = cache.get(cacheKey);\n    if (cached) return { output: cached, cached: true };\n  }\n\n  // Pass the relevant create options to availability() so the probe describes\n  // the configuration we are about to create. The narrower\n  // SummarizerAvailabilityOptions shape filters out create-only fields such as\n  // `sharedContext`.\n  const availability = await api\n    .availability({\n      ...(createOptions.type ? { type: createOptions.type } : {}),\n      ...(createOptions.format ? { format: createOptions.format } : {}),\n      ...(createOptions.length ? { length: createOptions.length } : {}),\n      ...(createOptions.preference\n        ? { preference: createOptions.preference }\n        : {}),\n      ...(createOptions.expectedInputLanguages\n        ? { expectedInputLanguages: createOptions.expectedInputLanguages }\n        : {}),\n      ...(createOptions.expectedContextLanguages\n        ? {\n            expectedContextLanguages: createOptions.expectedContextLanguages,\n          }\n        : {}),\n      ...(createOptions.outputLanguage\n        ? { outputLanguage: createOptions.outputLanguage }\n        : {}),\n    })\n    .catch(() => \"unavailable\" as const);\n  if (availability === \"unavailable\") {\n    throw new SummarizerUnavailableError(\"Summarizer reports unavailable.\");\n  }\n  if (options.signal?.aborted) throw new AbortError();\n\n  // The pin defers destruction (lease release, clear, eviction) until this\n  // call finishes.\n  const acquired = acquireSummarizer(api, createOptions);\n  try {\n    // Wrap session-create failures with context so consumers can branch on\n    // a single typed error instead of parsing browser-specific messages.\n    let summarizer: SummarizerInstance;\n    try {\n      summarizer = await acquired.session;\n    } catch (err) {\n      if (err instanceof AbortError) throw err;\n      const message = (err as Error)?.message ?? String(err);\n      throw new SummarizerUnavailableError(\n        `Summarizer.create() failed: ${message}`,\n      );\n    }\n    if (options.signal?.aborted) throw new AbortError();\n\n    // Browser implementations may emit delta or cumulative chunks. Detect the\n    // shape per chunk and merge accordingly.\n    const mergeChunk = (buffer: string, chunk: string): string =>\n      chunk.startsWith(buffer) ? chunk : buffer + chunk;\n\n    let finalText: string;\n    if (\n      typeof summarizer.summarizeStreaming === \"function\" &&\n      options.onUpdate\n    ) {\n      let buffer = \"\";\n      for await (const chunk of summarizer.summarizeStreaming(text)) {\n        if (options.signal?.aborted) throw new AbortError();\n        buffer = mergeChunk(buffer, chunk);\n        options.onUpdate(cleanSummary(buffer));\n      }\n      finalText = cleanSummary(buffer);\n    } else if (typeof summarizer.summarizeStreaming === \"function\") {\n      let buffer = \"\";\n      for await (const chunk of summarizer.summarizeStreaming(text)) {\n        if (options.signal?.aborted) throw new AbortError();\n        buffer = mergeChunk(buffer, chunk);\n      }\n      finalText = cleanSummary(buffer);\n    } else {\n      const raw = await summarizer.summarize(text);\n      if (options.signal?.aborted) throw new AbortError();\n      finalText = cleanSummary(raw);\n    }\n\n    if (finalText && cache) cache.set(cacheKey, finalText);\n    return { output: finalText || null, cached: false };\n  } finally {\n    acquired.done();\n  }\n};\n\nclass AbortError extends Error {\n  override readonly name = \"AbortError\";\n  constructor() {\n    super(\"Summarization aborted\");\n  }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n  isAvailable,\n  type SummarizeOptions,\n  SummarizerUnavailableError,\n  summarize,\n} from \"../index.js\";\n\nexport type SummarizerStatus =\n  | \"idle\"\n  | \"loading\"\n  | \"streaming\"\n  | \"done\"\n  | \"unavailable\";\n\nexport interface UseSummarizerOptions\n  extends Omit<SummarizeOptions, \"onUpdate\" | \"signal\"> {\n  /** Whether to automatically run on mount. Default: `true`. */\n  enabled?: boolean;\n}\n\nexport interface UseSummarizerReturn {\n  status: SummarizerStatus;\n  /** Final summary text (cleaned), or `null` while idle / unavailable. */\n  output: string | null;\n  error: Error | null;\n  /** Whether the result was loaded from cache (no model call). */\n  fromCache: boolean;\n  /** Imperatively dismiss; sets status to `\"unavailable\"` and clears output. */\n  dismiss(): void;\n}\n\n/**\n * Auto-run a summarization on mount and re-run when meaningful inputs\n * change. Pass primitive options inline; non-primitive options (`cache`,\n * `monitor`) should be stable references (memoize if necessary).\n */\nexport const useSummarizer = (\n  options: UseSummarizerOptions,\n): UseSummarizerReturn => {\n  const [status, setStatus] = useState<SummarizerStatus>(() =>\n    isAvailable() ? \"idle\" : \"unavailable\",\n  );\n  const [output, setOutput] = useState<string | null>(null);\n  const [error, setError] = useState<Error | null>(null);\n  const [fromCache, setFromCache] = useState(false);\n\n  const {\n    input,\n    language,\n    supportedLanguages,\n    type,\n    length,\n    format,\n    preference,\n    sharedContext,\n    monitor,\n    cache,\n    cacheKey,\n    cacheTtl,\n    cacheRefresh,\n    enabled = true,\n  } = options;\n\n  useEffect(() => {\n    if (!enabled) return;\n    if (!isAvailable()) {\n      setStatus(\"unavailable\");\n      return;\n    }\n    if (!input.trim()) {\n      setStatus(\"idle\");\n      setOutput(null);\n      return;\n    }\n\n    const controller = new AbortController();\n    setError(null);\n    setStatus(\"loading\");\n\n    summarize({\n      input,\n      language,\n      supportedLanguages,\n      type,\n      length,\n      format,\n      preference,\n      sharedContext,\n      monitor,\n      cache,\n      cacheKey,\n      cacheTtl,\n      cacheRefresh,\n      signal: controller.signal,\n      onUpdate: (chunk) => {\n        if (controller.signal.aborted) return;\n        setOutput(chunk);\n        setStatus(\"streaming\");\n      },\n    })\n      .then((result) => {\n        if (controller.signal.aborted) return;\n        setOutput(result.output);\n        setFromCache(result.cached);\n        setStatus(\"done\");\n      })\n      .catch((err: unknown) => {\n        if (controller.signal.aborted) return;\n        if ((err as { name?: string })?.name === \"AbortError\") return;\n        if (err instanceof SummarizerUnavailableError) {\n          setStatus(\"unavailable\");\n          return;\n        }\n        setError(err instanceof Error ? err : new Error(String(err)));\n        setStatus(\"unavailable\");\n      });\n\n    return () => {\n      controller.abort();\n    };\n  }, [\n    enabled,\n    input,\n    language,\n    supportedLanguages,\n    type,\n    length,\n    format,\n    preference,\n    sharedContext,\n    monitor,\n    cache,\n    cacheKey,\n    cacheTtl,\n    cacheRefresh,\n  ]);\n\n  const dismiss = () => {\n    setStatus(\"unavailable\");\n    setOutput(null);\n  };\n\n  return { status, output, error, fromCache, dismiss };\n};\n\nexport type {\n  CacheOption,\n  SummarizeOptions,\n  SummarizeResult,\n  SummaryCache,\n} from \"../index.js\";\n"]}