fix/dashboard-dead-screenshot-code #242
2 changed files with 17 additions and 29 deletions
|
|
@ -27,14 +27,10 @@ case "${SSH_ORIGINAL_COMMAND:-}" in
|
|||
;;
|
||||
"report-task-cost")
|
||||
# Read TaskCostSummary JSON from stdin, INSERT into mother_hive.task_costs.
|
||||
# Input: {"node_hostname":"debby","task_id":"abc","provider":"deepseek",
|
||||
# "model":"deepseek-chat","input_tokens":150,"output_tokens":80,
|
||||
# "cache_read_tokens":200,"cache_write_tokens":50,
|
||||
# "cost_usd":0.0042,"success":true,
|
||||
# "proof_text":"{\"agent\":\"zot\",\"state\":\"Done\",\"tokens_in\":150}",
|
||||
# "screenshot_uuid":"a1b2c3d4e5f6",
|
||||
# "finished_at":"2026-06-27T12:00:00Z"}
|
||||
psql -d mother_hive -tA -v ON_ERROR_STOP=1 <<'PSQL'
|
||||
# Uses psql variable interpolation (no pg_read_file — works with non-superuser).
|
||||
# Input: {"node_hostname":"debby","task_id":"abc",...}
|
||||
_json=$(cat)
|
||||
psql -d mother_hive -tA -v ON_ERROR_STOP=1 -v json_input="$_json" <<'PSQL'
|
||||
INSERT INTO task_costs (node_id, task_id, provider, model,
|
||||
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
||||
cost_usd, success, proof_text, screenshot_uuid, finished_at)
|
||||
|
|
@ -52,7 +48,7 @@ SELECT
|
|||
NULLIF(j->>'proof_text', ''),
|
||||
NULLIF(j->>'screenshot_uuid', ''),
|
||||
COALESCE((j->>'finished_at')::TIMESTAMPTZ, now())
|
||||
FROM (SELECT (pg_read_file('/dev/stdin')::JSONB) AS j) AS _;
|
||||
FROM (SELECT (:'json_input'::JSONB) AS j) AS _;
|
||||
PSQL
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -190,7 +190,6 @@ h1 .dot{display:inline-block; width:8px; height:8px; border-radius:50%; margin-r
|
|||
<div class="lightbox" id="lightbox">
|
||||
<button class="lightbox-close">Esc to close</button>
|
||||
<div class="lightbox-meta" id="lightbox-meta"></div>
|
||||
<img id="lb-img" src="" alt="screenshot proof" style="display:none">
|
||||
<pre id="lb-text"></pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -306,9 +305,10 @@ function renderCard(t) {
|
|||
const total = (t.input_tokens||0) + (t.cache_read_tokens||0);
|
||||
const cachePct = total > 0 ? Math.round((t.cache_read_tokens||0) / total * 100) : 0;
|
||||
const freshPct = 100 - cachePct;
|
||||
const hasProofText = !!t.proof_text;
|
||||
const hasScreenshot = !!t.screenshot_uuid;
|
||||
const hasProof = hasProofText || hasScreenshot;
|
||||
// Only proof_text exists — daemon captures glasspane state at task exit.
|
||||
// screenshot_uuid is a schema column for future visual capture, never
|
||||
// populated by the current daemon (no screenshot.rs module on main).
|
||||
const hasProof = !!t.proof_text;
|
||||
const cls = hasProof ? 'card has-proof' : 'card';
|
||||
const onClick = hasProof
|
||||
? `onclick="openProof(this,'${esc(t.task_id||'')}')"`
|
||||
|
|
@ -327,7 +327,7 @@ function renderCard(t) {
|
|||
<div class="card-tokens">${fmtTokens(t.input_tokens||0)} in · ${fmtTokens(t.output_tokens||0)} out
|
||||
${cachePct>0?` · ${cachePct}% cache` : ''}
|
||||
</div>
|
||||
${hasScreenshot ? '<div class="card-proof-badge">▸ screenshot</div>' : hasProofText ? '<div class="card-proof-badge">▸ text</div>' : ''}
|
||||
${hasProof ? '<div class="card-proof-badge">▸ proof</div>' : ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
|
@ -336,24 +336,16 @@ function openProof(_el, taskId) {
|
|||
const t = (DATA.tasks || []).find(t => t.task_id === taskId);
|
||||
const lb = document.getElementById('lightbox');
|
||||
const meta = document.getElementById('lightbox-meta');
|
||||
const img = document.getElementById('lb-img');
|
||||
const pre = document.getElementById('lb-text');
|
||||
meta.innerHTML = `<strong>${esc(taskId)}</strong> ${esc(t?.provider||'')} · $${(t?.cost_usd||0).toFixed(4)}`;
|
||||
|
||||
// Hide both, then show the appropriate one.
|
||||
img.style.display = 'none';
|
||||
pre.style.display = 'none';
|
||||
|
||||
if (t?.screenshot_uuid) {
|
||||
img.src = `../screenshots/${t.screenshot_uuid}.png`;
|
||||
img.style.display = 'block';
|
||||
} else if (t?.proof_text) {
|
||||
let display;
|
||||
try { display = JSON.stringify(JSON.parse(t.proof_text), null, 2); }
|
||||
catch(_) { display = t.proof_text; }
|
||||
pre.textContent = display;
|
||||
pre.style.display = 'block';
|
||||
}
|
||||
// Proof is always inline text (glasspane state JSON).
|
||||
const raw = t?.proof_text || '{}';
|
||||
let display;
|
||||
try { display = JSON.stringify(JSON.parse(raw), null, 2); }
|
||||
catch(_) { display = raw; }
|
||||
pre.textContent = display;
|
||||
pre.style.display = 'block';
|
||||
lb.classList.add('open');
|
||||
}
|
||||
function closeLb() { document.getElementById('lightbox').classList.remove('open'); }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue