Skip to content

D2COpenAIPlugin: Routing text to diagram backends

D2COpenAIPlugin is a FastAPI diagram service with a plugin manifest and an OpenAPI surface. Its implementation selects among PlantUML, Mermaid and Kroki paths based on the request’s diagram language.

Application and services
  • Updated
  • 9
  • Python · 100%
  • MIT
Repository languagesPython 100%1

Shares calculated from GitHub Linguist bytes.

Language%Bytes
Python100%60,743

GitHub · README · Language statistics

Overview

Why it exists

OpenAI ChatGPT plugin manifest and OpenAPI endpoint handler for text-to-diagram conversion.

Best fit

ChatGPT Plus GPT Store integration for software architects.

Getting started

These commands come from the repository documentation. They were not run during this review.

README.md · Quick start
git clone https://github.com/antoinebou12/D2COpenAIPlugin.git
cd D2COpenAIPlugin
python -m venv .venv
README.md · Quick start
.\.venv\Scripts\Activate.ps1
README.md · Quick start
source .venv/bin/activate
README.md · Quick start
pip install -r requirements-dev.txt
python -m pytest
uvicorn app:app --host 127.0.0.1 --port 5003
README.md · Quick start
python app.py
plantuml/README.md · Installation
pip install plantumlapi
plantuml/README.md · Installation
pip install git+https://github.com/antoinebou12/plantumlapi
plantuml/README.md · Command Line Usage
usage: plantuml.py [-h] [-o OUT] [-s SERVER] filename [filename ...]
Generate images from PlantUML defined files using PlantUML server
positional arguments: 
  filename            file(s) to generate images from
optional arguments: 
  -h, --help          show this help message and exit 
  -o OUT, --out OUT   directory to put the files into 
  -s SERVER, --server SERVER 
                      server to generate from; defaults to plantuml.com 
Tasks declared in manifests

Repository references

Excerpts from the repository’s guides, in their original language. Links open the inspected source revision.

Prerequisites and first run

Requirements

README.md

  • Python 3.10+ (CI uses 3.12)
  • pip and a virtual environment (recommended) Optional:
  • D2/main — small helper binary expected at ./D2/main for D2 encoding in D2/run_d2.py (only needed if you use the D2 code paths locally)

Read the full instructions ↗

Quick start

README.md

Activate the venv (Windows PowerShell): Activate the venv (macOS / Linux): Install dependencies and run the API: Equivalent one-liner after activation:

Read the full instructions ↗

Installation

plantuml/README.md

To install, run the following command:
Read the full instructions ↗
API and integration

API

README.md

FieldTypeRequiredDescription
langstringyese.g. plantuml, mermaid, d2, or a Kroki type allowed by the server
typestringyese.g. class, sequence, activity (used for validation / logging)
codestringyesDiagram source (max length enforced in app.py)
themestringnoPlantUML / Mermaid theming where applicable
Example (PlantUML) with curl (bash / Git Bash):
Example with PowerShell:

POST /generate_diagram JSON body:

Read the full instructions ↗
Operations and troubleshooting

Deployment (Vercel)

README.md


Read the full instructions ↗
Development and contributions

Contributing / security

README.md

  • Tests: python -m pytest (see .github/workflows/CI.yml)
  • Security policy: SECURITY.md

Read the full instructions ↗
Source documentation

2 documents read from 2 candidates.

Features and components 2

Request model
DiagramRequest contains lang, type, code and theme. Validators check the language and source length. /generate_diagram rejects missing fields before dispatching to a backend; the code then builds result and playground links.
Backend adapters
PlantUML uses its dedicated client, Mermaid builds an editor state, and D2 aliases are normalized to the Kroki d2 renderer. Other supported languages use the Kroki language registry. The adapters isolate differing URL and encoding conventions.

Architecture

The components and their connections remain available as text. The diagram adds an interactive view.

System context Context
  1. Structured diagram request
  2. FastAPI model and route
  3. PlantUML adapter
  4. Mermaid state encoder
  5. Kroki adapter
  6. Result and playground links

Links verified in the repository.

Mermaid Interactive diagram (loads on open)

