Commit Graph
670 Commits
Author SHA1 Message Date
bowenliang123 b6eda0833c chore(client): keep expected-path noise out of the test output
The three local until-polling copies let the debounced detail updates
land outside act — React warned 19 times per run. They collapse into
one shared act-per-tick until in the kit: timers and promise chains
only fire while a tick's sleep is awaiting, so the updates stay
act-attributed and commit as each scope exits.

The four browser specs that arm the fetch-on-miss retry with a
deliberately failing fetcher silence the production console.warn the
failure legitimately emits, restored by a file-level afterEach.

A default-reporter run now prints zero stderr.
2026-09-17 13:58:08 +08:00
bowenliang123 bda3537b2c chore: add 'dot' reporter to Vitest configuration 2026-09-17 13:06:14 +08:00
bowenliang123 981835b0d2 chore: print only sub-100% files in the coverage table
Enable vitest coverage.skipFull so the text table lists only the files
below 100% — an empty table means full coverage. The thresholds gate
(perFile 100) still fails the run and names the offending files. Sync
the AGENTS.md coverage-output example accordingly.
2026-09-17 10:03:38 +08:00
Bowen Liang 77839c8d3f feat(client): step token figures up to billions in fmt
Values at 1e9 and above rendered as four-digit M figures (1055.9M);
fmt now steps to a one-decimal B suffix, same style as k and M.
2026-09-17 08:27:38 +08:00
Bowen Liang 0003ceabaa fix(client): count only the sessions each KPI figure covers
The cost cell's sub-line now counts the sessions whose spend the price
book could estimate (costSessions), and the cache-hit cell's the
sessions whose usage feeds the rate (usageSessions) — a session with
usage but no book rates feeds the rate while pricing to nothing, and a
session without usage counts toward neither figure.
2026-09-17 00:53:49 +08:00
Bowen Liang 0d34b468fb chore: release v0.53.1 2026-09-17 00:38:26 +08:00
Bowen Liang b37dac10cb fix(client): shorten the overview KPI copy that clipped its cards
The cost and cache-hit subtitles now qualify with the session count they
aggregate over (a shared ov.kpi.sessionsSub key) instead of long
explanations that overflowed the narrow KPI cards; the heatmap card's
hint reads 'Filter by date'.
2026-09-17 00:36:20 +08:00
Bowen Liang dd0ccbf044 feat(client): add month labels to the activity heatmap
Each column is labeled when a month begins inside it: the month changes
between its Monday and Sunday, or its Monday is the 1st; the label names
the Sunday's month. Months that began before the window stay unlabeled.
2026-09-17 00:28:08 +08:00
bowenliang123 c463620b71 feat(client): add a per-user toggle for the Context Insights sidebar entry
New insightsEntry field ('show' | 'hide', default 'show') in the
dsh-context settings namespace, edited from the Plugin configuration
card. The sidebar entry subscribes to the store and renders null while
hidden; the seat stays registered so flipping back needs no remount.

Fails open everywhere: a schema-less host, an unserved namespace, a
section without the field, a stale persisted value (loose union), or a
write that never persists all resolve to the visible entry.
2026-09-16 21:22:10 +08:00
bowenliang123 95121ffe97 fix(client): keep the insights columns' scrollbars clear of the cards
The sessions/KPI columns' own 8px bar rendered flush against the card
edges, riding on them while scrolling, and a column gaining or losing
the bar reflowed its content by the bar's width. Reserve the track
(scrollbar-gutter: stable) and pad the columns so the thumb stays 8px
clear of the cards; the folded single-column layout resets the padding.
2026-09-16 21:08:07 +08:00
bowenliang123 67f956b920 chore: release v0.53.0 2026-09-16 18:22:32 +08:00
bowenliang123 80a8abd038 fix(host): refold version-stale timeline rows in the startup warm-up 2026-09-16 18:18:05 +08:00
bowenliang123 be08195086 feat(client): add tool-calls and active-time KPIs to the insights panel 2026-09-16 18:07:33 +08:00
bowenliang123 872c24c0ce feat(client): show the last user message on session cards 2026-09-16 18:05:14 +08:00
bowenliang123 068a4fb035 feat(client): split the insights panel into 3:7 columns 2026-09-16 17:37:38 +08:00
bowenliang123 2500ddb03c feat(client): split the insights panel into 2:3 columns 2026-09-16 17:30:03 +08:00
bowenliang123 8de11e2c32 fix(client): mirror the settings trigger's geometry in the entry button 2026-09-16 17:17:28 +08:00
bowenliang123 aca9f29a23 fix(client): rename the dashboard entry to Context Insights 2026-09-16 17:16:09 +08:00
bowenliang123 ff09c4298b fix(client): reword the heat card subtitle 2026-09-16 17:11:45 +08:00
bowenliang123 c4fa859d69 feat(client): tip heat cells instantly with active sessions 2026-09-16 17:10:50 +08:00
bowenliang123 2e1b746723 fix(client): shorten the heat card subtitle 2026-09-16 16:51:38 +08:00
bowenliang123 6cf805d0e5 fix(client): right-align the dashboard card's stat values 2026-09-16 15:18:25 +08:00
bowenliang123 9b8fe848ba feat(client): rework the context dashboard
- Page the session grid at 12 cards per page: a filter change re-anchors
  the pager at the first page, and clamping keeps a shrunken list's view
  in range instead of showing a blank page.
