Files
codebase-memory-mcp/graph-ui/tools/lib/compiler-bundle.mjs
T
Martin VogelandBernhard Jackiewicz 67e39d16c0 feat(ui): replace graph-ui with CodeAtlasWeb by Bernhard Jackiewicz
Imports the CodeAtlasWeb companion frontend verbatim from
BernhardJackiewicz/CodeAtlasWeb at commit
1825f9c850ac794066e02606012508b9d393c6aa as the new graph-ui and removes
the previous React frontend.

This is Bernhard Jackiewicz's work, contributed with his agreement and
squashed here from his development history (41 commits, cycles W0
through W15). The maintainer only relocates it: every product decision,
line of code and test below graph-ui/ is his. The seven galaxy files
that originate in this repository's previous graph-ui, and the pinned
3D libraries, are listed in graph-ui/THIRD_PARTY.md.

What it is: a local reading IDE on the CBM read surface. A read-only
Monaco source reader, a semantic twin that follows the caret, entry,
bug-hunt, change-scope and flow reading modes, deterministic
source-cited explanations with an optional local-model wording pass
(llama-server sidecar, off unless the reader starts one; no model or
binary ships), a persistent galaxy with focus following in both
directions, a live-agent overlay fed by a loopback bridge, explicit
air-gap, provenance and index-limit messaging, and an offline
acceptance and browser verification harness.

It consumes POST /rpc (the read-only tool allowlist), GET /api/layout,
and the atlas routes /api/tree, /api/trace, /api/flows and /api/flow,
plus the real ingest_traces store for observed calls; all of these are
on feat/atlas-r1 (#1860), which this change stacks on.

Not imported: CLAUDE.md (an agent-instruction file, which stays
local-only in this repository), and the recorded proof artifacts under
graph-ui/verification/, which follow in a separate commit so they can
be reviewed and dropped on their own.

Build wiring, the dev-proxy port contract, the CSP allowance for the
sidecar and bridge ports, and the control surfaces the previous
frontend had (project indexing, ADR editor, logs) follow in separate
maintainer commits.

Design and tracking: #1964.

Co-authored-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-09-05 20:05:43 +02:00

69 lines
2.9 KiB
JavaScript

/**
* The context compiler, made importable from a Node tool.
*
* The eval has to build cards the way the product builds them, and the product
* is TypeScript compiled by Vite for a browser. Three ways out of that existed
* and two were rejected:
*
* - **Reimplement the compiler in the tool.** Rejected: the eval would then be
* scoring cards no reader ever sees, and the first drift between the two
* would be invisible.
* - **Drive the eval through a browser.** Rejected: six models times forty
* questions is 240 requests, and putting Playwright between a measurement and
* the process it measures adds a second thing that can be slow.
* - **Bundle the compiler for Node with esbuild.** Taken. esbuild is already a
* dependency of Vite, so nothing is installed and nothing is fetched; the
* entry is src/compiler/eval-entry.ts, which re-exports the product's own
* modules and adds nothing.
*
* The bundle is written under .eval-build/ and rebuilt on every run, because a
* cached bundle of a compiler somebody just edited is the exact failure this
* whole arrangement exists to avoid.
*/
import { mkdir, rm } from 'node:fs/promises';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
/** Where the bundle lands. Gitignored, rebuilt per run. */
export const BUNDLE_DIR = join(ROOT, '.eval-build');
export const BUNDLE_FILE = join(BUNDLE_DIR, 'compiler.mjs');
/**
* Build the bundle and import it.
*
* `platform: 'neutral'` with an ESM format keeps Node's globals (fetch, crypto)
* as globals instead of shimming them, which is what the provider layer already
* expects: it reads `globalThis.fetch` and `globalThis.crypto.subtle`, both of
* which Node has had since 18.
*/
export async function loadCompiler() {
const esbuild = await import('esbuild');
await rm(BUNDLE_DIR, { recursive: true, force: true });
await mkdir(BUNDLE_DIR, { recursive: true });
const result = await esbuild.build({
entryPoints: [join(ROOT, 'src', 'compiler', 'eval-entry.ts')],
outfile: BUNDLE_FILE,
bundle: true,
format: 'esm',
platform: 'neutral',
target: 'node20',
mainFields: ['module', 'main'],
conditions: ['node', 'import'],
logLevel: 'silent',
metafile: true,
});
const inputs = Object.keys(result.metafile?.inputs ?? {}).length;
/*
* esbuild keeps a helper process alive after a build and Node will not exit
* while it is there. Measured, not guessed: without this line the eval sits
* at 100 percent done with an idle `esbuild --service --ping` beside it and
* never returns. A tool that has finished must end.
*/
await esbuild.stop();
const module = await import(pathToFileURL(BUNDLE_FILE).href);
return { module, inputs };
}