Download src/lib/sample-artifacts.ts from meljendy/proteinea: direct link, hf CLI and curl.
- Browser
- Download file 6.7 kB
-
https://huggingface.co/spaces/meljendy/proteinea/resolve/main/src/lib/sample-artifacts.ts
- Command line
-
hf download hf://spaces/meljendy/proteinea/src/lib/sample-artifacts.ts
-
curl -L -o sample-artifacts.ts https://huggingface.co/spaces/meljendy/proteinea/resolve/main/src/lib/sample-artifacts.ts
6.7 kB
| /** | |
| * Sample artifact builders — emitted by the demo engine at the end of a plan | |
| * execution (plus on-demand for phylo/MSA/structure prompts). | |
| * | |
| * Two shapes: | |
| * 1) Synthetic JSON/CSV artifacts embedded as `data:` URLs so downloads work | |
| * fully client-side without a backend round-trip. This mirrors the existing | |
| * test fixture at `.data/tasks/sess_b2c176cf8e6b.json`. | |
| * 2) Public sample files (`/sample-data/*.{nwk,fasta,pdb}`) referenced by URL. | |
| * Agent A owns those viewers; we just point at them with realistic sizes. | |
| */ | |
| import type { Artifact, PlanProposal, TraceEntry } from "./types"; | |
| // ---- utilities ------------------------------------------------------------- | |
| function encodeBase64(s: string): string { | |
| if (typeof window === "undefined") { | |
| return Buffer.from(s, "utf8").toString("base64"); | |
| } | |
| return btoa(unescape(encodeURIComponent(s))); | |
| } | |
| function dataUrl(mime: string, content: string): string { | |
| return `data:${mime};base64,${encodeBase64(content)}`; | |
| } | |
| function newId(): string { | |
| return "art-" + Math.random().toString(36).slice(2, 10); | |
| } | |
| function utf8Bytes(s: string): number { | |
| if (typeof TextEncoder !== "undefined") { | |
| return new TextEncoder().encode(s).length; | |
| } | |
| return Buffer.byteLength(s, "utf8"); | |
| } | |
| // ---- synthetic artifact builders ------------------------------------------ | |
| export interface DesignBriefInput { | |
| target: string; | |
| indication?: string; | |
| mechanism?: string; | |
| format?: string; | |
| epitope?: string; | |
| affinity?: string; | |
| species?: string; | |
| developability?: string; | |
| route?: string; | |
| competition?: string; | |
| seed?: string; | |
| scale?: string; | |
| } | |
| export function buildDesignBriefJson(brief: DesignBriefInput): string { | |
| const payload = { | |
| schema: "proteinea.design_brief/v1", | |
| generated_at: new Date().toISOString(), | |
| target: brief.target, | |
| indication: brief.indication || null, | |
| mechanism: brief.mechanism || null, | |
| format: brief.format || "VHH", | |
| epitope: brief.epitope || "no preference", | |
| affinity_goal: brief.affinity || null, | |
| species_cross_reactivity: brief.species || null, | |
| developability: brief.developability || null, | |
| route_of_administration: brief.route || null, | |
| competitive_landscape: brief.competition || null, | |
| starting_point: brief.seed || "de novo", | |
| design_count: parseInt(brief.scale || "50", 10) || 50, | |
| }; | |
| return JSON.stringify(payload, null, 2); | |
| } | |
| export function buildPipelinePlanJson(plan: PlanProposal): string { | |
| const payload = { | |
| schema: "proteinea.pipeline_plan/v1", | |
| generated_at: new Date().toISOString(), | |
| title: plan.title, | |
| steps: plan.steps.map((s, i) => ({ | |
| index: i + 1, | |
| label: s.label, | |
| tools: s.tools, | |
| })), | |
| }; | |
| return JSON.stringify(payload, null, 2); | |
| } | |
| export function buildExecutionTraceJson(trace: TraceEntry[]): string { | |
| const payload = { | |
| schema: "proteinea.execution_trace/v1", | |
| generated_at: new Date().toISOString(), | |
| event_count: trace.length, | |
| events: trace, | |
| }; | |
| return JSON.stringify(payload, null, 2); | |
| } | |
| export function buildTopDesignsCsv(n = 10): string { | |
| const aa = "ACDEFGHIKLMNPQRSTVWY"; | |
| const rows: string[] = [ | |
| "rank,design_id,cdr_h3,length,iPAE,pLDDT,affinity_nM,consensus_score", | |
| ]; | |
| for (let i = 0; i < n; i++) { | |
| const id = `d${String(i + 1).padStart(3, "0")}`; | |
| const len = 14 + Math.floor(Math.random() * 8); | |
| let cdr = ""; | |
| for (let j = 0; j < len; j++) cdr += aa[Math.floor(Math.random() * aa.length)]; | |
| const iPAE = (5 + Math.random() * 5).toFixed(2); | |
| const pLDDT = (82 + Math.random() * 12).toFixed(1); | |
| const kd = (0.3 + Math.random() * 40).toFixed(2); | |
| const score = (0.55 + Math.random() * 0.4).toFixed(3); | |
| rows.push(`${i + 1},${id},${cdr},${len},${iPAE},${pLDDT},${kd},${score}`); | |
| } | |
| return rows.join("\n"); | |
| } | |
| // ---- artifact constructors ------------------------------------------------- | |
| export function makeJsonArtifact(name: string, content: string): Artifact { | |
| return { | |
| id: newId(), | |
| name, | |
| bytes: utf8Bytes(content), | |
| mime: "application/json", | |
| url: dataUrl("application/json", content), | |
| createdAt: Date.now(), | |
| }; | |
| } | |
| export function makeCsvArtifact(name: string, content: string): Artifact { | |
| return { | |
| id: newId(), | |
| name, | |
| bytes: utf8Bytes(content), | |
| mime: "text/csv", | |
| url: dataUrl("text/csv", content), | |
| createdAt: Date.now(), | |
| }; | |
| } | |
| // ---- public sample-data artifacts (Agent A owns the files) ----------------- | |
| export function makePhyloTreeArtifact(): Artifact { | |
| return { | |
| id: newId(), | |
| name: "spike.nwk", | |
| bytes: 4096, | |
| mime: "text/x-nh", | |
| url: "/sample-data/spike.nwk", | |
| createdAt: Date.now(), | |
| }; | |
| } | |
| export function makeMsaArtifact(): Artifact { | |
| return { | |
| id: newId(), | |
| name: "igg-fc.fasta", | |
| bytes: 8192, | |
| mime: "text/x-fasta", | |
| url: "/sample-data/igg-fc.fasta", | |
| createdAt: Date.now(), | |
| }; | |
| } | |
| export function makeStructureArtifact(): Artifact { | |
| return { | |
| id: newId(), | |
| name: "her2-1n8z-mini.pdb", | |
| bytes: 24576, | |
| mime: "chemical/x-pdb", | |
| url: "/sample-data/her2-1n8z-mini.pdb", | |
| createdAt: Date.now(), | |
| }; | |
| } | |
| /** | |
| * Classify a raw user prompt for which sample-data viewer(s) to surface. | |
| * Keyword-based; matches are non-exclusive. | |
| */ | |
| export function detectSampleDataHints(msg: string): { | |
| phylo: boolean; | |
| msa: boolean; | |
| structure: boolean; | |
| } { | |
| const m = msg.toLowerCase(); | |
| return { | |
| phylo: | |
| m.includes("phylogen") || | |
| m.includes("tree") || | |
| m.includes(".nwk") || | |
| m.includes("newick") || | |
| m.includes("clade"), | |
| msa: | |
| m.includes("msa") || | |
| m.includes("alignment") || | |
| m.includes("multiple sequence") || | |
| m.includes("fasta") || | |
| m.includes("conservation"), | |
| structure: | |
| m.includes("structure") || | |
| m.includes("pdb") || | |
| m.includes("crystal") || | |
| m.includes("cryo-em") || | |
| m.includes("cryoem") || | |
| m.includes("3d structure"), | |
| }; | |
| } | |
| // ---- KB topic catalog ------------------------------------------------------ | |
| export interface KbTopic { | |
| name: string; | |
| ms: number; | |
| } | |
| /** | |
| * Deterministic-ish KB topics we "load" before planning. Timings are realistic | |
| * (60-300ms) and slightly randomized so no two plan previews look identical. | |
| */ | |
| export function buildKbTopics(): KbTopic[] { | |
| const jitter = (base: number, spread: number) => | |
| Math.round(base + (Math.random() - 0.5) * spread); | |
| return [ | |
| { name: "antibody design best practices", ms: jitter(150, 60) }, | |
| { name: "benchmark catalog", ms: jitter(80, 40) }, | |
| { name: "target intelligence", ms: jitter(120, 60) }, | |
| { name: "developability heuristics", ms: jitter(95, 40) }, | |
| ]; | |
| } | |