The Subagent page becomes the Tasks page per the approved Variant-D design: - tasks-model.ts feeds BOTH modes from one pre-order node list: graph canvas (TasksGraph: layered nodes over bezier edges, drag-pan, wheel-zoom-to-cursor, phase frames, bottom-right control cluster) and the classic tree (TasksTree: keyboard navigable) — the view toggle and fold toggle stay reachable in both modes. - Workflow runs (workflows.list) hang under their origin agent; member agents re-parent under the run node, missing ones synthesize from run data; completed leaf agents fold into per-parent aggregate nodes (click or cluster toggle to expand/re-collapse). - Agent Teams (experimental): roster enriches nodes; a header chip opens the shared task board popover with basic CAS operations (complete / reopen / delete / reassign / create / edit); no experimental layer → the whole block hides (structural degradation). - Background jobs move into a bottom drawer that auto-collapses at 8+ agents (manual toggle wins); job output opens as an anchored popover (event replay, never the model's cursor); two-click kill preserved. - Live activity lines render as glyph + tool + args (tool-icons map onto host primitive icons). - Node click jumps to the transcript; ⓘ opens the detail popover; popovers follow the selection-popup dismissal contract (Escape / outside click / anchor off-screen via IntersectionObserver). - tasksViewMode pref (graph default) with a select row in settings; 58 new copy keys across zh/en/ja + 18 third-language dictionaries; dead CSS from the old tree/dock pruned. - Tests: 6 new page-interaction specs (auto-collapse, both-mode toggle, jump, fold, popover); jobs-view suite re-pointed at the popover; prefs/builtins/smoke lock tests updated for the new pref.
227 lines
5.5 KiB
CSS
227 lines
5.5 KiB
CSS
/* Tasks page shell: header row, empty/error states, and the state dot. The
|
|
graph canvas / tree rows / popovers / jobs drawer live in
|
|
tasks-graph.module.css; the old indentation-tree and jobs-dock classes
|
|
were pruned when the page moved to the unified model. */
|
|
.subagent {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.subagentHeader {
|
|
flex: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
height: 36px;
|
|
padding: 0 8px 0 12px;
|
|
}
|
|
|
|
.subagentTitle {
|
|
flex: 1;
|
|
min-width: 0;
|
|
font: var(--dsw-font-s-14);
|
|
color: var(--dsw-alias-label-secondary);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* The descendant count badge ("3 · 1 运行中") beside the title. */
|
|
.subagentCount {
|
|
flex: none;
|
|
font: var(--dsw-font-xxxs-11);
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|
|
|
|
.subagentRefresh {
|
|
flex: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
border: none;
|
|
border-radius: 6px;
|
|
background: transparent;
|
|
color: var(--dsw-alias-label-secondary);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.subagentRefresh:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
.subagentRow:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
/* Keyboard focus (mirror of the official catalog row): a visible fill only
|
|
when focused via keyboard; the selected state below still wins on top. */
|
|
.subagentRow:focus-visible {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
/* The currently-open session, highlighted in place (mirror of the workspace
|
|
`.sessionRow.selected` — declared after the hover/focus rules so it wins). */
|
|
.subagentRowActive,
|
|
.subagentRowActive:hover,
|
|
.subagentRowActive:focus-visible {
|
|
background: var(--dsw-alias-interactive-bg-active);
|
|
}
|
|
|
|
.subagentRowDisabled:hover {
|
|
background: transparent;
|
|
}
|
|
|
|
/* Loading placeholders are disabled but keep the default cursor (official
|
|
`.loadingRow` distinction from `.disabled`). */
|
|
|
|
/* The state dot aligns to the first text line (official catalog detail). */
|
|
.subagentDot {
|
|
margin-top: 4px;
|
|
}
|
|
|
|
.subagentLabel,
|
|
|
|
/* ── Live lines (running cards only) ──────────────────────────────────── */
|
|
|
|
/* ── Tree connector lines (official catalog recipe) ────────────────────── */
|
|
|
|
.subagentChildren::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: -26px;
|
|
height: 26px;
|
|
border-left: 1px solid var(--dsw-alias-border-l2);
|
|
}
|
|
|
|
.subagentChildren[aria-busy='true']::before {
|
|
content: none;
|
|
}
|
|
|
|
.subagentChildren > .subagentNode::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: -4px;
|
|
border-left: 1px solid var(--dsw-alias-border-l2);
|
|
}
|
|
|
|
.subagentChildren > .subagentNode:last-child::before {
|
|
bottom: auto;
|
|
height: 17px;
|
|
}
|
|
|
|
.subagentChildren > .subagentNode > .subagentRow::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 16px;
|
|
left: -4px;
|
|
width: 14px;
|
|
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
}
|
|
|
|
.subagentEmpty {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
padding: 16px;
|
|
font: var(--dsw-font-xxs-12);
|
|
color: var(--dsw-alias-label-tertiary);
|
|
text-align: center;
|
|
}
|
|
|
|
.subagentEmptyHint {
|
|
font: var(--dsw-font-xxxs-11);
|
|
color: var(--dsw-alias-label-dimmed);
|
|
}
|
|
|
|
.subagentError {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
padding: 8px 10px;
|
|
font: var(--dsw-font-xxs-12);
|
|
color: var(--dsw-alias-state-error-primary);
|
|
}
|
|
|
|
.subagentErrorRetry {
|
|
flex: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
height: 24px;
|
|
padding: 0 8px;
|
|
border: none;
|
|
border-radius: 6px;
|
|
background: transparent;
|
|
color: var(--dsw-alias-label-secondary);
|
|
font: var(--dsw-font-xxxs-strong-11);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.subagentErrorRetry:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
color: var(--dsw-alias-label-primary);
|
|
}
|
|
|
|
/* ── Background-job section (below the topology tree) ────────────────── */
|
|
|
|
/* One job row; the whole row lights up on hover, the expandable target
|
|
stays transparent (the kill button rides on the row's right edge). */
|
|
|
|
.jobsRow:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
/* The row whose output is shown in the bottom dock. */
|
|
.jobsRowSelected,
|
|
.jobsRowSelected:hover {
|
|
background: var(--dsw-alias-interactive-bg-active);
|
|
}
|
|
|
|
.jobsRowMain:focus-visible {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
/* The command line: a kind badge followed by the command itself in the code
|
|
face, like the terminal's live lines. */
|
|
|
|
.jobsKill:hover {
|
|
background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);
|
|
color: var(--dsw-alias-state-error-primary);
|
|
}
|
|
|
|
/* The armed (first-click) state: a filled confirm chip instead of the icon. */
|
|
.jobsKillArmed,
|
|
.jobsKillArmed:hover {
|
|
width: auto;
|
|
height: 20px;
|
|
padding: 0 8px;
|
|
background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);
|
|
color: var(--dsw-alias-state-error-primary);
|
|
font: var(--dsw-font-xxxs-strong-11);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.jobsKill:disabled {
|
|
opacity: 0.5;
|
|
cursor: default;
|
|
}
|
|
|
|
/* ── The shared output dock (bottom of the page, sticky like a terminal) ── */
|
|
|
|
/* Direct child of the scrolling body, so it docks at the scrollport's bottom
|
|
edge while the job list scrolls above it; a solid background keeps the
|
|
tree from showing through. */
|
|
|
|
.jobsPaneClose:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|