Commit Graph
361 Commits
Author SHA1 Message Date
bowenliang123 cbbbfa5ff7 feat(files): count PTC nested calls, str_replace_editor, and real search targets
File Activity only folded top-level tool-result nodes, so PTC sessions
(run_code as the only tool) showed an empty card and the Minimal preset
went unseen. The fold now covers every surface that executes a file op:

- Nested Code-Mode calls: each settled sub-call in the conversation
  node's subCalls tree folds as one op, attributed to the nested tool
  and located on its parent run_code result (FileOp.parent; the op's
  own seq names the dispatch event, which has no surface row). The op
  log shows the program's description as the "why". Narrowing is fully
  defensive: malformed blocks drop out, and the walk is bounded by a
  depth cap plus a visited-set cycle guard.
- str_replace_editor (Minimal preset): view reads; create,
  str_replace, and insert write with their own line deltas.
- Searches resolve to real files when the result's presentation meta
  carries the complete matched-file list (FileOp.hits shows the count,
  include filters join the detail); a capped or malformed meta falls
  back to the searched path/pattern as before, and meta attribution
  survives an aged-out call head.

Closes #24
2026-08-27 23:48:32 +08:00
bowenliang123 e24dcdae87 docs: add workflow section with to-do list guidelines in AGENTS.md 2026-08-27 11:36:34 +08:00
bowenliang123 a20db6a781 docs: clarify usage of read and edit tools in AGENTS.md 2026-08-27 11:33:21 +08:00
bowenliang123 9ad168892e fix(trend): keep the chart scrollbar always visible
The scroller's scrollbar-width: thin made Chromium and Safari drop dsh's
global themed scrollbar skin (any non-auto scrollbar-width/-color silences
::-webkit-scrollbar* rules), falling back to the OS overlay bar that
auto-hides on macOS. Drop the property so the skin takes over; reserve the
bottom padding through its --dsh-scrollbar-width token.
2026-08-27 10:43:44 +08:00
Bowen Liang 201ac1879d fix(client): state each step-brief tooltip in its time window
The three rows draw from different slices of the log, and the tag bubbles only named the content, never the window — scrubbing read like the rows did not match up. Each bubble now opens with its window and closes with the one cross-bar fact that explains the half-step offset: inputs are what entered after the previous reply (nothing new on a turn opener), calls made here land in the NEXT bar's In row, and the opener recalls itself on every step of its turn.
2026-08-27 02:51:28 +08:00
Bowen Liang ce93eb755d fix(trend): hold the step brief at a constant height while scrubbing
Hovering around the trend chart used to change the detail panel's height: the brief section only rendered rows that resolved (the turn opener vanishes outside retention, usage-only replies carry no reply node), and collapsed entirely - margins included - when nothing did.