- Redesign the session cards: 3 columns, a project pill, a first-active-
  day line under the relative time, wrap-clamped titles with uniform row
  heights, a turns-and-steps lead figure, and the cost label shortened
  to 费用/Cost.
- Restack the insight band as one folding row — the KPI 2x2 block beside
  the activity heatmap — and drop the aggregate composition card with
  its now-unused fold, keys, and styles.
2026-09-16 14:25:43 +08:00
bowenliang123 a06a302f4c fix(client): keep overlay inputs focused across re-renders
useEscapeClose resubscribed on every render — callers pass a fresh
closure each time — and each resubscribe's cleanup re-ran the pre-open
focus restore, yanking focus out of the overlay's own inputs on every
keystroke. Hold the callback in a latest-ref so the subscription and
its restore live on the active transitions alone.
2026-09-16 14:25:13 +08:00
bowenliang123 5f9b773f01 feat(client): read the composition unit from the card subtitle
The donut center shows the total alone — the overflowing
"tokens (estimated)" moves to the card's subtitle as plain
"tokens" — and the sort buttons follow the workspace browser's
vocabulary: Last updated / Total Tokens / Current Context.
2026-09-16 11:59:58 +08:00
bowenliang123 6048aa7f18 feat(client): hug the dashboard's heat card to its grid
The card pins to the 252px its fixed grid needs — about half the
previous share — and the composition card takes the rest; wrapped
below the row's fold, the heat card stretches again.
2026-09-16 11:59:42 +08:00
bowenliang123 62ff87ea0a fix(client): hide archived sessions from the Context Dashboard
The raw session list carries every session while the workspace browser
hides its archive set, so the dashboard surfaced archived ghosts and
read as duplicates and stale rows. rowsOfSnapshot now drops rows present
in the workspaces snapshot's archivedSessionIds, failing open — an
absent seat or a hostile shape archives nothing.
2026-09-16 11:43:01 +08:00
bowenliang123 154f716f7a feat(client): compact the dashboard's activity heatmap
Default the window to the last 8 weeks, draw fixed-size cells centered
in the card (the block's height now follows the seven cell rows instead
of stretching to the card's width), floor data-less days with a visible
gray, and rebalance the chart row to heat:composition 2:3 so the
composition legend flows into multiple columns.
2026-09-16 11:42:46 +08:00
Bowen Liang dc6decc25a docs: document the Context Dashboard and its activity backfill
README gains the dashboard feature entry, a Use-it row, and a section with
the panel screenshot; compatibility.md records the additive contextActivity
key (stateVersion 1, no row invalidation) and the startup warm-up that
cold-reads sessions missing their projection rows.
2026-09-16 08:56:47 +08:00
Bowen Liang 2f265f3f18 feat(client): add the Context Dashboard panel above Settings
A cross-session insight surface: the sidebar-foot entry (stacked above
Settings by the harness's own foot layout, with a running-sessions badge)
opens a frame-wide overlay through the shared module store. The panel reads
the root-scope useSessions/useWorkspaces standard kit — every list row's
host-cached projection values — so no session log needs opening:

- KPI band over the picked range (7d / 30d / all): active sessions, billed
  tokens, estimated cost (models.dev book), cache-hit rate.
- Activity heatmap (GitHub-style, 12 weeks, square cells filling the card):
  a day click pins the session grid to that day.
- Aggregate composition donut over the range's sessions.
- Session cards with a mini composition ring, billed/turns/cost figures and
  a workspace-group / project breadcrumb (deduped when both names match);
  grid filters by range, pinned day, group chips (incl. Ungrouped), and
  search; sorts by recency, tokens, or context size; a card click opens the
  session through the harness's own sessions.open and closes the panel.

Subagent-origin rows are excluded, mirroring the workspace browser's own
predicate (plain open() cannot address them). Every row is sanitized in
isolation — a hostile row degrades to a metadata-only card, never an error.
2026-09-16 08:56:30 +08:00
Bowen Liang e33deda752 feat(host): add the contextActivity daily-ledger projection with a cold-read backfill
The Context Dashboard's heatmap and session cards read the session list's
projection column, which only serves durable cache rows. The new
contextActivity unit folds each assistant settlement into a per-day ledger
(billed tokens + completed requests, keyed by local day, 400-day retention)
alongside the existing contextTimeline/contextHeaders units.

A session folded before a unit existed — or one that predates the plugin
entirely — has no row until it next goes live, so a one-pass warm-up
(backfill.ts) cold-reads every such session's durable log through the
projection cache's own cold-read ladder (coldSnapshot): each unit seeds
from its cached rows, folds the remainder, and the refreshed checkpoint is
written back. Live sessions are skipped (a throwing liveness probe skips
conservatively too), unreadable logs are logged and skipped per session,
and the whole pass rides a deferred inject across the
sessionQuery/sessionProjectionCache/sessionPersistence/sessions services.
2026-09-16 08:55:49 +08:00
Bowen Liang 29a8514c7e feat(client): price the stats board's cost cells across the whole agent family
The Context card's cost cell now prices the current agent TOGETHER with
every subagent session's cumulative billed totals, and a new subagent-cost
cell prices the subagents' share alone; both hover bubbles explain their
scope, the merged one listing the per-model rates of every billed side.
The subagents' usage folds out of the session-list snapshot's warm
contextTimeline rows (subagentCostFoldOf, whole descendant subtree,
cycles cut), with cold relatives' slim heads standing in. Those head
fetches leave the Agent network card's factory closure for a shared
page-scope cache (agentHeads.ts) the stats board's seat reads too, so a
relative is fetched once no matter how many cards consume it; the card's
list-snapshot subscription moves there as useSessionsSnapshot.
2026-09-16 00:12:31 +08:00
Bowen Liang 3708012037 docs(readme): update context-trend.png 2026-09-15 22:53:49 +08:00
Bowen Liang b211f951c7 docs(readme): update history-delta.png 2026-09-15 22:45:10 +08:00
Bowen Liang 6b8541e64d chore: release v0.52.2 2026-09-15 10:16:59 +08:00
Bowen Liang ede62413e6 fix(client): replay the cached cold-relative head across graph remounts
The fetched composition heads lived in component state while the promise
cache lived in the factory closure, so a remount (tab switch) reset the
composed rings back to green and the cache hit kept every relative from
ever re-fetching. A cached read now replays into the fresh instance, with
an identity bail-out so the settled replay on every snapshot tick cannot
loop. Also drops a redundant route wrapper and aligns the spec helper with
the fetch transport it stubs.
2026-09-15 08:52:16 +08:00
Bowen Liang dae94c225a fix(client): backfill cold relatives' composition in the Agent network
The session-list block serves projection values only from the host's
projection cache, so a relative that never attached since the timeline unit
last changed lists pressure-only (occupancy without composition) and its
ring degraded to the single fallback arc — every subagent ring looked green
until its session was opened. The card now fetches those nodes' slim heads
from the /api detail route (one read per session per page, failures sticky)
and re-folds the forest with the row's missing contextTimeline injected; a
row's own value always wins, and any fetch failure degrades back to the
pressure-only ring.
2026-09-15 08:33:23 +08:00
Bowen Liang a82e6a1dc7 fix(host): mount the detail endpoint through Connection's /api fetch registry
The split generation's detail transport rode connection.rpc.handle, whose
registration reads webServer off the connection service's own context —
cordis's strict-read guard rejects that for plugin callers, so the channel
never armed and every detail read fell through to the static fallback (405).
Mount the handler through connection.fetch.register instead (the same
exact-route seam the harness's own file-upload and media-reference routes
use), riding the authenticated /api fence; the client POSTs it same-origin.

The detail payload now also carries the slim wire head at the same fold cut
(the composition scalars the Agent network's cold-node ring fetch renders
from); a missing or malformed head drops out alone, never rejecting the
payload the detail cards consume.
2026-09-15 08:32:14 +08:00
bowenliang123 6e306c31b9 chore: release v0.52.1 2026-09-14 17:40:56 +08:00
bowenliang123 f349430eda fix(host): degrade a missing injection source to an empty producer label
injectionSourceName read source.kind/plugin unguarded on its first line,
so a null/undefined source would have thrown the fold's caller (issue #69).
The fold's only call site already gates on isInjection, so the reachable
behavior is unchanged; the guard closes the trap for future callers and
matches isInjection's tolerance for foreign source shapes.
2026-09-14 17:16:11 +08:00
bowenliang123 e19aee7540 fix(package): build lib in prepare for git-hosted installs
pnpm >=10 blocks a git dependency's prepare until allowlisted, and the
prepare script ran husky only — so even an allowlisted
'dsh plugin add git+https://...dsh-context.git' packed the repo without
lib/ and the bundle had no main entry to load. Building in prepare makes
the packed git dependency complete; registry-tarball installs never run
prepare, so the npm path is unchanged.
2026-09-14 17:06:13 +08:00
bowenliang123 92bfcbd110 docs: update README with screenshots and new context stats and improved section titles 2026-09-14 15:16:22 +08:00
bowenliang123 59f9cae7ec docs: update README with screenshots and new context stats and improved section titles 2026-09-14 14:49:03 +08:00
bowenliang123 33fd7ae680 feat(client): hold the hover tint on the expanded browser category header
The Context browser's category header carried only the hover utility, so
the tint vanished the moment the pointer left an expanded card and the
header melted into its body. The open state now keeps the hover
background via a lc-br-cat-open state class - the same token as the
hover and hover-link tints - on every category card alike.
2026-09-14 14:25:51 +08:00
bowenliang123 053c4c2330 feat(client): face the /context slash row with a localized label and glyph
The slash menu candidate carried only its name, section, and description,
so the row rendered the bare "context" while every built-in command row
showed its icon and localized title. The candidate now carries the plugin
emblem and a cmd.label title (the name renders as the trailing alias on
builds that show titles). Both fields are pure display data: harness
builds that predate their rendering ignore them and keep the bare name.
2026-09-14 11:46:37 +08:00
bowenliang123 099b7073f4 feat(browser): label injected rows with the fold-stamped source identity
The Context browser's Injected Context and Skill Injections rows previewed
the raw injected content, while the Context Events card named the producer
(plugin id, reconciled instruction files, durable kind). The fold now
stamps that identity on the surface node alongside the event, and the rows
prefer it for the collapsed preview - the content stays one expand away,
and the row filter still scans the folded text. Nodes folded before the
stamp (additive-optional on the wire and persisted state, no stateVersion
bump) degrade to the previous content preview.
2026-09-14 11:22:47 +08:00
bowenliang123 73318a5cd6 style(client): reword the token-estimate footer note
Spell out DeepSeek Harness instead of the dsh shorthand and name the
note's subject (Token 数量统计 / Token amount) in both locales.
2026-09-14 10:27:43 +08:00
Bowen Liang 445c80d0c8 chore: release v0.52.0 2026-09-14 02:08:19 +08:00
Bowen Liang ee63b59e75 fix(client): group the /context slash row under a localized section heading
The slash menu renders one source-title row per trigger source, titled
from the harness's own slash.menu dictionary; the plugin's source name
`context` is not a key there, so the row showed the bare raw name and
read as a duplicate command (closes #67). Candidates now carry a
localized `section`, which the menu renders in place of the
source-title row — 上下文 in Chinese, Context in English.
2026-09-14 02:04:47 +08:00
Bowen Liang 022768ef54 fix(client): light the skill bucket in the trend chart's category hover-link
The hover-link's re-light rules are a hand-enumerated CSS list keyed by
category, and the skill bucket joined the vocabulary without one — hovering
the browser's skill section (or the overview's) dimmed every bar with
nothing lit. Add the missing rule and pin the list-must-track-Category
constraint next to it.
2026-09-14 01:32:04 +08:00