Compare commits

..

1 Commits

Author SHA1 Message Date
diegosouzapw
3113e571fc docs(api): document every implemented route in openapi.yaml (276 -> 692 paths)
Follow-up nº 3 of the 2026-08-31 docs audit: 416 implemented routes had no
OpenAPI entry (gamification, radar, skills, webhooks, mcp, a2a, tunnels,
version-manager and plugins were absent entirely). Adds a minimal, honest
entry for each — real methods parsed from every route.ts's exports, a group
tag and a neutral path-derived summary; no invented semantics. Rich schemas
remain hand-curated in the existing entries.

Generated by scripts/ad-hoc/gen-openapi-missing-paths.mjs, which enumerates
routes with the same lib check:api-docs-refs uses — the spec now covers
692/692 real routes and the gate verifies every spec path has a real route.
2026-08-31 14:37:12 -03:00
14 changed files with 6080 additions and 17 deletions

View File

@@ -13,10 +13,10 @@ Mermaid sources (`.mmd`) and exported SVGs for OmniRoute v3.8.0 architecture flo
| Source | Exported | Used in |
| ---------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------ |
| [request-pipeline.mmd](./request-pipeline.mmd) | [SVG](./exported/request-pipeline.svg) | docs/architecture/ARCHITECTURE.md, docs/architecture/CODEBASE_DOCUMENTATION.md |
| [auto-combo-scoring.mmd](./auto-combo-scoring.mmd) | [SVG](./exported/auto-combo-scoring.svg) | docs/routing/AUTO-COMBO.md |
| [auto-combo-12factor.mmd](./auto-combo-12factor.mmd) | [SVG](./exported/auto-combo-12factor.svg) | docs/routing/AUTO-COMBO.md |
| [resilience-3layers.mmd](./resilience-3layers.mmd) | [SVG](./exported/resilience-3layers.svg) | docs/architecture/RESILIENCE_GUIDE.md, CLAUDE.md |
| [i18n-flow.mmd](./i18n-flow.mmd) | [SVG](./exported/i18n-flow.svg) | docs/guides/I18N.md |
| [mcp-tools.mmd](./mcp-tools.mmd) | [SVG](./exported/mcp-tools.svg) | docs/frameworks/MCP-SERVER.md |
| [mcp-tools-107.mmd](./mcp-tools-107.mmd) | [SVG](./exported/mcp-tools-107.svg) | docs/frameworks/MCP-SERVER.md |
| [cloud-agent-flow.mmd](./cloud-agent-flow.mmd) | [SVG](./exported/cloud-agent-flow.svg) | docs/frameworks/CLOUD_AGENT.md |
| [authz-pipeline.mmd](./authz-pipeline.mmd) | [SVG](./exported/authz-pipeline.svg) | docs/architecture/AUTHZ_GUIDE.md |
| [db-schema-overview.mmd](./db-schema-overview.mmd) | [SVG](./exported/db-schema-overview.svg) | docs/architecture/CODEBASE_DOCUMENTATION.md |

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -163,9 +163,9 @@ Helper detekcji żyje w `src/lib/combos/modelNameCollision.ts`.
Silnik Auto-Combo dynamicznie wybiera najlepszego providera/model dla każdego żądania przy użyciu **13-czynnikowej funkcji scoringu** (zdefiniowanej w `open-sse/services/autoCombo/scoring.ts``DEFAULT_WEIGHTS`). Wszystkie wagi sumują się do **1.0**.
![Auto-Combo 13-factor scoring](../diagrams/exported/auto-combo-scoring.svg)
![Auto-Combo 13-factor scoring](../diagrams/exported/auto-combo-12factor.svg)
> Źródło: [diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd) (regeneruj przez `npm run docs:render-diagrams`). Historyczna nazwa pliku pochodzi sprzed dodania kolejnych czynników; bieżący diagram pokazuje wszystkie 13.
> Źródło: [diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd) (regeneruj przez `npm run docs:render-diagrams`). Historyczna nazwa pliku pochodzi sprzed dodania kolejnych czynników; bieżący diagram pokazuje wszystkie 13.
| Czynnik | Domyślna waga | Opis |
| :-------------------- | :------------ | :------------------------------------------------------------------------------------------------------- |

View File

