agentic-mermaid 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/AGENT_NATIVE.md +671 -0
  2. package/CHANGELOG.md +36 -0
  3. package/Instructions_for_agents.md +89 -0
  4. package/README.md +8 -8
  5. package/assets/hero.png +0 -0
  6. package/dist/agent-core.d.ts +2 -2
  7. package/dist/agent-core.js +2 -2
  8. package/dist/agent.d.ts +2 -2
  9. package/dist/agent.js +4 -4
  10. package/dist/agentic-mermaid-mcp.js +5 -5
  11. package/dist/am.js +8 -15
  12. package/dist/browser.global.js +777 -0
  13. package/dist/{chunk-WN3YDOBG.js → chunk-3QCXO4V6.js} +4 -4
  14. package/dist/{chunk-4QECACIA.js → chunk-AVCWKYII.js} +19 -19
  15. package/dist/{chunk-WI35L7IR.js → chunk-GILQUGFK.js} +2 -2
  16. package/dist/{chunk-QKDLMOJJ.js → chunk-HFD4MALA.js} +7 -9
  17. package/dist/{chunk-CDPKJ2BQ.js → chunk-UJNY65QS.js} +2 -2
  18. package/dist/{chunk-ZYMMKQ3I.js → chunk-WHYJLDYG.js} +299 -973
  19. package/dist/{index-D54dqSdC.d.ts → index-CLwYn6Im.d.ts} +7 -4
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/mcp-cli-SJVOGRA6.js +17 -0
  23. package/docs/README.md +35 -34
  24. package/docs/agent-api-cookbook.md +317 -0
  25. package/docs/agent-mutation-policy.md +104 -0
  26. package/docs/agent-workflow-examples.md +46 -0
  27. package/docs/api.md +418 -0
  28. package/docs/ascii.md +113 -0
  29. package/docs/browser.md +183 -0
  30. package/docs/code-mode-impact.md +214 -0
  31. package/docs/comparison.md +106 -0
  32. package/docs/computational-aesthetics-prototype-plan.md +252 -0
  33. package/docs/config.md +121 -0
  34. package/docs/custom-fonts.md +265 -0
  35. package/docs/custom-style-cookbook.md +275 -0
  36. package/docs/diagram-families.md +218 -0
  37. package/docs/features.md +154 -0
  38. package/docs/fork-differences.md +166 -0
  39. package/docs/getting-started.md +182 -0
  40. package/docs/issue-derived-test-cases.md +163 -0
  41. package/docs/mcp-code-mode-rationale.md +108 -0
  42. package/docs/mcp-http-transport.md +230 -0
  43. package/docs/mermaid-layout-complaints.md +851 -0
  44. package/docs/mutation-testing.md +285 -0
  45. package/docs/quality.md +224 -0
  46. package/docs/react.md +97 -0
  47. package/docs/style-authoring.md +336 -0
  48. package/docs/svg-semantic-contract.md +49 -0
  49. package/docs/testing-strategy.md +443 -0
  50. package/docs/theming.md +149 -0
  51. package/package.json +28 -9
  52. package/server.json +2 -2
  53. package/skills/agentic-mermaid-live-editor/SKILL.md +1 -1
  54. package/dist/mcp-cli-SBQSTJFC.js +0 -17
