← Files Biological Sequence & Alignment ViewerARCHIVED FILE

src/indexed-sequence-envelope.ts

5.93 KB · Sep 30, 2026 · 23:01 UTC

↓ Download file

import { z } from "zod";

import { SEQUENCE_VIEWER_LIMITS, utf8ByteLength } from "./runtime-contract";
import type { SequenceDocument } from "./sequence/types";

export const INDEXED_SEQUENCE_ENVELOPE_PREFIX =
  "OPENAI_SEQUENCE_VIEWER_INDEXED_V1\n";

const classificationSchema = z
  .object({
    alignment: z.unknown().nullable(),
    confidence: z.enum(["high", "low", "medium"]),
    evidence: z.array(z.string().max(2_000)).max(100),
    kind: z.enum([
      "annotated-sequence",
      "chromatogram",
      "fastq",
      "multiple-sequence-alignment",
      "sequence-collection",
      "single-sequence",
      "unknown",
    ]),
    molecule: z.enum([
      "dna",
      "nucleic-acid-ambiguous",
      "protein",
      "rna",
      "unknown",
    ]),
    suggestedViewer: z.enum(["msa", "raw", "sequence"]),
  })
  .strict();
const qualitySchema = z
  .object({
    ascii: z.string(),
    phred: z.array(z.number().int().min(0).max(93)),
  })
  .strict();
const recordSchema = z
  .object({
    description: z.string().max(10_000).optional(),
    features: z.array(z.never()).max(0),
    id: z.string().min(1).max(2_000),
    length: z.number().int().nonnegative(),
    metadata: z.record(z.string(), z.union([z.string(), z.array(z.string())])),
    molecule: z.enum([
      "dna",
      "nucleic-acid-ambiguous",
      "protein",
      "rna",
      "unknown",
    ]),
    quality: qualitySchema.optional(),
    sequence: z.string(),
    sourceLabel: z.string().min(1).max(2_000),
    topology: z.enum(["circular", "linear", "unknown"]).optional(),
  })
  .strict();
const warningSchema = z
  .object({
    code: z.string().min(1).max(200),
    column: z.number().int().positive().optional(),
    line: z.number().int().positive().optional(),
    message: z.string().min(1).max(10_000),
    severity: z.enum(["error", "info", "warning"]),
  })
  .strict();
const fastqSummarySchema = z
  .object({
    gcFraction: z.number().min(0).max(1),
    meanQuality: z.number().nonnegative(),
    meanReadLength: z.number().nonnegative(),
    nFraction: z.number().min(0).max(1),
    q20Fraction: z.number().min(0).max(1),
    q30Fraction: z.number().min(0).max(1),
    qualityEncoding: z.literal("phred+33-assumed"),
    readCount: z.number().int().nonnegative(),
    readLengthMax: z.number().int().nonnegative(),
    readLengthMin: z.number().int().nonnegative(),
    totalBases: z.number().int().nonnegative(),
  })
  .strict();
const indexedDocumentSchema = z
  .object({
    classification: classificationSchema,
    fastqSummary: fastqSummarySchema.optional(),
    fileName: z.string().max(2_000).optional(),
    format: z.enum(["fasta", "fastq"]),
    kind: z.enum(["fastq", "sequence-collection", "single-sequence"]),
    recordInventory: z
      .object({
        materializedCount: z.number().int().nonnegative(),
        totalCount: z.number().int().nonnegative(),
        truncated: z.boolean(),
      })
      .strict(),
    records: z
      .array(recordSchema)
      .max(SEQUENCE_VIEWER_LIMITS.input.maxSequenceRecords),
    warnings: z.array(warningSchema).max(1_000),
  })
  .strict();
const envelopeSchema = z
  .object({
    document: indexedDocumentSchema,
    index: z
      .object({
        complete: z.literal(true),
        compressed: z.boolean(),
        decodedBytes: z.number().int().nonnegative(),
        indexedRecordCount: z.number().int().nonnegative(),
        materializedBases: z.number().int().nonnegative(),
        materializedRecordCount: z.number().int().nonnegative(),
        sourceBytes: z.number().int().nonnegative(),
        sourceVersion: z.string().min(1).max(256),
      })
      .strict(),
    schemaVersion: z.literal(1),
  })
  .strict();

export type IndexedSequenceEnvelope = {
  document: SequenceDocument;
  index: z.infer<typeof envelopeSchema>["index"];
  schemaVersion: 1;
};

export function serializeIndexedSequenceEnvelope(
  envelope: IndexedSequenceEnvelope,
): string {
  const text = `${INDEXED_SEQUENCE_ENVELOPE_PREFIX}${JSON.stringify(envelope)}`;
  if (utf8ByteLength(text) > SEQUENCE_VIEWER_LIMITS.input.maxTextBytes) {
    throw new Error(
      "The indexed sequence preview exceeds the viewer transfer budget. Reduce the materialized cache size.",
    );
  }
  return text;
}

export function parseIndexedSequenceEnvelope(
  value: string,
): IndexedSequenceEnvelope | null {
  if (!value.startsWith(INDEXED_SEQUENCE_ENVELOPE_PREFIX)) return null;
  const parsed = envelopeSchema.parse(
    JSON.parse(value.slice(INDEXED_SEQUENCE_ENVELOPE_PREFIX.length)),
  );
  let materializedBases = 0;
  for (const record of parsed.document.records) {
    if (record.sequence.length !== record.length) {
      throw new Error(
        `Indexed record ${record.id} has inconsistent sequence length metadata.`,
      );
    }
    if (
      record.quality != null &&
      (record.quality.ascii.length !== record.length ||
        record.quality.phred.length !== record.length)
    ) {
      throw new Error(
        `Indexed FASTQ record ${record.id} has inconsistent quality length metadata.`,
      );
    }
    materializedBases += record.length;
  }
  if (
    materializedBases !== parsed.index.materializedBases ||
    parsed.document.records.length !== parsed.index.materializedRecordCount ||
    parsed.document.recordInventory.materializedCount !==
      parsed.document.records.length
  ) {
    throw new Error("Indexed sequence cache metadata is inconsistent.");
  }
  return parsed as IndexedSequenceEnvelope;
}

export function buildIndexedPreviewContents(
  document: SequenceDocument,
): string {
  if (document.format === "fastq") {
    return document.records
      .map(
        (record) =>
          `@${record.sourceLabel}${record.description == null ? "" : ` ${record.description}`}\n${record.sequence}\n+\n${record.quality?.ascii ?? "I".repeat(record.length)}`,
      )
      .join("\n");
  }
  return document.records
    .map(
      (record) =>
        `>${record.sourceLabel}${record.description == null ? "" : ` ${record.description}`}\n${record.sequence}`,
    )
    .join("\n");
}

SHA-256: 0efdeaa0f0646eb71fb0cc8ee724d6d779de6679474c45a98b0588823fcf5350