feat: session status at a glance, file & image drop, live Ops Alerts (0.4.0)
build-deb / Lint, test, package (push) Successful in 1m51s
build-deb / Deploy to CT 126 (push) Successful in 3s
build-deb / Notify on failure (push) Skipped

- devdesk-state-hook (Claude UserPromptSubmit/PostToolUse/Notification/Stop/
  SessionStart/SessionEnd) records whether each session is working, waiting on
  you or idle; --list carries it. The sidebar shows it, the header shows the
  current session's state, and a pulsing "needs you" chip jumps to sessions
  waiting for input. Session refresh no longer depends on the sidebar being open.
- `devdesk attach --upload SESSION FILE BYTES` receives a file as base64
  terminal input (raw mode, exact length, size-checked, sanitised name) into
  /var/lib/devdesk/uploads/<session>/. The UI uploads dropped or pasted files and
  pastes the path into Claude, which attaches images itself.
- `devdesk alerts` / `--alerts`: firing and pending Grafana alert rules with
  severity, instances, summary and a link. The panel's "Ask Claude" types an
  investigation prompt into the current session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 19:26:06 -04:00
co-authored by Claude Opus 5.5
parent 531b640ae9
commit 03e4a49e78
14 changed files with 625 additions and 44 deletions
+67 -10
View File
@@ -211,6 +211,24 @@ body.dd-sidebar-open .dd-sidebar {
.dd-session-item.is-recent .dd-session-name { color: var(--text-secondary); font-weight: 400; }
.dd-session-item.is-dormant .dd-session-name { color: var(--text-secondary); }
.dd-session-item.is-waiting { border-color: rgba(255, 45, 85, 0.45); background: var(--accent-red-dim); }
.dd-session-item.is-waiting .dd-session-meta { color: var(--accent-red); }
.dd-session-item.is-working .dd-session-meta { color: var(--accent-amber); }
/* Header chips: current session's Claude state, and sessions needing you. */
.dd-state-chip { display: none; }
.dd-state-chip[data-state="working"] { display: inline-flex; color: var(--accent-amber); background: var(--accent-amber-dim); }
.dd-state-chip[data-state="waiting"] { display: inline-flex; color: var(--accent-red); background: var(--accent-red-dim); text-shadow: var(--glow-red); }
.dd-state-chip[data-state="idle"] { display: inline-flex; color: var(--accent-green); background: var(--accent-green-dim); }
.dd-attention {
display: none;
cursor: pointer;
font-family: var(--font-mono);
color: var(--accent-red);
background: var(--accent-red-dim);
animation: lt-pulse 1.6s ease-in-out infinite;
}
.dd-attention.is-active { display: inline-flex; }
.dd-session-actions {
display: flex;
@@ -275,24 +293,63 @@ body.dd-sidebar-open .dd-sidebar {
gap: var(--space-sm);
}
/* ---- stub widgets ------------------------------------------------------------ */
/* ---- ops alerts --------------------------------------------------------------- */
.dd-alert-count { margin-left: auto; }
.dd-alert-count:empty { display: none; }
.dd-alert-list { display: flex; flex-direction: column; gap: var(--space-sm); }
.dd-alert {
display: flex;
align-items: center;
gap: var(--space-sm);
flex-direction: column;
gap: 3px;
padding: 6px 8px;
border: 1px solid var(--border-dim);
border-left: 2px solid var(--accent-amber);
font-size: 0.72rem;
color: var(--text-secondary);
}
.dd-alert-text { flex: 1 1 auto; }
.dd-alert:has(.lt-chip-critical) { border-left-color: var(--accent-red); }
.dd-alert-head { display: flex; align-items: center; gap: var(--space-sm); min-width: 0; }
.dd-alert-name { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-alert-age { margin-left: auto; white-space: nowrap; }
.dd-alert-instances { overflow-wrap: anywhere; }
.dd-alert-summary { color: var(--text-secondary); }
.dd-alert .dd-ask { align-self: flex-start; margin-top: 2px; }
.dd-all-clear { display: flex; align-items: center; gap: var(--space-sm); color: var(--accent-green); font-size: 0.74rem; }
.dd-context-grid { margin-top: var(--space-sm); }
[data-state="stub"] .lt-section-body,
#widget-context[data-state="empty"] .lt-kv-grid,
#widget-repo[data-state="empty"] .lt-kv-grid { opacity: 0.6; }
[data-state="stub"] .lt-section-body { opacity: 0.75; }
.lt-status a { color: inherit; text-shadow: none; }
.dd-widget .lt-kv-val { overflow-wrap: anywhere; }
/* ---- file drop / upload ------------------------------------------------------ */
.dd-drop-overlay {
position: absolute;
inset: 0;
z-index: 6;
display: flex;
align-items: center;
justify-content: center;
border: 2px dashed var(--accent-cyan);
background: rgba(0, 212, 255, 0.08);
color: var(--accent-cyan);
font-size: 0.9rem;
pointer-events: none;
}
.dd-drop-overlay[hidden] { display: none; }
.dd-upload-status {
position: absolute;
right: 14px;
bottom: 16px;
z-index: 6;
max-width: 70%;
padding: 6px 10px;
border: 1px solid var(--accent-cyan-border);
background: var(--bg-secondary);
color: var(--text-secondary);
font-size: 0.72rem;
box-shadow: var(--box-glow-cyan);
overflow-wrap: anywhere;
}
.dd-upload-status[hidden] { display: none; }
.dd-upload-status.is-error { border-color: rgba(255, 45, 85, 0.5); color: var(--accent-red); }
/* ---- overlay ----------------------------------------------------------------- */
.dd-overlay {