Download src/lib/task-title.ts from meljendy/proteinea: direct link, hf CLI and curl.
- Browser
- Download file 2.27 kB
-
https://huggingface.co/spaces/meljendy/proteinea/resolve/main/src/lib/task-title.ts
- Command line
-
hf download hf://spaces/meljendy/proteinea/src/lib/task-title.ts
-
curl -L -o task-title.ts https://huggingface.co/spaces/meljendy/proteinea/resolve/main/src/lib/task-title.ts
2.27 kB
| /** | |
| * Infer a short, pragmatic task title from the first user message. | |
| * | |
| * Biomni renames tasks within a few seconds of the first exchange — "Trastuzumab | |
| * HER2+ Breast Cancer Trials", "TCGA-BRCA RNA-seq Differential Expression", etc. | |
| * This is a small, heuristic version that runs instantly on the client: grab the | |
| * longest run of content words and compress them. | |
| */ | |
| const STOPWORDS = new Set([ | |
| "a","an","the","and","or","but","of","for","in","on","at","to","with","by","from", | |
| "is","are","was","were","be","being","been","have","has","had","do","does","did", | |
| "can","could","should","would","will","may","might","must","shall", | |
| "i","we","you","they","it","this","that","these","those","my","our","your","their", | |
| "please","kindly","help","me","us","need","want","like","get","give","tell","show", | |
| "using","based","above","below","about","into","than","then","as","so","also", | |
| "trial","run","pipeline","task","question","query", | |
| ]); | |
| /** Split to words, drop stopwords, keep scientific tokens (all-caps, digits, hyphens). */ | |
| function tokenize(text: string): string[] { | |
| return text | |
| .replace(/[\r\n]+/g, " ") | |
| .split(/[^A-Za-z0-9+\-./]+/) | |
| .filter(Boolean); | |
| } | |
| export function inferTaskTitle(firstUserMessage: string, maxChars = 48): string { | |
| if (!firstUserMessage) return "Untitled Session"; | |
| // Strip "TRIAL N (x):" style prefixes | |
| const stripped = firstUserMessage.replace(/^\s*TRIAL\s+\d+\s*\([^)]*\)\s*:\s*/i, "").trim(); | |
| const tokens = tokenize(stripped); | |
| const kept: string[] = []; | |
| for (const t of tokens) { | |
| const lower = t.toLowerCase(); | |
| if (STOPWORDS.has(lower)) continue; | |
| // Keep acronyms as-is; otherwise Title Case words | |
| const preserved = /^[A-Z0-9][A-Z0-9+./\-]+$/.test(t) | |
| ? t | |
| : t.charAt(0).toUpperCase() + t.slice(1).toLowerCase(); | |
| kept.push(preserved); | |
| if (kept.join(" ").length >= maxChars) break; | |
| } | |
| if (kept.length === 0) { | |
| // Fallback: first 6 raw words | |
| const fallback = stripped.split(/\s+/).slice(0, 6).join(" "); | |
| return truncate(fallback || "Untitled Session", maxChars); | |
| } | |
| return truncate(kept.join(" "), maxChars); | |
| } | |
| function truncate(s: string, max: number): string { | |
| return s.length <= max ? s : s.slice(0, max - 1).trimEnd() + "…"; | |
| } | |