← Files Biological Sequence & Alignment ViewerARCHIVED FILE

src/workspace-session-protocol.ts

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

↓ Download file

import { z } from "zod";

import { SEQUENCE_VIEWER_LIMITS, utf8ByteLength } from "./runtime-contract";
import { isSafeWorkspaceProvenancePath } from "./viewer-operations";
import { isSafeWorkspaceBrowserChildName } from "./workspace-browser-protocol";

export const SEQUENCE_LIST_WORKSPACE_SESSIONS_TOOL_NAME =
  "sequence.list_workspace_sessions";
export const SEQUENCE_RESTORE_WORKSPACE_SESSION_TOOL_NAME =
  "sequence.restore_workspace_session";

const uuidSchema = z.string().uuid();
const sha256Schema = z.string().regex(/^[a-f0-9]{64}$/u);
const safeWorkspacePathSchema = z
  .string()
  .min(1)
  .max(4_096)
  .refine(isSafeWorkspaceProvenancePath);
const safeNameSchema = z
  .string()
  .min(1)
  .max(255)
  .refine(isSafeWorkspaceBrowserChildName);

export const sequenceWorkspaceSessionDependencySchema = z
  .object({
    format: z.string().min(1).max(100),
    kind: z.enum(["artifact", "track"]),
    name: safeNameSchema,
    required: z.boolean(),
    sha256: sha256Schema,
    size: z.number().int().nonnegative(),
    workspacePath: safeWorkspacePathSchema,
  })
  .strict();

export const sequenceWorkspaceSessionManifestSchema = z
  .object({
    createdAt: z.string().datetime({ offset: true }),
    dependencies: z
      .array(sequenceWorkspaceSessionDependencySchema)
      .max(SEQUENCE_VIEWER_LIMITS.workspace.maxSessionDependencies),
    mode: z.enum(["alignment", "sequence"]),
    payload: z
      .string()
      .min(1)
      .refine(
        (value) =>
          utf8ByteLength(value) <= SEQUENCE_VIEWER_LIMITS.session.maxSessionBytes,
        "Workspace session payload exceeds the bounded session size.",
      ),
    payloadSha256: sha256Schema,
    plugin: z
      .object({
        name: z.literal("sequence-viewer"),
        version: z.string().regex(/^\d+\.\d+\.\d+$/u),
      })
      .strict(),
    schemaVersion: z.literal(1),
    source: z
      .object({
        sha256: sha256Schema,
        size: z.number().int().nonnegative(),
        workspacePath: safeWorkspacePathSchema,
      })
      .strict(),
    version: z.literal(1),
  })
  .strict();

export const sequenceListWorkspaceSessionsInputSchema = z
  .object({ sessionId: uuidSchema })
  .strict();

const dependencyStatusSchema = z
  .object({
    kind: z.enum(["artifact", "track"]),
    name: safeNameSchema,
    required: z.boolean(),
    status: z.enum(["changed", "matched", "missing", "unverified"]),
    workspacePath: safeWorkspacePathSchema,
  })
  .strict();

const workspaceSessionCandidateSchema = z
  .object({
    candidateId: uuidSchema,
    createdAt: z.string().datetime({ offset: true }),
    dependencies: z
      .array(dependencyStatusSchema)
      .max(SEQUENCE_VIEWER_LIMITS.workspace.maxSessionDependencies),
    mode: z.enum(["alignment", "sequence"]),
    name: safeNameSchema,
    sourceStatus: z.enum(["matched", "verification-required"]),
    workspacePath: safeWorkspacePathSchema,
  })
  .strict();

export const sequenceListWorkspaceSessionsResultSchema = z
  .object({
    candidates: z
      .array(workspaceSessionCandidateSchema)
      .max(SEQUENCE_VIEWER_LIMITS.workspace.maxSessionCandidates),
    omittedCandidates: z.number().int().nonnegative(),
  })
  .strict();

export const sequenceRestoreWorkspaceSessionInputSchema = z
  .object({ candidateId: uuidSchema, sessionId: uuidSchema })
  .strict();

export const sequenceRestoreWorkspaceSessionResultSchema = z
  .object({
    dependencies: z
      .array(dependencyStatusSchema)
      .max(SEQUENCE_VIEWER_LIMITS.workspace.maxSessionDependencies),
    mode: z.enum(["alignment", "sequence"]),
    name: safeNameSchema,
    restored: z.literal(true),
    workspacePath: safeWorkspacePathSchema,
  })
  .strict();

export type SequenceWorkspaceSessionManifest = z.infer<
  typeof sequenceWorkspaceSessionManifestSchema
>;
export type SequenceListWorkspaceSessionsInput = z.infer<
  typeof sequenceListWorkspaceSessionsInputSchema
>;
export type SequenceListWorkspaceSessionsResult = z.infer<
  typeof sequenceListWorkspaceSessionsResultSchema
>;
export type SequenceRestoreWorkspaceSessionInput = z.infer<
  typeof sequenceRestoreWorkspaceSessionInputSchema
>;
export type SequenceRestoreWorkspaceSessionResult = z.infer<
  typeof sequenceRestoreWorkspaceSessionResultSchema
>;

SHA-256: 72dcc8cbc27f35b03a266ebacc4ff7b53d42c7a62cacf8ba07770e02cf1ef121