Commit Graph
251 Commits
Author SHA1 Message Date
Bowen Liang 39554df985 feat: add a Tool Calls cell to the Context Stats board
The cell sits left of Images and counts the tool calls whose result is
live in the current context: one tool/result folds to exactly one tool
surface node, so the host derives the figure at view time from the live
surface (no persisted counter, no state-version bump). Calls still in
flight and results compacted or pruned out of the surface are excluded.
2026-08-24 00:01:47 +08:00
Bowen Liang 69c175e76a feat(client): narrow the Context Stats board cells
Shrink the stat-cell grid minimum (76px -> 62px), gap (8px -> 6px) and
padding (8px -> 6px) so the board's nine cells pack tighter.
2026-08-24 00:01:43 +08:00
Bowen Liang c4153d525c chore: bump version to 0.26.1 2026-08-23 23:37:28 +08:00
Bowen Liang 6b9566226d docs: update AGENTS.md to clarify local git clone instructions 2026-08-23 23:36:35 +08:00
Bowen Liang 05ec9bba40 docs: update AGENTS.md to include English usage in PR descriptions and commit messages 2026-08-23 23:34:57 +08:00
Bowen Liang e53c375a15 feat(client): hide the composer while the Context tab is active (#14)
* feat: add PR checks workflow for automated testing and validation

* feat(client): hide the composer while the Context tab is active

The view ring mounts one view at a time, so the tab's .lc-root existing
inside the shell scrollport is exactly 'Context tab active' — a single
:has() rule hides the sticky composer seat and hands its height to the
dashboard. display:none keeps the seat mounted, so drafts survive the
round trip.

Interactive takeovers (approval / question / plan-review panels) replace
the bar inside the same seat; keep the seat visible while one is present
so a pending decision is never hidden behind the focus mode.

Closes #11

* ci: build before test in PR checks

Client tests mount the built bundle (viewBed.ts reads lib/client.js), so
pnpm test without a prior build fails with ENOENT in a clean checkout.
2026-08-23 23:33:15 +08:00
Bowen Liang 9af89c6668 chore: bump version to 0.26.0 2026-08-23 23:04:12 +08:00
Bowen Liang a26f5437c3 fix(client): hoist hooks above early returns — React #310 on data/event arrival
ContextViewBody returned the loading frame BEFORE its displayRequests/
markers useMemos: when the projection value landed on the same mounted
instance (a pure timing race), the hook count grew between renders and
React threw #310, which the ErrorBoundary masked as a '数据读取失败'
card. EventList returned its empty branch before useRef/useLayoutEffect:
an empty -> non-empty transition in one instance at best corrupts the
hook list (React logs 'Expected static flag was missing') and at worst
throws the same #310 on builds that don't recover.

Both early returns now sit below every hook; data-less renders fall back
to empty collections so the memos stay unconditional.

Regression tests mount the built client bundle on real React in jsdom and
drive both transitions (loading -> loaded, events empty -> non-empty),
failing on a boundary catch or any hook-order console error.

Closes #12
2026-08-23 23:03:47 +08:00
sxgitmiao be751da48d feat(client): add Total/Diff display mode to the Context History chart
Adds a display-mode pair (全量/增量, Total/Diff) next to the Step/Turn granularity group in the Context History card. Diff mode plots each request's per-category |change| vs the previous request, with the hover tip reporting the signed net change (Δ +1.2k / Δ −535.5k); Total keeps the cumulative composition and stays the default.

Original PR by @xieshuaix (delta toggle); reworked before merge: the on/off delta switch became a two-way mode control (mode: 'total' | 'diff' end to end), the two toggle groups were wrapped so the title's auto-margin push happens once, trend.hint was shortened/localized, and the fiber-slot/button-count tests were updated.
2026-08-23 22:49:09 +08:00
Bowen Liang 095e2f525e fix(host): tag skill results even when the tool/call event is gone
- drop the redundant node.cat === 'tool' guard (categoryOf always
  returns 'tool' in the tool/result case)
- fall back to the rendered <skill_content> wrapper when node.tool is
  unresolvable (trimmed window, replay), so a skill load never silently
  degrades to an ordinary untagged tool row; the wrapper only appears in
  genuine skill results
- regression test for the fallback path, and that a plain tool result
  without the wrapper stays untagged
2026-08-23 22:25:30 +08:00
Bowen Liang 02807de68c Update src/client/i18n.ts 2026-08-23 21:34:56 +08:00
tangjunyan.5703 a2641b7d29 feat(host): surface skill-tool loads as tagged tool results + Skill inject event
A skill load via the `skill` tool returns the loaded skill's instructions
as a tool result. Keep it a tool result (that is what it is), but make it
findable: tag the node with the skill name (so the Context browser labels the
row `Skill · <name>`) and record an inject event so a `Skill 注入(name)`
entry shows in the Context Events card.

- fold: detect tool/result with node.tool === 'skill', parse the skill name
  from the rendered <skill_content name="…"> wrapper, set node.skill, emit a
  sub:'skill' inject event. Category stays 'tool'.
- browser: tool row shows the Skill · <name> tag when node.skill is set.
- i18n: add node.skillTag (zh/en).
- test: regression for the skill-tool result path.
2026-08-23 18:45:35 +08:00
bowenliang123 c2fb81eaaa chore: bump version to 0.25.3 2026-08-23 05:14:04 +08:00
bowenliang123 c27904b5f5 feat(client): chip the collapsed User Messages rows that carry image uploads
The row joins the conversation snapshot and counts image blocks via the
same imageRefOf the expanded body uses; the chip (localized 'attach.image',
×N when several) shows only while collapsed — expanded, the image grid
speaks for itself.
2026-08-23 05:13:56 +08:00
bowenliang123 70496e77c9 chore: bump version to 0.25.2 2026-08-23 05:11:36 +08:00
bowenliang123 93cf924445 fix(host): drop unnecessary ?? 0 guards on TimelineState.images (stateVersion 7 refold guarantees it) 2026-08-23 05:11:27 +08:00
bowenliang123 57ff90dfc3 chore: unify the repo on TypeScript — tests, vitest config, and the social-preview generator move from .mjs to .ts
vitest (esbuild) and Node 24 type stripping run the .ts files directly;
helper imports go extensionless like src. Typecheck stays scoped to src/
as before.
2026-08-23 05:11:27 +08:00
bowenliang123 4b8d00ee03 chore: bump version to 0.25.1 2026-08-23 05:05:31 +08:00
bowenliang123 eb9ff049f8 fix: exclude sourcemaps from the npm tarball (enumerate shipped files like official dsh packages) 2026-08-23 05:04:52 +08:00
bowenliang123 c4e242b5b1 chore: bump version to 0.25.0 2026-08-23 04:57:47 +08:00
bowenliang123 271f4e3395 refactor(client): unify Context browser detail rendering into one section-card system
Every expanded element body is now a uniform stack of Section cards
(labeled head + body): prose carries the Raw/MD switch in the head, tool
calls/params/images/raw JSON share the same frame, and one blocks→sections
pipeline serves user/assistant/tool-result/injection bodies. Replaces the
floating-switch, bare-pre, and per-kind card idioms; drops the dead
lc-br-blk/lc-br-pre/lc-br-md/lc-br-rich-inline styles and the unused
RichCard/inHead/dim parameters. Element-row tool tags lose their inverted
chip and share the subtle injection-form tag style. Test bed: function
components now receive props.children like real React.
2026-08-23 04:56:17 +08:00
bowenliang123 af8f695854 feat(client): Context tab browser stretches to the left column's height
The /context modal keeps the browser content-sized.
2026-08-23 04:32:56 +08:00
bowenliang123 93dfe3941d feat(client): shorter stats labels (Cache Hit / Cost) 2026-08-23 04:32:55 +08:00
bowenliang123 f15b9ecddc style(client): narrower stats cells (76px min, 8px side padding) 2026-08-23 04:18:32 +08:00
bowenliang123 78245e1b75 feat: whole-session image count in Context Stats
Fold counts image blocks (user uploads + nested tool-result images)
cumulatively over the complete session log, rides the wire snapshot as
an optional additive field, and the stats board shows it as a new cell
between prunes and cache hit. stateVersion 7 refolds cached rows.
2026-08-23 04:18:26 +08:00
bowenliang123 3c48acbed0 fix(host): weekends bill at off-peak rates all day
Follow DeepSeek's peak/off-peak rule adjustment: Saturdays and Sundays
(Beijing Time) no longer distinguish peak windows, so the whole weekend
prices at the half-price off-peak rate. Peak windows are now expressed in
Beijing Time (weekdays 09:00-12:00, 14:00-18:00), equivalent to the old
UTC windows on weekdays. List prices themselves are unchanged.
2026-08-23 03:55:18 +08:00
bowenliang123 61d3e16477 docs: update context-browser-images.png 2026-08-22 19:57:21 +08:00
bowenliang123 c40a919e60 chore: bump version to 0.24.1 2026-08-22 18:08:42 +08:00
bowenliang123 c208f55d07 feat(client): labeled Raw/Sent/Token rows on image cards, shown only when known
Each fact gets its own labeled row: Raw (pre-normalization dims), Sent
(normalized dims + stored size, dynamic B/kB/MB units), Token (estimate).
Facts that dsh never recorded (e.g. no originalDimensions, no byte size)
simply leave no row behind.
2026-08-22 18:08:41 +08:00
bowenliang123 eb5c8ebf2d fix(client): wrap long image attachment filenames instead of truncating 2026-08-22 18:08:35 +08:00
bowenliang123 9859f4702a chore: bump version to 0.24.0 2026-08-22 16:31:55 +08:00
bowenliang123 9dccec4e85 docs: composition card reads the official meter projections; image cards show token costs 2026-08-22 16:31:13 +08:00
bowenliang123 c003916360 feat(client): two equal-width image attachment columns with token badges
The attachment grid becomes a two-column equal-width grid
(repeat(2, minmax(0, 1fr))) and every image card gains a token-cost
line (≈N tokens, with an explanatory tooltip) estimated through the
official DeepSeek image-size conversion on the stored dimensions.
2026-08-22 16:31:13 +08:00
bowenliang123 d3cdc263d6 feat(client): read the official contextBreakdown projection for the composition card
The composition legend and tooltips now show the exact system/tools/
messages counts of the chat composer ring's click-open panel (the
token-meter's contextBreakdown projection) instead of the fold's own
sums re-anchored to the provider total: parts carry the heuristic count
(raw) for display beside the provider-anchored bar width (value), and
the message bucket subdivides into the four surface categories by the
fold's per-category ratios, always summing exactly to the official
message figure. Absent the projection (older harness), the fold's own
sums serve unchanged.
2026-08-22 16:31:05 +08:00
bowenliang123 d9c09782fc feat(host): price image blocks by DeepSeek's official image token calculator
The token-meter heuristic prices image blocks through its generic JSON
branch (~40 tokens for the durable ref), while DeepSeek's vision model
actually bills 117-384 tokens per image by pixel dimensions. Port the
official docs image-token calculator (patch grid 14px, downsample x3,
384-token cap, minPixels 384^2) into src/shared/imageTokens.ts and price
image blocks with it in the fold; unknown dimensions keep the JSON
fallback. stateVersion bumps to 6 so cached rows refold.

The differential fold check replays a parallel image-delta surface so
image-bearing logs still match the official contextBreakdown exactly,
and adapts to the 0.1.1 wire.view contract.
2026-08-22 16:30:55 +08:00
bowenliang123 1ddd99978f docs: update compatibility section in AGENTS.md to clarify runtime dependencies 2026-08-22 13:36:03 +08:00
bowenliang123 1fd605d2d2 docs: add dsh version compatibility contract to AGENTS.md 2026-08-22 13:29:16 +08:00
bowenliang123 641322a351 chore: bump version to 0.23.0 2026-08-22 04:34:10 +08:00
bowenliang123 8066ce5b86 docs: add guidelines for committing mixed changes separately 2026-08-22 04:34:08 +08:00
bowenliang123 75d1ec8917 test: shift ContextView hook slot indices for the focusTurn state
The clickable turn strip added a focusTurn useState between granularity
and hoverCat, shifting hoverCat to slot 6 and toolFocus to slot 8; the
composition-link and tool-chip-bridge specs still addressed the old
slots.
2026-08-22 04:33:45 +08:00
bowenliang123 ad1e6872ba feat(client): collapsed browser rows lead with an inverted tool breadcrumb + call summary
Tool-result and call-bearing assistant rows now open with an inverted
mono chip naming the tool(s) (label/surface tokens swapped — black on
white in light mode, white on black in dark), multiple calls joining as
a breadcrumb (bash › write). The preview then carries the call's own
summary line: a bash-style `description`, else the target path of
path-taking tools (edit/read/write via file_path/path/filePath), falling
back to the reply text or the generic label. The redundant 'calls: …'
preview is gone — the chip says it once.
2026-08-22 04:31:34 +08:00
bowenliang123 654eca8cdb feat(client): tool calls in assistant messages and tool results share one arg card
Both render the call as a card whose head names the tool (→ / ←) with
the argument count, the body lists arguments as name/value rows — the
type column is gone, the name sits in a narrow wrapping left column,
the value wraps in a mono right column (height-capped). The tool name
steps up to 13px mono. The tool result's raw lc-br-call block is
replaced by the same card.
2026-08-22 04:16:56 +08:00
bowenliang123 bef73a5723 feat(client): clickable turn strip — click a turn block to jump to turn granularity and center it 2026-08-22 03:58:26 +08:00
bowenliang123 db56081cd0 fix: keep the trend chart scrollbar off the turn strip
Reserve 8px below the scrollable chart so the horizontal scrollbar no
longer overlays the turn labels.
2026-08-22 03:50:57 +08:00
bowenliang123 c55ab3da3d perf(client): memoize trend-chart bars; fix stale retention comment
The retained request log is bounded by maxKeptTurns/maxRequestSteps
(defaults 300/1500), not 160 as the comment claimed — a long session's
chart is thousands of bar nodes, and every bar hover re-rendered all of
them through ContextViewBody.

Extract the bar as a React.memo component (hover flips flags on at most
two bars; req/marker identities stay stable between projection pushes)
and memoize the parent's turn-aggregation and marker attachment so turn
mode stops allocating fresh bar props on every hover render. Bars carry
data-seq for identification now that the element key lives on the
memoized component; the fake-React test beds learn memo().
2026-08-22 03:49:32 +08:00
bowenliang123 5967200a9b perf(host): consume callNames entries on tool-result fold
The callId→name map is looked up exactly once — when the result event
folds in — but entries were kept for the session's whole lifetime. As
persisted state, the map was serialized on every projection checkpoint
and shallow-copied by every fold step's lazy clone.

Rebuild the map without the consumed ids at lookup time (no dynamic
delete, per repo lint); consume-once holds it at pending-call size, so
the copy is trivial.
2026-08-22 03:45:50 +08:00
bowenliang123 903b779f89 docs: emphasize the importance of modular code for maintainability in AGENTS.md 2026-08-22 03:38:50 +08:00
bowenliang123 b5b96887c5 docs: clarify GitHub Actions workflow for automated publishing in AGENTS.md 2026-08-22 03:36:23 +08:00
bowenliang123 ad1677f579 docs: add versioning information to AGENTS.md 2026-08-22 03:35:06 +08:00
bowenliang123 dd81b5b437 ci: fold the plugin check into the publish job
One job instead of two: the dsh-plugin-checker step now runs right after
checkout inside publish, dropping the needs: handoff (saves a runner
spin-up per release; the check still gates every later step).
2026-08-22 03:33:18 +08:00