Ask "how does execute reach getFile" in the search box and the viewer draws the call path between them, left to right, opening every card at the exact line that makes the next call. Dynamic-dispatch hops are dashed and name the site they were wired at; "Read as flow" turns a trail walked by hand into the same strip. The path finder is NOT new. `codegraph_explore` already leads its answers with the longest call chain among the symbols an agent named, and a viewer that drew a different path would get the two quoted against each other in a review. So the search moved out of `ToolHandler` into `src/graph/named-symbol-flow.ts` and both callers ride it — same tokens, same overload rules, same synthesized edges. What stayed behind in `tools.ts` is the prose. A pinned from/to question is the same search with two options changed, because both ends being named is the evidence explore's one-unnamed-bridge cap stands in for: it bridges freely, keeps twelve candidates per endpoint instead of six (the CLI's own `main` sorts seventh of ten), and searches from both ends at once — identical paths to the one-way walk on twelve measured pairs, 3-6x faster. `/api/flow` is deliberately the one endpoint with no cache: its cards carry source read from disk, and a drift verdict changes without the index changing. Verified on this repo (`execute` to `rowToFileRecord`, 8 hops; `main` to `resolveOne`, 7) and on a fresh excalidraw index, where `mutateElement` to `renderStaticScene` crosses callback, react-render and jsx-child hops and lists exactly the hops `codegraph_explore` prints. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
3.1 KiB
Markdown
71 lines
3.1 KiB
Markdown
# ui/ — the `codegraph ui` viewer
|
|
|
|
The browser reader for an indexed project: Svelte 5 + Vite, built as static
|
|
files and served by the CLI over loopback. An npm workspace of the engine, so
|
|
`npm ci` at the repo root installs its toolchain; nothing here is a runtime
|
|
dependency of the engine and nothing here is published to npm on its own.
|
|
|
|
Design spec (every token, size and measurement):
|
|
`../docs/design/codegraph-ui-design-spec.md`.
|
|
|
|
## Build
|
|
|
|
```bash
|
|
npm run build # from the repo root: tsc -> copy-assets -> this app
|
|
npm run build:ui # just this app, plus the dist assertion
|
|
npm run dev -w ui # Vite dev server on 127.0.0.1:5174
|
|
npm run check -w ui # svelte-check
|
|
```
|
|
|
|
`npm run build` emits **`dist/viewer/`** (`index.html` + hashed assets).
|
|
`scripts/check-ui-build.mjs` then asserts the tree is complete, so a broken UI
|
|
build fails the release instead of shipping a CLI that serves a 404. The same
|
|
check runs again in `scripts/build-bundle.sh` (after the bundle stage copies
|
|
`dist`) and in `scripts/pack-npm.sh` (after each archive is unpacked).
|
|
|
|
### Why `dist/viewer` and not `dist/ui`
|
|
|
|
`src/ui/` is the engine's **terminal** UI (shimmer progress and its worker) and
|
|
tsc compiles it to `dist/ui/`. Pointing Vite there deletes those modules — the
|
|
CLI then dies at startup with `Cannot find module '../ui/shimmer-progress'` —
|
|
and would also leave the static server handing out compiled engine internals.
|
|
`check-ui-build.mjs` re-asserts the compiled engine is intact after every UI
|
|
build so that mistake cannot land twice.
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/
|
|
main.ts fonts + tokens, mounts App into index.html's #app
|
|
app.css design tokens (light/dark), reset, shell grid
|
|
App.svelte top bar / trail bar / main, global keys
|
|
lib/router.svelte.ts hash router: #/s/<id>, #/file/<path>, #/map, #/flow
|
|
lib/trail.svelte.ts the walked path; mirrored into the `t` query param
|
|
lib/kinds.ts kind glyph letters
|
|
lib/map-model.ts the Map's deterministic layered layout (pure)
|
|
lib/flow-model.ts the Flow strip's card/link geometry — a DAG (pure)
|
|
components/ TopBar, TrailBar, KindGlyph, map/, flow/, symbol/, file/
|
|
views/ one component per route
|
|
```
|
|
|
|
Fonts (Archivo Variable, IBM Plex Mono) are vendored through `@fontsource*` and
|
|
emitted into `dist/viewer/assets`: a local reader must work offline and must not
|
|
announce the project to a font CDN.
|
|
|
|
## Routes
|
|
|
|
| hash | view |
|
|
|---|---|
|
|
| `#/` | nothing selected |
|
|
| `#/s/<id>?hl=<line>&t=<trail>` | symbol view |
|
|
| `#/file/<path>?hl=<line>` | file view |
|
|
| `#/map?root=&depth=&tests=1` | module map |
|
|
| `#/flow?from=&to=` | flow strip — the call path between two symbols |
|
|
| `#/flow?symbols=a,b,c` | flow strip — `codegraph_explore`'s own question |
|
|
| `#/flow?t=<trail>` | flow strip — the trail you walked, read as a flow |
|
|
|
|
Node ids and file paths are encoded per slash-separated segment, so
|
|
`#/file/src/mcp/tools.ts` stays readable and still round-trips a segment
|
|
containing a reserved character. Build hashes with `symbolHref()` /
|
|
`fileHref()` / `mapHref()` / `flowHref()` rather than by hand.
|