mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 15:22:12 +03:00
refactor(docs): cleanup fumadocs PR — revert deepseek, add i18n fallback, restore LanguageSelector
- Revert unrelated deepseek-web.ts changes (should be separate PR) - Add .source/ to .gitignore (Fumadocs generated files) - Remove contributor IP from allowedDevOrigins - Add i18n runtime fallback: reads NEXT_LOCALE cookie, loads translated .md from docs/i18n/<locale>/docs/ (preserves existing translation pipeline) - Restore LanguageSelector in Fumadocs layout nav - Restore SEO metadata (title template, description, robots)
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -177,3 +177,6 @@ scripts/i18n/_pending-keys.json
|
||||
.claude/commands/port-upstream-features-cc.md
|
||||
.claude/commands/port-upstream-issues-cc.md
|
||||
.claude/worktrees/
|
||||
|
||||
# Fumadocs generated source
|
||||
.source/
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { browser } from "fumadocs-mdx/runtime/browser";
|
||||
import type * as Config from "../source.config";
|
||||
|
||||
const create = browser<
|
||||
typeof Config,
|
||||
import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
||||
DocData: {};
|
||||
}
|
||||
>();
|
||||
const browserCollections = {
|
||||
docs: create.doc("docs", {
|
||||
"architecture/ARCHITECTURE.md": () =>
|
||||
import("../docs/architecture/ARCHITECTURE.md?collection=docs"),
|
||||
"architecture/AUTHZ_GUIDE.md": () =>
|
||||
import("../docs/architecture/AUTHZ_GUIDE.md?collection=docs"),
|
||||
"architecture/CODEBASE_DOCUMENTATION.md": () =>
|
||||
import("../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs"),
|
||||
"architecture/REPOSITORY_MAP.md": () =>
|
||||
import("../docs/architecture/REPOSITORY_MAP.md?collection=docs"),
|
||||
"architecture/RESILIENCE_GUIDE.md": () =>
|
||||
import("../docs/architecture/RESILIENCE_GUIDE.md?collection=docs"),
|
||||
"compression/COMPRESSION_ENGINES.md": () =>
|
||||
import("../docs/compression/COMPRESSION_ENGINES.md?collection=docs"),
|
||||
"compression/COMPRESSION_GUIDE.md": () =>
|
||||
import("../docs/compression/COMPRESSION_GUIDE.md?collection=docs"),
|
||||
"compression/COMPRESSION_LANGUAGE_PACKS.md": () =>
|
||||
import("../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs"),
|
||||
"compression/COMPRESSION_RULES_FORMAT.md": () =>
|
||||
import("../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs"),
|
||||
"compression/RTK_COMPRESSION.md": () =>
|
||||
import("../docs/compression/RTK_COMPRESSION.md?collection=docs"),
|
||||
"frameworks/A2A-SERVER.md": () => import("../docs/frameworks/A2A-SERVER.md?collection=docs"),
|
||||
"frameworks/AGENT_PROTOCOLS_GUIDE.md": () =>
|
||||
import("../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs"),
|
||||
"frameworks/CLOUD_AGENT.md": () => import("../docs/frameworks/CLOUD_AGENT.md?collection=docs"),
|
||||
"frameworks/EVALS.md": () => import("../docs/frameworks/EVALS.md?collection=docs"),
|
||||
"frameworks/GAMIFICATION.md": () =>
|
||||
import("../docs/frameworks/GAMIFICATION.md?collection=docs"),
|
||||
"frameworks/MCP-SERVER.md": () => import("../docs/frameworks/MCP-SERVER.md?collection=docs"),
|
||||
"frameworks/MEMORY.md": () => import("../docs/frameworks/MEMORY.md?collection=docs"),
|
||||
"frameworks/OPENCODE.md": () => import("../docs/frameworks/OPENCODE.md?collection=docs"),
|
||||
"frameworks/SKILLS.md": () => import("../docs/frameworks/SKILLS.md?collection=docs"),
|
||||
"frameworks/WEBHOOKS.md": () => import("../docs/frameworks/WEBHOOKS.md?collection=docs"),
|
||||
"guides/DOCKER_GUIDE.md": () => import("../docs/guides/DOCKER_GUIDE.md?collection=docs"),
|
||||
"guides/ELECTRON_GUIDE.md": () => import("../docs/guides/ELECTRON_GUIDE.md?collection=docs"),
|
||||
"guides/FEATURES.md": () => import("../docs/guides/FEATURES.md?collection=docs"),
|
||||
"guides/I18N.md": () => import("../docs/guides/I18N.md?collection=docs"),
|
||||
"guides/KIRO_SETUP.md": () => import("../docs/guides/KIRO_SETUP.md?collection=docs"),
|
||||
"guides/PWA_GUIDE.md": () => import("../docs/guides/PWA_GUIDE.md?collection=docs"),
|
||||
"guides/SETUP_GUIDE.md": () => import("../docs/guides/SETUP_GUIDE.md?collection=docs"),
|
||||
"guides/TERMUX_GUIDE.md": () => import("../docs/guides/TERMUX_GUIDE.md?collection=docs"),
|
||||
"guides/TROUBLESHOOTING.md": () => import("../docs/guides/TROUBLESHOOTING.md?collection=docs"),
|
||||
"guides/UNINSTALL.md": () => import("../docs/guides/UNINSTALL.md?collection=docs"),
|
||||
"guides/USER_GUIDE.md": () => import("../docs/guides/USER_GUIDE.md?collection=docs"),
|
||||
"ops/COVERAGE_PLAN.md": () => import("../docs/ops/COVERAGE_PLAN.md?collection=docs"),
|
||||
"ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": () =>
|
||||
import("../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs"),
|
||||
"ops/FLY_IO_DEPLOYMENT_GUIDE.md": () =>
|
||||
import("../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs"),
|
||||
"ops/PROXY_GUIDE.md": () => import("../docs/ops/PROXY_GUIDE.md?collection=docs"),
|
||||
"ops/RELEASE_CHECKLIST.md": () => import("../docs/ops/RELEASE_CHECKLIST.md?collection=docs"),
|
||||
"ops/SQLITE_RUNTIME.md": () => import("../docs/ops/SQLITE_RUNTIME.md?collection=docs"),
|
||||
"ops/TUNNELS_GUIDE.md": () => import("../docs/ops/TUNNELS_GUIDE.md?collection=docs"),
|
||||
"ops/VM_DEPLOYMENT_GUIDE.md": () =>
|
||||
import("../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs"),
|
||||
"routing/AUTO-COMBO.md": () => import("../docs/routing/AUTO-COMBO.md?collection=docs"),
|
||||
"routing/REASONING_REPLAY.md": () =>
|
||||
import("../docs/routing/REASONING_REPLAY.md?collection=docs"),
|
||||
"security/CLI_TOKEN.md": () => import("../docs/security/CLI_TOKEN.md?collection=docs"),
|
||||
"security/CLI_TOKEN_AUTH.md": () =>
|
||||
import("../docs/security/CLI_TOKEN_AUTH.md?collection=docs"),
|
||||
"security/COMPLIANCE.md": () => import("../docs/security/COMPLIANCE.md?collection=docs"),
|
||||
"security/ERROR_SANITIZATION.md": () =>
|
||||
import("../docs/security/ERROR_SANITIZATION.md?collection=docs"),
|
||||
"security/GUARDRAILS.md": () => import("../docs/security/GUARDRAILS.md?collection=docs"),
|
||||
"security/PUBLIC_CREDS.md": () => import("../docs/security/PUBLIC_CREDS.md?collection=docs"),
|
||||
"security/ROUTE_GUARD_TIERS.md": () =>
|
||||
import("../docs/security/ROUTE_GUARD_TIERS.md?collection=docs"),
|
||||
"security/STEALTH_GUIDE.md": () => import("../docs/security/STEALTH_GUIDE.md?collection=docs"),
|
||||
"reference/API_REFERENCE.md": () =>
|
||||
import("../docs/reference/API_REFERENCE.md?collection=docs"),
|
||||
"reference/CLI-TOOLS.md": () => import("../docs/reference/CLI-TOOLS.md?collection=docs"),
|
||||
"reference/ENVIRONMENT.md": () => import("../docs/reference/ENVIRONMENT.md?collection=docs"),
|
||||
"reference/FREE_TIERS.md": () => import("../docs/reference/FREE_TIERS.md?collection=docs"),
|
||||
"reference/PROVIDER_REFERENCE.md": () =>
|
||||
import("../docs/reference/PROVIDER_REFERENCE.md?collection=docs"),
|
||||
}),
|
||||
};
|
||||
export default browserCollections;
|
||||
@@ -1,14 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { dynamic } from "fumadocs-mdx/runtime/dynamic";
|
||||
import * as Config from "../source.config";
|
||||
|
||||
const create = await dynamic<
|
||||
typeof Config,
|
||||
import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
||||
DocData: {};
|
||||
}
|
||||
>(
|
||||
Config,
|
||||
{ configPath: "source.config.ts", environment: "next", outDir: ".source" },
|
||||
{ doc: { passthroughs: ["extractedReferences"] } }
|
||||
);
|
||||
@@ -1,147 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { default as __fd_glob_63 } from "../docs/security/meta.json?collection=docs";
|
||||
import { default as __fd_glob_62 } from "../docs/reference/openapi.yaml?collection=docs";
|
||||
import { default as __fd_glob_61 } from "../docs/reference/meta.json?collection=docs";
|
||||
import { default as __fd_glob_60 } from "../docs/routing/meta.json?collection=docs";
|
||||
import { default as __fd_glob_59 } from "../docs/ops/meta.json?collection=docs";
|
||||
import { default as __fd_glob_58 } from "../docs/guides/meta.json?collection=docs";
|
||||
import { default as __fd_glob_57 } from "../docs/frameworks/meta.json?collection=docs";
|
||||
import { default as __fd_glob_56 } from "../docs/compression/meta.json?collection=docs";
|
||||
import { default as __fd_glob_55 } from "../docs/architecture/meta.json?collection=docs";
|
||||
import { default as __fd_glob_54 } from "../docs/meta.json?collection=docs";
|
||||
import * as __fd_glob_53 from "../docs/reference/PROVIDER_REFERENCE.md?collection=docs";
|
||||
import * as __fd_glob_52 from "../docs/reference/FREE_TIERS.md?collection=docs";
|
||||
import * as __fd_glob_51 from "../docs/reference/ENVIRONMENT.md?collection=docs";
|
||||
import * as __fd_glob_50 from "../docs/reference/CLI-TOOLS.md?collection=docs";
|
||||
import * as __fd_glob_49 from "../docs/reference/API_REFERENCE.md?collection=docs";
|
||||
import * as __fd_glob_48 from "../docs/security/STEALTH_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_47 from "../docs/security/ROUTE_GUARD_TIERS.md?collection=docs";
|
||||
import * as __fd_glob_46 from "../docs/security/PUBLIC_CREDS.md?collection=docs";
|
||||
import * as __fd_glob_45 from "../docs/security/GUARDRAILS.md?collection=docs";
|
||||
import * as __fd_glob_44 from "../docs/security/ERROR_SANITIZATION.md?collection=docs";
|
||||
import * as __fd_glob_43 from "../docs/security/COMPLIANCE.md?collection=docs";
|
||||
import * as __fd_glob_42 from "../docs/security/CLI_TOKEN_AUTH.md?collection=docs";
|
||||
import * as __fd_glob_41 from "../docs/security/CLI_TOKEN.md?collection=docs";
|
||||
import * as __fd_glob_40 from "../docs/routing/REASONING_REPLAY.md?collection=docs";
|
||||
import * as __fd_glob_39 from "../docs/routing/AUTO-COMBO.md?collection=docs";
|
||||
import * as __fd_glob_38 from "../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_37 from "../docs/ops/TUNNELS_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_36 from "../docs/ops/SQLITE_RUNTIME.md?collection=docs";
|
||||
import * as __fd_glob_35 from "../docs/ops/RELEASE_CHECKLIST.md?collection=docs";
|
||||
import * as __fd_glob_34 from "../docs/ops/PROXY_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_33 from "../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_32 from "../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs";
|
||||
import * as __fd_glob_31 from "../docs/ops/COVERAGE_PLAN.md?collection=docs";
|
||||
import * as __fd_glob_30 from "../docs/guides/USER_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_29 from "../docs/guides/UNINSTALL.md?collection=docs";
|
||||
import * as __fd_glob_28 from "../docs/guides/TROUBLESHOOTING.md?collection=docs";
|
||||
import * as __fd_glob_27 from "../docs/guides/TERMUX_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_26 from "../docs/guides/SETUP_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_25 from "../docs/guides/PWA_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_24 from "../docs/guides/KIRO_SETUP.md?collection=docs";
|
||||
import * as __fd_glob_23 from "../docs/guides/I18N.md?collection=docs";
|
||||
import * as __fd_glob_22 from "../docs/guides/FEATURES.md?collection=docs";
|
||||
import * as __fd_glob_21 from "../docs/guides/ELECTRON_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_20 from "../docs/guides/DOCKER_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_19 from "../docs/frameworks/WEBHOOKS.md?collection=docs";
|
||||
import * as __fd_glob_18 from "../docs/frameworks/SKILLS.md?collection=docs";
|
||||
import * as __fd_glob_17 from "../docs/frameworks/OPENCODE.md?collection=docs";
|
||||
import * as __fd_glob_16 from "../docs/frameworks/MEMORY.md?collection=docs";
|
||||
import * as __fd_glob_15 from "../docs/frameworks/MCP-SERVER.md?collection=docs";
|
||||
import * as __fd_glob_14 from "../docs/frameworks/GAMIFICATION.md?collection=docs";
|
||||
import * as __fd_glob_13 from "../docs/frameworks/EVALS.md?collection=docs";
|
||||
import * as __fd_glob_12 from "../docs/frameworks/CLOUD_AGENT.md?collection=docs";
|
||||
import * as __fd_glob_11 from "../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_10 from "../docs/frameworks/A2A-SERVER.md?collection=docs";
|
||||
import * as __fd_glob_9 from "../docs/compression/RTK_COMPRESSION.md?collection=docs";
|
||||
import * as __fd_glob_8 from "../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs";
|
||||
import * as __fd_glob_7 from "../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs";
|
||||
import * as __fd_glob_6 from "../docs/compression/COMPRESSION_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_5 from "../docs/compression/COMPRESSION_ENGINES.md?collection=docs";
|
||||
import * as __fd_glob_4 from "../docs/architecture/RESILIENCE_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_3 from "../docs/architecture/REPOSITORY_MAP.md?collection=docs";
|
||||
import * as __fd_glob_2 from "../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs";
|
||||
import * as __fd_glob_1 from "../docs/architecture/AUTHZ_GUIDE.md?collection=docs";
|
||||
import * as __fd_glob_0 from "../docs/architecture/ARCHITECTURE.md?collection=docs";
|
||||
import { server } from "fumadocs-mdx/runtime/server";
|
||||
import type * as Config from "../source.config";
|
||||
|
||||
const create = server<
|
||||
typeof Config,
|
||||
import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
||||
DocData: {};
|
||||
}
|
||||
>({ doc: { passthroughs: ["extractedReferences"] } });
|
||||
|
||||
export const docs = await create.docs(
|
||||
"docs",
|
||||
"docs",
|
||||
{
|
||||
"meta.json": __fd_glob_54,
|
||||
"architecture/meta.json": __fd_glob_55,
|
||||
"compression/meta.json": __fd_glob_56,
|
||||
"frameworks/meta.json": __fd_glob_57,
|
||||
"guides/meta.json": __fd_glob_58,
|
||||
"ops/meta.json": __fd_glob_59,
|
||||
"routing/meta.json": __fd_glob_60,
|
||||
"reference/meta.json": __fd_glob_61,
|
||||
"reference/openapi.yaml": __fd_glob_62,
|
||||
"security/meta.json": __fd_glob_63,
|
||||
},
|
||||
{
|
||||
"architecture/ARCHITECTURE.md": __fd_glob_0,
|
||||
"architecture/AUTHZ_GUIDE.md": __fd_glob_1,
|
||||
"architecture/CODEBASE_DOCUMENTATION.md": __fd_glob_2,
|
||||
"architecture/REPOSITORY_MAP.md": __fd_glob_3,
|
||||
"architecture/RESILIENCE_GUIDE.md": __fd_glob_4,
|
||||
"compression/COMPRESSION_ENGINES.md": __fd_glob_5,
|
||||
"compression/COMPRESSION_GUIDE.md": __fd_glob_6,
|
||||
"compression/COMPRESSION_LANGUAGE_PACKS.md": __fd_glob_7,
|
||||
"compression/COMPRESSION_RULES_FORMAT.md": __fd_glob_8,
|
||||
"compression/RTK_COMPRESSION.md": __fd_glob_9,
|
||||
"frameworks/A2A-SERVER.md": __fd_glob_10,
|
||||
"frameworks/AGENT_PROTOCOLS_GUIDE.md": __fd_glob_11,
|
||||
"frameworks/CLOUD_AGENT.md": __fd_glob_12,
|
||||
"frameworks/EVALS.md": __fd_glob_13,
|
||||
"frameworks/GAMIFICATION.md": __fd_glob_14,
|
||||
"frameworks/MCP-SERVER.md": __fd_glob_15,
|
||||
"frameworks/MEMORY.md": __fd_glob_16,
|
||||
"frameworks/OPENCODE.md": __fd_glob_17,
|
||||
"frameworks/SKILLS.md": __fd_glob_18,
|
||||
"frameworks/WEBHOOKS.md": __fd_glob_19,
|
||||
"guides/DOCKER_GUIDE.md": __fd_glob_20,
|
||||
"guides/ELECTRON_GUIDE.md": __fd_glob_21,
|
||||
"guides/FEATURES.md": __fd_glob_22,
|
||||
"guides/I18N.md": __fd_glob_23,
|
||||
"guides/KIRO_SETUP.md": __fd_glob_24,
|
||||
"guides/PWA_GUIDE.md": __fd_glob_25,
|
||||
"guides/SETUP_GUIDE.md": __fd_glob_26,
|
||||
"guides/TERMUX_GUIDE.md": __fd_glob_27,
|
||||
"guides/TROUBLESHOOTING.md": __fd_glob_28,
|
||||
"guides/UNINSTALL.md": __fd_glob_29,
|
||||
"guides/USER_GUIDE.md": __fd_glob_30,
|
||||
"ops/COVERAGE_PLAN.md": __fd_glob_31,
|
||||
"ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": __fd_glob_32,
|
||||
"ops/FLY_IO_DEPLOYMENT_GUIDE.md": __fd_glob_33,
|
||||
"ops/PROXY_GUIDE.md": __fd_glob_34,
|
||||
"ops/RELEASE_CHECKLIST.md": __fd_glob_35,
|
||||
"ops/SQLITE_RUNTIME.md": __fd_glob_36,
|
||||
"ops/TUNNELS_GUIDE.md": __fd_glob_37,
|
||||
"ops/VM_DEPLOYMENT_GUIDE.md": __fd_glob_38,
|
||||
"routing/AUTO-COMBO.md": __fd_glob_39,
|
||||
"routing/REASONING_REPLAY.md": __fd_glob_40,
|
||||
"security/CLI_TOKEN.md": __fd_glob_41,
|
||||
"security/CLI_TOKEN_AUTH.md": __fd_glob_42,
|
||||
"security/COMPLIANCE.md": __fd_glob_43,
|
||||
"security/ERROR_SANITIZATION.md": __fd_glob_44,
|
||||
"security/GUARDRAILS.md": __fd_glob_45,
|
||||
"security/PUBLIC_CREDS.md": __fd_glob_46,
|
||||
"security/ROUTE_GUARD_TIERS.md": __fd_glob_47,
|
||||
"security/STEALTH_GUIDE.md": __fd_glob_48,
|
||||
"reference/API_REFERENCE.md": __fd_glob_49,
|
||||
"reference/CLI-TOOLS.md": __fd_glob_50,
|
||||
"reference/ENVIRONMENT.md": __fd_glob_51,
|
||||
"reference/FREE_TIERS.md": __fd_glob_52,
|
||||
"reference/PROVIDER_REFERENCE.md": __fd_glob_53,
|
||||
}
|
||||
);
|
||||
@@ -1,19 +0,0 @@
|
||||
// source.config.ts
|
||||
import { defineDocs, defineConfig } from "fumadocs-mdx/config";
|
||||
var docs = defineDocs({
|
||||
dir: "docs",
|
||||
docs: {
|
||||
files: [
|
||||
"./architecture/**/*.md",
|
||||
"./guides/**/*.md",
|
||||
"./reference/**/*.md",
|
||||
"./frameworks/**/*.md",
|
||||
"./routing/**/*.md",
|
||||
"./security/**/*.md",
|
||||
"./compression/**/*.md",
|
||||
"./ops/**/*.md",
|
||||
],
|
||||
},
|
||||
});
|
||||
var source_config_default = defineConfig();
|
||||
export { source_config_default as default, docs };
|
||||
@@ -148,7 +148,7 @@ const nextConfig = {
|
||||
"process",
|
||||
],
|
||||
transpilePackages: ["@omniroute/open-sse", "@lobehub/icons", "fumadocs-ui", "fumadocs-core"],
|
||||
allowedDevOrigins: ["localhost", "127.0.0.1", "192.168.0.250", "192.168.0.111"],
|
||||
allowedDevOrigins: ["localhost", "127.0.0.1", "192.168.0.250"],
|
||||
typescript: {
|
||||
// TODO: Re-enable after fixing all sub-component useTranslations scope issues
|
||||
ignoreBuildErrors: true,
|
||||
|
||||
@@ -212,7 +212,7 @@ function transformSSE(deepseekStream: ReadableStream, model: string): ReadableSt
|
||||
}
|
||||
}
|
||||
|
||||
// response/fragments path (array of fragments)
|
||||
// response/fragments path (incremental updates)
|
||||
if ((data as any)?.p === "response/fragments" && Array.isArray((data as any)?.v)) {
|
||||
if (!emittedRole) {
|
||||
emittedRole = true;
|
||||
@@ -229,36 +229,6 @@ function transformSSE(deepseekStream: ReadableStream, model: string): ReadableSt
|
||||
}
|
||||
}
|
||||
|
||||
// Incremental APPEND to fragment content (expert/pro mode)
|
||||
const p = (data as any)?.p;
|
||||
const o = (data as any)?.o;
|
||||
if (
|
||||
typeof p === "string" &&
|
||||
p.includes("/content") &&
|
||||
o === "APPEND" &&
|
||||
typeof (data as any)?.v === "string"
|
||||
) {
|
||||
if (!emittedRole) {
|
||||
emittedRole = true;
|
||||
chunk({ role: "assistant", content: "" });
|
||||
}
|
||||
const isThink = p.includes("thinking") || p.includes("think");
|
||||
if (isThink) {
|
||||
chunk({ reasoning_content: (data as any).v });
|
||||
} else {
|
||||
chunk({ content: (data as any).v });
|
||||
}
|
||||
}
|
||||
|
||||
// Bare string tokens: {"v": "word"} with no "p" field
|
||||
if (typeof (data as any)?.v === "string" && !p && !o) {
|
||||
if (!emittedRole) {
|
||||
emittedRole = true;
|
||||
chunk({ role: "assistant", content: "" });
|
||||
}
|
||||
chunk({ content: (data as any).v });
|
||||
}
|
||||
|
||||
if ((data as any)?.p === "response/status" && (data as any)?.v === "FINISHED") {
|
||||
if (!emittedRole) {
|
||||
emittedRole = true;
|
||||
@@ -316,19 +286,6 @@ async function collectSSEContent(deepseekStream: ReadableStream): Promise<string
|
||||
if (typeof frag.content === "string") parts.push(frag.content);
|
||||
}
|
||||
}
|
||||
// APPEND to fragment content
|
||||
if (
|
||||
typeof data?.p === "string" &&
|
||||
data.p.includes("/content") &&
|
||||
data?.o === "APPEND" &&
|
||||
typeof data?.v === "string"
|
||||
) {
|
||||
parts.push(data.v);
|
||||
}
|
||||
// Bare string tokens
|
||||
if (typeof data?.v === "string" && !data?.p && !data?.o) {
|
||||
parts.push(data.v);
|
||||
}
|
||||
} catch {
|
||||
// skip
|
||||
}
|
||||
@@ -338,44 +295,6 @@ async function collectSSEContent(deepseekStream: ReadableStream): Promise<string
|
||||
return parts.join("");
|
||||
}
|
||||
|
||||
// ── Prompt builder (DeepSeek native format, matches Chat2API) ────────────
|
||||
|
||||
function messagesToPrompt(messages: Array<{ role: string; content: string }>): string {
|
||||
const extractText = (content: unknown): string => {
|
||||
if (Array.isArray(content)) {
|
||||
return (content as any[])
|
||||
.filter((item: any) => item.type === "text")
|
||||
.map((item: any) => item.text)
|
||||
.join("\n");
|
||||
}
|
||||
return String(content || "");
|
||||
};
|
||||
|
||||
if (messages.length === 0) return "";
|
||||
|
||||
// Collect system prompt(s) and find the last user message
|
||||
const systemParts: string[] = [];
|
||||
let lastUserContent = "";
|
||||
for (const m of messages) {
|
||||
if (m.role === "system") {
|
||||
const text = extractText(m.content).trim();
|
||||
if (text) systemParts.push(text);
|
||||
} else if (m.role === "user") {
|
||||
lastUserContent = extractText(m.content).trim();
|
||||
}
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
if (systemParts.length > 0) {
|
||||
parts.push(systemParts.join("\n\n"));
|
||||
}
|
||||
if (lastUserContent) {
|
||||
parts.push(lastUserContent);
|
||||
}
|
||||
|
||||
return parts.join("\n\n").replace(/!\[.+\]\(.+\)/g, "");
|
||||
}
|
||||
|
||||
// ── DeepSeek API calls (Bearer token auth, like Chat2API) ───────────────
|
||||
|
||||
async function acquireAccessToken(
|
||||
@@ -405,11 +324,6 @@ async function acquireAccessToken(
|
||||
}
|
||||
|
||||
const json = await resp.json();
|
||||
if (json?.code && json.code !== 0) {
|
||||
const errMsg = json.msg || json?.data?.biz_msg || `error code ${json.code}`;
|
||||
tokenCache.delete(userToken);
|
||||
throw new Error(`DeepSeek rejected token: ${errMsg}`);
|
||||
}
|
||||
const bizData = json?.data?.biz_data || json?.biz_data;
|
||||
if (!bizData?.token) {
|
||||
const errMsg = json?.msg || json?.data?.biz_msg || "Unknown error";
|
||||
@@ -548,8 +462,14 @@ export class DeepSeekWebExecutor extends BaseExecutor {
|
||||
const powAnswer = await solvePow(powChallenge);
|
||||
log?.info?.("DEEPSEEK-WEB", `PoW solved in ${Date.now() - t0}ms`);
|
||||
|
||||
// 5. Build prompt from messages (DeepSeek native chat markers, matching Chat2API)
|
||||
const prompt = messagesToPrompt(messages);
|
||||
// 5. Build prompt from messages
|
||||
const prompt = messages
|
||||
.map((m) => {
|
||||
if (m.role === "system") return `[System]: ${m.content}`;
|
||||
if (m.role === "assistant") return `[Assistant]: ${m.content}`;
|
||||
return m.content;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
// 6. Resolve model type, thinking, and search from model name + body flags
|
||||
const { modelType, thinkingEnabled, searchEnabled } = resolveModelOptions(
|
||||
@@ -602,7 +522,6 @@ export class DeepSeekWebExecutor extends BaseExecutor {
|
||||
let errMsg = `DeepSeek API error (${status})`;
|
||||
if (status === 401 || status === 403) {
|
||||
tokenCache.delete(userToken);
|
||||
sessionCache.delete((rawCreds.connectionId as string) || "");
|
||||
errMsg = "DeepSeek token expired — get a fresh userToken from localStorage.";
|
||||
} else if (status === 429) {
|
||||
errMsg = "DeepSeek rate limited. Wait and retry.";
|
||||
@@ -635,10 +554,7 @@ export class DeepSeekWebExecutor extends BaseExecutor {
|
||||
const errMsg = `DeepSeek error ${json.code}: ${json.msg}`;
|
||||
log?.warn?.("DEEPSEEK-WEB", errMsg);
|
||||
const status = json.code === 40003 ? 401 : json.code === 40002 ? 429 : 502;
|
||||
if (json.code === 40003) {
|
||||
tokenCache.delete(userToken);
|
||||
sessionCache.delete((rawCreds.connectionId as string) || "");
|
||||
}
|
||||
if (json.code === 40003) tokenCache.delete(userToken);
|
||||
return {
|
||||
response: errorResponse(status, errMsg, json.code),
|
||||
url: COMPLETION_URL,
|
||||
|
||||
@@ -3,14 +3,84 @@ import { DocsPage, DocsBody } from "fumadocs-ui/layouts/docs/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import type { Metadata } from "next";
|
||||
import { cookies } from "next/headers";
|
||||
import { DEFAULT_LOCALE, LOCALE_COOKIE } from "@/i18n/config";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { marked } from "marked";
|
||||
|
||||
// ── Locale detection ────────────────────────────────────────────────────────
|
||||
|
||||
function getDocsLocale(): string {
|
||||
try {
|
||||
const cookieStore = cookies();
|
||||
return (cookieStore as any).get(LOCALE_COOKIE)?.value || DEFAULT_LOCALE;
|
||||
} catch {
|
||||
return DEFAULT_LOCALE;
|
||||
}
|
||||
}
|
||||
|
||||
// ── i18n fallback ───────────────────────────────────────────────────────────
|
||||
// When locale ≠ "en", try to load the translated .md from
|
||||
// `docs/i18n/<locale>/docs/<section>/<FILE>.md` — the exact path layout that
|
||||
// `scripts/i18n/run-translation.mjs` produces. Returns rendered HTML or null.
|
||||
|
||||
function tryI18nFallback(slug: string[], locale: string): string | null {
|
||||
if (!locale || locale === "en") return null;
|
||||
|
||||
const docsRoot = path.resolve(process.cwd(), "docs");
|
||||
const sectionDir = path.join(docsRoot, "i18n", locale, "docs", ...slug.slice(0, -1));
|
||||
if (!fs.existsSync(sectionDir)) return null;
|
||||
|
||||
// Fumadocs lowercases slugs — match case-insensitively against i18n dir
|
||||
const target = slug[slug.length - 1];
|
||||
let files: string[];
|
||||
try {
|
||||
files = fs.readdirSync(sectionDir);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const match = files.find((f) => f.toLowerCase().replace(/\.md$/, "") === target.toLowerCase());
|
||||
if (!match) return null;
|
||||
|
||||
const filePath = path.join(sectionDir, match);
|
||||
const raw = fs.readFileSync(filePath, "utf8");
|
||||
|
||||
// Strip the i18n header (heading + language bar + ---) before rendering.
|
||||
// Translated files have: # Title (Native)\n\n🌐 Languages: ...\n\n---\n\nbody
|
||||
const bodyMatch = raw.match(/^---\s*$/m);
|
||||
const body =
|
||||
bodyMatch && bodyMatch.index != null
|
||||
? raw.slice(bodyMatch.index + bodyMatch[0].length).trim()
|
||||
: raw;
|
||||
|
||||
return marked.parse(body) as string;
|
||||
}
|
||||
|
||||
// ── Page component ──────────────────────────────────────────────────────────
|
||||
|
||||
export default async function Page(props: { params: Promise<{ slug: string[] }> }) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const MDX = page.data.body;
|
||||
const locale = getDocsLocale();
|
||||
const i18nHtml = tryI18nFallback(params.slug, locale);
|
||||
|
||||
if (i18nHtml) {
|
||||
// Render translated markdown (non-English locale with available translation)
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsBody>
|
||||
<div className="prose-content" dangerouslySetInnerHTML={{ __html: i18nHtml }} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
// Default: English MDX rendered natively by Fumadocs
|
||||
const MDX = page.data.body;
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsBody>
|
||||
@@ -20,7 +90,9 @@ export default async function Page(props: { params: Promise<{ slug: string[] }>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
// ── Static params & metadata ────────────────────────────────────────────────
|
||||
|
||||
export function generateStaticParams() {
|
||||
return source.generateParams();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,31 @@ import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||
import { source } from "@/lib/source";
|
||||
import type { ReactNode } from "react";
|
||||
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
|
||||
import { Suspense } from "react";
|
||||
import LanguageSelector from "@/shared/components/LanguageSelector";
|
||||
|
||||
export const metadata = {
|
||||
title: {
|
||||
template: "%s — OmniRoute Docs",
|
||||
default: "OmniRoute Documentation",
|
||||
},
|
||||
description:
|
||||
"Comprehensive documentation for OmniRoute AI gateway — setup, API, compression, deployment, and more.",
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const docsLayoutOptions: BaseLayoutProps = {
|
||||
nav: {
|
||||
title: "OmniRoute Docs",
|
||||
url: "/docs",
|
||||
children: (
|
||||
<Suspense fallback={<div className="w-24 h-8" />}>
|
||||
<LanguageSelector />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
links: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user