Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions webviews/src/agent-session/acpmux/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -248305,7 +248305,7 @@
"backgroundTasks.section.running": {"comment":"Agent pane Background tasks panel: the heading over the agents still running, followed by their count","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"translated","value":"Running"}},"ar":{"stringUnit":{"state":"needs_review","value":"قيد التشغيل"}},"bs":{"stringUnit":{"state":"needs_review","value":"U toku"}},"da":{"stringUnit":{"state":"needs_review","value":"Kører"}},"de":{"stringUnit":{"state":"needs_review","value":"Läuft"}},"es":{"stringUnit":{"state":"needs_review","value":"En curso"}},"fr":{"stringUnit":{"state":"needs_review","value":"En cours"}},"it":{"stringUnit":{"state":"needs_review","value":"In corso"}},"ja":{"stringUnit":{"state":"needs_review","value":"実行中"}},"km":{"stringUnit":{"state":"needs_review","value":"កំពុងដំណើរការ"}},"ko":{"stringUnit":{"state":"needs_review","value":"실행 중"}},"nb":{"stringUnit":{"state":"needs_review","value":"Kjører"}},"pl":{"stringUnit":{"state":"needs_review","value":"Uruchomione"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"Em execução"}},"ru":{"stringUnit":{"state":"needs_review","value":"Выполняются"}},"th":{"stringUnit":{"state":"needs_review","value":"กำลังทำงาน"}},"tr":{"stringUnit":{"state":"needs_review","value":"Çalışıyor"}},"uk":{"stringUnit":{"state":"needs_review","value":"Виконуються"}},"vi":{"stringUnit":{"state":"needs_review","value":"Đang chạy"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"运行中"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"執行中"}}}},
"backgroundTasks.section.finished": {"comment":"Agent pane Background tasks panel: the heading over the agents that ended, followed by their count","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"translated","value":"Finished"}},"ar":{"stringUnit":{"state":"needs_review","value":"منتهية"}},"bs":{"stringUnit":{"state":"needs_review","value":"Završeno"}},"da":{"stringUnit":{"state":"needs_review","value":"Færdige"}},"de":{"stringUnit":{"state":"needs_review","value":"Abgeschlossen"}},"es":{"stringUnit":{"state":"needs_review","value":"Terminadas"}},"fr":{"stringUnit":{"state":"needs_review","value":"Terminées"}},"it":{"stringUnit":{"state":"needs_review","value":"Completate"}},"ja":{"stringUnit":{"state":"needs_review","value":"完了"}},"km":{"stringUnit":{"state":"needs_review","value":"បានបញ្ចប់"}},"ko":{"stringUnit":{"state":"needs_review","value":"완료"}},"nb":{"stringUnit":{"state":"needs_review","value":"Fullført"}},"pl":{"stringUnit":{"state":"needs_review","value":"Zakończone"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"Concluídas"}},"ru":{"stringUnit":{"state":"needs_review","value":"Завершены"}},"th":{"stringUnit":{"state":"needs_review","value":"เสร็จแล้ว"}},"tr":{"stringUnit":{"state":"needs_review","value":"Tamamlandı"}},"uk":{"stringUnit":{"state":"needs_review","value":"Завершені"}},"vi":{"stringUnit":{"state":"needs_review","value":"Đã xong"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"已完成"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"已完成"}}}},
"turn.live.waitingOnSubagents": {
"comment": "Agent pane: the running turn's live line while the agent waits on subagents it started, {n} of them still running (Waiting on 2 subagents · 1h 24m total)",
"comment": "Agent pane: the running turn's live line while the agent waits on subagents it started, {n} of them still running (Waiting on 2 subagents · 1h 24m)",
"extractionState": "manual",
"localizations": {
"ar": {
Expand Down Expand Up @@ -248737,7 +248737,7 @@
}
},
"turn.live.writing": {
"comment": "Agent pane: the running turn's live line while the agent writes its reply (Writing · 2m total)",
"comment": "Agent pane: the running turn's live line while the agent writes its reply (Writing · 2m)",
"extractionState": "manual",
"localizations": {
"ar": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,37 @@ export default agentPaneEntry({
{ isWorking: true },
),
},
thinking: {
note: "Past the first step with nothing streaming and no own time: Thinking 1h 24m 7s, the turn's clock beside the word, no dot and no word total (#34866).",
snapshot: chat(
[
prompt(),
activity([tool("git log --oneline -5", "execute", "completed", { command: "git log --oneline -5" })], 3),
assistant("The signing step waits on a single runner.", 2),
],
{ isWorking: true },
),
},
"ran-command": {
note: "A command that just finished: its own 0s on its words, then the turn's clock after the dot, 4px each side and one dim tone, as in Leo's capture of the running-step line (2026-11-03: \"same here it's annoying to look at\").",
snapshot: chat(
[
prompt(),
plan(),
activity(
[
tool("cat /tmp/copy/message.md | head -30", "execute", "completed", {
command: "cat /tmp/copy/message.md | head -30",
startedAt: minutesAgo(0.2),
endedAt: minutesAgo(0.2) + 300,
}),
],
0.2,
),
],
{ isWorking: true },
),
},
writing: {
note: "The reply paused mid-stream a moment ago: Writing, with the turn's clock. (One that paused past 5 s reads Thinking again.)",
snapshot: chat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
cursor: default;
user-select: none;
}
.cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) > .cv-agent-activity__control {
color: var(--cv-text);
}
.cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) .cv-agent-activity__chevron {
/* The line's words keep their rest tone under the pointer and focus; only its chevron lifts, and
only on a line that is a button and opens something. A hover highlight covers only its own
control, never the whole row (Leo, 2026-11-03, on "2 background updates" brightening edge to
edge: "this thing appears/lights up on hover for no reason!?"; test
webviews/test/transcript-row-hover-scope.test.ts). */
/* A line whose chevron sits beside its button, not inside it (SubagentDoneLine.tsx). */
.cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) > button.cv-agent-activity__control .cv-agent-activity__chevron,
.cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))):has(> button.cv-agent-activity__control) > .cv-agent-activity__chevron {
color: var(--cv-text);
}
.cv-agent-activity__control {
Expand Down Expand Up @@ -52,8 +56,9 @@
flex: none;
}

