/** * 任务计时 (task-timer) — "how long has THIS turn been running, and what is it * waiting on right now". * * WHY THIS CARD EXISTS, next to 工具调用 (the tool fold) and 会话统计 (the session * counters): both of those answer retrospective questions — how many calls, how * much time the session has spent. Neither answers the LIVE one, which is the * question the rail is actually watched with: is this turn wedged, or is that * `pwsh` call just slow? The readings here are the only ones on the rail that move * while a turn runs, so they share one card and are read as a pair: a climbing turn * clock over 模型 means the model is thinking, the same clock over a named tool means * the wait is that tool. * * WHERE THE NUMBERS COME FROM (no new data source — all three are already projected): * - TURN — `stats.liveTurnMs`, the collector's reading of the open turn, counted * from the START of the earliest step inside it (`start.time`), so it measures * the whole turn and not just the step that happens to be current. It is null * when no turn is open, which is a DIFFERENT statement from "0 ms elapsed" — * an idle card prints `—` and says 空闲 rather than a fake `0:00`. * - STEP — `stats.liveStepMs`, the open MODEL step's own elapsed time; null when * the turn is between steps (the model has answered and nothing is in flight). * It is what tells "the model is thinking" apart from "a tool is working" — * without it both states print the same climbing turn clock. * - TOOL — `stats.tools.running`, the tool fold's longest in-flight call * (`{ name, ms, count }`), i.e. the call that has been holding a slot longest. * `null` when nothing is running. `count` is how many calls run in parallel, * which is why a second figure rides the same line: at two or more, the longest * one's elapsed time understates the wait (`2 个并行`). * * WHY THERE IS NO RENDERER TICK. A widget render cannot own an interval and the * rail only re-renders a card when its data changes (30s at idle). That is * deliberately not worked around here, the way the dial's hands had to be: while a * turn is open the collector rebuilds this projection on its own 1s beat and the * turn clock advances second by second on real re-renders, and when no turn is open * there is nothing to advance — the card shows 空闲, and a ticking `—` would be a * lie. So the widget stays a pure data description with no `rich` block. * * WHAT EACH SIZE SAYS. 2×2 has room for one figure plus one line: the figure is the * turn clock, and the line names what the turn is waiting on, in three states — * a running tool, else an open model step, else 空闲. 2×4 is twice as wide and can * carry that pair plus the session's own totals, which is why the turn clock moves * up into `headAfter` (leaving the body free for the figures). * * WHY THE TITLE STAYS (docs/design/CARD-TITLE-STANDARD.md, T2 度量型): the body is * a bare `M:SS` figure, and a bare figure names nothing — `3:12` is the turn, the * tool, or the session depending on who wrote it. The title is this card's only * statement of what its numbers are measured over, and T2 keeps it. For the same * reason the 2×2 body keeps that figure in `value` rather than beside a ring: this * is a one-figure card, and C2 (the body fills the tile) is false, so the empty * title strip would leave a hole at the top of the card. */ import type { WidgetRenderMeta, WidgetRenderOut, WidgetStats } from '../../client/lib/contract/types'; declare function taskTimerRender(stats: WidgetStats, meta?: WidgetRenderMeta): WidgetRenderOut; declare const _default: { id: string; name: () => string; desc: () => string; builtin: true; group: string; sizes: ("2x2" | "2x4")[]; render: typeof taskTimerRender; configSchema: never[]; simToggle: () => string; example: { stats: { liveTurnMs: number; liveStepMs: number; turns: number; steps: number; tools: { calls: number; tools: number; failures: number; slowest: { name: string; ms: number; }; running: { name: string; ms: number; count: number; }; }; }; sim: { liveTurnMs: number; liveStepMs: number; toolName: string; toolMs: number; toolCount: number; }; simSteps: ({ liveTurnMs: number; liveStepMs: number; toolName: string; toolMs: number; toolCount: number; } | { liveTurnMs: number; liveStepMs: number; toolName: null; toolMs: null; toolCount: null; } | { liveTurnMs: null; liveStepMs: null; toolName?: undefined; toolMs?: undefined; toolCount?: undefined; })[]; note: string; }; }; export default _default;