- the brief lane ALWAYS renders: a fixed three-row min-height, rows appear inside it, unknown steps leave blanks instead of collapsing
- the In row is one of those constants - an empty step shows a muted "(nothing new)" placeholder in place of its chips, and stays inert (a row with no node has nothing to locate)
2026-08-27 02:51:04 +08:00
Bowen Liang fb99ba983a fix(client): remove the trend chart scroll edge fades
The 26px gradient overlays at the chart's left/right edges (shown when the history overflows) read as washed-out white patches; drop the overlays, their edges state machine, and the .lc-chart-fade styles. Scroll anchoring, turn-label centering, and the hover tip are untouched.
2026-08-27 02:12:56 +08:00
Bowen Liang 8e0cc30cc7 fix: move the trend hover tip out of the chart scroller to stop hover layout jumps
The absolutely positioned tooltip contributed scrollable overflow inside
.lc-chart-scroll: a wide reply preview hovering a right-edge bar inflated
scrollWidth and toggled the horizontal scrollbar per hover, jumping the
whole trend card. A new positioned .lc-chart-wrap now anchors the edge
fades and the tip beside the scrollable content; syncTip glues the tip to
its bar visible slice via transform (edge-clamped, centered when wider
than the viewport), which also pins the left fade that used to drift
off-screen with the scrolled content.
2026-08-27 01:50:14 +08:00
Bowen Liang 8d6b2851f8 fix: wrap/shrink card internals instead of spilling past the card edge at narrow widths
Header rows (trend toggles, event kind chips, browser picker), the
file-activity filter/meta strips, and brief input chips now wrap under
width pressure; detail rows fall to one column; browser row tags and
tool-schema param columns shrink so long values ellipsize instead of
forcing their row past the card. Desktop-wide rendering is unchanged.
2026-08-27 01:03:07 +08:00
Bowen Liang 53209a14df release: v0.34.0 2026-08-26 23:28:18 +08:00
Bowen Liang 6735bf150d docs: condense the Agent Network section to its three key points 2026-08-26 23:16:40 +08:00
Bowen Liang 1a31b33191 feat: Agent Network card — live multi-agent context map in the Context tab (#21)
A new Agent Network card at the foot of the Context tab: the whole agent family (current agent, ancestors, subagents at any depth) as a live, fully responsive node map — fused context rings per session, family-colored lineage, halo status language, hover inspector, and click-to-jump into any agent's session. 693 tests, 100% coverage.
2026-08-26 23:09:19 +08:00
bowenliang123 f6564d6958 refactor: assemble registry URL inside readVersion
Drop the static REGISTRY_URLS array; readVersion(host) now concatenates
the plugin name and `/latest` path per call so the registry list holds
only the differing domain.
2026-08-26 17:19:00 +08:00
bowenliang123 3c7ca98d32 feat: fall back to npmmirror when official npm registry fails
Order registries as official npm then npmmirror; each source failure
(non-ok response, missing/non-string version, network error) advances to
the next source, and only an all-source failure resolves to null so the
plugin info card keeps its baked-in version. TTL cache and module-level
promise reuse are unchanged.
2026-08-26 17:16:09 +08:00
bowenliang123 114cd6490c docs: update language support guidelines for UI elements 2026-08-26 17:09:50 +08:00
bowenliang123 82dc480659 docs: add build step to the development checklist 2026-08-26 17:01:36 +08:00
bowenliang123 a0fc6d31d3 fix(docs): clarify commit guidelines for mixed changes and push behavior 2026-08-26 17:00:56 +08:00
bowenliang123 28f0761e7d fix(client): wrap file activity paths at any character 2026-08-26 16:56:48 +08:00
bowenliang123 0f8de3dce6 perf(client): memoize FileCard/RequestDetail and stabilize their props
The cards re-reconciled on every context-tab render — including pure
hover/select renders that never touched their inputs. FileCard and
RequestDetail are now wrapped in React.memo at the factory level, and
the view hands them reference-stable inputs across those renders:
convOf and the locate handlers are useCallback'd, the step brief and
the file activity fold are useMemo'd (the latter with convOf in its
deps so a conversation-snapshot update can never serve a stale join),
and the hook order stays ahead of the loading early-return (React #310).
Composition-chip hovers and kind-filter toggles now skip both cards
entirely.
2026-08-26 16:40:16 +08:00
bowenliang123 61f3405471 fix(client): stop remounting the events list on every push
Two compounding defects made every incoming event flash the whole card:

- Rows were keyed by seq PLUS reverse-index; the list renders newest-
  first, so an appended event lands at index 0 and shifted every
  existing row's key, forcing React to destroy and rebuild the entire
  list on each push. Rows now key on the durable seq alone, so a push
  prepends one row and keeps every other row's DOM node.
- The truncation-title layout effect had no deps: every render (hover
  included) re-read scrollWidth/clientWidth for every label — one
  forced synchronous layout per row — and rebound the resize listener.
  It now resyncs only when the events list changes, with the resize
  listener bound once (root resolved inside the callback so the
  empty-to-non-empty transition keeps it live).
2026-08-26 16:39:54 +08:00
bowenliang123 01d16bbcf0 fix(client): re-anchor the trend chart only on real data pushes
The chart's layout effect ran after every render (no deps), so any
hover/select re-render near the right edge re-ran the stick-to-end
check — and by the time it read el.scrollWidth the value was already
the post-append width, which could misfire the anchor. The effect now
runs only when granularity, focusTurn, or the request list changes,
and the near-end check compares against the PREVIOUS pass's scrollWidth
(kept in a ref), so a reader near the right edge still follows an
appended bar while a mid-chart reader is never yanked back, and a
hover/select render never touches the scroll at all.
2026-08-26 16:39:19 +08:00
bowenliang123 1b2590e0db fix(client): pin context events and file activity lists to a fixed height
Replace max-height with height on .lc-events/.lc-fa-list so both card
bodies hold a constant 320px instead of growing with row count, keeping
the dashboard layout stable as events and file entries accumulate.
2026-08-26 15:16:58 +08:00
bowenliang123 bb05794fa0 test(client): silence deliberate render-error noise in error-boundary specs
React 18 dev replays a failed render through a fake DOM event; jsdom
reports it as an uncaught window error and vitest forwards it to an
uncaughtException, which no console.error spy can catch. A window error
listener that prevents the default keeps the deliberate throw inside the
test, alongside the spy silencing React's own boundary message.
2026-08-26 14:27:37 +08:00
bowenliang123 20e3f45364 fix(client): narrow args non-null after the path guard in file activity
parseCallArgs returns null for a call that never carried arguments; the
path===null guard already implied args!==null (pathOfArgs yields null for
null args) but did not narrow it, so the delta/detail reads below failed
typecheck. State the args check explicitly.
2026-08-26 14:27:30 +08:00
bowenliang123 728426ec0e fix(docs): update test command in AGENTS.md for coverage execution 2026-08-26 14:11:58 +08:00
bowenliang123 53feea9fea feat(client): list every File Activity op on expand and drop the unresolved footnote
- Remove the MAX_OPS=8 cap: an expanded file renders its whole operation
  log instead of folding older ops behind a static "+n earlier ops" line.
- Remove the unresolved counter and footnote: a file-kind call whose
  arguments aged out of the retained window names no target and is now
  skipped outright, with totals[kind].ops incremented only after path
  resolution — every op the card counts, it also rows.
- Drop the files.unresolved/files.moreOps strings and the dead
  .lc-fa-more/.lc-fa-note rules.
2026-08-26 13:58:22 +08:00
bowenliang123 6ee52bf3ed docs: keep docs end-user faced — drop the internal design/research notes and record the rule 2026-08-26 13:41:57 +08:00
bowenliang123 66a5f0361d docs(readme): add the File Activity screenshot and describe its sort modes and row details 2026-08-26 13:37:12 +08:00
bowenliang123 02878dd6bd fix(scripts): drop the stale loadOlderHistory provide assertion from the bundle smoke 2026-08-26 13:11:10 +08:00
bowenliang123 0803b9a741 chore: bump version to 0.33.1 2026-08-26 12:17:34 +08:00
bowenliang123 4cb85812f7 style(client): keep File Activity kind chips colored while idle 2026-08-26 11:39:11 +08:00
bowenliang123 be06b09940 feat(client): tint active File Activity kind chips and count-sort by the selected kind 2026-08-26 11:36:39 +08:00
bowenliang123 57999941f5 fix(docs): update test command in AGENTS.md for coverage execution 2026-08-26 11:30:38 +08:00
bowenliang123 1a046f63c5 feat(settings): add a default sort preference for File Activity 2026-08-26 11:28:49 +08:00
bowenliang123 7280e6e90b fix(docs): correct lint command syntax in AGENTS.md 2026-08-26 11:20:28 +08:00
bowenliang123 49c65b017c feat(client): add a by-path ascending option to the File Activity sort 2026-08-26 10:45:58 +08:00
bowenliang123 14dc922c63 feat(client): add a most-active/latest sort toggle to File Activity
The file list now defaults to most-operations-first (ties broken by
recency) and a lc-gran toggle on the meta strip switches to
most-recently-touched order; the sort applies to the filtered copy, so
the fold keeps serving entries latest-first.
2026-08-26 10:33:18 +08:00
bowenliang123 fefe40ff64 style(client): restyle the File Activity card layout and colors
Expanded files read as contained layer-2 cards with a hairline frame, the
per-operation log hangs on a tree-guide rail under the chevron, count badges
and op tool chips become pills, and rows get roomier padding with tabular
timestamps.
2026-08-26 10:32:45 +08:00
Bowen Liang 6c56230f08 chore: bump version to 0.33.0 2026-08-26 08:38:10 +08:00
Bowen Liang fe7d8dafb9 feat(client): replace the Messages card with a File Activity card
The bottom-right card no longer lists model-visible messages; it answers
what the agent DID to the user's files up to the picked step. Tool-result
nodes (live + archive) join the conversation snapshot for call arguments
and fold into one row per file with per-purpose counts (read/written/
searched), estimated line deltas from edit/write arguments, multimodal
and directory form glyphs, and failure dots. Header chips double as
purpose/form filters next to a path search box; a row expands into the
file's operation log, and each operation reveals the exact tool result
in the Context browser. The card scrubs live with the trend chart pick
(exclusive next-request bound); ops whose paths aged out of retention
are honestly counted in a footnote.
2026-08-26 08:36:02 +08:00
Bowen Liang da394d7e0a refactor(context): drop the 'Top Tool Schemas' chip row from the overview
The chip row lived in CurrentComposition, was fed the fold's per-tool
toolList summary, and the chips focused the Context browser on a tool
via a one-shot toolFocus callback. The browser already exposes the
tool schemas through its headers section, so the chip row was a
duplicate entry point that no longer pulled its weight.

Removes the lc-tools DOM block, the toolFocus/onToolFocusHandled
prop wiring across ContextView/ContextModal/Browser, the
'tools.top'/'tools.more' translations, the .lc-tools* CSS, and the
now-unused toolList summary across the wire + state schemas
(stateVersion 9 -> 10). estimateToolSchema stays because headers.ts
still prices individual tools for the browser's tool-schema cards.
2026-08-26 03:45:04 +08:00
Bowen Liang 5cc028ff00 feat(client): replace history paging with seq-targeted content fetch
The Context browser joined full content against the chat conversation
window; when a surface node's seq sat outside it, the fallback paged
blindly backwards through session.loadOlder() (up to 20 pages of 50
messages prepended into the shared chat window) and finally dead-ended
on a static note.

sessions.history already supports seq-anchored pages cut on whole
append-origin message boundaries, so ONE call with beforeSeq: seq + 1
returns exactly the page holding the event whenever the durable log
still has it. The browser now:

- fetches on miss with that single anchored read and maps the raw page
  into the node shapes it already renders (new client/historyPage.ts:
  user messages, assistant blocks, tool results paired with their
  in-page call head, compaction checkpoints with their summary);
- merges fetched nodes under the zero-cost window join (join wins);
- reports honest states instead of one dead end: loading, absent from
  the session log (compacted or cleared), failed with a retry button;
- drops the sessions.provide contribution and the MAX_AUTO_PAGES
  machinery entirely - the chat scrollback is never mutated again.

Hosts without the connection api keep the static preview-plus-hint
degradation.
2026-08-26 03:34:24 +08:00
Bowen Liang 5a2b742d50 docs(AGENTS.md): clarify pnpm coverage requirement
Document the intent of the pnpm coverage check: ensure code coverage is
literally 100%.
2026-08-26 02:18:55 +08:00
Bowen Liang eb9c9b0352 ci: test without a build step; verify packaging via the bundle smoke script
The source-level suite needs no lib/ artifacts, so PR checks test
first and build afterwards solely to feed scripts/bundle-smoke.mjs;
the release workflow gains the same smoke step between test and
publish.
2026-08-26 00:59:15 +08:00
Bowen Liang a9b6d287fe test: remove the legacy bundle-dependent suite
All 19 root-level specs and the fake-React viewBed helper are
superseded by the source-level suite (606 tests, 100% per-file
coverage). The packaging behaviors they pinned (bundle handoff, CSS
channel, HMR disposal) live on in scripts/bundle-smoke.mjs.
2026-08-26 00:58:57 +08:00
Bowen Liang f106b720ac test: rebuild the suite at source level with 100% per-file coverage gates
The old suite exercised the built lib/ bundle, so v8 remapped almost
nothing (8% src coverage) and every run needed a build first. The new
suite imports src/ directly under two vitest projects (node for
host/shared, jsdom for client), rendering real React 18 trees against
the real dictionaries and ui-primitives, with faithful in-memory
harness faces (cordis inject/effect, locale chain, slots, sessions
provide) instead of plugin mocks.

- 43 fine-grained, stateless, single-module spec files (606 tests)
  forked across workers: ~2.5s wall, no build step
- v8 thresholds at 100/100/100/100 per file over src/**
- host specs drive the real projection definitions (init/apply/view)
  plus one full cordis + SessionStore + SessionProjectionRegistry
  integration; the framework's snapshotJsonValue pins the
  projection-cache precondition on every intermediate fold state
- oxlint's src ruleset now covers tests/** as well
- typecheck covers the tests via tsconfig.tests.json
2026-08-26 00:58:39 +08:00
Bowen Liang f45bd7e8d2 chore(scripts): move diff-fold out of tests/ and drop its lib/ dependency
The session-log divergence check runs under bun against src/ directly,
tracking the working tree instead of the last build. Also add
scripts/bundle-smoke.mjs (pnpm run test:bundle): the one check that
must exercise the built bundle — module-loader handoff, CSS channel
tagging, registration disposal and HMR style-tag semantics in jsdom
with real React.
2026-08-26 00:57:58 +08:00
Bowen Liang ba586e18f7 test(src): annotate evidence-backed dead branches for strict v8 coverage
Every annotation carries its evidence inline (guard dominance chains,
the 8:1 aspect clamp making the wide-solve arm unreachable, a
500k-dimension fuzz with zero hits). browser.tsx also drops two
redundant `?? null` in JSX render positions — undefined and null
render identically.
2026-08-26 00:57:28 +08:00
Bowen Liang 4e5e71a96c fix(client): widen slot-face types to the harness's real call shapes
SlotRegistration.inject is invoked without a session id for root-scope
keyed slots (settings.plugin.item), and slot components receive
harness-injected props beyond sessionId (useProjection, hooks). The
narrower types made the plugin's own registrations fail a strict
typecheck of the test harness's faithful slot registry.
2026-08-26 00:57:08 +08:00
Bowen Liang ecd9af93a8 feat(client): open the system prompt row by default when its category is clicked 2026-08-25 23:08:31 +08:00