/* A received message's line keeps one tone under the pointer and focus (conversation.css
`.cv-received__text`); other disclosure lines still lift. */
.cv-agent-activity-row.cv-disclosure__line:not(.cv-received > *):is(:hover, :active, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) {
/* A disclosure line (DisclosureRow: subagent, inbox and subsession lines) keeps its words at one
tone too; only its chevron lifts. A received message's line keeps even that steady
(conversation.css `.cv-received__text`). */
.cv-agent-activity-row.cv-disclosure__line:not(.cv-received > *):is(:hover, :active, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) .cv-disclosure__toggle > .cv-rotor {
color: var(--cv-text);
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,14 @@ test("subagent, messaging, and inbox activity use the shared row and agent tag",
expect(source("./TranscriptActivityRow.tsx")).toContain("<AgentTag name={name}");
});

test("the shared activity row lights its text on hover and press", () => {
test("the shared activity row lights only its chevron on hover and press, never its words", () => {
const css = source("./TranscriptActivityRow.css");
expect(css).toContain(".cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within)");
expect(css).toContain(
".cv-agent-activity-row:is(:hover, :active, :focus-visible, :focus-within):not(:has(.cv-agent-tag.is-open:is(:hover, :focus))) > button.cv-agent-activity__control .cv-agent-activity__chevron,",
);
expect(css).not.toMatch(/\) > \.cv-agent-activity__control \{/);
// A chevron beside the line's button lifts too (SubagentDoneLine.tsx).
expect(css).toContain(":has(> button.cv-agent-activity__control) > .cv-agent-activity__chevron {");
expect(source("./AgentTag.css")).toContain(":is(:hover, :focus-visible, :active)");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ test("background activity has one secondary tone and lifts on hover or focus; a
// The lift skips a row whose session link chip has the focus: the chip lights alone (AgentTag.css).
// A tool run's or group's summary line (`is-run`) is left out: it lights on hover only. A sent
// message's row keeps one steady tone, as a received one's does.
expect(css).toContain(".cv-tool:not(.is-run, .cv-sent):focus-within:not(:has(.cv-agent-tag.is-open:focus)),");
expect(css).toContain(".cv-tool:not(.is-run, .cv-sent, .cv-agent-activity__control):focus-within:not(:has(.cv-agent-tag.is-open:focus)),");
expect(css).not.toContain(".cv-tool:focus-within");
expect(css).toMatch(/\.cv-tool\.is-run:hover > \.cv-tool__text \{\s*color: var\(--cv-text\);/);
// A step row draws nothing more on hover (agent-pane-step-rows.test.ts).
expect(css).not.toMatch(/\.cv-tool:hover(,| \.cv-tool__(chevron|detail))/);
expect(css).toContain(".cv-worked:hover,");
// Only the "Worked for" button lifts; the live line has nothing behind it (transcript-row-hover-scope.test.ts).
expect(css).toContain("button.cv-worked:hover,");
// A received message keeps one tone under the pointer and focus (Leo, 2026-11-03).
expect(css).not.toMatch(/\.cv-received:is\(:hover/);
expect(css).toContain(".cv-received__text :is(.cv-md, .cv-h),");
Expand Down
25 changes: 19 additions & 6 deletions webviews/src/agent-session/acpmux/conversation/conversation.css
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,13 @@ pre.cv-math-source {
.cv-worked__total .cv-worked__time {
margin-inline: 0;
}
/* The live line's counts ("Ran cat x 0s · 39s · 1K tokens") read in one tone: every dot, time and
count at the time's dim tone, so no segment after the words reads brighter than another (Leo,
2026-11-03: "same here it's annoying to look at"; test webviews/test/transcript-row-hover-scope.test.ts).
Their 4px around each dot is `.cv-worked__count`'s (#34866). */
.cv-worked--live > .cv-worked__count:not(:has(.cv-worked__open)) {
color: var(--cv-text-dim);
}
/* A command in flight leads with the terminal glyph (WorkingFor.tsx), still, like the tool rows'. */
.cv-worked__glyph {
flex: none;
Expand Down Expand Up @@ -2434,14 +2441,19 @@ pre.cv-math-source {
run's or group's summary line lights on hover only (below), so its focus is left out. */
/* A message row keeps one steady tone (design/chat-transcript.md, as a received message's line):
a sent row the reader clicked never reads brighter than the ones around it (Leo, 2026-11-02, on
rows "in bright and dim text with no clear rule": "i also think this is quite weird looking"). */
.cv-tool:not(.is-run, .cv-sent):focus-within:not(:has(.cv-agent-tag.is-open:focus)),
.cv-worked:hover,
.cv-worked:focus-visible {
rows "in bright and dim text with no clear rule": "i also think this is quite weird looking").
An activity row (TranscriptActivityRow) is left out: a click leaves it focused, and its words
keep their rest tone (TranscriptActivityRow.css). */
/* Only the "Worked for" button lifts: the live line (`div.cv-worked`, Thinking.tsx) has nothing
behind it, so it never lights up under the pointer (Leo, 2026-11-03: "this thing appears/lights
up on hover for no reason!?"). */
.cv-tool:not(.is-run, .cv-sent, .cv-agent-activity__control):focus-within:not(:has(.cv-agent-tag.is-open:focus)),
button.cv-worked:hover,
button.cv-worked:focus-visible {
color: var(--cv-text);
}
.cv-tool:not(.is-run, .cv-sent):focus-within:not(:has(.cv-agent-tag.is-open:focus)) .cv-tool__chevron,
.cv-tool:not(.is-run, .cv-sent):focus-within:not(:has(.cv-agent-tag.is-open:focus)) .cv-tool__detail {
.cv-tool:not(.is-run, .cv-sent, .cv-agent-activity__control):focus-within:not(:has(.cv-agent-tag.is-open:focus)) .cv-tool__chevron,
.cv-tool:not(.is-run, .cv-sent, .cv-agent-activity__control):focus-within:not(:has(.cv-agent-tag.is-open:focus)) .cv-tool__detail {
color: var(--cv-text);
}
/* The running rows' mark (`Spinner`: compaction, tool groups, MCP calls, command and shell rows).
Expand Down Expand Up @@ -2653,6 +2665,7 @@ pre.cv-math-source {
}
.cv-worked:focus-visible,
.cv-tool.is-toggle:focus-visible,
.cv-agent-activity__control:focus-visible,
.cv-iconbtn:focus-visible {
/* Inset: the transcript row clips paint (`contain: paint`), so an outset ring would be cut. */
outline: 1.5px solid color-mix(in srgb, var(--agent-accent) 55%, transparent);
Expand Down
4 changes: 2 additions & 2 deletions webviews/src/agent-session/acpmux/conversation/turns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1328,7 +1328,7 @@ function codexLiveTurn(
// Past the streaming text's pause the line says the agent writes, never "Thinking".
line.liveState = "writing";
}
// Past the turn's first step its clock reads as the turn's whole time ("4m total"), so a long wait
// Past the turn's first step its clock reads as the turn's whole time ("2s · 4m" after a step's own time, else "4m" beside the label), so a long wait
// never reads as that long a think, call or step (Leo, 2026-11-03: "i think the "thinking"
// accounting is also off pretty frequently", on "Thinking 1h 24m 7s" for a turn that waited on
// its subagents).
Expand Down Expand Up @@ -1357,7 +1357,7 @@ function codexLiveTurn(
line.doing = lifted.doing;
line.doingShell = lifted.shell;
line.doingDone = true;
// The step's own time, not the turn's ("Opened 1 agent session 3m 27s · 1h 22m total").
// The step's own time, not the turn's ("Opened 1 agent session 3m 27s · 1h 22m").
if (lifted.ms !== undefined) line.doingForMs = lifted.ms;
}
}
Expand Down
2 changes: 1 addition & 1 deletion webviews/src/agent-session/acpmux/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ export type AcpmuxRow = {
/// With the line reading "Thinking" past the first step: how long the turn's thoughts streamed,
/// summed (conversation/turns.ts `thoughtTime`), the time it shows beside the word.
thoughtMs?: number;
/// The live line's clock is the turn's whole time, past its first step: it reads "4m total", so
/// The live line's clock is the turn's whole time, past its first step: it reads "4m" beside the label, or "2s · 4m" after a step's own time, so
/// the time never reads as what the line names (conversation/Thinking.tsx).
turnTotal?: boolean;
/// The call in flight sends another agent a message (conversation/turns.ts `sendingTo`: a shell
Expand Down
Loading
Loading