package/docs/ascii.md ADDED
@@ -0,0 +1,113 @@
1
+ # ASCII and terminal output
2
+
3
+ Agentic Mermaid can render Mermaid diagrams as terminal text. Unicode box drawing is the default; 7-bit ASCII is available for logs, email, CI output, and constrained terminals.
4
+
5
+ ## Quick start
6
+
7
+ ```ts
8
+ import { renderMermaidASCII } from 'agentic-mermaid/agent'
9
+
10
+ const unicode = renderMermaidASCII(`flowchart LR
11
+ API --> DB`)
12
+ const ascii = renderMermaidASCII(`flowchart LR
13
+ API --> DB`, { useAscii: true })
14
+ ```
15
+
16
+ CLI:
17
+
18
+ ```bash
19
+ am render diagram.mmd --format ascii
20
+ am render diagram.mmd --format unicode
21
+ ```
22
+
23
+ ## Options
24
+
25
+ `AsciiRenderOptions` extends the canonical shared `RenderOptions` used by SVG
26
+ and PNG, so Style stacks, colors, font choice, security policy, and other
27
+ shared request fields enter through the same boundary. Call
28
+ `sharedRenderOptionsJsonSchema()` for the machine-readable shared field set.
29
+ The options below are terminal-specific.
30
+
31
+ ```ts
32
+ renderMermaidASCII(source, {
33
+ useAscii: true,
34
+ paddingX: 4,
35
+ paddingY: 2,
36
+ boxBorderPadding: 1,
37
+ colorMode: 'none',
38
+ targetWidth: 80,
39
+ })
40
+ ```
41
+
42
+ | Option | Type | Default | Meaning |
43
+ |---|---|---:|---|
44
+ | `useAscii` | `boolean` | `false` | Use `+`, `-`, `|` instead of Unicode box drawing. |
45
+ | `paddingX` | `number` | `5` | Horizontal spacing between boxes. |
46
+ | `paddingY` | `number` | `5` | Vertical spacing between layers. |
47
+ | `boxBorderPadding` | `number` | `1` | Padding inside node boxes. |
48
+ | `colorMode` | `string` | `'auto'` | `'none'`, `'auto'`, `'ansi16'`, `'ansi256'`, `'truecolor'`, or `'html'`. |
49
+ | `theme` | `Partial<AsciiTheme>` | — | Override terminal colors. |
50
+ | `maxWidth` | `number` | — | Deprecated best-effort label wrapping; the canvas may exceed it. |
51
+ | `targetWidth` | `number` | — | Hard maximum in terminal display cells; impossible geometry throws `AsciiWidthError` with code `ASCII_TARGET_WIDTH_IMPOSSIBLE`. |
52
+
53
+ HTML is an escaped terminal projection, selected programmatically with
54
+ `renderMermaidASCII(source, { colorMode: 'html' })`. It is not a standalone
55
+ `am render --format` value; CLI discovery advertises only directly supported
56
+ artifact formats.
57
+
58
+ ## ASCII with metadata
59
+
60
+ Agents and TUIs can use `renderMermaidASCIIWithMeta` to map terminal cells back to diagram regions:
61
+
62
+ ```ts
63
+ import { renderMermaidASCIIWithMeta } from 'agentic-mermaid/agent'
64
+
65
+ const { ascii, regions, actions, warnings, routeParity } = renderMermaidASCIIWithMeta(source)
66
+ ```
67
+
68
+ `regions` includes best-effort terminal spans for load-bearing node labels, edge labels where mapped, participant/task/chart labels, and semantic containers such as clusters, sequence fragments, class compartments, chart plots, and radar rings. It is suitable for click mapping, but is not a full cell-by-cell box/edge hit-test tree. `actions` contains inert action metadata only; a host must decide whether and how to handle it. `routeParity` is an explicit V1 contract: ASCII/Unicode does not consume SVG route certificates directly; the converter seeds edges with shared `classifyRoutes()` route intent and the grid router maps that intent into terminal placement/routing. `warnings` reports structured degradation such as `ASCII_EDGE_REGION_UNMAPPED` when edge cell spans are not instrumented even though route drawing still follows the parity mapping.
69
+
70
+ ## Reversing simple flowcharts
71
+
72
+ ```ts
73
+ import { asciiToMermaid } from 'agentic-mermaid/agent'
74
+
75
+ const result = asciiToMermaid(ascii)
76
+ if (result.ok) {
77
+ const source = result.value // reconstructed Mermaid source
78
+ }
79
+ ```
80
+
81
+ `asciiToMermaid` returns a `Result<string, ParseError[]>`: `result.value` holds the
82
+ Mermaid source on success, and `result.error` lists parse errors (e.g. `NO_BOXES`)
83
+ otherwise. This is best-effort and lossy. It is useful for simple linear flowcharts,
84
+ not for reconstructing arbitrary Mermaid source.
85
+
86
+ ## Supported families
87
+
88
+ Family support is registry-driven rather than maintained as a second list in
89
+ this guide. Run `am capabilities --json` for live discovery; the generated
90
+ [Section A capability matrix](./project/section-a-capability-report.md) records
91
+ terminal projection support and named losses for every registered family.
92
+
93
+ Style appearance is projected to terminal colors and glyphs. Use a
94
+ receipt-bearing render API to compare its `appearanceDigest` with graphical
95
+ outputs, and inspect projection diagnostics when a graphical feature has no
96
+ terminal equivalent. `colorMode: 'auto'` disables color for non-TTY output,
97
+ `TERM=dumb`, and `NO_COLOR` before considering color-depth hints.
98
+
99
+ PNG output is separate: use `renderMermaidPNG(source)` or `am render --format png --output file.png` when a raster artifact is required.
100
+
101
+ ## XY charts
102
+
103
+ XY charts render to a compact terminal plot:
104
+
105
+ ```ts
106
+ const chart = renderMermaidASCII(`xychart-beta
107
+ title "Latency"
108
+ x-axis [p50, p95, p99]
109
+ y-axis "ms" 0 --> 500
110
+ line [50, 180, 420]`)
111
+ ```
112
+
113
+ Use SVG or PNG for publication-quality chart artifacts; use ASCII/Unicode for terminal summaries and agent-visible evidence.
@@ -0,0 +1,183 @@
1
+ # Browser and static sites
2
+
3
+ Two supported ways to get a diagram onto a web page. Pick by one question: **is
4
+ the diagram source known before the page is served?**
5
+
6
+ | Your case | Use | JS shipped |
7
+ |---|---|---|
8
+ | Source is fixed at publish time — blog post, docs page, README | [Pre-render at build time](#pre-render-at-build-time) | none |
9
+ | Source is authored or edited in the page — editor, playground, user input | [Browser bundle](#browser-bundle) | ~873 KB gzip |
10
+
11
+ Most sites are the first row. `renderMermaidSVG` is synchronous and needs no DOM,
12
+ so a static site never has to ship the renderer to a reader.
13
+
14
+ ## Pre-render at build time
15
+
16
+ Call the library from whatever already builds your site. Emit one SVG per theme
17
+ and let CSS choose, so a theme toggle is instant and needs no re-render:
18
+
19
+ ```ts
20
+ // scripts/render-diagrams.ts
21
+ import { writeFileSync } from 'node:fs'
22
+ import { renderMermaidSVG } from 'agentic-mermaid'
23
+
24
+ const source = `timeline
25
+ title History of Social Media
26
+ 2002 : LinkedIn
27
+ 2004 : Facebook : Google
28
+ 2006 : Twitter`
29
+
30
+ const light = renderMermaidSVG(source, { style: 'zinc-light' })
31
+ const dark = renderMermaidSVG(source, { style: 'zinc-dark' })
32
+
33
+ writeFileSync(
34
+ 'dist/timeline.html',
35
+ `<div class="diagram">
36
+ <div class="diagram-light">${light}</div>
37
+ <div class="diagram-dark">${dark}</div>
38
+ </div>`,
39
+ )
40
+ ```
41
+
42
+ ```css
43
+ .diagram-dark { display: none }
44
+ .dark .diagram-light { display: none } /* `.dark` = your dark-mode class */
45
+ .dark .diagram-dark { display: block }
46
+ ```
47
+
48
+ Or from the CLI, with no build script at all:
49
+
50
+ ```bash
51
+ am render diagram.mmd --format svg --style zinc-light --output dist/diagram-light.svg
52
+ am render diagram.mmd --format svg --style zinc-dark --output dist/diagram-dark.svg
53
+ ```
54
+
55
+ Either way the reader downloads two inline SVGs rather than a renderer, so the
56
+ diagram still shows up with JavaScript disabled and inside an RSS reader.
57
+
58
+ ## Browser bundle
59
+
60
+ When the source is not known until the page runs, load the prebuilt IIFE. The
61
+ ESM entry would need a bundler or an import map; this file needs neither:
62
+
63
+ ```html
64
+ <script
65
+ src="https://unpkg.com/agentic-mermaid@0.3.0/dist/browser.global.js"
66
+ integrity="sha384-YcMQSsCGfs4ZfuWkYNET2L2z0f+YNPJftR5krUhTWrHDQ9cUcsRRp5ux5zbBYKd9"
67
+ crossorigin="anonymous"></script>
68
+ <script>
69
+ const svg = agenticMermaid.renderMermaidSVG('timeline\n title Roadmap\n 2026 : Ship', {
70
+ style: 'zinc-dark',
71
+ security: 'strict',
72
+ })
73
+ const parsed = new DOMParser().parseFromString(svg, 'image/svg+xml')
74
+ if (parsed.querySelector('parsererror') || parsed.documentElement.localName !== 'svg') {
75
+ throw new Error('renderer returned invalid SVG')
76
+ }
77
+ document.querySelector('#diagram').replaceChildren(
78
+ document.importNode(parsed.documentElement, true),
79
+ )
80
+ </script>
81
+ ```
82
+
83
+ The global is **`agenticMermaid`** and carries the same render surface as the
84
+ package entry — `renderMermaidSVG`, `renderMermaidASCII`, style helpers.
85
+
86
+ Keep `security: 'strict'` for authored or user-provided source, and insert the
87
+ accepted result as parsed XML nodes as shown above. Do not assign renderer output
88
+ to `innerHTML`: strict rendering and DOM insertion are separate trust boundaries.
89
+ The integrity value pins the reviewed bytes as well as the version. When the
90
+ package version changes, recompute it with:
91
+
92
+ ```bash
93
+ openssl dgst -sha384 -binary dist/browser.global.js | openssl base64 -A
94
+ ```
95
+
96
+ For a strict Content Security Policy, either self-host the bundle under
97
+ `script-src 'self'` or allow the pinned CDN origin (for example
98
+ `script-src 'self' https://unpkg.com`). Put the initializer in an external
99
+ same-origin file, or authorize it with a nonce or hash; do not add
100
+ `'unsafe-inline'` just for this example.
101
+
102
+ **The bundle ships from v0.3.0.** Earlier releases are ESM-only and have no
103
+ `dist/browser.global.js`, so an unversioned CDN URL 404s against them. Pin the
104
+ version as above rather than tracking `latest`: it fixes that, and it stops a
105
+ future major from changing the file under a page you are not watching.
106
+
107
+ ### Browser support
108
+
109
+ **Chrome 97, Firefox 104, Safari 15.4, Edge 97** and newer.
110
+
111
+ `Array.prototype.findLast` sets that floor. It is a runtime method, so lowering
112
+ the build target will not help: esbuild rewrites syntax and leaves method calls
113
+ as they are. The bundle also calls `Array.prototype.at`, `Object.hasOwn`, and
114
+ `String.prototype.replaceAll`, all of which ship earlier than `findLast`. To
115
+ support older browsers, load polyfills for those four before the bundle.
116
+
117
+ CI runs the contract against the current Playwright Chromium, Firefox, and
118
+ WebKit engines. The historical version floors above are derived from runtime API
119
+ availability; this project does not execute those legacy browser releases in CI.
120
+
121
+ The bundle contains no WebAssembly and makes no network request at load, so it
122
+ works offline and needs no cross-origin isolation.
123
+
124
+ **If you already run a bundler, do not use this file.** Import the package
125
+ normally; your bundler will tree-shake, which the IIFE cannot:
126
+
127
+ ```js
128
+ import { renderMermaidSVG } from 'agentic-mermaid'
129
+ ```
130
+
131
+ ### Weight
132
+
133
+ `dist/browser.global.js` is 2.85 MB raw, **873 KB gzip**. Most of that is the ELK
134
+ layout engine. Because a page whose diagrams never change pays that cost on every
135
+ cold visit for nothing, the build-time path above is the recommendation.
136
+
137
+ ### Self-hosting it
138
+
139
+ unpkg and jsDelivr already do the right thing. If you serve the file yourself,
140
+ send `Content-Type: text/javascript; charset=utf-8`, and compress it — 2.85 MB
141
+ uncompressed against 873 KB gzipped is the difference your readers pay.
142
+
143
+ Declare the encoding in at least one of the two places. The bundle contains
144
+ non-ASCII characters inside a Unicode character class, and a classic
145
+ `<script src>` whose response omits `charset` is decoded using the host
146
+ document's encoding. If neither the response nor the page says UTF-8, the
147
+ browser picks a legacy encoding and the file throws
148
+
149
+ ```txt
150
+ SyntaxError: Invalid regular expression: Range out of order in character class
151
+ ```
152
+
153
+ before any of your code runs, with nothing in the stack trace pointing at the
154
+ encoding. A page with `<meta charset="utf-8">` is already safe; a hand-written
155
+ page with no `<head>` metadata is the one that breaks.
156
+
157
+ ### Rolling your own bundle
158
+
159
+ You should not need to. If you do, two traps fail quietly enough to cost an
160
+ afternoon:
161
+
162
+ - **Do not combine `--global-name=X` with `window.X = …` in your entry file.**
163
+ esbuild emits `var X = (() => { … })()`, and at top-level script scope that
164
+ `var` *is* `window.X`. Your assignment runs first, then the IIFE's return
165
+ value — `undefined`, if your entry exports nothing — overwrites it. The build
166
+ succeeds and the global is empty. Use `export * from 'agentic-mermaid'` in the
167
+ entry and let `--global-name` do the work.
168
+ - **`dist/` is a build artifact and is not in the git repository.** Install from
169
+ npm, or run `bun install && bun run build` in a clone before pointing a
170
+ bundler at `dist/`.
171
+
172
+ ## Coming from Beautiful Mermaid
173
+
174
+ Upstream's `THEMES` export does not exist here; it was replaced by the composable
175
+ Style/Palette system. The theme names survive as style names:
176
+
177
+ ```js
178
+ renderMermaidSVG(src, THEMES['zinc-dark']) // upstream
179
+ renderMermaidSVG(src, { style: 'zinc-dark' }) // Agentic Mermaid
180
+ ```
181
+
182
+ See [`fork-differences.md`](./fork-differences.md) for the full list of
183
+ divergences, and [`theming.md`](./theming.md) for the Style model.
@@ -0,0 +1,214 @@
1
+ # Code Mode in Agentic Mermaid: impact, comparison, and costs
2
+
3
+ Agentic Mermaid uses Code Mode to keep a diagram edit inside one execution:
4
+ parse the source, narrow it to a mutable family, apply typed operations, verify
5
+ the result, and serialize only after verification passes. This changes both
6
+ the model-facing boundary and the execution boundary. The model writes a small
7
+ algorithm instead of relaying each intermediate diagram through another tool
8
+ call, while the server retains the trusted diagram lineage needed to reject
9
+ forged or invalid edits.
10
+
11
+ This document uses **local Code Mode** for the self-hosted MCP process running
12
+ on the agent's machine and **hosted Code Mode** for the public
13
+ `https://agentic-mermaid.dev/mcp` endpoint. Cloudflare calls the same split
14
+ client-side and server-side Code Mode. The names describe where the sandbox
15
+ runs, not where the model runs.
16
+
17
+ ## Local Code Mode
18
+
19
+ The local `agentic-mermaid-mcp` exposes `execute(code)`, which runs synchronous
20
+ JavaScript against the typed `mermaid.*` SDK in a hardened `node:vm` context.
21
+ The execution can retain parsed diagrams between SDK calls, so the model does
22
+ not have to copy an intermediate representation into another JSON request.
23
+ That matters because Agentic Mermaid's mutation checks depend on provenance:
24
+ SDK results are read-only, and structured changes must pass through
25
+ `mermaid.mutate`.
26
+
27
+ Running beside the agent also keeps diagram source local and avoids hosted
28
+ compute charges. The local server can return managed PNG files or URLs through
29
+ its direct `render_png` helper, while multi-step editing remains in `execute`.
30
+ The [MCP Code Mode rationale](./mcp-code-mode-rationale.md) explains why those
31
+ helpers stay narrow rather than recreating the full SDK as individual tools.
32
+
33
+ Progressive SDK discovery removed the largest client-side cost. The initial
34
+ `execute` declaration now contains the core SDK, while
35
+ `describe_sdk({ family, detail })` returns the mutation schema for one diagram
36
+ family. An agent that already knows an operation can skip discovery; an agent
37
+ handling an unfamiliar family can request compact signatures or exact fields.
38
+
39
+ ## Hosted Code Mode
40
+
41
+ The hosted endpoint puts the sandbox behind the MCP server, so an ordinary MCP
42
+ client gets Code Mode without shipping its own execution environment. Each
43
+ hosted `execute` runs in a Cloudflare Dynamic Worker configured with an empty
44
+ environment, `globalOutbound: null`, no subrequests, and a bounded CPU budget.
45
+ The isolate configuration is the security boundary. The hardened SDK facade is
46
+ kept for behavioural parity with the local server.
47
+
48
+ Hosted execution has a per-call cost, so common pure operations do not enter
49
+ the sandbox. `render_svg`, `render_ascii`, `render_png`, `verify`, `describe`,
50
+ and `describe_sdk` run as ordinary Worker calls whose successful deterministic
51
+ results can be reused by the private server-side Workers Cache. The JSON-RPC
52
+ HTTP responses remain `cache-control: no-store`.
53
+ Declarative `mutate` and `build` apply typed operation lists through the same
54
+ mutation core and verify before returning source. They give smaller models a
55
+ direct path for routine edits while reserving `execute` for control flow that
56
+ the operation list cannot express.
57
+
58
+ Local and hosted Code Mode share the same `mermaid.*` facade. Differential
59
+ tests compare result envelopes, errors, trace behaviour, read-only enforcement,
60
+ and serialization across both runtimes. The
61
+ [hosted MCP as-built record](./project/archive/hosted-mcp-cloudflare-plan.md) documents
62
+ the remaining runtime differences and abuse controls.
63
+
64
+ ## Measured effect
65
+
66
+ [PR #157](https://github.com/adewale/agentic-mermaid/pull/157) measured the
67
+ serialized declarations and tool lists with `o200k_base`. These counts are a
68
+ stable before-and-after proxy, not a provider billing claim.
69
+
70
+ | Model-facing surface | Before | After | Tokens saved |
71
+ |---|---:|---:|---:|
72
+ | `execute` SDK declaration | 10,527 | 903 | 9,624 (91.4%) |
73
+ | Local `tools/list` | 11,781 | 1,840 | 9,941 (84.4%) |
74
+ | Hosted `tools/list` | 15,646 | 2,969 | 12,677 (81.0%) |
75
+
76
+ The median complete family schema is 495 tokens. A hosted client that loads the
77
+ initial tool list and then requests that schema consumes 3,464 tokens, 77.9%
78
+ less than the old hosted list. The largest family, flowchart, brings the total
79
+ to 4,928 tokens, which is still 68.5% lower. Compact signature responses have a
80
+ 113-token median.
81
+
82
+ The same PR ran four schema-sensitive edits against the exact before and after
83
+ hosted tool lists. Each proposed mutation was replayed through the real
84
+ `applyOps` implementation and checked against semantic facts.
85
+
86
+ | Model | Before task-correct | After task-correct | After discovery |
87
+ |---|---:|---:|---:|
88
+ | `gpt-5.4-mini` | 3/4 | 4/4 | 4/4 |
89
+ | `gpt-5.3-codex-spark` | 4/4 | 4/4 | 4/4 |
90
+ | **Combined** | **7/8** | **8/8** | **8/8** |
91
+
92
+ All 16 mutations across both conditions applied successfully. The one incorrect
93
+ before-case omitted a requested Architecture edge label; the after-case kept
94
+ it. The combined four-case prompt fell from 16,048 to 5,833 tokens, a 63.7%
95
+ reduction even though the test prompt included all four family responses at
96
+ once. A normal request discloses one family.
97
+
98
+ This eval is evidence for the discovery change, not a broad model-quality
99
+ claim. It covers four tasks and two small models. Larger task sets, more model
100
+ families, and production latency measurements remain separate work.
101
+
102
+ ## Comparison with Cloudflare and Anthropic
103
+
104
+ Agentic Mermaid applies Code Mode to a pure diagram library. Cloudflare and
105
+ Anthropic apply the same technique to general tool catalogs, where generated
106
+ code may call remote services and carry data between them. That scope
107
+ difference explains most of the implementation differences.
108
+
109
+ | Dimension | Agentic Mermaid | Cloudflare | Anthropic |
110
+ |---|---|---|---|
111
+ | Primary scope | One deterministic diagram SDK | MCP tools and large APIs | General tool catalogs |
112
+ | Discovery | `describe_sdk` for one diagram family | Typed connectors, or `search` over an OpenAPI document | Tool Search, or filesystem-shaped tool definitions |
113
+ | Model-written code | Synchronous JavaScript | Asynchronous JavaScript | Python in Programmatic Tool Calling |
114
+ | Execution | Local `node:vm` or hosted Dynamic Worker | Dynamic Worker isolate | Anthropic Code Execution sandbox |
115
+ | Calls made from code | Pure in-process SDK calls | MCP calls or an authenticated request callback | Developer-provided tools |
116
+ | External effects | None beyond returned diagram artifacts | Allowed through host-controlled bindings and authorization | Allowed for tools that opt into programmatic calling |
117
+ | Persistent state | None | Durable runtime options are available | Filesystem state and reusable skills are possible |
118
+
119
+ ### Cloudflare
120
+
121
+ Cloudflare's first Code Mode implementation converted connected MCP tools into
122
+ a TypeScript API and ran the model's JavaScript in a Dynamic Worker. Its current
123
+ MCP patterns cover both a single `code` tool, where the complete generated API
124
+ fits in the tool description, and `search` plus `execute`, where a large
125
+ OpenAPI document stays inside the discovery sandbox. Authentication remains in
126
+ the host callback rather than entering generated code.
127
+
128
+ That general implementation supports asynchronous calls, remote APIs,
129
+ authorization and, in the durable runtime, pause-and-resume approval. Agentic
130
+ Mermaid does not need those facilities because its SDK calls are synchronous,
131
+ pure, and confined to one diagram transaction. It does use the same Dynamic
132
+ Worker substrate for hosted isolation, but it does not depend on
133
+ `@cloudflare/codemode`.
134
+
135
+ Cloudflare measured its server-side `search` and `execute` surface at roughly
136
+ 1,000 tokens for more than 2,500 API endpoints, 99.9% fewer than direct MCP
137
+ definitions. Agentic Mermaid's percentage is not directly comparable because
138
+ its catalog is smaller and its hosted tool list retains more direct helpers.
139
+
140
+ Sources: [original Code Mode design](https://blog.cloudflare.com/code-mode/),
141
+ [server-side API implementation](https://blog.cloudflare.com/code-mode-mcp/),
142
+ and [current MCP server patterns](https://developers.cloudflare.com/agents/model-context-protocol/codemode/).
143
+
144
+ ### Anthropic
145
+
146
+ Anthropic's November 2025 architecture generated a filesystem-like tree of MCP
147
+ tool definitions so an agent could inspect only the files it needed. It also
148
+ proposed a `search_tools` alternative with selectable detail levels. The code
149
+ execution environment could filter large results, retain intermediate state,
150
+ and pass data between tools without putting that data into the model context.
151
+
152
+ Anthropic later shipped the mechanism as Tool Search and Programmatic Tool
153
+ Calling. Deferred tools stay out of the initial prompt, while Python running in
154
+ the Code Execution sandbox can pause for an allowed tool, process the result,
155
+ and continue without sending that result through another model inference.
156
+ Anthropic reported an 85% token reduction for Tool Search in a large catalog,
157
+ along with accuracy gains on its MCP evaluations.
158
+
159
+ Agentic Mermaid's `describe_sdk` follows the same progressive-disclosure
160
+ principle but uses a family key instead of general search. Its execution model
161
+ is intentionally smaller: no filesystem, no persistence, no arbitrary tool
162
+ catalog, and no asynchronous callback loop.
163
+
164
+ Sources: [Code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp)
165
+ and [advanced tool use](https://www.anthropic.com/engineering/advanced-tool-use).
166
+
167
+ ## Costs and limits
168
+
169
+ Progressive discovery moves schema tokens out of the initial prompt, but an
170
+ unfamiliar edit now needs a `describe_sdk` call before `mutate`, `build`, or
171
+ `execute`. That extra round trip is wasted on a small catalog whose definitions
172
+ are used in every session. It pays off here because most diagram tasks use one
173
+ registered family, and the old declarations devoted 93.1% of the hosted tool-list
174
+ tokens to the full SDK and repeated mutation menus.
175
+
176
+ Code execution also adds work that a direct tool does not need. A one-shot
177
+ render, verification, or straightforward operation list should use the hosted
178
+ direct tools. Models, especially smaller ones, can make JavaScript mistakes or
179
+ violate the SDK's provenance and serialization rules; `mutate` and `build`
180
+ exist because those failures were observed in practice.
181
+
182
+ The local and hosted sandboxes have deliberate constraints:
183
+
184
+ - Code Mode is synchronous. It rejects `async`/`await`, Promise jobs, dynamic
185
+ imports, finalizers, and queued microtasks.
186
+ - Sandbox code has no filesystem, external network, environment variables, or
187
+ persistent workspace.
188
+ - Local `node:vm` is hardened but is not an operating-system or container
189
+ security boundary. It is a local tool for trusted use.
190
+ - Hosted execution contacts a billable Dynamic Worker on every call. Worker
191
+ Loader IDs are content-addressed so identical code can reuse a warm isolate,
192
+ while direct tools and their private compute cache keep routine work off that
193
+ path.
194
+ - Hosted `execute` responses are never compute-cached: Code Mode exposes time
195
+ and randomness, so retaining the first result would violate its observable
196
+ contract.
197
+ - Local timeouts use wall-clock time, while hosted limits use CPU time. Warm
198
+ hosted isolates can retain module globals, hosted output is capped, and
199
+ hosted PNG bytes are not part of the cross-runtime byte-determinism contract.
200
+
201
+ Keeping intermediate results outside model context is useful only when code
202
+ can decide what to discard. If the model must inspect each intermediate result
203
+ to make a semantic judgment, direct calls may be more appropriate. Anthropic
204
+ makes the same distinction for simple lookups and tasks where Claude should see
205
+ all intermediate data.
206
+
207
+ ## Decision
208
+
209
+ Because Agentic Mermaid's useful unit of work is a verified diagram
210
+ transaction rather than a general agent computer, its Code Mode surface can
211
+ stay narrow. The model receives the core SDK, requests one family schema when
212
+ needed, and returns reviewable Mermaid source only after the same verifier used
213
+ by the library and CLI has accepted it. That verified source is the outcome by
214
+ which the extra sandbox and discovery call should be judged.
@@ -0,0 +1,106 @@
1
+ # Mermaid, Beautiful Mermaid, and Agentic Mermaid
2
+
3
+ Use this page to decide which of the three projects fits your task. The
4
+ table maps what each one can do; the sections after it name what only each
5
+ one does, and the final section tells you which to install for common jobs.
6
+
7
+ - **[Mermaid](https://github.com/mermaid-js/mermaid)** (`mermaid`) is the
8
+ original. It defines the grammar that both other projects implement,
9
+ supports roughly 25 diagram types, and is rendered natively by GitHub,
10
+ GitLab, Notion, and Obsidian — which is why most diagrams-as-text you will
11
+ encounter are written in its language.
12
+ - **[Beautiful Mermaid](https://github.com/lukilabs/beautiful-mermaid)**
13
+ (`beautiful-mermaid`, by Craft) re-implements Mermaid rendering as a
14
+ synchronous TypeScript library: it computes layout itself and emits SVG
15
+ strings, so it runs in Node, Bun, or an edge function with no browser and
16
+ no Puppeteer. Its theming derives a full palette from two colors and
17
+ accepts Shiki/VS Code themes directly, and it renders to ASCII/Unicode for
18
+ terminals. It is the foundation this fork is built on.
19
+ - **Agentic Mermaid** (`agentic-mermaid`, this repo) extends Beautiful
20
+ Mermaid for programs that edit diagrams — AI agents foremost. It adds a
21
+ typed parse → mutate → verify → serialize loop, byte-identical output
22
+ across runs, structured verification, and CLI/MCP surfaces. The trade is explicit: the checked registry covers a focused subset of Mermaid's
23
+ broader catalogue in exchange for the guarantee that parsing and re-serializing
24
+ a diagram never drops syntax.
25
+
26
+ Facts below reflect Mermaid 11.16.0 and the upstream `beautiful-mermaid`
27
+ repository as of mid-2026; both projects move quickly, so check their
28
+ changelogs for the current state.
29
+
30
+ ## At a glance
31
+
32
+ | | Mermaid | Beautiful Mermaid | Agentic Mermaid |
33
+ |---|---|---|---|
34
+ | Primary job | Define and render the diagram language everywhere | Fast, beautiful, browserless rendering | Agent-safe diagram *editing* plus rendering |
35
+ | Runtime | Browser DOM (Node via Puppeteer/`mermaid-cli`) | Pure TypeScript, zero DOM, synchronous | Pure TypeScript, zero DOM, synchronous |
36
+ | Diagram types | Broad Mermaid catalogue, including newer experimental families | Flowchart, state, sequence, class, ER, and XY chart | Registry-backed subset listed by `am capabilities --json` |
37
+ | Output formats | SVG (PNG/PDF via CLI tooling) | SVG, ASCII/Unicode | SVG, PNG (offline resvg), ASCII/Unicode, JSON layout |
38
+ | Theming | Theme config + CSS | Two-color foundation, 15+ named themes, Shiki/VS Code compatibility, live CSS-variable switching | Style + Palette stacks: named looks, palette-only styles, custom JSON records, and deterministic seeds |
39
+ | Parse to a typed AST for editing | — (internal parser, not an editing API) | — (render-only API) | ✅ `parseRegisteredMermaid` → typed `ValidDiagram` |
40
+ | Typed mutation | — | — | ✅ every registered family, structured-or-opaque and never lossy |
41
+ | Structural verification | — | — | ✅ 3 warning tiers + perceptual quality metrics, all families |
42
+ | Deterministic output | Not a goal (browser/layout variance) | Mostly stable, not a tested guarantee | ✅ byte-identical across runs/processes, CI-gated |
43
+ | Round-trip guarantee (parse → serialize keeps your source) | — | — | ✅ verbatim for unmodeled syntax, canonical for structured bodies |
44
+ | CLI | `mermaid-cli` (`mmdc`, Puppeteer-based) | — | `am` (render/verify/mutate/batch/preview/…, single-binary build) |
45
+ | MCP / agent surface | Official hosted MCP (validation, PNG, Mermaid Chart integration) | — | Local Code Mode MCP (`execute`, `describe_sdk`, `render_png`, `describe`) plus hosted `/mcp` (`execute`, progressive schema discovery, render/verify/describe, `mutate`/`build`), `llms.txt`, agent skill |
46
+ | Interactivity (click handlers, animations) | ✅ | Partial (tooltips) | Inherited where upstream has it; not a focus |
47
+ | Ecosystem & docs | Vast — the de-facto standard, GitHub/GitLab/Notion render it natively | Growing, popular for terminal/AI use | Small; this repo |
48
+
49
+ ## What each does that the others don't
50
+
51
+ **Only Mermaid:** the full diagram-type catalogue (gantt, mindmap, gitgraph,
52
+ sankey, and the 11.x additions like kanban, radar, treemap, venn, wardley,
53
+ treeview, event modeling); native rendering inside GitHub, GitLab, Notion,
54
+ Obsidian, and hundreds of tools; the grammar itself — both other projects
55
+ implement *Mermaid's* language, and compatibility with Mermaid is the
56
+ correctness bar they measure against.
57
+
58
+ **Only Beautiful Mermaid (vs Mermaid):** synchronous, dependency-light
59
+ rendering with no browser; a deliberate two-color theming foundation with
60
+ enriched palettes and Shiki theme compatibility; ASCII/Unicode terminal
61
+ output. Agentic Mermaid inherits all of this — it is upstream's work, and
62
+ credit belongs there.
63
+
64
+ **Only Agentic Mermaid:** the typed editing loop. `parseRegisteredMermaid` returns a
65
+ sealed IR; family narrowers (`asFlowchart` … `asXyChart`) expose typed
66
+ mutation ops; `verifyMermaid` returns structured warnings instead of asking
67
+ an agent to eyeball pixels; `serializeMermaid` round-trips losslessly
68
+ (structured-or-opaque: anything the parser doesn't model is preserved
69
+ verbatim, never silently dropped). Plus offline PNG, JSON layout, an `am`
70
+ CLI built for agents (exit codes, JSONL batch, `capabilities --json`
71
+ self-discovery), a local Code Mode MCP server, a bounded hosted MCP endpoint
72
+ for zero-install render/verify/describe and structured edits, and tested
73
+ byte-identical determinism. Neither upstream project needed any of this: both serve humans who write
74
+ diagrams once, while this surface serves programs that edit them repeatedly.
75
+
76
+ ## Mindmap/GitGraph and the terminal ecosystem
77
+
78
+ The checked fixtures follow the official [Mindmap](https://mermaid.ai/open-source/syntax/mindmap.html) and [GitGraph](https://mermaid.ai/open-source/syntax/gitgraph.html) syntax pages and render from the same authored source in Mermaid 11.16.0 and Agentic Mermaid. See the captioned [Mindmap comparison](./design/families/mindmap.md#visual-evidence) and [GitGraph comparison](./design/families/gitgraph.md#visual-evidence). Compare semantic structure—labels, shapes, hierarchy, lanes, commits, parentage, tags, and bounds—not pixels, because the layout/style engines differ.
79
+
80
+ [AlexanderGrooff/mermaid-ascii](https://github.com/AlexanderGrooff/mermaid-ascii) 1.4.0 does not currently implement either family. Replaying the documented CLI against the same fixtures exits 1 with:
81
+
82
+ ```text
83
+ unsupported graph type 'mindmap'. Supported types: graph TD, graph TB, graph LR, flowchart TD, flowchart TB, flowchart LR
84
+ unsupported graph type 'gitGraph'. Supported types: graph TD, graph TB, graph LR, flowchart TD, flowchart TB, flowchart LR
85
+ ```
86
+
87
+ Its [diagram coverage issue #74](https://github.com/AlexanderGrooff/mermaid-ascii/issues/74) tracks additional families. This is a capability difference, not a claim that an unsupported render is visually worse.
88
+
89
+ ## Choosing
90
+
91
+ - Rendering inside a web app, or you need a family absent from `am capabilities --json` → **Mermaid**.
92
+ - Fast, beautiful SVG/ASCII rendering of the core families in
93
+ Node/Bun/terminal, render-only → **Beautiful Mermaid**.
94
+ - An AI agent (or any program) needs to *edit* diagrams safely, verify them
95
+ structurally, or guarantee reproducible output in CI → **Agentic Mermaid**.
96
+
97
+ ## Compatibility notes
98
+
99
+ Agentic Mermaid aims to parse what Mermaid parses for its supported
100
+ families and to reject what Mermaid rejects (e.g. ER cardinality tokens
101
+ match Mermaid's lexer exactly). Where this fork's renderer accepts a
102
+ construct it cannot model for editing, the diagram still parses, renders,
103
+ verifies, and round-trips — it just doesn't expose typed mutation for the
104
+ unmodeled part. Upstream-relevant fixes are extracted into small PRs back to
105
+ `lukilabs/beautiful-mermaid` per the
106
+ [upstreaming strategy](./fork-differences.md#upstreaming-strategy).