From 675668c4308573d56cd35e7f7e6487e0e6a86685 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 13 May 2026 13:53:56 -0300 Subject: [PATCH 1/3] docs(diagrams): create 8 canonical Mermaid sources + folder structure Introduce docs/diagrams/ with the README index and 8 versioned Mermaid sources that reflect the v3.8.0 platform: - request-pipeline.mmd /v1/chat/completions request pipeline - auto-combo-9factor.mmd Auto-Combo 9-factor scoring weights - resilience-3layers.mmd Provider breaker / cooldown / model lockout - i18n-flow.mmd Hash-based incremental doc translation - mcp-tools-37.mmd MCP Server tool inventory by category - cloud-agent-flow.mmd Codex / Devin / Jules task lifecycle - authz-pipeline.mmd 3-class authz pipeline (PUBLIC/CLIENT_API/MANAGEMENT) - db-schema-overview.mmd Selected core SQLite relations Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/diagrams/README.md | 48 ++++++++++++++++++++++++++++ docs/diagrams/authz-pipeline.mmd | 23 +++++++++++++ docs/diagrams/auto-combo-9factor.mmd | 23 +++++++++++++ docs/diagrams/cloud-agent-flow.mmd | 32 +++++++++++++++++++ docs/diagrams/db-schema-overview.mmd | 16 ++++++++++ docs/diagrams/i18n-flow.mmd | 14 ++++++++ docs/diagrams/mcp-tools-37.mmd | 23 +++++++++++++ docs/diagrams/request-pipeline.mmd | 24 ++++++++++++++ docs/diagrams/resilience-3layers.mmd | 21 ++++++++++++ 9 files changed, 224 insertions(+) create mode 100644 docs/diagrams/README.md create mode 100644 docs/diagrams/authz-pipeline.mmd create mode 100644 docs/diagrams/auto-combo-9factor.mmd create mode 100644 docs/diagrams/cloud-agent-flow.mmd create mode 100644 docs/diagrams/db-schema-overview.mmd create mode 100644 docs/diagrams/i18n-flow.mmd create mode 100644 docs/diagrams/mcp-tools-37.mmd create mode 100644 docs/diagrams/request-pipeline.mmd create mode 100644 docs/diagrams/resilience-3layers.mmd diff --git a/docs/diagrams/README.md b/docs/diagrams/README.md new file mode 100644 index 0000000000..9912a4ddd4 --- /dev/null +++ b/docs/diagrams/README.md @@ -0,0 +1,48 @@ +# Diagrams + +Mermaid sources (`.mmd`) and exported SVGs for OmniRoute v3.8.0 architecture flows. + +## Canonical diagrams + +| Source | Exported | Used in | +| -------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------- | +| [request-pipeline.mmd](./request-pipeline.mmd) | [SVG](./exported/request-pipeline.svg) | docs/ARCHITECTURE.md, docs/CODEBASE_DOCUMENTATION.md | +| [auto-combo-9factor.mmd](./auto-combo-9factor.mmd) | [SVG](./exported/auto-combo-9factor.svg) | docs/AUTO-COMBO.md | +| [resilience-3layers.mmd](./resilience-3layers.mmd) | [SVG](./exported/resilience-3layers.svg) | docs/RESILIENCE_GUIDE.md, CLAUDE.md | +| [i18n-flow.mmd](./i18n-flow.mmd) | [SVG](./exported/i18n-flow.svg) | docs/I18N.md | +| [mcp-tools-37.mmd](./mcp-tools-37.mmd) | [SVG](./exported/mcp-tools-37.svg) | docs/MCP-SERVER.md | +| [cloud-agent-flow.mmd](./cloud-agent-flow.mmd) | [SVG](./exported/cloud-agent-flow.svg) | docs/CLOUD_AGENT.md | +| [authz-pipeline.mmd](./authz-pipeline.mmd) | [SVG](./exported/authz-pipeline.svg) | docs/AUTHZ_GUIDE.md | +| [db-schema-overview.mmd](./db-schema-overview.mmd) | [SVG](./exported/db-schema-overview.svg) | docs/CODEBASE_DOCUMENTATION.md | + +## How to update + +1. Edit `*.mmd`. +2. Re-render: `npm run docs:render-diagrams` (uses `@mermaid-js/mermaid-cli`). +3. Commit both `.mmd` and `.svg`. + +If `@mermaid-js/mermaid-cli` is not available locally, install it once: + +```bash +npm install -g @mermaid-js/mermaid-cli +``` + +The script renders every `.mmd` in `docs/diagrams/` into `docs/diagrams/exported/*.svg` +with a white background, suitable for both dark and light themes. + +## Linking from a doc + +```markdown +![Request pipeline](./diagrams/exported/request-pipeline.svg) + +> Source: [diagrams/request-pipeline.mmd](./diagrams/request-pipeline.mmd) +``` + +## Conventions + +- One concept per diagram. Don't try to fit the whole platform in one chart. +- Keep node labels short (3–6 words). Use `
` for line breaks inside nodes. +- Prefer `flowchart LR` for pipelines and `flowchart TB` for layered models. +- Use `sequenceDiagram` for interactive (request/response) flows. +- Use `erDiagram` for database schema overviews. +- Update both `.mmd` and `.svg` in the same commit. Keep them in lock-step. diff --git a/docs/diagrams/authz-pipeline.mmd b/docs/diagrams/authz-pipeline.mmd new file mode 100644 index 0000000000..78b9b5b09c --- /dev/null +++ b/docs/diagrams/authz-pipeline.mmd @@ -0,0 +1,23 @@ +%% AuthZ pipeline (3 route classes + policy evaluation) +%% Reflects: src/middleware.ts, src/server/authz/pipeline.ts, +%% src/server/authz/policies/{public,clientApi,management}.ts +%% v3.8.0 +flowchart LR + Req["Incoming request"] --> Strip["Strip trusted internal headers
(x-omniroute-auth-*)"] + Strip --> Classify["classifyRoute()"] + Classify -->|PUBLIC| PubP["publicPolicy
(login, health, status)"] + Classify -->|CLIENT_API| CliP["clientApiPolicy
(/api/v1/*, /v1/*)"] + Classify -->|MANAGEMENT| MgmtP["managementPolicy
(dashboard, settings, admin)"] + + PubP -->|allow| Stamp["Stamp x-omniroute-auth-*
(kind / id / label / scopes)"] + CliP -->|extract Bearer| Validate["validateApiKey()"] + Validate -->|valid| Stamp + Validate -->|"invalid (REQUIRE_API_KEY=true)"| Reject401["401 AUTH_002"] + Validate -->|"absent (REQUIRE_API_KEY=false)"| Anon["anonymous fallthrough"] --> Stamp + + MgmtP -->|session ok| Stamp + MgmtP -->|Bearer w/ manage scope| Stamp + MgmtP -->|"Bearer invalid"| Reject403["403 AUTH_001"] + MgmtP -->|no auth| Reject401Mgmt["401 / 302 /login"] + + Stamp --> Handler["Handler
(uses assertAuth)"] diff --git a/docs/diagrams/auto-combo-9factor.mmd b/docs/diagrams/auto-combo-9factor.mmd new file mode 100644 index 0000000000..7b604b43d3 --- /dev/null +++ b/docs/diagrams/auto-combo-9factor.mmd @@ -0,0 +1,23 @@ +%% Auto-Combo 9-factor scoring +%% Reflects: open-sse/services/autoCombo/scoring.ts (DEFAULT_WEIGHTS, sum = 1.0) +%% v3.8.0 +flowchart TB + Request["Incoming request"] --> Candidates["Eligible candidates
(provider × model × account)"] + Candidates --> Score["Compute composite score
per candidate"] + + subgraph Factors["9-factor scoring weights (sum = 1.0)"] + f1["health (0.22)"] + f2["quota (0.17)"] + f3["costInv (0.17)"] + f4["latencyInv (0.13)"] + f5["taskFit (0.08)"] + f6["specificityMatch (0.08)"] + f7["stability (0.05)"] + f8["tierPriority (0.05)"] + f9["tierAffinity (0.05)"] + end + + Score --> Factors + Factors --> Final["Sort by score
(desc)"] + Final --> Top["Pick top-N targets"] + Top --> Dispatch["Dispatch sequentially
(short-circuit on success)"] diff --git a/docs/diagrams/cloud-agent-flow.mmd b/docs/diagrams/cloud-agent-flow.mmd new file mode 100644 index 0000000000..32b5a9cea6 --- /dev/null +++ b/docs/diagrams/cloud-agent-flow.mmd @@ -0,0 +1,32 @@ +%% Cloud Agent task lifecycle +%% Reflects: src/lib/cloudAgent/* and src/app/api/v1/agents/tasks/* +%% Supported agents: codex-cloud, devin, jules +%% v3.8.0 +sequenceDiagram + participant U as User + participant API as /v1/agents/tasks + participant Reg as Cloud Agent Registry + participant Ag as Cloud Agent
(codex-cloud / devin / jules) + participant DB as SQLite domain DB + + U->>API: POST createTask (description, sources) + API->>API: Zod validation + AuthZ (management) + API->>Reg: getAgent(providerId) + Reg->>Ag: instantiate with credentials + Ag->>Ag: createTask() returns planning + Ag-->>API: taskId + status: planning + API->>DB: insertCloudAgentTask + API-->>U: taskId + + U->>API: GET /tasks/:id (poll) + API->>Ag: getStatus(externalId) + Ag-->>API: status, plan, messages + API->>DB: updateCloudAgentTask + API-->>U: snapshot + + U->>API: POST approvePlan + API->>Ag: approvePlan(externalId) + Ag-->>API: status: running + Note over Ag: Async execution upstream + + Ag-->>DB: stream events / final result diff --git a/docs/diagrams/db-schema-overview.mmd b/docs/diagrams/db-schema-overview.mmd new file mode 100644 index 0000000000..debf71f3b1 --- /dev/null +++ b/docs/diagrams/db-schema-overview.mmd @@ -0,0 +1,16 @@ +%% Database schema overview (selected core tables) +%% Reflects: src/lib/db/* (45+ modules, 55 migrations) +%% v3.8.0 +erDiagram + api_keys ||--o{ api_key_usage : tracks + api_keys ||--o{ rate_limits : enforces + providers ||--o{ provider_connections : holds + provider_connections ||--o{ domain_circuit_breakers : protected_by + combos ||--o{ combo_targets : contains + combos ||--o{ combo_executions : logs + spend_buffer ||--o{ usage_aggregations : flushed_to + memory_documents ||--o{ memory_chunks : split_into + skills_runs ||--o{ skills_logs : produced + agent_tasks ||--o{ agent_task_events : streams + audit_log }|--|| api_keys : by + mcp_audit }|--|| api_keys : by diff --git a/docs/diagrams/i18n-flow.mmd b/docs/diagrams/i18n-flow.mmd new file mode 100644 index 0000000000..50ddb293c9 --- /dev/null +++ b/docs/diagrams/i18n-flow.mmd @@ -0,0 +1,14 @@ +%% Incremental hash-based i18n pipeline +%% Reflects: scripts/i18n/* and docs/i18n//*.md mirror layout +%% v3.8.0 +flowchart LR + Src["Source MDs
(CLAUDE.md, docs/**/*.md)"] --> Hash["sha256 hash"] + Hash --> State[".i18n-state.json"] + State -->|diff| Dirty["Mark source dirty"] + Dirty --> Loop{"For each locale
(39 langs)"} + Loop --> LLM["OmniRoute
/chat/completions
(cx/gpt-5.4-mini)"] + LLM --> Target["Write
docs/i18n/<locale>/<rel-path>.md"] + Target --> State + Target --> CI{"CI drift check
(npm run i18n:check)"} + CI -->|in sync| Pass["pass"] + CI -->|drift| Fail["fail
(exit 1)"] diff --git a/docs/diagrams/mcp-tools-37.mmd b/docs/diagrams/mcp-tools-37.mmd new file mode 100644 index 0000000000..bd0afb082c --- /dev/null +++ b/docs/diagrams/mcp-tools-37.mmd @@ -0,0 +1,23 @@ +%% MCP Server tool inventory by category +%% Reflects: open-sse/mcp-server/tools/* and docs/MCP-SERVER.md +%% v3.8.0 +flowchart LR + MCP["MCP Server
37 tools total"] --> Core["Core (30)"] + MCP --> Mem["Memory (3)"] + MCP --> Skl["Skills (4)"] + + Core --> Essential["Essential (8)
get_health, list_combos,
switch_combo, check_quota,
route_request, cost_report,
list_models_catalog,
get_combo_metrics"] + Core --> Search["Search (1)
web_search"] + Core --> Advanced["Advanced (11)
simulate_route, set_budget_guard,
set_routing_strategy,
set_resilience_profile,
test_combo, get_provider_metrics,
best_combo_for_task, explain_route,
get_session_snapshot,
db_health_check, sync_pricing"] + Core --> Cache["Cache (2)"] + Core --> Compression["Compression (5)"] + Core --> Tunnels["1Proxy / Tunnels (3)"] + + Mem --> M1["memory_search"] + Mem --> M2["memory_save"] + Mem --> M3["memory_delete"] + + Skl --> S1["skill_invoke"] + Skl --> S2["skill_list"] + Skl --> S3["skill_diagnose"] + Skl --> S4["skill_uninstall"] diff --git a/docs/diagrams/request-pipeline.mmd b/docs/diagrams/request-pipeline.mmd new file mode 100644 index 0000000000..d0883aa76c --- /dev/null +++ b/docs/diagrams/request-pipeline.mmd @@ -0,0 +1,24 @@ +%% Request pipeline for /v1/chat/completions +%% Reflects: src/app/api/v1/chat/completions/route.ts → open-sse/handlers/chatCore.ts +%% v3.8.0 +flowchart LR + Client["Client
(IDE/CLI/SDK)"] --> Route["Next.js Route
/v1/chat/completions"] + Route --> CORS["CORS preflight"] + CORS --> Validate["Zod validation
(request body)"] + Validate --> Authz["AuthZ pipeline
(extractApiKey +
isValidApiKey)"] + Authz --> Policy["API key policy
(allowlist + scopes)"] + Policy --> Guard["Prompt-injection
guardrail"] + Guard --> ChatCore["handleChatCore"] + ChatCore --> Cache{"Cache hit?"} + Cache -->|yes| Return["Return cached"] + Cache -->|no| Rate["Rate limit
(per-key, per-IP)"] + Rate --> Combo{"Combo
target?"} + Combo -->|combo| Resolve["resolveComboTargets
(14 strategies)"] + Resolve --> Single["handleSingleModel
(per target)"] + Combo -->|single| Single + Single --> Translate["translateRequest
(OpenAI↔Claude↔Gemini)"] + Translate --> Exec["getExecutor
(31 executors)"] + Exec --> Upstream["Upstream Provider
(177 providers)"] + Upstream --> Stream["SSE / JSON"] + Stream --> Transformer["responsesTransformer
(Responses↔Chat)"] + Transformer --> Client diff --git a/docs/diagrams/resilience-3layers.mmd b/docs/diagrams/resilience-3layers.mmd new file mode 100644 index 0000000000..777198946a --- /dev/null +++ b/docs/diagrams/resilience-3layers.mmd @@ -0,0 +1,21 @@ +%% 3-layer resilience model +%% Reflects: src/shared/utils/circuitBreaker.ts, src/sse/services/auth.ts, +%% open-sse/services/accountFallback.ts +%% v3.8.0 +flowchart TB + Req["Request"] --> L1{"Provider Circuit Breaker
(scope: whole provider)"} + L1 -->|CLOSED| L2 + L1 -->|OPEN| Block1["Skip provider
(or 503 retry-after)"] + L1 -->|HALF_OPEN| Probe["Allow probe"] + Probe --> L2 + + L2{"Connection Cooldown
(scope: one account/key)"} -->|available| L3 + L2 -->|cooling down| Skip2["Skip this connection
fall back to next"] + + L3{"Model Lockout
(scope: provider × conn × model)"} -->|allowed| Exec["Execute upstream"] + L3 -->|locked| Skip3["Fall back to next model"] + + Exec -->|success| Clear["Clear cooldowns/lockouts"] + Exec -->|"408 / 500 / 502 / 503 / 504"| TripL1["Trip provider breaker"] + Exec -->|"401 / 403 (account)"| TripL2["Start connection cooldown"] + Exec -->|"429 quota (model)"| TripL3["Start model lockout"] From 519fdf41b84deac41e5c7a0f033aba0f5338e531 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 13 May 2026 13:54:09 -0300 Subject: [PATCH 2/3] chore(docs): add npm run docs:render-diagrams and export SVGs Add scripts/docs/render-diagrams.mjs as a thin wrapper around @mermaid-js/mermaid-cli (mmdc): - Renders every docs/diagrams/*.mmd into docs/diagrams/exported/*.svg - Writes a Puppeteer config with --no-sandbox for Ubuntu 23.10+/WSL - Exits non-zero on first failure so CI can gate on rendering Expose it as `npm run docs:render-diagrams` and commit the initial 8 rendered SVGs so reviewers see the diagrams without having to install the renderer locally. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/diagrams/exported/authz-pipeline.svg | 1 + docs/diagrams/exported/auto-combo-9factor.svg | 1 + docs/diagrams/exported/cloud-agent-flow.svg | 1 + docs/diagrams/exported/db-schema-overview.svg | 1 + docs/diagrams/exported/i18n-flow.svg | 1 + docs/diagrams/exported/mcp-tools-37.svg | 1 + docs/diagrams/exported/request-pipeline.svg | 1 + docs/diagrams/exported/resilience-3layers.svg | 1 + package.json | 3 +- scripts/docs/render-diagrams.mjs | 85 +++++++++++++++++++ 10 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 docs/diagrams/exported/authz-pipeline.svg create mode 100644 docs/diagrams/exported/auto-combo-9factor.svg create mode 100644 docs/diagrams/exported/cloud-agent-flow.svg create mode 100644 docs/diagrams/exported/db-schema-overview.svg create mode 100644 docs/diagrams/exported/i18n-flow.svg create mode 100644 docs/diagrams/exported/mcp-tools-37.svg create mode 100644 docs/diagrams/exported/request-pipeline.svg create mode 100644 docs/diagrams/exported/resilience-3layers.svg create mode 100644 scripts/docs/render-diagrams.mjs diff --git a/docs/diagrams/exported/authz-pipeline.svg b/docs/diagrams/exported/authz-pipeline.svg new file mode 100644 index 0000000000..cf29408a46 --- /dev/null +++ b/docs/diagrams/exported/authz-pipeline.svg @@ -0,0 +1 @@ +

PUBLIC

CLIENT_API

MANAGEMENT

allow

extract Bearer

valid

invalid (REQUIRE_API_KEY=true)

absent (REQUIRE_API_KEY=false)

session ok

Bearer w/ manage scope

Bearer invalid

no auth

Incoming request

Strip trusted internal headers
(x-omniroute-auth-*)

classifyRoute()

publicPolicy
(login, health, status)

clientApiPolicy
(/api/v1/*, /v1/*)

managementPolicy
(dashboard, settings, admin)

Stamp x-omniroute-auth-*
(kind / id / label / scopes)

validateApiKey()

401 AUTH_002

anonymous fallthrough

403 AUTH_001

401 / 302 /login

Handler
(uses assertAuth)

\ No newline at end of file diff --git a/docs/diagrams/exported/auto-combo-9factor.svg b/docs/diagrams/exported/auto-combo-9factor.svg new file mode 100644 index 0000000000..54e8ebb9c0 --- /dev/null +++ b/docs/diagrams/exported/auto-combo-9factor.svg @@ -0,0 +1 @@ +

9-factor scoring weights (sum = 1.0)

health (0.22)

quota (0.17)

costInv (0.17)

latencyInv (0.13)

taskFit (0.08)

specificityMatch (0.08)

stability (0.05)

tierPriority (0.05)

tierAffinity (0.05)

Incoming request

Eligible candidates
(provider × model × account)

Compute composite score
per candidate

Sort by score
(desc)

Pick top-N targets

Dispatch sequentially
(short-circuit on success)

\ No newline at end of file diff --git a/docs/diagrams/exported/cloud-agent-flow.svg b/docs/diagrams/exported/cloud-agent-flow.svg new file mode 100644 index 0000000000..8196fc2036 --- /dev/null +++ b/docs/diagrams/exported/cloud-agent-flow.svg @@ -0,0 +1 @@ +SQLite domain DBCloud Agent(codex-cloud / devin / jules)Cloud Agent Registry/v1/agents/tasksUserSQLite domain DBCloud Agent(codex-cloud / devin / jules)Cloud Agent Registry/v1/agents/tasksUserAsync execution upstreamPOST createTask (description, sources)Zod validation + AuthZ (management)getAgent(providerId)instantiate with credentialscreateTask() returns planningtaskId + status: planninginsertCloudAgentTasktaskIdGET /tasks/:id (poll)getStatus(externalId)status, plan, messagesupdateCloudAgentTasksnapshotPOST approvePlanapprovePlan(externalId)status: runningstream events / final result \ No newline at end of file diff --git a/docs/diagrams/exported/db-schema-overview.svg b/docs/diagrams/exported/db-schema-overview.svg new file mode 100644 index 0000000000..1aabb59678 --- /dev/null +++ b/docs/diagrams/exported/db-schema-overview.svg @@ -0,0 +1 @@ +

tracks

enforces

holds

protected_by

contains

logs

flushed_to

split_into

produced

streams

by

by

api_keys

api_key_usage

rate_limits

providers

provider_connections

domain_circuit_breakers

combos

combo_targets

combo_executions

spend_buffer

usage_aggregations

memory_documents

memory_chunks

skills_runs

skills_logs

agent_tasks

agent_task_events

audit_log

mcp_audit

\ No newline at end of file diff --git a/docs/diagrams/exported/i18n-flow.svg b/docs/diagrams/exported/i18n-flow.svg new file mode 100644 index 0000000000..dc0d44561e --- /dev/null +++ b/docs/diagrams/exported/i18n-flow.svg @@ -0,0 +1 @@ +

diff

in sync

drift

Source MDs
(CLAUDE.md, docs/**/*.md)

sha256 hash

.i18n-state.json

Mark source dirty

For each locale
(39 langs)

OmniRoute
/chat/completions
(cx/gpt-5.4-mini)

Write
docs/i18n/<locale>/<rel-path>.md

CI drift check
(npm run i18n:check)

pass

fail
(exit 1)

\ No newline at end of file diff --git a/docs/diagrams/exported/mcp-tools-37.svg b/docs/diagrams/exported/mcp-tools-37.svg new file mode 100644 index 0000000000..2877bf0caf --- /dev/null +++ b/docs/diagrams/exported/mcp-tools-37.svg @@ -0,0 +1 @@ +

MCP Server
37 tools total

Core (30)

Memory (3)

Skills (4)

Essential (8)
get_health, list_combos,
switch_combo, check_quota,
route_request, cost_report,
list_models_catalog,
get_combo_metrics

Search (1)
web_search

Advanced (11)
simulate_route, set_budget_guard,
set_routing_strategy,
set_resilience_profile,
test_combo, get_provider_metrics,
best_combo_for_task, explain_route,
get_session_snapshot,
db_health_check, sync_pricing

Cache (2)

Compression (5)

1Proxy / Tunnels (3)

memory_search

memory_save

memory_delete

skill_invoke

skill_list

skill_diagnose

skill_uninstall

\ No newline at end of file diff --git a/docs/diagrams/exported/request-pipeline.svg b/docs/diagrams/exported/request-pipeline.svg new file mode 100644 index 0000000000..f64c7903fe --- /dev/null +++ b/docs/diagrams/exported/request-pipeline.svg @@ -0,0 +1 @@ +

yes

no

combo

single

Client
(IDE/CLI/SDK)

Next.js Route
/v1/chat/completions

CORS preflight

Zod validation
(request body)

AuthZ pipeline
(extractApiKey +
isValidApiKey)

API key policy
(allowlist + scopes)

Prompt-injection
guardrail

handleChatCore

Cache hit?

Return cached

Rate limit
(per-key, per-IP)

Combo
target?

resolveComboTargets
(14 strategies)

handleSingleModel
(per target)

translateRequest
(OpenAI↔Claude↔Gemini)

getExecutor
(31 executors)

Upstream Provider
(177 providers)

SSE / JSON

responsesTransformer
(Responses↔Chat)

\ No newline at end of file diff --git a/docs/diagrams/exported/resilience-3layers.svg b/docs/diagrams/exported/resilience-3layers.svg new file mode 100644 index 0000000000..b1804b1da2 --- /dev/null +++ b/docs/diagrams/exported/resilience-3layers.svg @@ -0,0 +1 @@ +

CLOSED

OPEN

HALF_OPEN

available

cooling down

allowed

locked

success

408 / 500 / 502 / 503 / 504

401 / 403 (account)

429 quota (model)

Request

Provider Circuit Breaker
(scope: whole provider)

Connection Cooldown
(scope: one account/key)

Skip provider
(or 503 retry-after)

Allow probe

Model Lockout
(scope: provider × conn × model)

Skip this connection
fall back to next

Execute upstream

Fall back to next model

Clear cooldowns/lockouts

Trip provider breaker

Start connection cooldown

Start model lockout

\ No newline at end of file diff --git a/package.json b/package.json index 03cee3da5f..ccc0f0f644 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "check:docs-counts": "node scripts/check-docs-counts-sync.mjs", "check:deprecated-versions": "node scripts/check-deprecated-versions.mjs", "check:docs-all": "npm run check:docs-sync && npm run check:docs-counts && npm run check:env-doc-sync && npm run check:deprecated-versions", + "docs:render-diagrams": "node scripts/docs/render-diagrams.mjs", "check:node-runtime": "node --import tsx/esm scripts/check-supported-node-runtime.ts", "check:pack-artifact": "node --import tsx/esm scripts/validate-pack-artifact.ts", "audit:deps": "npm audit --audit-level=moderate && npm run audit:electron", @@ -128,7 +129,7 @@ "express": "^5.2.1", "fetch-socks": "^1.3.3", "fuse.js": "^7.3.0", -"gray-matter": "^4.0.3", + "gray-matter": "^4.0.3", "http-proxy-middleware": "^4.0.0", "https-proxy-agent": "^9.0.0", "ioredis": "^5.10.1", diff --git a/scripts/docs/render-diagrams.mjs b/scripts/docs/render-diagrams.mjs new file mode 100644 index 0000000000..01cd7c7377 --- /dev/null +++ b/scripts/docs/render-diagrams.mjs @@ -0,0 +1,85 @@ +#!/usr/bin/env node +/** + * Render every Mermaid source in docs/diagrams/*.mmd into docs/diagrams/exported/*.svg + * + * Usage: + * npm run docs:render-diagrams + * + * Requirements: + * - @mermaid-js/mermaid-cli (`mmdc`) on PATH or installed globally. + * `npm install -g @mermaid-js/mermaid-cli` if missing. + * + * Notes: + * - Puppeteer needs `--no-sandbox` on Ubuntu 23.10+ / WSL. A temp config file + * is written automatically. + * - Each diagram is rendered with `--backgroundColor white` so the SVG works + * against both light and dark themes. + * - The script exits non-zero on first failure so CI / pre-commit hooks can + * gate on it. + */ +import { spawnSync } from "node:child_process"; +import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { tmpdir } from "node:os"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const repoRoot = resolve(__dirname, "..", ".."); +const srcDir = resolve(repoRoot, "docs", "diagrams"); +const outDir = resolve(srcDir, "exported"); + +if (!existsSync(srcDir)) { + console.error(`[render-diagrams] missing source dir: ${srcDir}`); + process.exit(1); +} +if (!existsSync(outDir)) { + mkdirSync(outDir, { recursive: true }); +} + +// Puppeteer needs --no-sandbox on many Linux distros (Ubuntu 23.10+, WSL). +const puppeteerConfigPath = join(tmpdir(), "omniroute-mmdc-puppeteer.json"); +writeFileSync( + puppeteerConfigPath, + JSON.stringify({ args: ["--no-sandbox", "--disable-setuid-sandbox"] }, null, 2) +); + +const sources = readdirSync(srcDir) + .filter((f) => f.endsWith(".mmd")) + .sort(); + +if (sources.length === 0) { + console.error(`[render-diagrams] no .mmd files in ${srcDir}`); + process.exit(1); +} + +console.log(`[render-diagrams] rendering ${sources.length} diagram(s)`); +let failures = 0; +for (const src of sources) { + const input = join(srcDir, src); + const output = join(outDir, src.replace(/\.mmd$/, ".svg")); + console.log(` - ${src} -> ${output.replace(repoRoot + "/", "")}`); + const result = spawnSync( + "mmdc", + [ + "-i", + input, + "-o", + output, + "--backgroundColor", + "white", + "--puppeteerConfigFile", + puppeteerConfigPath, + ], + { stdio: "inherit" } + ); + if (result.status !== 0) { + console.error(` [FAIL] ${src} (exit ${result.status})`); + failures += 1; + } +} + +if (failures > 0) { + console.error(`[render-diagrams] ${failures} failure(s)`); + process.exit(1); +} +console.log(`[render-diagrams] all ${sources.length} diagram(s) rendered.`); From ee97583e02c03cc21f7df8ec2451e7034f76eebd Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 13 May 2026 13:54:26 -0300 Subject: [PATCH 3/3] docs: link Mermaid diagrams from 8 architecture/framework docs Wire the new docs/diagrams/exported/*.svg into the documents that already describe each flow, with the .mmd source linked alongside so edits stay auditable: - CLAUDE.md resilience-3layers - docs/ARCHITECTURE.md request-pipeline + resilience-3layers - docs/AUTO-COMBO.md auto-combo-9factor - docs/RESILIENCE_GUIDE.md resilience-3layers - docs/I18N.md i18n-flow - docs/MCP-SERVER.md mcp-tools-37 - docs/CLOUD_AGENT.md cloud-agent-flow - docs/AUTHZ_GUIDE.md authz-pipeline - docs/CODEBASE_DOCUMENTATION.md request-pipeline + db-schema-overview Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 5 ++++- docs/ARCHITECTURE.md | 15 +++++++++++++++ docs/AUTHZ_GUIDE.md | 4 ++++ docs/AUTO-COMBO.md | 4 ++++ docs/CLOUD_AGENT.md | 4 ++++ docs/CODEBASE_DOCUMENTATION.md | 8 ++++++++ docs/I18N.md | 4 ++++ docs/MCP-SERVER.md | 4 ++++ docs/RESILIENCE_GUIDE.md | 4 ++++ 9 files changed, 51 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3c96cb643f..8e13ad6f6c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,7 +79,10 @@ API routes follow a consistent pattern: `Route → CORS preflight → Zod body v ## Resilience Runtime State OmniRoute has three related but distinct temporary-failure mechanisms. Keep their -scope separate when debugging routing behavior. +scope separate when debugging routing behavior. See the +[3-layer resilience diagram](./docs/diagrams/exported/resilience-3layers.svg) +(source: [docs/diagrams/resilience-3layers.mmd](./docs/diagrams/resilience-3layers.mmd)) +for an at-a-glance map. ### Provider Circuit Breaker diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 719c530dcd..e3880b477a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -78,6 +78,21 @@ Primary runtime model: - Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs - A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage +## Reference Diagrams + +Canonical, version-controlled Mermaid sources for the v3.8.0 platform live in +[`docs/diagrams/`](./diagrams/README.md). Two are reproduced below for orientation; +the rest are linked from their domain-specific guides. + +![Request pipeline (/v1/chat/completions)](./diagrams/exported/request-pipeline.svg) + +> Source: [diagrams/request-pipeline.mmd](./diagrams/request-pipeline.mmd) + +![3-layer resilience model](./diagrams/exported/resilience-3layers.svg) + +> Source: [diagrams/resilience-3layers.mmd](./diagrams/resilience-3layers.mmd) — also linked from +> [RESILIENCE_GUIDE.md](./RESILIENCE_GUIDE.md) and the `CLAUDE.md` resilience reference. + ## Scope and Boundaries ### In Scope diff --git a/docs/AUTHZ_GUIDE.md b/docs/AUTHZ_GUIDE.md index 6043be9aa4..b7128a1cee 100644 --- a/docs/AUTHZ_GUIDE.md +++ b/docs/AUTHZ_GUIDE.md @@ -5,6 +5,10 @@ OmniRoute has a route-aware authorization pipeline that gates every API request. Classification is **deterministic** and **fail-closed** — anything that cannot be classified ends up as `MANAGEMENT` and demands a session or management-grade token. This page explains the model for engineers maintaining routes or designing new endpoints. +![AuthZ pipeline (3 route classes + policy evaluation)](./diagrams/exported/authz-pipeline.svg) + +> Source: [diagrams/authz-pipeline.mmd](./diagrams/authz-pipeline.mmd) + ## Two Auth Modes ### 1. API Key (Bearer) diff --git a/docs/AUTO-COMBO.md b/docs/AUTO-COMBO.md index 14421afd6a..a15fd2d756 100644 --- a/docs/AUTO-COMBO.md +++ b/docs/AUTO-COMBO.md @@ -77,6 +77,10 @@ Auto-scoring selects best provider/model per request The Auto-Combo Engine dynamically selects the best provider/model for each request using a **9-factor scoring function** (defined in `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`). All weights sum to **1.0**. +![Auto-Combo 9-factor scoring](./diagrams/exported/auto-combo-9factor.svg) + +> Source: [diagrams/auto-combo-9factor.mmd](./diagrams/auto-combo-9factor.mmd) + | Factor | Default Weight | Description | | :----------------- | :------------- | :---------------------------------------------------------------------- | | `health` | 0.22 | Health score from circuit breaker (CLOSED=1.0, HALF_OPEN=0.5, OPEN=0.0) | diff --git a/docs/CLOUD_AGENT.md b/docs/CLOUD_AGENT.md index f0c538284d..5bd7b64575 100644 --- a/docs/CLOUD_AGENT.md +++ b/docs/CLOUD_AGENT.md @@ -12,6 +12,10 @@ A Cloud Agent task is **not** a regular chat completion. It is a durable, multi- unit of work that may take minutes to hours, can produce a Pull Request as its artifact, and supports follow-up messages and (in some providers) plan approval gates. +![Cloud Agent task lifecycle](./diagrams/exported/cloud-agent-flow.svg) + +> Source: [diagrams/cloud-agent-flow.mmd](./diagrams/cloud-agent-flow.mmd) + ## Supported Agents | Provider ID | Class | Source | Upstream Base URL | Plan Approval | diff --git a/docs/CODEBASE_DOCUMENTATION.md b/docs/CODEBASE_DOCUMENTATION.md index bf8bdf5d31..e4d944573d 100644 --- a/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/CODEBASE_DOCUMENTATION.md @@ -286,6 +286,10 @@ Top-level files in `src/lib/`: Singleton SQLite database (`getDbInstance()` in `core.ts`, WAL journaling). **Never write raw SQL in routes or handlers** — go through these modules. +![Database schema overview (selected core tables)](./diagrams/exported/db-schema-overview.svg) + +> Source: [diagrams/db-schema-overview.mmd](./diagrams/db-schema-overview.mmd) + Domain modules (each owns one or more tables): `apiKeys.ts`, `backup.ts`, `batches.ts`, `cleanup.ts`, `cliToolState.ts`, `combos.ts`, `commandCodeAuth.ts`, `compression.ts`, `compressionAnalytics.ts`, @@ -638,6 +642,10 @@ Common commands: ## 9. Request Pipeline (Summary) +![Request pipeline (/v1/chat/completions)](./diagrams/exported/request-pipeline.svg) + +> Source: [diagrams/request-pipeline.mmd](./diagrams/request-pipeline.mmd) + ``` Client request → /v1/chat/completions (route.ts) diff --git a/docs/I18N.md b/docs/I18N.md index 458e5df371..3a6264b86b 100644 --- a/docs/I18N.md +++ b/docs/I18N.md @@ -17,6 +17,10 @@ OmniRoute supports **30 languages** with full dashboard UI translation, translat ## Architecture +![Incremental hash-based i18n pipeline](./diagrams/exported/i18n-flow.svg) + +> Source: [diagrams/i18n-flow.mmd](./diagrams/i18n-flow.mmd) + ### Source of Truth - **UI strings**: `src/i18n/messages/en.json` (English source, ~2800 keys) diff --git a/docs/MCP-SERVER.md b/docs/MCP-SERVER.md index fe91b6bd2e..ee1b87ec55 100644 --- a/docs/MCP-SERVER.md +++ b/docs/MCP-SERVER.md @@ -4,6 +4,10 @@ > > Source of truth: `open-sse/mcp-server/schemas/tools.ts` (30 tools) + `open-sse/mcp-server/tools/memoryTools.ts` (3 tools) + `open-sse/mcp-server/tools/skillTools.ts` (4 tools). Tool registration and scope wiring lives in `open-sse/mcp-server/server.ts`. +![MCP tool inventory (37 tools by category)](./diagrams/exported/mcp-tools-37.svg) + +> Source: [diagrams/mcp-tools-37.mmd](./diagrams/mcp-tools-37.mmd) + ## Installation OmniRoute MCP is built-in. Start it with: diff --git a/docs/RESILIENCE_GUIDE.md b/docs/RESILIENCE_GUIDE.md index 1e630d85d8..085f0b25ae 100644 --- a/docs/RESILIENCE_GUIDE.md +++ b/docs/RESILIENCE_GUIDE.md @@ -2,6 +2,10 @@ OmniRoute has three distinct but related resilience mechanisms. Each has a different scope and purpose. Keep them separate when debugging routing behavior. +![3-layer resilience model](./diagrams/exported/resilience-3layers.svg) + +> Source: [diagrams/resilience-3layers.mmd](./diagrams/resilience-3layers.mmd) + ## 1. Provider Circuit Breaker **Scope:** entire provider (e.g., `glm`, `openai`, `anthropic`).