Spaces:
Sleeping
Sleeping
Download scripts/mic_loop_support.mjs from jasonmdong/notepilot: direct link, hf CLI and curl.
- Browser
- Download file 4.29 kB
-
https://huggingface.co/spaces/jasonmdong/notepilot/resolve/main/scripts/mic_loop_support.mjs
- Command line
-
hf download hf://spaces/jasonmdong/notepilot/scripts/mic_loop_support.mjs
-
curl -L -o mic_loop_support.mjs https://huggingface.co/spaces/jasonmdong/notepilot/resolve/main/scripts/mic_loop_support.mjs
4.29 kB
| // Small CDP client and retry policy shared with the harness regression test. | |
| export function nextAttempt(index, position, attempt, maxRetries) { | |
| if (position > index) return { index: Math.max(index + 1, position), attempt: 0 }; | |
| if (attempt >= maxRetries) return { index: index + 1, attempt: 0, gaveUp: true }; | |
| // Never rewind to a lagging follower after giving up on an earlier event. | |
| return { index, attempt: attempt + 1, retry: true }; | |
| } | |
| // A retry is scheduled after the bounded wait, but a slow follower can commit | |
| // during the beat of grace before that retry is emitted. Re-read the tracker | |
| // immediately before dispatch so a stale retry cannot re-strike an event that | |
| // has already advanced. | |
| export function retryAlreadyCommitted(index, position) { | |
| return Number.isFinite(position) && position > index; | |
| } | |
| export function notePilotTarget(targets) { | |
| return targets.find(t => t.type === 'page' && /^http:\/\/(localhost|127\.0\.0\.1):8000\//.test(t.url)); | |
| } | |
| export function summariseRun(trace) { | |
| const attempts = trace.events.filter(e => e.type === 'input.testEvent'); | |
| const commits = trace.events.filter(e => e.type === 'follow.advance' && e.accepted !== false); | |
| const indices = new Set(attempts.map(e => e.index)); | |
| const onTime = new Set(), late = new Set(); | |
| const unmatched = []; | |
| const latencies = []; | |
| for (const c of commits) { | |
| const previous = attempts.filter(a => a.index === c.toIndex && a.t <= c.t); | |
| const a = previous.at(-1); | |
| if (!a) { unmatched.push({index:c.toIndex,t:c.t,reason:'no prior attempt for this score event'}); continue; } | |
| const lag = c.t - a.t; | |
| if (lag <= 450) { onTime.add(c.toIndex); latencies.push(lag); } | |
| else late.add(c.toIndex); | |
| } | |
| return { | |
| attemptedEvents:indices.size, attempts:attempts.length, | |
| detectedWithin450ms:onTime.size, | |
| detectedOnlyLate:[...late].filter(i => !onTime.has(i)).length, | |
| undetected:[...indices].filter(i => !onTime.has(i) && !late.has(i)), | |
| commitsWithoutPriorAttempt:unmatched, | |
| retries:attempts.filter(a => a.attempt > 0).length, | |
| autoSkips:trace.events.filter(e => e.type === 'skip' && e.reason === 'auto') | |
| .map(e => ({index:e.fromIndex,heldMs:e.heldMs,dueHeldMs:e.dueHeldMs})), | |
| medianDetectionMs:latencies.length ? latencies.sort((a,b)=>a-b)[Math.floor(latencies.length/2)] : null, | |
| invalid:trace.events.filter(e => e.type === 'test.invalid').map(e => e.reason), | |
| }; | |
| } | |
| export async function connectNotePilot(port = 9222) { | |
| const targets = await (await fetch(`http://127.0.0.1:${port}/json/list`, {signal:AbortSignal.timeout(5000)})).json(); | |
| const page = notePilotTarget(targets); | |
| if (!page) throw Error('No NotePilot tab found on localhost:8000'); | |
| const ws = new WebSocket(page.webSocketDebuggerUrl); | |
| await new Promise((resolve, reject) => { | |
| const timer = setTimeout(() => { ws.close(); reject(Error('CDP connection timed out')); }, 5000); | |
| ws.onopen = () => { clearTimeout(timer); resolve(); }; | |
| ws.onerror = () => { clearTimeout(timer); reject(Error('CDP connection failed')); }; | |
| }); | |
| let id = 0; | |
| const pending = new Map(); | |
| ws.onmessage = e => { | |
| const msg = JSON.parse(e.data), call = pending.get(msg.id); | |
| if (!call) return; | |
| pending.delete(msg.id); clearTimeout(call.timer); | |
| if (msg.error) call.reject(Error(JSON.stringify(msg.error))); else call.resolve(msg.result); | |
| }; | |
| ws.onclose = () => { | |
| for (const call of pending.values()) { clearTimeout(call.timer); call.reject(Error('CDP closed')); } | |
| pending.clear(); | |
| }; | |
| const send = (method, params = {}, timeout = 15000) => new Promise((resolve, reject) => { | |
| const requestId = ++id; | |
| const timer = setTimeout(() => { pending.delete(requestId); reject(Error(`CDP timed out: ${method}`)); }, timeout); | |
| pending.set(requestId, {resolve, reject, timer}); | |
| ws.send(JSON.stringify({id:requestId, method, params})); | |
| }); | |
| const evaluate = async (expression, timeout = 15000) => { | |
| const r = await send('Runtime.evaluate', {expression, awaitPromise:true, returnByValue:true, userGesture:true}, timeout); | |
| if (r.exceptionDetails) throw Error(r.exceptionDetails.exception?.description || JSON.stringify(r.exceptionDetails)); | |
| return r.result.value; | |
| }; | |
| return {send, evaluate, close: () => ws.close()}; | |
| } | |