Spaces:
Running
Running
Agent Manager
terminal ⇄ conversation: one switch, in the bottom bar, and a better answer rule
a5d1eab | /* The conversation grammar (docs/conversation-view.md §4.3), shared by the | |
| Overview card and the pane's RENDER mode. App tokens only — --panel, --border, | |
| --accent, --muted, --font-mono. Nothing terminal-flavoured: no --term-bg, no | |
| uppercase role pills, no per-row chips. */ | |
| /* ---------- one exchange ---------- */ | |
| /* padding-left is the gutter the prompt's ❯ hangs into. Everything else — | |
| answer, work, fold control — starts at the content edge, so the arrow is the | |
| only mark outside the column and turns are findable while scrolling. */ | |
| .cx { display: flex; flex-direction: column; gap: 7px; min-width: 0; padding: 2px 0 2px 16px; } | |
| .cx.dim { opacity: 0.72; } | |
| .cx.dim .cx-answer { -webkit-line-clamp: 6; } | |
| /* one meta row, under the prompt: the work on the left, which turn on the right. | |
| Nothing sits above the prompt any more. */ | |
| .cx-meta { | |
| display: flex; align-items: baseline; gap: 8px; min-width: 0; | |
| font-size: 11px; color: var(--muted); | |
| } | |
| .cx-meta .spacer { flex: 1; min-width: 4px; } | |
| .cx-n, .cx-time, .cx-model { flex: none; font-variant-numeric: tabular-nums; } | |
| .cx-n { color: color-mix(in srgb, var(--accent) 65%, var(--muted)); } | |
| .cx-model { opacity: 0.8; } | |
| /* the prompt: a lightly tinted band between hairlines, with the chevron hanging | |
| in the gutter — what your eye lands on when scrolling a long conversation */ | |
| .cx-prompt { | |
| position: relative; margin-left: -16px; padding: 6px 10px 7px 16px; | |
| background: color-mix(in srgb, var(--accent) 7%, transparent); | |
| border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); | |
| font-size: 13px; font-weight: 550; color: var(--text); | |
| white-space: pre-wrap; overflow-wrap: break-word; | |
| } | |
| .cx-prompt::before { | |
| content: '❯'; position: absolute; left: 3px; top: 6px; | |
| font-family: var(--font-mono); color: var(--accent); font-weight: 700; | |
| } | |
| /* the fold control names what it hides — never a bare caret */ | |
| .cx-fold { | |
| display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; | |
| background: none; border: none; padding: 0; margin: 0; | |
| font: inherit; color: var(--muted); cursor: pointer; text-align: left; | |
| white-space: nowrap; overflow: hidden; text-overflow: ellipsis; | |
| } | |
| .cx-fold.flat { cursor: default; padding-left: 19px; } | |
| .cx-fold:hover { color: var(--text); } | |
| .cx-fold.on { color: var(--text); } | |
| .cx-fold .cs-tri { color: var(--muted); } | |
| .cx-fold.on .cs-tri { color: var(--accent); } | |
| /* ---------- the work: a rail of one-line steps ---------- */ | |
| .cx-steps { display: flex; flex-direction: column; padding: 1px 0; } | |
| .cs { min-width: 0; } | |
| .cs-head { | |
| display: flex; align-items: baseline; gap: 6px; width: 100%; min-width: 0; | |
| background: none; border: none; padding: 2px 4px 2px 0; margin: 0; | |
| font: inherit; font-size: 12px; color: var(--text); text-align: left; cursor: pointer; | |
| border-radius: var(--r-sm); | |
| } | |
| .cs-head:hover:not(:disabled) { background: color-mix(in srgb, var(--border) 45%, transparent); } | |
| .cs-head:disabled { cursor: default; } | |
| /* one column, two meanings: a tool reports its outcome, everything else offers | |
| to open. Greyed triangle = nothing more to see. */ | |
| .cs-tri, .cs-mark { | |
| flex: none; width: 13px; font-size: 10px; line-height: 1.6; | |
| font-family: var(--font-mono); color: var(--muted); | |
| } | |
| .cs-tri.off { color: color-mix(in srgb, var(--border-strong) 65%, transparent); } | |
| .cs-mark { font-size: 11px; } | |
| .cs-mark.ok { color: color-mix(in srgb, var(--ok, #4b9e6a) 85%, var(--muted)); } | |
| .cs-mark.bad { color: var(--danger, #c05353); } | |
| .cs-label { flex: none; font-size: 11px; font-weight: 600; color: var(--muted); } | |
| .cs.tools .cs-label { color: color-mix(in srgb, var(--accent) 70%, var(--muted)); } | |
| .cs.think .cs-label { color: #8b73c4; } | |
| .cs-detail { | |
| min-width: 0; flex: 1; font-size: 11.5px; color: var(--muted); | |
| white-space: nowrap; overflow: hidden; text-overflow: ellipsis; | |
| } | |
| /* expanded in place: same font, same colour, just no longer cut */ | |
| .cs-detail.full { white-space: pre-wrap; overflow: visible; text-overflow: clip; overflow-wrap: break-word; } | |
| .cs.note .cs-detail { color: var(--text); opacity: 0.78; } | |
| .cs-more { font-size: 10px; color: var(--muted); padding: 2px 0 0; } | |
| .cs-body { padding: 2px 0 6px 13px; } | |
| .cs-pre { | |
| white-space: pre-wrap; word-break: break-word; margin: 3px 0; padding: 6px 8px; | |
| background: var(--panel-2); border-radius: var(--r-sm); | |
| font-family: var(--font-mono); font-size: 11px; line-height: 1.5; | |
| max-height: 20rem; overflow: auto; | |
| } | |
| .cs-pre.out { color: var(--muted); } | |
| .cs-pre.out.bad { | |
| border: 1px solid color-mix(in srgb, var(--danger, #c05353) 55%, transparent); | |
| background: color-mix(in srgb, var(--danger, #c05353) 7%, var(--panel-2)); | |
| } | |
| .cs-pre.think { color: color-mix(in srgb, #8b73c4 70%, var(--text)); } | |
| .cs-img { max-width: 100%; max-height: 18rem; border-radius: var(--r-sm); } | |
| /* ---------- the answer: the one thing written for the reader ---------- */ | |
| .cx-answer { min-width: 0; } | |
| .markdown.cx-md { border: none; background: none; padding: 0; font-size: 12.5px; line-height: 1.55; } | |
| .cx-md > :first-child { margin-top: 0; } | |
| .cx-md > :last-child { margin-bottom: 0; } | |
| .cx-md pre { font-size: 11px; } | |
| .cx-note { font-size: 10.5px; color: var(--muted); padding-top: 4px; } | |
| .cx-running { | |
| display: flex; align-items: baseline; min-width: 0; font-size: 12.5px; color: var(--muted); | |
| } | |
| .cx-running-at { margin-left: 7px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.85; } | |
| .cx-running::before { | |
| content: '⠋'; display: inline-block; width: 1.2em; color: var(--accent); | |
| animation: ov-spin 0.9s steps(1) infinite; | |
| } | |
| /* ---------- card: history grows upward, one exchange at a time ---------- */ | |
| .cx-earlier { display: flex; align-items: center; justify-content: center; gap: 12px; font-size: 11px; } | |
| .cx-earlier-btn { | |
| background: none; border: none; padding: 0; font: inherit; font-size: 10.5px; | |
| color: var(--accent); cursor: pointer; | |
| } | |
| .cx-earlier-btn:hover { text-decoration: underline; } | |
| .cx-earlier-n { color: var(--muted); } | |
| .cx-earlier-note { color: var(--muted); } | |
| /* ---------- search hits ---------- */ | |
| mark.cx-hit { | |
| background: color-mix(in srgb, var(--accent) 28%, transparent); | |
| color: inherit; border-radius: 2px; padding: 0 1px; | |
| } | |
| mark.cx-hit.on { background: var(--accent); color: var(--panel); } | |
| /* ---------- RENDER mode: the same thing, stacked ---------- */ | |
| .cxv { display: flex; flex-direction: column; min-height: 0; } | |
| .cxv-bar { | |
| /* wraps at ANY width, not behind a media query: a pane is a container, and | |
| a 390px pane on a desktop never triggers a viewport media query */ | |
| display: flex; align-items: center; gap: 7px 8px; flex: none; flex-wrap: wrap; | |
| padding: 5px 9px; background: var(--panel-2); border-bottom: 1px solid var(--border); | |
| font-size: 10.5px; color: var(--muted); | |
| } | |
| .cxv-bar .spacer { flex: 1; } | |
| .cxv-chip { padding: 0 5px; border: 1px solid var(--border); border-radius: var(--r-sm); white-space: nowrap; } | |
| .cxv-count, .cxv-tok { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; } | |
| .cxv-tok { flex: 0 1 auto; } | |
| .cxv-mini { | |
| flex: none; white-space: nowrap; background: none; border: 1px solid transparent; border-radius: var(--r-sm); | |
| padding: 1px 5px; font: inherit; font-size: 10.5px; color: var(--muted); cursor: pointer; | |
| } | |
| .cxv-mini:hover { color: var(--text); border-color: var(--border); } | |
| .cxv-mini.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); } | |
| .cxv-nav { display: inline-flex; gap: 2px; } | |
| .cxv-hits { flex: none; font-variant-numeric: tabular-nums; color: var(--muted); } | |
| .cxv-search { | |
| flex: 1 1 7rem; width: auto; min-width: 4.5rem; max-width: 22rem; | |
| padding: 2px 6px; font: inherit; font-size: 11px; | |
| background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); | |
| } | |
| /* Panel background, and a column that FILLS the pane. A fixed reading width | |
| left a gutter of nothing on each side while the prompt band — which is what | |
| you scan for — still spanned the full width, so the two disagreed about where | |
| the conversation began. The pane is the measure: make it narrow and the | |
| conversation is narrow. */ | |
| .cxv-body { flex: 1; min-height: 0; overflow-y: auto; background: var(--panel); padding: 4px 14px 30px; } | |
| .cxv-col { display: flex; flex-direction: column; min-width: 0; } | |
| .cxv-msg { font-size: 11px; color: var(--muted); padding: 6px 0; } | |
| .cxv-foot { | |
| display: flex; align-items: center; gap: 8px; flex: none; | |
| padding: 5px 10px; border-top: 1px solid var(--border); background: var(--panel); | |
| color: var(--muted); font-size: 10.5px; overflow: hidden; | |
| } | |
| .cxv-foot .cxv-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |
| .cxv-foot .spacer { flex: 1; min-width: 4px; } | |
| /* the prompt band sticks: deep inside a long turn, the thing you want overhead | |
| is what you asked for — not a row of numbers */ | |
| .cxv-col .cx-prompt { | |
| position: sticky; top: 0; z-index: 2; | |
| background: color-mix(in srgb, var(--accent) 7%, var(--panel)); | |
| } | |
| /* ---------- phone ---------- */ | |
| @media (max-width: 720px) { | |
| .cxv-body { padding: 4px 8px 24px; } | |
| .cs-detail { font-size: 12px; } | |
| } | |
| /* ---------- conversation mode inside a session pane ---------- */ | |
| /* Drawn over the live terminal, which stays mounted underneath. */ | |
| .pane-render { position: absolute; inset: 0; z-index: 3; display: flex; background: var(--panel); } | |
| .pane-render > .cxv { flex: 1; min-width: 0; } | |
| .cxv-empty { margin: auto; padding: 24px; font-size: 11.5px; color: var(--muted); text-align: center; } | |
| .ph-modes { flex: none; } | |
| .ph-modes button { padding: 1px 7px; font-size: 9.5px; letter-spacing: 0.06em; } | |
| /* The overlay needs a positioned host; .term-host is otherwise plain. */ | |
| .slot .term-host { position: relative; } | |
| /* ---------- the card inline in the Overview list ---------- */ | |
| /* There it is a summary, not a room: one turn, the answer clamped. The window | |
| (and RENDER mode) is where a conversation gets to be long. */ | |
| .ov-card.ov-compact .cx-answer .markdown { | |
| display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; | |
| } | |
| /* ---------- an expanded tool call ---------- */ | |
| .cs-call { display: flex; flex-direction: column; } | |
| .ct-cap { font-size: 10.5px; color: var(--muted); padding: 3px 0 1px; overflow-wrap: anywhere; } | |
| .ct-note { font-size: 11px; color: var(--muted); padding: 1px 0 2px; } | |
| .cs-pre.ct-cmd { color: var(--text); } | |
| .cs-pre.ct-cmd::before { content: '$ '; color: var(--accent); } | |
| /* a before and an after — tinted, not barred */ | |
| .cs-pre.ct-was { background: color-mix(in srgb, var(--danger, #c05353) 8%, var(--panel-2)); } | |
| .cs-pre.ct-now { background: color-mix(in srgb, var(--ok, #4b9e6a) 9%, var(--panel-2)); } | |
| .ct-fields { margin: 3px 0 0; font-size: 11px; } | |
| .ct-row { display: grid; grid-template-columns: minmax(4.5rem, auto) 1fr; gap: 8px; padding: 1px 0; align-items: baseline; } | |
| .ct-row dt { color: var(--muted); } | |
| .ct-row dd { margin: 0; min-width: 0; color: var(--text); overflow-wrap: anywhere; } | |
| .ct-row dd .cs-pre { margin: 2px 0; } | |
| /* The reply line under a rendered conversation — the card's own composer, so | |
| answering an agent looks the same wherever you are reading it. */ | |
| .cxv-live { flex: none; padding: 6px 12px; border-top: 1px solid var(--border); background: var(--panel); } | |
| .cxv-note { flex: none; padding: 0 12px 6px; } | |