System overview of the components and connections verified in the repository.

Static architecture view for D2COpenAIPlugin
Static preview. The interactive diagram replaces it after Mermaid loads.
flowchart LR

subgraph group_api["API surface"]
  node_api["FastAPI endpoint<br/>[app.py]"]
  node_request["Request validation<br/>[app.py]"]
  node_response["Diagram response<br/>[app.py]"]
end

subgraph group_formats["Diagram formats"]
  node_plantuml["PlantUML renderer<br/>[__init__.py]"]
  node_mermaid["Mermaid state and links<br/>[mermaid.py]"]
  node_d2encoder["D2 encoder<br/>[d2.py]"]
  node_d2runner["D2 binary runner<br/>[run_d2.py]"]
  node_kroki["Kroki client<br/>[kroki.py]"]
end

subgraph group_integration["Rendering services"]
  node_plantservice["PlantUML server"]
  node_mermaidink["Mermaid image service"]
  node_mermaidlive["Mermaid Live Editor"]
  node_krokiservice["Kroki service"]
end

subgraph group_assets["Plugin assets"]
  node_pluginassets["Plugin metadata<br/>[ai-plugin.json]"]
  node_openapi["OpenAPI specification<br/>[openapi.yaml]"]
  node_privacy["Privacy policy<br/>[privacy.txt]"]
  node_logo["Plugin logo"]
end

node_client(("Plugin client"))

node_client -->|"submits request"| node_api
node_api -->|"validates"| node_request
node_api -->|"dispatches PlantUML"| node_plantuml
node_plantuml -->|"requests rendering"| node_plantservice
node_api -->|"dispatches Mermaid"| node_mermaid
node_api -->|"dispatches D2 or allow-list"| node_kroki
node_kroki -->|"requests rendering"| node_krokiservice
node_mermaid -->|"creates image URL"| node_mermaidink
node_mermaid -->|"creates editor URL"| node_mermaidlive
node_api -->|"returns result"| node_response
node_pluginassets -->|"served by"| node_api
node_openapi -->|"describes API"| node_api
node_privacy -->|"served by"| node_api
node_logo -->|"served by"| node_api
node_d2runner -.->|"runs encoder binary"| node_d2encoder


class node_api,node_request,node_response,node_client toneBlue
class node_plantuml,node_mermaid,node_d2encoder,node_d2runner,node_kroki toneAmber
class node_plantservice,node_mermaidink,node_mermaidlive,node_krokiservice toneMint
class node_pluginassets,node_openapi,node_privacy,node_logo toneRose

A FastAPI diagram backend that validates requests, selects a PlantUML, Mermaid, D2 or Kroki path, and returns rendered content plus editor links. The service also publishes plugin, OpenAPI and privacy assets.

Components
17
Connections
15
Links supported by code or README
13/15
Text version of the diagram
  • Structured diagram request → FastAPI model and route
  • FastAPI model and route → PlantUML adapter
  • FastAPI model and route → Mermaid state encoder
  • FastAPI model and route → Kroki adapter
  • PlantUML adapter → Result and playground links
  • Mermaid state encoder → Result and playground links
  • Kroki adapter → Result and playground links
Follow one path through the code

Compare the PlantUML and D2 branches in app.py. They accept the same request model but use different rendering adapters. The type validator logs an invalid type rather than raising, so it is not equivalent to strict language validation.

Types and file structure

21 declared types, with 12 in the base-relationship overview.

