kimi-code/packages/agent-core-v2/scripts/dep-graph/cli.ts
haozhe.yang 5bdee931e5 feat(agent-core-v2): dep-graph dev viewer + scope lint
Adds a dev-only tool under `scripts/dep-graph/` that statically analyses the
DI service graph and serves it as an interactive React Flow viewer:

- `analyzer/`: ts-morph pass over `src/**/*.ts` extracts every
  `registerScopedService` binding as a node keyed by `${scope}::${token}`,
  then records ctor / accessor / publish / subscribe / emit / on edges. Each
  edge is resolved to the concrete impl visible from the source's scope
  (walking source scope up to App); if no binding is visible the edge is
  marked `unresolved` — the exact signal for a container-construction
  failure. Framework tokens (`IKaos`, `ISessionContext`, …) are seeded so
  they don't sink into false-positive unresolveds.
- `plugin/virtual-dep-graph.ts`: Vite plugin that exposes the analyzer
  output as a `virtual:dep-graph` module, mirrors it to
  `.local/dep-graph.json`, and re-analyses on any `src/**/*.ts` change via
  chokidar with a 200 ms debounce, then invalidates the virtual module for
  HMR.
- `web/`: React + React Flow frontend with dagre auto-layout in RL mode
  (base primitives on the left, facades on the right). Sidebar filters by
  scope / edge kind / domain / search; toggles for `hide orphans` and
  `group by scope` (horizontal App | Session | Agent bands). Isolated
  nodes are pinned to the sink rank so they sit with the base primitives.
- `cli.ts` (`pnpm dep-graph:analyze`): one-shot JSON dump for CI / offline
  inspection.
- `lint.ts` (`pnpm dep-graph:lint`): treats unresolved ctor edges as
  errors (container will crash) and unresolved accessor edges as warnings
  (only safe under an active inner scope). Auto-runs the analyzer when the
  snapshot is stale.

Isolation from deploy: everything lives under `scripts/dep-graph/` and is
never referenced from `src/index.ts`, so `tsdown` doesn't bundle it into
`dist/`. The added `ts-morph`, `vite`, `react`, `react-dom`,
`@vitejs/plugin-react`, `@xyflow/react`, `@dagrejs/dagre`, `tsx`, and
`@types/react*` all land in `devDependencies` — `pnpm install --prod`
skips them.

Also adds `.vite/` to `.gitignore` so Vite's per-package dep pre-bundling
cache isn't tracked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-01 17:19:18 +08:00

21 lines
860 B
TypeScript

#!/usr/bin/env -S npx tsx
/**
* One-shot analyzer entry point. Writes the current `Graph` snapshot to
* `.local/dep-graph.json` (git-ignored) so it can be diffed, committed to a
* scratch review branch, or piped to another tool without running the dev
* server.
*
* pnpm dep-graph:analyze
*
* The dev server (`pnpm dep-graph:dev`) writes the same file continuously
* while running — this CLI is for CI, hooks, or offline inspection.
*/
import { SNAPSHOT_PATH, analyze, readHeadSha, summarize, writeSnapshot } from './analyzer/analyze';
const graph = analyze({ generatedAt: readHeadSha() ?? new Date().toISOString() });
writeSnapshot(graph);
console.log(`wrote ${SNAPSHOT_PATH}\n ${summarize(graph)}`);
if (graph.unknownTokens.length > 0) {
console.log(` unknownTokens=${graph.unknownTokens.length}: ${graph.unknownTokens.join(', ')}`);
}