@askalf/dario
Advanced tools
+27
-18
@@ -115,13 +115,14 @@ /** | ||
| if (state.buffer.length === 0) { | ||
| lines.push(' ' + brand('Hits') + dim(' — live request stream')); | ||
| lines.push(truncate(' ' + brand('Hits') + dim(' — live request stream'), w)); | ||
| lines.push(''); | ||
| if (state.connectionError) { | ||
| lines.push(' ' + fg('red', `SSE error: ${state.connectionError}`)); | ||
| lines.push(' ' + dim('Is `dario proxy` running? The stream reconnects automatically on the next mount.')); | ||
| // The error text is upstream-supplied and unbounded. | ||
| lines.push(truncate(' ' + fg('red', `SSE error: ${state.connectionError}`), w)); | ||
| lines.push(truncate(' ' + dim('Is `dario proxy` running? The stream reconnects automatically on the next mount.'), w)); | ||
| } | ||
| else if (!state.subscribed) { | ||
| lines.push(' ' + dim('Connecting to /analytics/stream …')); | ||
| lines.push(truncate(' ' + dim('Connecting to /analytics/stream …'), w)); | ||
| } | ||
| else { | ||
| lines.push(' ' + dim('Waiting for requests. Send one through dario to see it land here.')); | ||
| lines.push(truncate(' ' + dim('Waiting for requests. Send one through dario to see it land here.'), w)); | ||
| } | ||
@@ -140,17 +141,25 @@ return lines.join('\n'); | ||
| const colIn = 8, colOut = 7, colLat = 7, colStatus = 5; | ||
| lines.push(' ' + brand('Hits') + | ||
| dim(` ${state.buffer.length} buffered · ${state.subscribed ? fg('green', 'live') : fg('yellow', 'disconnected')}`)); | ||
| lines.push(truncate(' ' + brand('Hits') + | ||
| dim(` ${state.buffer.length} buffered · ${state.subscribed ? fg('green', 'live') : fg('yellow', 'disconnected')}`), w)); | ||
| // ── Overage-halt banner (v4.1, dario#288) ────────────────── | ||
| // Pinned at the top so it's always visible while scrolling the buffer. | ||
| // | ||
| // Both lines are ordered most-actionable-first and kept short enough | ||
| // to fit 80 columns, because a banner that wraps costs a second | ||
| // physical row and pushes the panel head off the top of the screen — | ||
| // and it wraps exactly when the user needs to read it. The account is | ||
| // last on line 1 so a narrow terminal clips the least-critical field; | ||
| // the resume instructions on line 2 fit outright. | ||
| if (state.halt) { | ||
| const since = formatTimestamp(state.halt.since); | ||
| const cooldown = formatRemaining(state.halt.cooldownUntil - Date.now()); | ||
| const line1 = ` ${fg('red', '⚠ HALTED')} ${state.halt.request.claim} detected at ${since} on ${state.halt.request.model} (account=${state.halt.request.account})`; | ||
| const line2 = ` ${dim('→ New /v1/messages requests return 503 until')} ${fg('cyan', 'R')} ${dim('here, or')} ${fg('cyan', 'dario resume')}${dim(' from any shell. Auto-resume in')} ${cooldown}${dim('.')}`; | ||
| lines.push(line1); | ||
| lines.push(line2); | ||
| const line1 = ` ${fg('red', '⚠ HALTED')} ${state.halt.request.claim} · ${since} · ${shortenModel(state.halt.request.model)} · ${dim(state.halt.request.account)}`; | ||
| const line2 = ` ${dim('→ 503 until')} ${fg('cyan', 'R')} ${dim('or')} ${fg('cyan', 'dario resume')} ${dim(`· auto-resume in ${cooldown}`)}`; | ||
| lines.push(truncate(line1, w)); | ||
| lines.push(truncate(line2, w)); | ||
| } | ||
| lines.push(''); | ||
| // Header row (aligned with data rows) | ||
| lines.push(' ' + dim(pad('time', colTime) + | ||
| // Header row — truncated to the same budget as the data rows below | ||
| // (`w - 2`) so the columns stay aligned when the terminal is narrow. | ||
| lines.push(truncate(' ' + dim(pad('time', colTime) + | ||
| pad('model', colModel) + | ||
@@ -160,3 +169,3 @@ pad('in', colIn) + | ||
| pad('lat', colLat) + | ||
| pad('st', colStatus))); | ||
| pad('st', colStatus)), w - 2)); | ||
| for (let i = startIdx; i < endIdx; i++) { | ||
@@ -191,5 +200,5 @@ const r = newestFirst[i]; | ||
| if (newestFirst.length > listRows) { | ||
| lines.push(' ' + dim(`${state.selectedIdx + 1} / ${newestFirst.length} ` + | ||
| lines.push(truncate(' ' + dim(`${state.selectedIdx + 1} / ${newestFirst.length} ` + | ||
| (startIdx > 0 ? '↑ more ' : '') + | ||
| (endIdx < newestFirst.length ? '↓ more' : ''))); | ||
| (endIdx < newestFirst.length ? '↓ more' : '')), w)); | ||
| } | ||
@@ -201,3 +210,3 @@ // Separator | ||
| const r = newestFirst[state.selectedIdx]; | ||
| lines.push(' ' + brand('Selected') + dim(` ${formatTime(r.timestamp)}`)); | ||
| lines.push(truncate(' ' + brand('Selected') + dim(` ${formatTime(r.timestamp)}`), w)); | ||
| lines.push(' ' + renderKvRow('Account', r.account, w - 4)); | ||
@@ -213,3 +222,3 @@ lines.push(' ' + renderKvRow('Model', r.model, w - 4)); | ||
| lines.push(''); | ||
| lines.push(' ' + dim('Use ↑↓ to select a request for details.')); | ||
| lines.push(truncate(' ' + dim('Use ↑↓ to select a request for details.'), w)); | ||
| } | ||
@@ -216,0 +225,0 @@ return lines.join('\n'); |
+1
-1
| { | ||
| "name": "@askalf/dario", | ||
| "version": "5.4.4", | ||
| "version": "5.4.5", | ||
| "description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1475177
0.05%28089
0.03%