{
  "format": "odb-inspection/1",
  "executed": false,
  "source": {
    "path": "components/ultrasound/preview-source/1.0.0/source.ts",
    "sha256": "1cda72d841ad4aa767b365712a236accf323823719c312636954dc1fd42964f1",
    "build": "Built into @opendevicedb/components/video; host service is explicitly implemented, never dynamically evaluated.",
    "text": "// SPDX-License-Identifier: AGPL-3.0-or-later\n// Read-only client for the explicit local preview bridge. No USB or acquisition commands.\nexport const MAX_PREVIEW_BYTES = 8 * 1024 * 1024;\nexport interface UltrasoundStatus {\n  format: \"odb.ultrasound-preview/1\";\n  profile: \"linear-01\" | \"convex-01\" | \"unknown\";\n  phase: string; session: number; frame: number | null; replay: boolean;\n}\nexport interface UltrasoundFrame {\n  format: \"odb.video.frame/1\"; encoding: \"image/png\"; data: ArrayBuffer;\n  width: number; height: number; sequence: number; session: string;\n  received_at: number; timebase: \"host-receipt\"; mode: \"live\" | \"replay\" | \"snapshot\";\n  profile: UltrasoundStatus[\"profile\"]; calibrated: false;\n}\nexport function previewOrigin(value: string): string {\n  const url = new URL(value);\n  if (url.protocol !== \"http:\" || ![\"127.0.0.1\", \"[::1]\"].includes(url.hostname) || url.username || url.password || url.search || url.hash || url.pathname !== \"/\") throw Error(\"Use a local preview bridge URL such as http://127.0.0.1:4337\");\n  return url.origin;\n}\nexport async function boundedResponse(response: Response, limit: number): Promise<ArrayBuffer> {\n  if (!response.ok) throw Error(`Preview request failed (HTTP ${response.status})`);\n  const reader = response.body?.getReader(); if (!reader) throw Error(\"Empty preview response\");\n  const chunks: Uint8Array[] = []; let size = 0;\n  for (;;) { const { done, value } = await reader.read(); if (done) break; size += value.length; if (size > limit) { await reader.cancel(); throw Error(\"Preview exceeds its size limit\"); } chunks.push(value); }\n  const bytes = new Uint8Array(size); let offset = 0; for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length; } return bytes.buffer;\n}\nexport function pngDimensions(buffer: ArrayBuffer): { width: number; height: number } {\n  const bytes = new Uint8Array(buffer), view = new DataView(buffer);\n  if (bytes.length < 33 || ![137,80,78,71,13,10,26,10].every((n, i) => bytes[i] === n) || view.getUint32(8) !== 13 || String.fromCharCode(...bytes.slice(12,16)) !== \"IHDR\") throw Error(\"The preview is not a PNG frame\");\n  const width = view.getUint32(16), height = view.getUint32(20);\n  if (!width || !height || width > 2048 || height > 2048) throw Error(\"Preview dimensions exceed 2048 × 2048 pixels\");\n  return { width, height };\n}\nexport class UltrasoundPreviewSource {\n  readonly origin: string;\n  private previous = \"\";\n  private expectedProfile: string;\n  private request: typeof fetch;\n  constructor(url: string, expectedProfile: string, request: typeof fetch = fetch) {\n    this.origin = previewOrigin(url); this.expectedProfile = expectedProfile; this.request = request.bind(globalThis);\n    if (![\"linear-01\", \"convex-01\"].includes(expectedProfile)) throw Error(\"Choose the linear or convex probe profile\");\n  }\n  async poll(signal: AbortSignal): Promise<{ status: UltrasoundStatus; frame?: UltrasoundFrame }> {\n    const options = { signal, credentials: \"omit\" as const, cache: \"no-store\" as const, redirect: \"error\" as const };\n    const response = await this.request(`${this.origin}/status`, options);\n    const s: UltrasoundStatus = JSON.parse(new TextDecoder().decode(await boundedResponse(response, 16384)));\n    if (s?.format !== \"odb.ultrasound-preview/1\" || ![\"linear-01\", \"convex-01\", \"unknown\"].includes(s.profile) || typeof s.phase !== \"string\" || typeof s.replay !== \"boolean\" || !Number.isSafeInteger(s.session) || s.session < 0 || !(s.frame === null || Number.isSafeInteger(s.frame) && s.frame > 0)) throw Error(\"Invalid ultrasound preview status\");\n    // Legacy replay servers may omit a profile. They remain explicitly unassigned replays.\n    if (s.profile !== this.expectedProfile && !(s.profile === \"unknown\" && s.replay)) throw Error(`The local driver reports ${s.profile}; this application expects ${this.expectedProfile}`);\n    const key = `${s.session}:${s.frame}:${s.profile}:${s.replay}:${[\"acquiring\", \"reconstructing\"].includes(s.phase)}`;\n    if (s.frame === null || key === this.previous) return { status: s };\n    const image = await this.request(`${this.origin}/image/${s.session}/${s.frame}`, options);\n    const data = await boundedResponse(image, MAX_PREVIEW_BYTES), dimensions = pngDimensions(data);\n    signal.throwIfAborted(); this.previous = key;\n    return { status: s, frame: { format: \"odb.video.frame/1\", encoding: \"image/png\", data, ...dimensions,\n      sequence: s.frame, session: String(s.session), received_at: Date.now(), timebase: \"host-receipt\", mode: s.replay ? \"replay\" : [\"acquiring\", \"reconstructing\"].includes(s.phase) ? \"live\" : \"snapshot\", profile: s.profile, calibrated: false } };\n  }\n}\n"
  },
  "behavior": "GET-only polling of /status and /image/<session>/<frame> on an explicitly selected loopback bridge. One frame in flight, bounded PNG dimensions and bytes. Known profiles must match. Unidentified recordings are labelled replay and never establish device compatibility. No acquisition, settings, USB transfers or calibrated measurement. Bridge address is runtime-only and excluded from compositions.",
  "ports": {
    "frames": {
      "direction": "out",
      "kind": "stream",
      "contract": "odb.video.frame/1"
    }
  },
  "parameters": {
    "profile": {
      "type": "string",
      "default": "convex-01"
    },
    "interval": {
      "type": "integer",
      "default": 250,
      "minimum": 100,
      "maximum": 10000
    }
  },
  "fixtures": [],
  "evidence": []
}