Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions TODO.client-work/08-neural-demo-island.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 08-neural-demo-island

Live neural inference demo on interscript.org: model picker with tier badges + sizes, progress bar during resolve, streaming output, low-confidence highlighting (11), cache/offline status

Status: implementing (2026-09-01).
5 changes: 5 additions & 0 deletions TODO.client-work/09-resumable-downloads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 09-resumable-downloads

Range-based resume for flaky networks: interrupted zip downloads continue from the received byte offset instead of restarting 250MB

Status: DONE (2026-09-01) (2026-09-01).
5 changes: 5 additions & 0 deletions TODO.client-work/10-api-batch-infer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 10-api-batch-infer

POST /v1/infer/batch on the API worker: N inputs per request, sequential Modal upstream, per-item error isolation

Status: implementing (2026-09-01).
5 changes: 5 additions & 0 deletions TODO.client-work/11-confidence-highlighting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 11-confidence-highlighting

Demo UI surfaces onConfidence gaps as output highlighting (low-confidence spans marked)

Status: implementing (2026-09-01).
5 changes: 5 additions & 0 deletions TODO.client-work/12-e3-browser-bench.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 12-e3-browser-bench

The browser benchmark cell (paper C): Playwright timing of the real demo page — load, cold/warm cache, decode latency on WASM

Status: implementing (2026-09-01).
47 changes: 36 additions & 11 deletions src/ml/imf/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,49 @@ async function evictStaleEntries(
}
}

/** Fetch with progress via a streamed body (TODO.client-work 03). */
/** Fetch with progress via a streamed body, resuming across dropped
* connections with Range requests (TODO.client-work 03/09): a flaky
* network continues from the received byte offset instead of
* restarting a 250MB artifact. */
async function fetchWithProgress(
url: string,
onProgress?: (fraction: number, bytes: number) => void,
): Promise<Uint8Array> {
if (!onProgress) return new Uint8Array(await (await fetch(url)).arrayBuffer())
const res = await fetch(url)
if (!res.ok || !res.body) throw new RegistryError(`fetch failed: ${url} -> ${res.status}`)
const total = Number(res.headers.get("content-length") ?? 0)
const reader = res.body.getReader()
const chunks: Uint8Array[] = []
let received = 0
for (;;) {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
received += value.length
onProgress(total > 0 ? received / total : 0, received)
let total = 0
for (let attempt = 0; attempt < 5; attempt++) {
let res: Response
try {
res = await fetch(url, received > 0 ? { headers: { range: `bytes=${received}-` } } : {})
} catch {
continue
}
if (!res.ok && res.status !== 206) throw new RegistryError(`fetch failed: ${url} -> ${res.status}`)
if (received === 0) total = Number(res.headers.get("content-length") ?? 0)
else if (res.status !== 206) {
// server ignored Range: restart cleanly rather than corrupt
chunks.length = 0
received = 0
total = Number(res.headers.get("content-length") ?? 0)
}
const reader = res.body?.getReader()
if (!reader) continue
let dropped = false
for (;;) {
try {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
received += value.length
onProgress(total > 0 ? Math.min(1, received / total) : 0, received)
} catch {
dropped = true
break
}
}
if (!dropped) break
}
const out = new Uint8Array(received)
let offset = 0
Expand Down
Loading