mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-01 03:52:17 +03:00
Compare commits
1 Commits
docs/renam
...
docs/opena
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3113e571fc |
@@ -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 |
|
||||
|
||||
1
docs/diagrams/exported/auto-combo-12factor.svg
Normal file
1
docs/diagrams/exported/auto-combo-12factor.svg
Normal file
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 |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -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**.
|
||||
|
||||

|
||||

|
||||
|
||||
> Ź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 |
|
||||
| :-------------------- | :------------ | :------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -104,9 +104,9 @@ handleComboChat(与持久化 Combo 相同的引擎)
|
||||
|
||||
Auto-Combo 引擎使用**13 因子评分函数**(定义在 `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`)为每次请求动态选择最佳服务商/模型。所有权重之和为 **1.0**。
|
||||
|
||||

|
||||

|
||||
|
||||
> 来源:[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 个因子。
|
||||
|
||||
| 因子 | 默认权重 | 描述 |
|
||||
| :---------------------- | :------- | :--------------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -116,9 +116,9 @@ handleComboChat(與持久化組合使用相同引擎)
|
||||
|
||||
自動組合引擎使用**13 因子評分函數**(定義於 `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`)為每個請求動態選擇最佳的提供者/模型。所有權重合計為 **1.0**。
|
||||
|
||||

|
||||

|
||||
|
||||
> 來源:[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 個因子。
|
||||
|
||||
| 因子 | 預設權重 | 說明 |
|
||||
| :-------------------------------------- | :------- | :--------------------------------------------------------------------------- |
|
||||
|
||||
4833
docs/openapi.yaml
4833
docs/openapi.yaml
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
> 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 |
|
||||
| :-------------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
|
||||
122
scripts/ad-hoc/gen-openapi-missing-paths.mjs
Normal file
122
scripts/ad-hoc/gen-openapi-missing-paths.mjs
Normal 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`);
|
||||
@@ -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
Reference in New Issue
Block a user