Type diagram
classDiagram
direction TB
class te235e58dd5f7["DiagramRequest"] {
  validate_lang()
  validate_type()
  validate_code()
}
class t4e73a5f77051["KrokiError"] {
}
class t7b9c286d0daa["KrokiConnectionError"] {
}
class t125669ef086e["KrokiHTTPError"] {
  __init__()
}
class te53f5e9c5fc5["Kroki"] {
  __init__()
  get_url()
  get_playground_url()
  render_diagram()
}
class t8bdd6c0a1a17["Serde"] {
  serialize()
  deserialize()
}
class tb6d1e408057f["Base64Serde"] {
  serialize()
  deserialize()
}
class td8a94fefdf74["PakoSerde"] {
  serialize()
  deserialize()
  pako_deflate()
  pako_inflate()
}
class t3d10982f0435["Layout"] {
}
class tda3378b45b31["Theme"] {
}
class tc157562f2b44["PlantUMLError"] {
}
class t0b0db7ecf15c["PlantUMLConnectionError"] {
}
class bda110f9bf6d7["BaseModel"] {
  <<unresolved_base>>
}
bda110f9bf6d7 <|-- te235e58dd5f7
class b03e969ca3e08["Exception"] {
  <<unresolved_base>>
}
b03e969ca3e08 <|-- t4e73a5f77051
t4e73a5f77051 <|-- t7b9c286d0daa
t4e73a5f77051 <|-- t125669ef086e
t8bdd6c0a1a17 <|-- tb6d1e408057f
t8bdd6c0a1a17 <|-- td8a94fefdf74
class bb5991911b5e9["Enum"] {
  <<unresolved_base>>
}
bb5991911b5e9 <|-- t3d10982f0435
bb5991911b5e9 <|-- tda3378b45b31
class b864a57f6df91["Exception"] {
  <<unresolved_base>>
}
b864a57f6df91 <|-- tc157562f2b44
tc157562f2b44 <|-- t0b0db7ecf15c

Unresolved bases remain labelled; full signatures are not reconstructed.

Type index
  • DiagramRequest (class) · app.py:47

    Methods in the overview: validate_lang, validate_type, validate_code.

    Declared bases: BaseModel.

  • KrokiError (class) · kroki/kroki.py:50

    Declared bases: Exception.

  • KrokiConnectionError (class) · kroki/kroki.py:55

    Declared bases: KrokiError.

  • KrokiHTTPError (class) · kroki/kroki.py:60

    Methods in the overview: __init__.

    Declared bases: KrokiError.

  • Kroki (class) · kroki/kroki.py:70

    Methods in the overview: __init__, get_url, get_playground_url, render_diagram.

  • Serde (class) · mermaid/mermaid.py:32

    Methods in the overview: serialize, deserialize.

  • Base64Serde (class) · mermaid/mermaid.py:39

    Methods in the overview: serialize, deserialize.

    Declared bases: Serde.

  • PakoSerde (class) · mermaid/mermaid.py:48

    Methods in the overview: serialize, deserialize, pako_deflate, pako_inflate.

    Declared bases: Serde.

  • Layout (class) · D2/d2.py:90

    Declared bases: Enum.

  • Theme (class) · D2/d2.py:95

    Declared bases: Enum.

  • PlantUMLError (class) · plantuml/__init__.py:23

    Declared bases: Exception.

  • PlantUMLConnectionError (class) · plantuml/__init__.py:30

    Declared bases: PlantUMLError.

Reference

17 / 17 eligible files read (35 in the tree); 0 oversized, 0 failed reads and 0 syntax diagnostics.

What the scan covers

Known dependency/build folders, credential files and binaries are excluded. The scan covers READMEs, recognized manifests and parser-supported source files.

Linguist statistics cover the whole repository and may include other languages.

File map
flowchart TD
  root["D2COpenAIPlugin"]
  f0["app.py"]
  root --> f0
  f1["kroki/kroki.py"]
  root --> f1
  f2["mermaid/mermaid.py"]
  root --> f2
  f3["README.md"]
  root --> f3
  f4["__init__.py"]
  root --> f4
  f5["package.json"]
  root --> f5
  f6["requirements.txt"]
  root --> f6
  f7["test_app.py"]
  root --> f7
  f8["D2/__init__.py"]
  root --> f8
  f9["D2/d2.py"]
  root --> f9
  f10["D2/run_d2.py"]
  root --> f10
  f11["kroki/__init__.py"]
  root --> f11
  f12["mermaid/__init__.py"]
  root --> f12
  f13["plantuml/README.md"]
  root --> f13
  f14["plantuml/__init__.py"]
  root --> f14
  f15["plantuml/themes/__init__.py"]
  root --> f15

Files to read 3

References