@@ -104,9 +104,9 @@ handleComboChat与持久化 Combo 相同的引擎)
Auto-Combo 引擎使用**13 因子评分函数**(定义在 `open-sse/services/autoCombo/scoring.ts``DEFAULT_WEIGHTS`)为每次请求动态选择最佳服务商/模型。所有权重之和为 **1.0**
![Auto-Combo 13-factor scoring](../diagrams/exported/auto-combo-scoring.svg)
![Auto-Combo 13-factor scoring](../diagrams/exported/auto-combo-12factor.svg)
> 来源:[diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd)(通过 `npm run docs:render-diagrams` 重新生成)。文件名为历史名称;当前图表包含全部 13 个因子。
> 来源:[diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd)(通过 `npm run docs:render-diagrams` 重新生成)。文件名为历史名称;当前图表包含全部 13 个因子。
| 因子 | 默认权重 | 描述 |
| :---------------------- | :------- | :--------------------------------------------------------------------------------------------- |

View File

@@ -116,9 +116,9 @@ handleComboChat與持久化組合使用相同引擎
自動組合引擎使用**13 因子評分函數**(定義於 `open-sse/services/autoCombo/scoring.ts``DEFAULT_WEIGHTS`)為每個請求動態選擇最佳的提供者/模型。所有權重合計為 **1.0**
![自動組合 13 因子評分](../diagrams/exported/auto-combo-scoring.svg)
![自動組合 13 因子評分](../diagrams/exported/auto-combo-12factor.svg)
> 來源:[diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd)(可透過 `npm run docs:render-diagrams` 重新生成)。檔名是歷史名稱;目前圖表包含全部 13 個因子。
> 來源:[diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd)(可透過 `npm run docs:render-diagrams` 重新生成)。檔名是歷史名稱;目前圖表包含全部 13 個因子。
| 因子 | 預設權重 | 說明 |
| :-------------------------------------- | :------- | :--------------------------------------------------------------------------- |

File diff suppressed because it is too large Load Diff

View File

