From 9ba3e216d8cfa3ee38881afa718a3083e0377e3e Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Tue, 29 Sep 2026 16:30:12 +0800 Subject: [PATCH] feat(config): opt-in autoModelPath for SDK model-path pinning The SDK now defaults automatic DeepSeek model-path selection to off, so surface it as an operator setting: `autoModelPath` in ~/.routstrd/config.json (default false), threaded into routeRequests via the daemon request handler. Explicit x-routstr-model-path headers are unaffected. Requires a daemon restart after changing the value, matching how the other startup config fields reach the handler. Documented in the README config section; the config-store scenario covers the default and a round-trip. --- README.md | 6 ++++++ src/daemon/http/index.ts | 3 +++ src/daemon/index.ts | 1 + src/utils/config.ts | 3 +++ tests/daemon/config-store.scenario.ts | 3 +++ 5 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 59096b3..56173c9 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,7 @@ Configuration is stored in `~/.routstrd/config.json`: "host": "127.0.0.1", "provider": null, "cocodPath": null, + "autoModelPath": false, "autoRefresh": { "enabled": true } } ``` @@ -287,6 +288,11 @@ every 21 minutes. Set it to `false` (or run refresh manually with `routstrd clients --manual-refresh`. `autoRefresh.intervalMs` overrides the 21-minute interval. +`autoModelPath` defaults to `false`. Set it to `true` to let the SDK automatically +choose and pin an advertised model path for `deepseek-v4.1-flash` requests. +Explicit `x-routstr-model-path` request headers work independently of this +setting and take precedence. Restart the daemon after changing `autoModelPath`. + ### Environment Variables - `ROUTSTRD_DIR` - Config directory (default: `~/.routstrd`) diff --git a/src/daemon/http/index.ts b/src/daemon/http/index.ts index b6fca34..05349bb 100644 --- a/src/daemon/http/index.ts +++ b/src/daemon/http/index.ts @@ -392,6 +392,8 @@ export function createDaemonRequestHandler(deps: { mode?: "xcashu" | "apikeys"; /** Default max_tokens/max_output_tokens to inject when the client omits one. */ maxTokens: number; + /** Enable SDK automatic DeepSeek V4.1 Flash model-path selection. */ + autoModelPath?: boolean; /** Nostr hex pubkey for routstr review/audit events (kind 38425). */ routstrPubkey?: string; /** Nostr hex pubkey for the routstr-21 model list only (kind 38423). Falls back to routstrPubkey. */ @@ -1932,6 +1934,7 @@ export function createDaemonRequestHandler(deps: { requestBody, path: url.pathname, forcedProvider, + autoModelPath: deps.autoModelPath === true, headers: incomingHeaders, walletAdapter: deps.walletAdapter, storageAdapter: deps.storageAdapter, diff --git a/src/daemon/index.ts b/src/daemon/index.ts index 410c48c..3fb5689 100644 --- a/src/daemon/index.ts +++ b/src/daemon/index.ts @@ -214,6 +214,7 @@ export async function runDaemon(argv: string[] = process.argv): Promise { getModelProviders, refreshProvidersAndModels, mode: config.mode || "apikeys", + autoModelPath: config.autoModelPath === true, maxTokens: config.maxTokens ?? 64000, routstrPubkey: config.routstrPubkey, routstrModelsPubkey: config.routstrModelsPubkey, diff --git a/src/utils/config.ts b/src/utils/config.ts index bc35480..6ffa9d1 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -48,6 +48,8 @@ export interface RoutstrdConfig { provider: string | null; cocodPath: string | null; mode?: "xcashu" | "apikeys"; + /** Opt into SDK automatic model-path selection for DeepSeek V4.1 Flash. Disabled by default; requires daemon restart after changing. */ + autoModelPath?: boolean; /** Raw upstream request/response logging. Disabled by default because logs can contain sensitive prompts, outputs, and auth/payment headers. */ requestResponseLogging?: { /** Enable raw request/response file logging. */ @@ -87,5 +89,6 @@ export const DEFAULT_CONFIG: RoutstrdConfig = { provider: null, cocodPath: null, mode: "apikeys", + autoModelPath: false, maxTokens: 64000, }; diff --git a/tests/daemon/config-store.scenario.ts b/tests/daemon/config-store.scenario.ts index ae9b5b3..24b96cf 100644 --- a/tests/daemon/config-store.scenario.ts +++ b/tests/daemon/config-store.scenario.ts @@ -38,8 +38,10 @@ const scenario = process.argv[2]; switch (scenario) { case "fresh-install": { + assert(loadDaemonConfigSync().autoModelPath === false, "autoModelPath must default to false"); saveDaemonConfig({ ...baseConfig, + autoModelPath: true, nsec: "nsec1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", }); assert(modeOf(CONFIG_DIR) === 0o700, `dir mode ${modeOf(CONFIG_DIR).toString(8)} != 700`); @@ -54,6 +56,7 @@ switch (scenario) { "nsec round-trip failed", ); assert(loaded.port === 8008, "port round-trip failed"); + assert(loaded.autoModelPath === true, "autoModelPath round-trip failed"); await ensureDirs(); assert(modeOf(CONFIG_DIR) === 0o700, "ensureDirs dir mode");