@@ -186,9 +186,9 @@ See [#7992](https://github.com/diegosouzapw/OmniRoute/issues/7992) and [#7111](h
The Auto-Combo Engine dynamically selects the best provider/model for each request using a **15-factor scoring function** (defined in `open-sse/services/autoCombo/scoring.ts``DEFAULT_WEIGHTS`). The default weights sum to `1.0`; custom weights are renormalized by `normalizeScoringWeights()`. Two of the fifteen — `cacheAffinity` and `resetWindowAffinity` — carry a default weight of `0`: they are still computed for every candidate, and `cacheAffinity` gates prompt-cache deduplication outside the score, so they are declared factors that simply do not vote by default.
![Auto-Combo 15-factor scoring](../diagrams/exported/auto-combo-scoring.svg)
![Auto-Combo 15-factor scoring](../diagrams/exported/auto-combo-12factor.svg)
> Source: [diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd) (regenerate via `npm run docs:render-diagrams`). The filename is historical; the source and rendered diagram show all 15 factors declared in `DEFAULT_WEIGHTS`.
> Source: [diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd) (regenerate via `npm run docs:render-diagrams`). The filename is historical; the source and rendered diagram show all 15 factors declared in `DEFAULT_WEIGHTS`.
| Factor | Default Weight | Description |
| :-------------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

View File

@@ -0,0 +1,122 @@
#!/usr/bin/env node
// One-shot generator (2026-08-31 docs audit follow-up nº 3): append a minimal,
// honest OpenAPI entry for every real route that docs/openapi.yaml does not
// document yet. Enumerates routes with the SAME lib the check:api-docs-refs
// gate uses, so the generated set can never diverge from the gate's universe.
// Minimal by design: real methods (parsed from each route.ts's exports), a
// group tag, a neutral path-derived summary and a generic 200 — no invented
// semantics. Rich schemas stay hand-curated in the existing entries.
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { collectApiRouteFiles, toApiUrlPath, apiRoot } from "../check/lib/apiRoutes.mjs";
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
const SPEC = path.join(ROOT, "docs", "openapi.yaml");
const APPLY = process.argv.includes("--apply");
const normalizeParams = (p) => p.replace(/\{[^}]+\}/g, "{}");
// --- real routes + their exported HTTP methods --------------------------------
const METHOD_RE =
/export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b|export\s+const\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b|export\s*\{[^}]*\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b[^}]*\}/g;
function routeMethods(absFile) {
const src = fs.readFileSync(absFile, "utf8");
const methods = new Set();
for (const m of src.matchAll(METHOD_RE)) {
const name = m[1] || m[2];
if (name) methods.add(name);
if (m[3]) {
// re-export list: capture every method inside the braces
for (const inner of m[0].matchAll(/\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g))
methods.add(inner[1]);
}
}
methods.delete("OPTIONS"); // CORS preflight — not a documented operation
methods.delete("HEAD");
return [...methods];
}
const routeFiles = collectApiRouteFiles(ROOT);
const API_ROOT = apiRoot(ROOT);
const routes = new Map(); // urlPath -> methods
for (const rel of routeFiles) {
const abs = path.join(ROOT, rel);
const url = toApiUrlPath(path.dirname(abs), API_ROOT);
if (url) routes.set(url, routeMethods(abs));
}
// --- paths already in the spec -------------------------------------------------
const spec = fs.readFileSync(SPEC, "utf8");
const specPaths = new Set();
for (const m of spec.matchAll(/^ {2}(\/[^\s:]+):\s*$/gm)) specPaths.add(normalizeParams(m[1]));
const missing = [...routes.entries()]
.filter(([url]) => !specPaths.has(normalizeParams(url)))
.filter(([, methods]) => methods.length > 0)
.sort(([a], [b]) => a.localeCompare(b));
// --- tag + summary derivation --------------------------------------------------
const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
function groupTag(url) {
const seg = url.replace(/^\/api\//, "").split("/");
if (seg[0] === "v1") return seg[1] ? `V1 ${cap(seg[1].replace(/\{|\}/g, ""))}` : "V1";
return cap(seg[0].replace(/\{|\}/g, "").replace(/-/g, " "));
}
function summaryFor(url, method) {
const tail = url
.replace(/^\/api\/(v1\/)?/, "")
.replace(/\{([^}]+)\}/g, "<$1>")
.replace(/[/]/g, " ")
.replace(/-/g, " ");
return `${method} ${tail}`;
}
// --- emit YAML -----------------------------------------------------------------
const existingTags = new Set(
[...spec.matchAll(/^ {2}- name: (.+)$/gm)].map((m) => m[1].trim().toLowerCase())
);
const newTags = new Map();
const lines = [];
lines.push("");
lines.push(" # --- Generated route coverage (docs audit 2026-08-31) -----------------------");
lines.push(" # Minimal entries for every implemented route not documented above. Methods");
lines.push(" # are parsed from each route.ts's exports; summaries are path-derived.");
lines.push(" # Regenerate with: node scripts/ad-hoc/gen-openapi-missing-paths.mjs --apply");
for (const [url, methods] of missing) {
const tag = groupTag(url);
if (!existingTags.has(tag.toLowerCase()) && !newTags.has(tag))
newTags.set(tag, `${tag} endpoints (generated route coverage)`);
lines.push(` ${url}:`);
for (const method of methods.sort()) {
lines.push(` ${method.toLowerCase()}:`);
lines.push(` tags:`);
lines.push(` - ${tag}`);
lines.push(` summary: "${summaryFor(url, method)}"`);
lines.push(` responses:`);
lines.push(` "200":`);
lines.push(` description: OK`);
}
}
const tagLines = [...newTags.entries()]
.sort(([a], [b]) => a.localeCompare(b))
.map(([name, description]) => ` - name: ${name}\n description: ${description}`)
.join("\n");
console.log(
`real routes: ${routes.size} · already in spec: ${specPaths.size} · missing with methods: ${missing.length} · new tags: ${newTags.size}`
);
if (!APPLY) {
console.log("(dry-run) pass --apply to write docs/openapi.yaml");
process.exit(0);
}
let out = spec;
// append new tags right after the last existing tag entry (before `paths:`)
if (tagLines) out = out.replace(/\npaths:\n/, `\n${tagLines}\n\npaths:\n`);
// insert generated paths right before the components section
out = out.replace(/\ncomponents:\n/, `\n${lines.join("\n")}\n\ncomponents:\n`);
fs.writeFileSync(SPEC, out);
console.log(`wrote ${missing.length} paths + ${newTags.size} tags to docs/openapi.yaml`);

View File

@@ -598,7 +598,7 @@ export function buildChecks() {
"docs/guides/FEATURES.md",
"docs/guides/FREE_PROVIDER_RANKINGS.md",
"docs/diagrams/strategies-grid.svg",
"docs/diagrams/auto-combo-scoring.mmd",
"docs/diagrams/auto-combo-12factor.mmd",
"llm.txt",
"open-sse/services/autoCombo/routerStrategy.ts",
"open-sse/services/taskAwareRouter.ts",

File diff suppressed because it is too large Load Diff