@lynn123411/dsh-a6api 1.5.7 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +4 -3
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import fsp from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-home-paths@0.1.
|
|
6
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-home-paths@0.1.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-home-paths/lib/index.js
|
|
7
7
|
import { opendir, realpath } from "node:fs/promises";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { basename, dirname, join, resolve } from "node:path";
|
package/lib/index.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/server/catalog.ts", "../node_modules/.pnpm/@deepseek-ai+dsh-home-paths@0.1.
|
|
3
|
+
"sources": ["../src/server/catalog.ts", "../node_modules/.pnpm/@deepseek-ai+dsh-home-paths@0.1.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-home-paths/lib/index.js", "../src/server/net.ts", "../src/server/a6api-client.ts", "../src/server/probe.ts", "../src/server/sync.ts", "../src/types.ts", "../src/index.ts"],
|
|
4
4
|
"sourcesContent": ["import fs from 'node:fs';\nimport fsp from 'node:fs/promises';\nimport path from 'node:path';\nimport { dshHomePath } from '@deepseek-ai/dsh-home-paths';\nimport { fetchWithNetRetry } from './net.js';\nimport type { A6ApiModelMeta, CatalogModelEntry } from '../types.js';\n\n/**\n * \u6A21\u578B\u76EE\u5F55\uFF08\u8FD0\u884C\u65F6\u6570\u636E\uFF0C\u53D6\u4EE3\u65E7\u7684\u9759\u6001 A6API_CATALOG\uFF09\u3002\n *\n * - \u6301\u4E45\u5316\uFF1A`$DSH_HOME/dsh-a6api/catalog.json`\uFF08\u7ED3\u6784 `{ version: 1, entries: [...] }`\uFF09\uFF0C\n * \u521D\u59CB\u4E3A\u7A7A\uFF1B\u300C\u6A21\u578B\u76EE\u5F55\u300D\u9875\u4ECE A6API \u5E02\u573A\u62C9\u53D6\u6A21\u578B ID\u3001\u4ECE OpenRouter \u67E5\u8BE2\u53C2\u6570\u540E\u5EFA\u7ACB\u3002\n * v1.4 \u8D77\u4F4D\u4E8E\u63D2\u4EF6\u5B50\u76EE\u5F55\uFF08\u4E0E DSH\u300C\u7EC4\u4EF6\u81EA\u5EFA home \u5B50\u76EE\u5F55\u300D\u60EF\u4F8B\u4E00\u81F4\uFF09\uFF0C\u4E0D\u518D\u5360\u7528\n * `$DSH_HOME` \u6839\u76EE\u5F55\uFF1B\u65E7\u7248\u6839\u76EE\u5F55\u6587\u4EF6\uFF08<=1.3 `dsh-a6api-catalog.json`\uFF09\u9996\u6B21\u8BFB\u53D6\u65F6\n * \u81EA\u52A8\u642C\u8FC1\uFF08\u4FDD\u6301\u6570\u636E\u65E0\u635F\uFF09\uFF0C\u642C\u8FC1\u540E\u65E7\u6587\u4EF6\u5373\u5220\u9664\u3002\n * - \u6761\u76EE\u5B57\u6BB5 = DSH settings.yaml \u7684 llm-pi-ai \u539F\u751F\u6A21\u578B\u5B57\u6BB5\uFF08id/name/contextWindow/\n * maxTokens/input/reasoningEfforts\uFF09\uFF0C\u5916\u52A0\u5185\u90E8\u9644\u5E26\u7684 brand\uFF08\u6765\u81EA A6API \u5E02\u573A\u6E20\u9053\uFF0C\n * \u4EC5\u7528\u4E8E\u53EF\u7528\u6A21\u578B\u5361\u7247\u5C55\u793A\uFF0C\u4E0D\u5199\u5165 settings.yaml\uFF09\u3002\n * - \u76EE\u5F55\u4E3A\u552F\u4E00\u53C2\u6570\u771F\u76F8\u6E90\uFF1A\u300C\u53EF\u7528\u6A21\u578B\u300D\u9875\u5199\u5165 settings.yaml \u65F6\u4ECE\u6B64\u53D6\u5B57\u6BB5\uFF0C\u7F3A\u5219\u7701\u7565\n * \uFF08\u7531 llm-pi-ai \u9ED8\u8BA4\u503C\u515C\u5E95\uFF09\uFF0C\u4E0D\u518D\u6709\u4EFB\u4F55\u5185\u7F6E\u624B\u5199\u9ED8\u8BA4\u53C2\u6570\u3002\n */\n\nconst CATALOG_VERSION = 1;\n\n/** \u5F53\u524D catalog \u6587\u4EF6\u8DEF\u5F84\uFF08v1.4+\uFF1A\u63D2\u4EF6\u5B50\u76EE\u5F55\uFF0C\u4E0D\u518D\u5360\u7528 DSH home \u6839\u76EE\u5F55\uFF09\u3002\n * dshHomePath \u4E0E DSH \u7684 resolveDshHome \u5B8C\u5168\u4E00\u81F4\uFF1A\u663E\u5F0F\u914D\u7F6E home \u2192 $DSH_HOME\uFF08~ \u5C55\u5F00\uFF09\u2192 ~/.dsh\u3002 */\nexport function catalogFile(): string {\n return dshHomePath('dsh-a6api', 'catalog.json');\n}\n\n/** \u65E7\u7248\uFF08<=1.3\uFF09\u6839\u76EE\u5F55\u6587\u4EF6\uFF0C\u4EC5\u7528\u4E8E\u4E00\u6B21\u6027\u642C\u8FC1\u3002 */\nfunction legacyCatalogFile(): string {\n return dshHomePath('dsh-a6api-catalog.json');\n}\n\n/**\n * \u4E00\u6B21\u6027\u642C\u8FC1\u65E7\u7248\u6839\u76EE\u5F55 catalog\uFF08<=1.3\uFF09\u5230\u63D2\u4EF6\u5B50\u76EE\u5F55\uFF0C\u4FDD\u6301\u6570\u636E\u65E0\u635F\u3002\n * \u540C\u6B65\u6267\u884C\uFF08ensureLoaded \u4E3A\u540C\u6B65\u8DEF\u5F84\uFF09\uFF0C\u5E42\u7B49\uFF1A\n * - \u65B0\u8DEF\u5F84\u5DF2\u6709\u6587\u4EF6 \u2192 \u65E7\u6587\u4EF6\u53EA\u662F\u6B8B\u7559\uFF0C\u76F4\u63A5\u6E05\u7406\uFF1B\n * - \u65B0\u8DEF\u5F84\u7F3A\u5931\u4E14\u65E7\u6587\u4EF6\u5B58\u5728 \u2192 \u5EFA\u76EE\u5F55\u540E rename\uFF08\u540C\u5377\u539F\u5B50\uFF09\uFF1B\u5931\u8D25\u5219\u7531\u8BFB\u53D6\u4FA7\u56DE\u9000\u65E7\u8DEF\u5F84\uFF1B\n * - \u90FD\u65E0 \u2192 \u7A7A\u76EE\u5F55\u3002\n */\nfunction ensureRelocated(): void {\n const target = catalogFile();\n const legacy = legacyCatalogFile();\n try {\n fs.accessSync(target);\n try {\n fs.unlinkSync(legacy);\n } catch {}\n return;\n } catch {\n // target \u4E0D\u5B58\u5728\uFF0C\u7EE7\u7EED\u642C\u8FC1\n }\n try {\n fs.mkdirSync(path.dirname(target), { recursive: true });\n fs.renameSync(legacy, target);\n } catch {\n // \u65E7\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u642C\u8FC1\u5931\u8D25\uFF1A\u7531\u8BFB\u53D6\u4FA7\u56DE\u9000\u5230\u65E7\u8DEF\u5F84\n }\n}\n\n/** \u8FDB\u7A0B\u5185\u7F13\u5B58\uFF1AresolveModelMeta \u7B49\u540C\u6B65\u8DEF\u5F84\u76F4\u63A5\u8BFB\u5185\u5B58 */\nlet catalogCache: CatalogModelEntry[] | null = null;\n\nfunction ensureLoaded(): CatalogModelEntry[] {\n if (catalogCache) return catalogCache;\n ensureRelocated();\n const sources = [catalogFile(), legacyCatalogFile()];\n for (const file of sources) {\n try {\n const raw = fs.readFileSync(file, 'utf8');\n const j = JSON.parse(raw);\n // \u5F62\u72B6\u8FC7\u6EE4\uFF1A\u8DF3\u8FC7\u65E0\u5B57\u7B26\u4E32 id \u7684\u635F\u574F\u6761\u76EE\uFF0C\u907F\u514D getCatalogEntry \u7684 .toLowerCase() \u629B\u9519\u62D6\u57AE /state\n catalogCache = Array.isArray(j?.entries)\n ? j.entries.filter((e: any) => e && typeof e.id === 'string')\n : [];\n if (file !== catalogFile()) {\n // \u642C\u8FC1\u5931\u8D25\u7684\u56DE\u9000\u8BFB\u53D6\uFF1A\u6570\u636E\u5DF2\u8FDB\u5185\u5B58\uFF0C\u6E05\u7406\u65E7\u6587\u4EF6\n try {\n fs.unlinkSync(file);\n } catch {}\n }\n return catalogCache as CatalogModelEntry[];\n } catch {\n // \u5C1D\u8BD5\u4E0B\u4E00\u4E2A\u6E90\uFF08\u635F\u574F/\u7F3A\u5931\u90FD\u8DF3\u8FC7\uFF09\n }\n }\n catalogCache = [];\n return catalogCache as CatalogModelEntry[];\n}\n\nexport function getCatalog(): CatalogModelEntry[] {\n return ensureLoaded();\n}\n\nexport function getCatalogEntry(id: string): CatalogModelEntry | undefined {\n const t = id.toLowerCase();\n return ensureLoaded().find((e) => e.id.toLowerCase() === t);\n}\n\n/**\n * \u76EE\u5F55\u5199\u64CD\u4F5C\u4E32\u884C\u961F\u5217\uFF1Afetch-models / query-openrouter / update / clear \u5171\u4EAB\u540C\u4E00\u5199\u94FE\uFF0C\n * \u907F\u514D\u8BFB-\u6539-\u5199\u4EA4\u9519\u4E22\u66F4\u65B0\uFF08\u5982\u300C\u7F16\u8F91\u4FDD\u5B58\u300D\u4E0E\u300C\u4E00\u952E\u67E5\u8BE2\u300D\u5E76\u53D1\u65F6\u540E\u5199\u8005\u8986\u76D6\u5148\u5199\u8005\uFF09\u3002\n */\nlet writeChain: Promise<void> = Promise.resolve();\n\nfunction enqueueWrite(fn: () => Promise<void>): Promise<void> {\n const next = writeChain.then(fn, fn);\n writeChain = next.then(\n () => {},\n () => {},\n );\n return next;\n}\n\n/** \u539F\u5B50\u5199\u76D8\uFF08tmp+rename\uFF09\u6210\u529F\u540E\u624D\u66F4\u65B0\u5185\u5B58\u7F13\u5B58\uFF1B\u5199\u5931\u8D25\u65F6\u7F13\u5B58\u4FDD\u6301\u4E0E\u78C1\u76D8\u4E00\u81F4\u7684\u65E7\u503C */\nasync function writeCatalog(entries: CatalogModelEntry[]): Promise<void> {\n const file = catalogFile();\n await fsp.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.tmp`;\n await fsp.writeFile(tmp, JSON.stringify({ version: CATALOG_VERSION, entries }, null, 2), {\n encoding: 'utf8',\n mode: 0o644,\n });\n await fsp.rename(tmp, file);\n catalogCache = entries;\n}\n\n/** \u5408\u5E76\u65B0\u589E\u6761\u76EE\uFF08\u4E0D\u8986\u76D6\u5DF2\u6709\u6761\u76EE\u7684\u65E2\u6709\u5B57\u6BB5\uFF1B\u4EC5\u8865\u7F3A\u5931\u5B57\u6BB5\uFF0C\u53C2\u6570\u4EE5\u7528\u6237\u5DF2\u4FDD\u5B58/\u67E5\u8BE2\u5230\u7684\u4E3A\u51C6\uFF09\u3002\n * undefined \u5B57\u6BB5\u4E0D\u53C2\u4E0E\u5408\u5E76\uFF08\u907F\u514D\u8986\u76D6\u5DF2\u6709\u503C\uFF09\uFF1B\u6309\u5C0F\u5199 id \u53BB\u91CD\uFF08\u4FDD\u7559\u9996\u4E2A casing\uFF0C\u907F\u514D\u5927\u5C0F\u5199\u5E7D\u7075\u91CD\u590D\uFF09\u3002 */\nexport async function upsertCatalogEntries(entries: CatalogModelEntry[]): Promise<void> {\n await enqueueWrite(async () => {\n const cur = ensureLoaded();\n const map = new Map<string, CatalogModelEntry>();\n for (const e of cur) map.set(e.id.toLowerCase(), e);\n for (const e of entries) {\n const clean = Object.fromEntries(Object.entries(e).filter(([, v]) => v !== undefined)) as CatalogModelEntry;\n const key = clean.id.toLowerCase();\n const prev = map.get(key);\n map.set(key, prev ? { ...prev, ...clean } : clean);\n }\n await writeCatalog([...map.values()]);\n });\n}\n\n/** \u6E05\u7A7A\u76EE\u5F55\uFF08\u91CD\u65B0\u4ECE A6API \u62C9\u53D6/OpenRouter \u586B\u5145\u524D\u4F7F\u7528\uFF09\u3002settings.yaml \u5DF2\u542F\u7528\u6761\u76EE\u4E0D\u53D7\u5F71\u54CD */\nexport async function clearCatalog(): Promise<void> {\n await enqueueWrite(async () => {\n await writeCatalog([]);\n });\n}\n\n/** \u5168\u91CF\u66FF\u6362\u5F0F\u66F4\u65B0\u5355\u4E2A\u6761\u76EE\uFF08\u6A21\u578B\u76EE\u5F55\u9875\u4FDD\u5B58\u4FEE\u6539\u7528\uFF09\uFF1Bpatch \u4E2D\u503C\u4E3A null \u7684\u5B57\u6BB5 = \u5220\u9664\u8BE5\u5B57\u6BB5\u3002\u8FD4\u56DE\u66F4\u65B0\u540E\u7684\u6761\u76EE */\nexport async function updateCatalogEntry(\n id: string,\n patch: Partial<Omit<CatalogModelEntry, 'id'>>,\n): Promise<CatalogModelEntry | null> {\n let result: CatalogModelEntry | null = null;\n await enqueueWrite(async () => {\n const cur = ensureLoaded();\n const idx = cur.findIndex((e) => e.id.toLowerCase() === id.toLowerCase());\n if (idx < 0) return;\n const next: CatalogModelEntry = { ...cur[idx], ...patch, id: cur[idx].id, updatedAt: Date.now() };\n for (const k of Object.keys(patch)) {\n if ((patch as any)[k] === null) delete (next as any)[k];\n }\n const list = cur.slice();\n list[idx] = next;\n await writeCatalog(list);\n result = next;\n });\n return result;\n}\n\n// ===== \u54C1\u724C\u5F52\u4E00\u5316\uFF08\u5E02\u573A\u6E20\u9053\u8FD4\u56DE\u7684\u539F\u59CB\u54C1\u724C \u2192 \u5361\u7247\u5C55\u793A\u98CE\u683C\uFF09 =====\n\nconst BRAND_NORMALIZE: Record<string, string> = {\n meituan: 'MeiTuan',\n tencent: 'Tencent',\n xiaomi: 'Xiaomi',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google',\n deepseek: 'DeepSeek',\n zhipu: 'Zhipu',\n moonshot: 'Moonshot',\n alibaba: 'Alibaba',\n minimax: 'MiniMax',\n};\n\nfunction normalizeBrand(raw: string): string {\n const k = String(raw || '').toLowerCase();\n return BRAND_NORMALIZE[k] || raw || 'Other';\n}\n\n/** \u4ECE A6API \u6A21\u578B\u540D\u63A8\u65AD\u54C1\u724C\uFF08\u76EE\u5F55\u65E0\u6570\u636E\u65F6\u7684\u5C55\u793A\u515C\u5E95\uFF0C\u4E0E\u65E7\u884C\u4E3A\u4E00\u81F4\uFF09 */\nexport function inferBrand(modelId: string): string {\n const m = modelId.toLowerCase();\n if (m.startsWith('gpt') || m.startsWith('o1') || m.startsWith('o3') || m.startsWith('chatgpt')) return 'OpenAI';\n if (m.startsWith('claude')) return 'Anthropic';\n if (m.startsWith('gemini') || m.startsWith('google') || m.startsWith('imagen')) return 'Google';\n if (m.startsWith('deepseek')) return 'DeepSeek';\n if (m.startsWith('grok')) return 'xAI';\n if (m.startsWith('glm') || m.startsWith('zhipu') || m.startsWith('cog')) return 'Zhipu';\n if (m.startsWith('kimi') || m.startsWith('moonshot')) return 'Moonshot';\n if (m.startsWith('qwen')) return 'Alibaba';\n if (m.startsWith('minimax')) return 'MiniMax';\n if (m.startsWith('mimo') || m.startsWith('xiaomi')) return 'Xiaomi';\n if (m.startsWith('hunyuan') || m.startsWith('tencent') || m.startsWith('hy')) return 'Tencent';\n return 'Other';\n}\n\n/**\n * \u9ED8\u8BA4\u63A8\u7406\u6863\u4F4D\uFF1ADSH llm-pi-ai \u652F\u6301\u7684\u5168\u90E8\u601D\u8003\u6863\u4F4D\uFF08THINKING_LEVELS\uFF09\uFF0C\n * wire \u503C\u53D6\u6863\u4F4D\u540D\u672C\u8EAB\uFF08identity\uFF09\uFF0C`off` \u65E0 wire \u503C\uFF08null = \u53D1\u9001\u65F6\u4E0D\u5E26\u601D\u8003\u53C2\u6570\uFF09\u3002\n * \u65B0\u83B7\u53D6\u7684\u5E02\u573A\u6A21\u578B\u9ED8\u8BA4\u58F0\u660E\u5168\u90E8\u6863\u4F4D\uFF0C\u7528\u6237\u53EF\u81EA\u884C\u4FEE\u6539\u3002\n */\nexport const DEFAULT_REASONING_EFFORTS: Record<string, string | null> = {\n off: null,\n minimal: 'minimal',\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n};\n\n/**\n * \u89E3\u6790\u6A21\u578B\u5143\u4FE1\u606F\uFF08\u540C\u6B65\uFF09\uFF1A\u76EE\u5F55\u6570\u636E\u4F18\u5148\uFF0C\u7F3A\u5931\u65F6\u8FD4\u56DE\u5C55\u793A\u515C\u5E95\u503C\u3002\n * \u6CE8\u610F\uFF1A\u5199 settings.yaml \u65F6\u4E0D\u8981\u7528\u6B64\u51FD\u6570\u7684\u515C\u5E95\u503C\u2014\u2014\u7F3A\u5B57\u6BB5\u5E94\u7701\u7565\uFF08\u89C1 buildA6apiBlock\uFF09\u3002\n */\nexport function resolveModelMeta(modelId: string): A6ApiModelMeta {\n const entry = getCatalogEntry(modelId);\n if (entry) {\n return {\n id: entry.id,\n name: entry.name || entry.id,\n brand: entry.brand || inferBrand(entry.id),\n contextWindow: entry.contextWindow ?? 262144,\n maxTokens: entry.maxTokens ?? 32768,\n modalities: entry.input && entry.input.length > 0 ? [...entry.input] : ['text'],\n ...(entry.reasoningEfforts && typeof entry.reasoningEfforts === 'object' && Object.keys(entry.reasoningEfforts).length > 0\n ? {\n reasoningEfforts: Object.fromEntries(\n Object.entries(entry.reasoningEfforts).filter(([, v]) => v !== null && v !== undefined),\n ) as Record<string, string>,\n }\n : {}),\n };\n }\n const lowerId = modelId.toLowerCase();\n const isVision = lowerId.includes('vision') || lowerId.includes('vl') || lowerId.includes('image');\n const hasReasoning = lowerId.includes('think') || lowerId.includes('reason') || lowerId.includes('pro') || lowerId.includes('sol');\n return {\n id: modelId,\n name: modelId,\n brand: inferBrand(modelId),\n contextWindow: 262144,\n maxTokens: 32768,\n modalities: isVision ? ['text', 'image'] : ['text'],\n ...(hasReasoning ? { thinkingFormat: 'deepseek' } : {}),\n };\n}\n\n// ===== A6API \u5E02\u573A\u5168\u91CF\u6A21\u578B\u62C9\u53D6\uFF08\u7FFB\u9875 channels/search\uFF0C\u5E26 Web \u4F1A\u8BDD\u9274\u6743\uFF09 =====\n\nconst MARKET_SEARCH = 'https://a6api.com/api/marketplace/channels/search';\nconst PAGE_SIZE = 500;\nconst CONCURRENCY = 6;\n\nfunction buildWebHeaders(userId?: string, accessToken?: string): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',\n };\n const uid = userId ? String(userId).trim() : '';\n const token = accessToken ? String(accessToken).trim() : '';\n if (uid) headers['New-Api-User'] = uid;\n if (token) {\n headers['Authorization'] = token;\n headers['Cookie'] = `session=${token}`;\n }\n return headers;\n}\n\n/**\n * \u62C9\u53D6 A6API \u5E02\u573A\u652F\u6301\u7684\u5168\u90E8\u6A21\u578B ID\uFF08\u542B\u54C1\u724C\uFF09\u3002\n * \u4E0D\u6392\u9664\u4EFB\u4F55\u6A21\u578B\uFF08\u56FE\u50CF\u751F\u6210\u7B49\u4E00\u5E76\u6536\u5F55\uFF0C\u53C2\u6570\u7531 OpenRouter \u67E5\u8BE2\u51B3\u5B9A\u80FD\u5426\u586B\u5145\uFF09\u3002\n */\nexport async function fetchMarketplaceModels(\n userId?: string,\n accessToken?: string,\n): Promise<{ models: { id: string; brand?: string; reasoningEfforts: Record<string, string | null> }[]; failedPages: number }> {\n if (!userId && !accessToken) {\n throw new Error('\u9700\u5148\u914D\u7F6E\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\u624D\u80FD\u83B7\u53D6\u5E02\u573A\u6A21\u578B');\n }\n const headers = buildWebHeaders(userId, accessToken);\n const first = await (async () => {\n const res = await fetchWithNetRetry(`${MARKET_SEARCH}?view=list&page=1&page_size=${PAGE_SIZE}`, {\n headers,\n timeoutMs: 15000,\n });\n if (!res.ok) throw new Error(`A6API \u5E02\u573A\u63A5\u53E3 HTTP ${res.status}`);\n return res.json();\n })();\n const total = Number(first?.data?.total || 0);\n const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));\n const all: any[] = [...(first?.data?.items || [])];\n let failedPages = 0;\n let idx = 2;\n const worker = async () => {\n while (idx <= pages) {\n const p = idx++;\n try {\n const res = await fetchWithNetRetry(`${MARKET_SEARCH}?view=list&page=${p}&page_size=${PAGE_SIZE}`, {\n headers,\n timeoutMs: 15000,\n });\n const j = await res.json();\n all.push(...(j?.data?.items || []));\n } catch (err: any) {\n failedPages++;\n console.warn('[dsh-a6api] fetchMarketplaceModels page', p, 'failed:', err?.message || err);\n }\n }\n };\n await Promise.all(Array.from({ length: CONCURRENCY }, () => worker()));\n\n const byModel = new Map<string, { id: string; brand?: string; reasoningEfforts: Record<string, string | null> }>();\n for (const it of all) {\n const name = it?.model_name;\n if (!name) continue;\n if (!byModel.has(name)) {\n byModel.set(name, {\n id: String(name),\n brand: normalizeBrand(it?.brand),\n // \u9ED8\u8BA4\u58F0\u660E DSH \u5168\u90E8\u601D\u8003\u6863\u4F4D\uFF08\u7528\u6237\u53EF\u4FEE\u6539\uFF1Bupsert \u4EC5\u8865\u7F3A\u5931\u5B57\u6BB5\uFF0C\u5DF2\u6709\u81EA\u5B9A\u4E49\u4E0D\u53D7\u5F71\u54CD\uFF09\n reasoningEfforts: { ...DEFAULT_REASONING_EFFORTS },\n });\n }\n }\n const models = [...byModel.values()].sort((a, b) => a.id.localeCompare(b.id));\n return { models, failedPages };\n}\n\n// ===== OpenRouter \u6A21\u578B\u53C2\u6570\u67E5\u8BE2\uFF08\u516C\u5F00 /api/v1/models\uFF0C\u8FDB\u7A0B\u5185\u7F13\u5B58 1h\uFF09 =====\n\nconst OPENROUTER_URL = 'https://openrouter.ai/api/v1/models';\nconst OR_TTL_MS = 60 * 60 * 1000;\n\nlet orCache: { at: number; models: any[] } | null = null;\n\nasync function getOpenRouterModels(): Promise<any[]> {\n if (orCache && Date.now() - orCache.at < OR_TTL_MS) return orCache.models;\n try {\n const res = await fetchWithNetRetry(OPENROUTER_URL, {\n headers: { Accept: 'application/json', 'User-Agent': 'Mozilla/5.0' },\n timeoutMs: 20000,\n });\n if (!res.ok) throw new Error(`OpenRouter HTTP ${res.status}`);\n const j: any = await res.json();\n if (!Array.isArray(j?.data)) throw new Error('OpenRouter \u8FD4\u56DE\u683C\u5F0F\u5F02\u5E38');\n orCache = { at: Date.now(), models: j.data };\n return orCache.models;\n } catch (err) {\n // \u62C9\u53D6\u5931\u8D25\uFF1A\u5B58\u5728\u8FC7\u671F\u7F13\u5B58\u65F6\u964D\u7EA7\u7528\u65E7\u6570\u636E\uFF08stale \u515C\u5E95\uFF09\uFF0C\u5426\u5219\u4E0A\u629B\n if (orCache) return orCache.models;\n throw err;\n }\n}\n\nconst tailOf = (s: string): string => String(s).split('/').pop() || '';\n\n/** \u5339\u914D\u7B56\u7565\uFF1Atail \u7CBE\u786E \u2192 \u5F52\u4E00\u5316\uFF08. _ \u7A7A\u683C \u2192 -\uFF09\u2192 \u5265\u79BB\u65E5\u671F/\u7248\u672C\u540E\u7F00 \u2192 \u5305\u542B\u3002\u8FD4\u56DE null = \u67E5\u65E0 */\nfunction matchOpenRouter(models: any[], target: string): any | null {\n const t = target.toLowerCase();\n const tTail = tailOf(t);\n const norm = (s: string) => s.toLowerCase().replace(/[\\s_.]+/g, '-');\n\n const byTail = models.find((m) => tailOf(String(m.id)).toLowerCase() === tTail);\n if (byTail) return byTail;\n\n const nTail = norm(tTail);\n const byNorm = models.find((m) => norm(tailOf(String(m.id))) === nTail);\n if (byNorm) return byNorm;\n\n // \u5265\u79BB\u65E5\u671F/\u7248\u672C\u540E\u7F00\uFF1A-2025-12-11 / -20251001 / -0309 / -0.1 \u7B49\uFF0C\u518D\u7CBE\u786E\u5339\u914D\n const stripped = tTail.replace(/-(?:\\d{4}-\\d{2}-\\d{2}|\\d{8}|-\\d{2,4}|\\d\\.\\d+)$/, '');\n if (stripped && stripped !== tTail) {\n const byStripped = models.find((m) => tailOf(String(m.id)).toLowerCase() === stripped);\n if (byStripped) return byStripped;\n }\n\n // \u5305\u542B\u5339\u914D\uFF08\u6700\u540E\u624B\u6BB5\uFF09\uFF1A\u4EC5\u63A5\u53D7\u300C-\u300D\u5206\u6BB5\u5B8C\u6574\u5305\u542B target \u7684\u6761\u76EE\uFF0C\n // \u907F\u514D 'gpt-4o' \u8BEF\u547D\u4E2D 'gpt-4o-mini' \u4E4B\u7C7B\u7684\u524D\u7F00\u5305\u542B\n const tSeg = t.split('/').pop() || t;\n return (\n models.find((m) => {\n const id = String(m.id).toLowerCase();\n if (!id.includes(t)) return false;\n const tailSeg = id.split('/').pop() || '';\n return tailSeg === t || tailSeg.split('-').includes(tSeg);\n }) || null\n );\n}\n\n/** \u8F93\u5165\u6A21\u6001\uFF1A\u53EA\u53D6 architecture.input_modalities\uFF08\u8F93\u51FA\u6A21\u6001\u4E0D\u58F0\u660E\u4E3A\u8F93\u5165\uFF0C\u907F\u514D\u6587\u751F\u56FE\u6A21\u578B\u88AB\u8BEF\u6807 image \u8F93\u5165\uFF09 */\nfunction orModalities(m: any): ('text' | 'image')[] {\n const set = new Set<'text' | 'image'>();\n const input: string[] = m?.architecture?.input_modalities || [];\n for (const mod of input) {\n const k = String(mod).toLowerCase();\n if (k === 'text') set.add('text');\n else if (k === 'image') set.add('image');\n }\n return [...set];\n}\n\nexport interface OrQueryResult {\n updated: CatalogModelEntry[];\n notFound: string[];\n}\n\n/**\n * \u5BF9\u4E00\u6279\u6A21\u578B ID \u67E5\u8BE2 OpenRouter \u5E76\u586B\u5145\u76EE\u5F55\uFF08\u80FD\u67E5\u5230\u7684\u586B\u5145\uFF0C\u67E5\u4E0D\u5230\u7684\u4FDD\u6301\u7A7A\u53C2\u6570\u5B57\u6BB5\uFF09\u3002\n * \u8FD4\u56DE\u66F4\u65B0\u7EDF\u8BA1\uFF1Aupdated \u4E3A\u672C\u6B21\u586B\u5145/\u53D8\u66F4\u7684\u6761\u76EE\uFF0CnotFound \u4E3A\u67E5\u65E0\u7684 ID\u3002\n */\nexport async function queryOpenRouter(ids: string[]): Promise<OrQueryResult> {\n const uniq = [...new Set(ids.map((s) => String(s).trim()).filter(Boolean))];\n if (uniq.length === 0) return { updated: [], notFound: [] };\n const models = await getOpenRouterModels();\n const updated: CatalogModelEntry[] = [];\n const notFound: string[] = [];\n\n for (const id of uniq) {\n const hit = matchOpenRouter(models, id);\n if (!hit) {\n notFound.push(id);\n continue;\n }\n const patch: Partial<Omit<CatalogModelEntry, 'id'>> = {\n updatedAt: Date.now(),\n };\n const ctx = hit.context_length ?? hit.top_provider?.context_length;\n if (ctx != null && Number(ctx) > 0) patch.contextWindow = Number(ctx);\n const maxOut = hit.top_provider?.max_completion_tokens ?? hit.max_completion_tokens;\n if (maxOut != null && Number(maxOut) > 0) patch.maxTokens = Number(maxOut);\n const mods = orModalities(hit);\n if (mods.length > 0) patch.input = mods;\n // name \u4EC5\u5141\u8BB8\u7528\u6237\u624B\u52A8\u586B\u5199\uFF1A\u4E0D\u4ECE\u6B64\u5904\u586B\u5145\uFF08\u7528\u6237\u672A\u586B\u5219\u4FDD\u6301\u4E3A\u7A7A\uFF0C\u5199 settings.yaml \u65F6\u7701\u7565\uFF09\n updated.push({ id, ...patch });\n }\n\n if (updated.length > 0) {\n await upsertCatalogEntries(updated);\n }\n return { updated, notFound };\n}\n", "import { opendir, realpath } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n//#region lib/types/index.js\n/**\n* Shared filesystem path helpers for DeepSeek Harness user data.\n*\n* @module @deepseek-ai/dsh-home-paths\n*/\n/** Directory name for the default DeepSeek Harness home under the OS home. */\nconst DSH_HOME_DIR_NAME = \".dsh\";\n/** Stable user-facing display form for the default DeepSeek Harness home. */\nconst DEFAULT_DSH_HOME_DISPLAY = `~/${DSH_HOME_DIR_NAME}`;\n/** Environment variable that overrides the default DeepSeek Harness home. */\nconst DSH_HOME_ENV = \"DSH_HOME\";\n/**\n* Give a native filesystem watcher one canonical spelling of a path, even\n* when its final components do not exist yet. The deepest existing ancestor\n* is resolved through {@link realpath}; when a suffix is missing, that\n* ancestor is also proved to be an enumerable directory before the suffix is\n* restored. This prevents Windows from treating a regular-file ancestor as\n* ordinary absence, and prevents short-name aliases from being mixed with\n* long paths emitted by the native watcher backend.\n* @param path - Watch target or root, resolved against the current directory.\n* @returns the target with its existing ancestor canonicalized.\n* @throws when ancestor traversal encounters an error other than absence, or\n* the existing ancestor of a missing suffix is not an enumerable directory.\n*/\nasync function canonicalizeWatchPath(path) {\n\tlet current = resolve(path);\n\tconst missing = [];\n\twhile (true) try {\n\t\tconst canonical = await realpath(current);\n\t\tif (missing.length > 0) await (await opendir(canonical)).close();\n\t\treturn join(canonical, ...missing.reverse());\n\t} catch (error) {\n\t\tif (error.code !== \"ENOENT\") throw error;\n\t\tconst parent = dirname(current);\n\t\t/* v8 ignore next -- a filesystem root exists, so traversal resolves before this guard */\n\t\tif (parent === current) throw error;\n\t\tmissing.push(basename(current));\n\t\tcurrent = parent;\n\t}\n}\n/**\n* Resolve the default DeepSeek Harness home using Node's platform path rules.\n* @returns the absolute default harness home path.\n*/\nfunction defaultDshHome() {\n\treturn join(homedir(), DSH_HOME_DIR_NAME);\n}\n/**\n* Expand supported tilde prefixes against the operating-system home.\n* @param path - configured path that may begin with `~`, `~/`, or `~\\`.\n* @returns the expanded path, or the original value when no supported prefix is present.\n*/\nfunction expandHomePath(path) {\n\tif (path === \"~\") return homedir();\n\tif (path.startsWith(\"~/\") || path.startsWith(\"~\\\\\")) return join(homedir(), path.slice(2));\n\treturn path;\n}\n/**\n* Resolve the single-root DeepSeek Harness home.\n*\n* Precedence, highest first: an explicit configured path, `$DSH_HOME`, then\n* `~/.dsh`. The harness keeps all user data under one root. An empty or\n* whitespace-only `$DSH_HOME` is treated as unset, so a blank override never\n* resolves the home to the current working directory.\n* @param configured - explicit harness-home override, which has highest precedence.\n* @param env - environment mapping used to read `DSH_HOME`.\n* @returns the normalized absolute harness home path.\n*/\nfunction resolveDshHome(configured, env = process.env) {\n\tconst fromEnv = env[DSH_HOME_ENV];\n\treturn resolve(expandHomePath(configured ?? (fromEnv !== void 0 && fromEnv.trim().length > 0 ? fromEnv : defaultDshHome())));\n}\n/**\n* Join path segments onto the resolved DeepSeek Harness home.\n* @param segments - path segments appended to the Harness home; an empty list returns the home itself.\n* @returns the normalized absolute joined path.\n*/\nfunction dshHomePath(...segments) {\n\treturn join(resolveDshHome(), ...segments);\n}\n/**\n* Describe a resolved harness home symbolically for user-facing display.\n*\n* It never returns an absolute machine path: the default home is labelled\n* `~/.dsh`, and any configured home is labelled `$DSH_HOME`.\n* @param resolvedHome - the absolute path returned by {@link resolveDshHome}.\n* @returns `~/.dsh` for the default home, otherwise `$DSH_HOME`.\n*/\nfunction dshHomeDisplay(resolvedHome) {\n\treturn resolvedHome === resolve(defaultDshHome()) ? DEFAULT_DSH_HOME_DISPLAY : `$${DSH_HOME_ENV}`;\n}\n//#endregion\nexport { DEFAULT_DSH_HOME_DISPLAY, DSH_HOME_DIR_NAME, DSH_HOME_ENV, canonicalizeWatchPath, defaultDshHome, dshHomeDisplay, dshHomePath, expandHomePath, resolveDshHome };\n", "/**\n * \u4E0A\u6E38\u7F51\u7EDC\u5C42\u52A9\u624B\uFF1A\u7F51\u7EDC\u7EA7\u77AC\u65AD\u7684\u5355\u53D1\u81EA\u52A8\u91CD\u8BD5\u3002\n *\n * \u5B9E\u6D4B\u4F9D\u636E\uFF082026-09\uFF0CNode 24 undici \u5168\u63A5\u53E3\u6D4B\u8BD5\u77E9\u9635\uFF09\uFF1A\n * A6API \u4E0A\u6E38 nginx/CDN \u79EF\u6781\u56DE\u6536\u7A7A\u95F2 keep-alive \u8FDE\u63A5\uFF08\u5B9E\u6D4B\u9608\u503C\u5728 60~95s \u4E4B\u95F4\uFF09\uFF0C\n * \u8FDE\u63A5\u6C60\u62FF\u5230\u88AB\u5BF9\u7AEF\u9759\u9ED8\u5173\u95ED\u7684\"\u6B7B socket\"\u65F6\uFF0C\u9996\u4E2A\u8BF7\u6C42\u7EA6 5s \u540E\u629B\n * `TypeError: fetch failed`\uFF08cause: ECONNRESET\uFF09\uFF0C\u65B0\u8FDE\u63A5\u91CD\u8BD5\u7ACB\u5373\u6210\u529F\uFF1B\n * \u70ED\u8FDE\u63A5\u8FDE\u53D1\u671F 0/54 \u5931\u8D25\uFF0C\u968F\u673A\u6574\u4F53\u7EA6 2~5% \u8BF7\u6C42\u6B7B\u5728\u4F20\u8F93\u5C42\u3002\n *\n * \u8FD9\u7C7B\u9519\u8BEF\u53D1\u751F\u5728\u4F20\u8F93\u5C42\u2014\u2014\u8BF7\u6C42\u786E\u5B9A\u672A\u6536\u5230\u4EFB\u4F55\u54CD\u5E94\uFF08\u4E0D\u4F1A\u8BA1\u8D39\u3001\u65E0\u526F\u4F5C\u7528\uFF09\uFF0C\n * \u662F\u552F\u4E00\u9002\u5408\u76F2\u91CD\u8BD5\u7684\u7C7B\u522B\u3002\u8D85\u65F6\uFF08TimeoutError\uFF09\u4E0D\u91CD\u8BD5\uFF1A\u8BF7\u6C42\u53EF\u80FD\u5DF2\u5728\u4E0A\u6E38\u5904\u7406\u3002\n */\n\nexport const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n/** \u7F51\u7EDC\u7EA7\u77AC\u65AD\u5224\u5B9A\uFF08\u786E\u5B9A\u672A\u6536\u5230\u54CD\u5E94\uFF0C\u53EF\u5B89\u5168\u91CD\u8BD5\uFF09\uFF1B\u8D85\u65F6/\u4E2D\u6B62\u4E0D\u5728\u5176\u5217 */\nexport function isFlakyNetworkError(err: any): boolean {\n if (err?.name === 'TimeoutError' || err?.name === 'AbortError') return false;\n const cause = err?.cause;\n const raw = `${err?.message || ''} ${cause?.code || ''} ${cause?.message || ''}`;\n return /fetch failed|ECONNRESET|ECONNREFUSED|EHOSTUNREACH|ENETUNREACH|ENOTFOUND|EPIPE|socket hang up|other side closed|UND_ERR_SOCKET|UND_ERR_CONNECT_TIMEOUT|SSL_ERROR|ERR_SSL/i.test(\n raw,\n );\n}\n\nexport interface RetryFetchInit extends RequestInit {\n /** \u6BCF\u6B21\u5C1D\u8BD5\u72EC\u7ACB\u7684\u8D85\u65F6\u7A97\u53E3\uFF08ms\uFF09\uFF1B\u8BBE\u7F6E\u540E\u66FF\u4EE3 init.signal\uFF0C\u91CD\u8BD5\u4E0D\u4F1A\u88AB\u9996\u53D1\u8017\u5C3D\u7684\u65F6\u95F4\u7A97\u76F4\u63A5\u6390\u6B7B */\n timeoutMs?: number;\n}\n\n/**\n * fetch + \u7F51\u7EDC\u7EA7\u77AC\u65AD\u81EA\u52A8\u91CD\u8BD5\uFF08\u9ED8\u8BA4 1 \u6B21\u3001\u95F4\u9694 800ms\uFF09\u3002\n * HTTP \u72B6\u6001\u9519\u8BEF\uFF084xx/5xx\uFF09\u539F\u6837\u8FD4\u56DE Response \u7531\u8C03\u7528\u65B9\u5904\u7406\uFF1B\u53EA\u6709\u629B\u51FA\u7684\u4F20\u8F93\u5C42\u9519\u8BEF\u624D\u91CD\u8BD5\u3002\n */\nexport async function fetchWithNetRetry(\n url: string,\n init: RetryFetchInit = {},\n opts?: { retries?: number; delayMs?: number },\n): Promise<Response> {\n const retries = opts?.retries ?? 1;\n const delayMs = opts?.delayMs ?? 800;\n const { timeoutMs, ...rest } = init;\n let lastErr: any;\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const signal = timeoutMs ? AbortSignal.timeout(timeoutMs) : rest.signal;\n return await fetch(url, { ...rest, signal });\n } catch (err: any) {\n lastErr = err;\n if (attempt < retries && isFlakyNetworkError(err)) {\n console.warn(\n `[dsh-a6api] \u4E0A\u6E38\u8FDE\u63A5\u77AC\u65AD(${err?.cause?.code || err?.message || 'network'})\uFF0C${delayMs}ms \u540E\u91CD\u8BD5:`,\n url.split('?')[0],\n );\n await sleep(delayMs);\n continue;\n }\n throw err;\n }\n }\n throw lastErr;\n}\n", "import type { BalanceInfo, MerchantChannelInfo, OfficialPrices, ApiRoutingLogItem, MarketplacePin, A6ApiTokenItem } from '../types.js';\nimport { resolveModelMeta } from './catalog.js';\nimport { fetchWithNetRetry, isFlakyNetworkError } from './net.js';\n\n/** Normalize Base URL removing trailing slashes */\nexport function cleanBaseUrl(url: string): string {\n if (!url) return 'https://api.a6api.com';\n return url.trim().replace(/\\/+$/, '');\n}\n\n/** Format relative time */\nexport function formatRelativeTime(timestampSec: number): string {\n if (!timestampSec || timestampSec <= 0) return '\u521A\u521A';\n const now = Math.floor(Date.now() / 1000);\n const diff = now - timestampSec;\n if (diff < 0) return '\u521A\u521A';\n if (diff < 60) return '\u521A\u521A';\n if (diff < 3600) return `${Math.floor(diff / 60)} \u5206\u949F\u524D`;\n if (diff < 86400) return `${Math.floor(diff / 3600)} \u5C0F\u65F6\u524D`;\n return `${Math.floor(diff / 86400)} \u5929\u524D`;\n}\n\n/** Format CNY Price */\nexport function formatCnyPrice(micros: number, exchangeRate = 6.7209): string {\n if (micros === undefined || micros === null) return '\u2014';\n if (micros === 0) return '\u00A50';\n const usd = micros / 1_000_000;\n const cny = usd * exchangeRate;\n if (cny < 0.0001) return `\u00A5${cny.toFixed(6)}`;\n if (cny < 0.01) return `\u00A5${cny.toFixed(4)}`;\n if (cny < 1) return `\u00A5${cny.toFixed(4)}`;\n return `\u00A5${cny.toFixed(3)}`;\n}\n\n/** \u6DF7\u5408\u4EF7\u4F30\u7B97\u5E38\u6570\uFF1A\u8F93\u51FA token \u5360\u603B token \u6BD4\u4F8B\u56FA\u5B9A 0.35%\uFF08\u4E0E\u5B98\u7F51\u6A21\u578B\u5E02\u573A \u00A5/100M \u6807\u6CE8\u53E3\u5F84\u4E00\u81F4\uFF09 */\nconst BLENDED_OUT_SHARE = 0.0035;\n\n/**\n * \u6DF7\u5408\u4EF7\u4F30\u7B97\uFF08\u00A5 / 1\u4EBF tokens\uFF0C\u4F9B\u6A21\u578B\u5361\u7247\u5FBD\u6807\u5C55\u793A\uFF0C\u6362\u7B97\u4E0E\u53E3\u5F84\u540C\u5B98\u7F51\u6807\u6CE8\u811A\u672C\uFF09\uFF1A\n * \u8F93\u5165\u7C7B token \u5360 99.65%\uFF0C\u6309 24h \u5B9E\u6D4B\u7F13\u5B58\u547D\u4E2D\u7387\u5206\u4E3A\u300C\u547D\u4E2D \u00D7 \u7F13\u5B58\u8BFB\u4EF7\u300D\u4E0E\u300C\u672A\u547D\u4E2D \u00D7 \u8F93\u5165\u4EF7\u300D\uFF0C\n * \u8F93\u51FA\u56FA\u5B9A\u5360 0.35% \u00D7 \u8F93\u51FA\u4EF7\u3002\u5355\u4EF7\u6309 micros/1e6 \u00D7 \u6C47\u7387\u6298\u7B97\u4E3A \u00A5/1M\uFF1B\n * \u4E09\u7C7B\u5355\u4EF7\u5168\u4E3A 0\uFF08\u6309\u6B21\u8BA1\u8D39\u7B49\u65E0 token \u5355\u4EF7\uFF09\u65F6\u8FD4\u56DE undefined\uFF0C\u524D\u7AEF\u4E0D\u5C55\u793A\u3002\n */\nexport function computeBlendedPrice100m(\n inMicros: number,\n cacheReadMicros: number,\n outMicros: number,\n cacheHitRatePct: number,\n exchangeRate: number,\n): number | undefined {\n const inY = (inMicros / 1_000_000) * exchangeRate; // \u672A\u547D\u4E2D\uFF08\u8F93\u5165\uFF09\u4EF7 \u00A5/1M\n const hitY = (cacheReadMicros / 1_000_000) * exchangeRate; // \u547D\u4E2D\uFF08\u7F13\u5B58\u8BFB\uFF09\u4EF7 \u00A5/1M\n const outY = (outMicros / 1_000_000) * exchangeRate; // \u8F93\u51FA\u4EF7 \u00A5/1M\n if (inY <= 0 && hitY <= 0 && outY <= 0) return undefined;\n const h = Math.min(1, Math.max(0, cacheHitRatePct / 100));\n const inShare = 1 - BLENDED_OUT_SHARE; // \u8F93\u5165\u7C7B token \u5360\u6BD4 99.65%\n const per1M = h * inShare * hitY + (1 - h) * inShare * inY + BLENDED_OUT_SHARE * outY;\n return per1M * 100;\n}\n\nexport function buildWebHeaders(userId?: string, accessToken?: string): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',\n };\n const uid = userId ? String(userId).trim() : '';\n if (uid) {\n headers['New-Api-User'] = uid;\n }\n if (accessToken && accessToken.trim()) {\n const raw = accessToken.trim();\n if (raw.startsWith('session=')) {\n headers['Cookie'] = raw;\n } else if (raw.includes(';')) {\n headers['Cookie'] = raw;\n } else {\n // Set both Authorization (for System Access Token) and Cookie fallback\n headers['Authorization'] = raw;\n headers['Cookie'] = `session=${raw}`;\n }\n }\n return headers;\n}\n\n/** Fetch User Balance (Real Account Balance Only) */\nexport async function fetchBalance(\n baseURL: string,\n apiKey: string,\n userId?: string,\n accessToken?: string,\n): Promise<BalanceInfo | null> {\n const cleanUrl = cleanBaseUrl(baseURL);\n\n let hasAccountAuth = false;\n let accountBalanceUsd = 0;\n let accountBalanceFormatted = '\u672A\u8FDE\u63A5';\n let accountBalanceCnyFormatted = '';\n let username: string | undefined;\n let responseUserId: string | number | undefined = userId;\n let usedUsd = 0;\n let requestCount = 0;\n\n // 1. Fetch real account balance from Web Console API\n if (userId || accessToken) {\n const candidates = ['https://a6api.com/api/user/self', `${cleanUrl}/api/user/self`];\n const uniqueCandidates = [...new Set(candidates)];\n\n for (const url of uniqueCandidates) {\n try {\n const res = await fetchWithNetRetry(url, {\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 6000,\n });\n if (res.ok) {\n const json = await res.json();\n if (json?.data && json.data.quota !== undefined) {\n const quota = Number(json.data.quota || 0);\n const rawUsed = Number(json.data.used_quota || 0);\n const usd = Number((quota / 500000).toFixed(4));\n const cny = Number((usd * 6.7209).toFixed(2));\n const used = Number((rawUsed / 500000).toFixed(4));\n\n hasAccountAuth = true;\n accountBalanceUsd = usd;\n accountBalanceFormatted = `$${usd.toFixed(2)}`;\n accountBalanceCnyFormatted = `\u2248 \u00A5${cny.toFixed(2)}`;\n usedUsd = used;\n requestCount = Number(json.data.request_count || 0);\n username = json.data.username || json.data.display_name || undefined;\n if (json.data.id) responseUserId = json.data.id;\n break;\n }\n }\n } catch {\n // continue candidate\n }\n }\n }\n\n // 2. If only API Key is present, query usage for consumed statistics if auth is not yet connected\n if (!hasAccountAuth && apiKey && apiKey.trim()) {\n try {\n const usageRes = await fetchWithNetRetry(`${cleanUrl}/v1/dashboard/billing/usage?start_date=2024-01-01&end_date=2030-12-31`, {\n headers: {\n Authorization: `Bearer ${apiKey.trim()}`,\n Accept: 'application/json',\n },\n timeoutMs: 6000,\n }).catch(() => null);\n\n if (usageRes && usageRes.ok) {\n const usageJson = await usageRes.json();\n usedUsd = Number(usageJson?.total_usage || 0);\n }\n } catch {}\n }\n\n if (!hasAccountAuth && (!apiKey || !apiKey.trim()) && (!userId || !userId.trim())) {\n return null;\n }\n\n return {\n hasAccountAuth,\n accountBalanceUsd,\n accountBalanceFormatted,\n accountBalanceCnyFormatted,\n usedUsd,\n usedFormatted: `$${usedUsd.toFixed(2)}`,\n requestCount,\n username,\n userId: responseUserId,\n isLow: hasAccountAuth ? accountBalanceUsd < 0.5 : false,\n updatedAt: Date.now(),\n };\n}\n\n/** Fetch Token Allowed Models */\nexport async function fetchTokenModels(baseURL: string, apiKey: string): Promise<string[]> {\n const cleanUrl = cleanBaseUrl(baseURL);\n if (!apiKey || !apiKey.trim()) return [];\n\n const endpoints = [`${cleanUrl}/v1/models`, `${cleanUrl}/models`];\n let lastErr = null;\n\n for (const url of endpoints) {\n try {\n const res = await fetchWithNetRetry(url, {\n headers: {\n Authorization: `Bearer ${apiKey.trim()}`,\n Accept: 'application/json',\n },\n timeoutMs: 8000,\n });\n if (res.ok) {\n const json = await res.json();\n if (Array.isArray(json?.data)) {\n return json.data.map((m: any) => String(m.id || m.name)).filter(Boolean);\n }\n }\n } catch (err) {\n lastErr = err;\n }\n }\n\n if (lastErr) {\n console.warn('[dsh-a6api] fetchTokenModels failed:', lastErr);\n }\n return [];\n}\n\n/** Fetch Recent User Routing Logs */\nexport async function fetchRecentLogs(\n userId?: string,\n accessToken?: string,\n limit = 30,\n): Promise<ApiRoutingLogItem[]> {\n if (!userId && !accessToken) return [];\n try {\n const res = await fetchWithNetRetry(`https://a6api.com/api/log/self?p=1&page_size=${limit}&type=0`, {\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 8000,\n });\n if (res.ok) {\n const json = await res.json();\n if (Array.isArray(json?.data?.items)) {\n return json.data.items.map((it: any) => {\n const rawQuota = Number(it.quota || 0);\n const costUsd = rawQuota / 500000;\n let costFormatted = '$0.00';\n if (costUsd > 0) {\n if (costUsd < 0.0001) costFormatted = `$${costUsd.toFixed(6)}`;\n else if (costUsd < 0.01) costFormatted = `$${costUsd.toFixed(4)}`;\n else costFormatted = `$${costUsd.toFixed(4)}`;\n }\n\n const rawChannel = Number(it.channel || 0);\n let channelId: number | undefined = rawChannel > 0 ? rawChannel : undefined;\n if (!channelId && it.other) {\n try {\n const otherObj = JSON.parse(it.other);\n if (otherObj.actual_channel_id && Number(otherObj.actual_channel_id) > 0) {\n channelId = Number(otherObj.actual_channel_id);\n } else if (otherObj.billed_channel_id && Number(otherObj.billed_channel_id) > 0) {\n channelId = Number(otherObj.billed_channel_id);\n }\n } catch {}\n }\n\n const isError =\n it.type !== 2 ||\n (it.other && (\n it.other.includes('\"request_final_status\":\"failed\"') ||\n it.other.includes('\"request_final_status\":\"error\"') ||\n it.other.includes('\"request_final_status\":\"upstream_error\"')\n )) ||\n Boolean(it.content && it.content.startsWith('status_code='));\n\n return {\n id: it.id || it.request_id || String(Math.random()),\n created_at: Number(it.created_at || Date.now() / 1000),\n model_name: it.model_name || it.marketplace_model_name || '',\n channel: channelId,\n channel_name: it.channel_name || (channelId ? `\u5546\u6237 #${channelId}` : undefined),\n token_id: it.token_id !== undefined && it.token_id !== null ? Number(it.token_id) : undefined,\n prompt_tokens: Number(it.prompt_tokens || 0),\n completion_tokens: Number(it.completion_tokens || 0),\n use_time: Number(it.use_time || 0),\n quota: rawQuota,\n cost_usd: costUsd,\n cost_formatted: costFormatted,\n token_name: it.token_name || 'API',\n status: isError ? ('error' as const) : ('success' as const),\n other: it.other,\n raw: it,\n };\n });\n }\n }\n } catch (err) {\n console.warn('[dsh-a6api] fetchRecentLogs error:', err);\n }\n return [];\n}\n\n/** Fetch Channel Card details from A6API Marketplace */\nexport async function fetchChannelDetails(\n channelId: number,\n userId?: string,\n accessToken?: string,\n targetModelName?: string,\n logSnapshot?: any,\n): Promise<MerchantChannelInfo | null> {\n if (!channelId) return null;\n const targetName = targetModelName || '';\n const meta = resolveModelMeta(targetName);\n\n try {\n const res = await fetchWithNetRetry(\n `https://a6api.com/api/marketplace/channels/search?channel_id=${channelId}&view=list&page=1&page_size=20`,\n {\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 8000,\n },\n );\n if (res.ok) {\n const json = await res.json();\n const items: any[] = json?.data?.items || [];\n if (items.length > 0) {\n // Find match for targetModelName if provided, otherwise first item\n const item =\n (targetName\n ? items.find((it) => it.model_name?.toLowerCase() === targetName.toLowerCase())\n : null) || items[0];\n\n const rate = Number(item.realtime_ratio_exchange_rate || 6.7209);\n const inMicros = Number(item.input_price_micros || 0);\n const outMicros = Number(item.output_price_micros || 0);\n const cacheReadMicros = Number(item.cache_read_price_micros || 0);\n const cacheWriteMicros = Number(item.cache_write_price_micros || 0);\n\n // Parse Smart Routing Labels\n const labels: string[] = [];\n if (item.authenticity_guaranteed) {\n const badge = item.authenticity_guarantee_badge_key;\n if (badge === 'gold') labels.push('\u4FDD\u771F \u00B7 \u91D1\u6807');\n else if (badge === 'silver') labels.push('\u4FDD\u771F \u00B7 \u94F6\u6807');\n else if (badge === 'bronze') labels.push('\u4FDD\u771F \u00B7 \u94DC\u6807');\n else labels.push('\u4FDD\u771F');\n }\n if (Array.isArray(item.smart_routing_labels)) {\n for (const l of item.smart_routing_labels) {\n if (l === 'stable' && !labels.includes('\u7A33\u5B9A')) labels.push('\u7A33\u5B9A');\n if (l === 'cheap' && !labels.includes('\u4F4E\u4EF7')) labels.push('\u4F4E\u4EF7');\n if (l === 'fast' && !labels.includes('\u9AD8\u901F')) labels.push('\u9AD8\u901F');\n if (l === 'quality' && !labels.includes('\u9AD8\u8D28')) labels.push('\u9AD8\u8D28');\n }\n }\n if (labels.length === 0) {\n labels.push('\u7A33\u5B9A', '\u4F4E\u4EF7', '\u9AD8\u901F', '\u9AD8\u8D28');\n }\n\n // Official Prices\n let official_price: OfficialPrices | undefined;\n if (item.official_price && item.official_price.input_price_micros !== undefined) {\n const offIn = Number(item.official_price.input_price_micros || 0);\n const offOut = Number(item.official_price.output_price_micros || 0);\n const offCR = Number(item.official_price.cache_read_price_micros || 0);\n const offCW = Number(item.official_price.cache_write_price_micros || 0);\n official_price = {\n input_price_micros: offIn,\n output_price_micros: offOut,\n cache_read_price_micros: offCR,\n cache_write_price_micros: offCW,\n input_cny: formatCnyPrice(offIn, rate),\n output_cny: formatCnyPrice(offOut, rate),\n cache_read_cny: formatCnyPrice(offCR, rate),\n cache_write_cny: formatCnyPrice(offCW, rate),\n };\n } else if (meta.officialPriceMicros) {\n const offIn = meta.officialPriceMicros.input;\n const offOut = meta.officialPriceMicros.output;\n const offCR = meta.officialPriceMicros.cacheRead;\n const offCW = meta.officialPriceMicros.cacheWrite;\n official_price = {\n input_price_micros: offIn,\n output_price_micros: offOut,\n cache_read_price_micros: offCR,\n cache_write_price_micros: offCW,\n input_cny: formatCnyPrice(offIn, rate),\n output_cny: formatCnyPrice(offOut, rate),\n cache_read_cny: formatCnyPrice(offCR, rate),\n cache_write_cny: formatCnyPrice(offCW, rate),\n };\n }\n\n const successRate24h =\n item.success_rate_24h !== undefined ? Number(item.success_rate_24h) / 100 : 99.3;\n const recentSuccessRate =\n item.recent_success_rate !== undefined ? Number(item.recent_success_rate) / 100 : 100;\n const cacheHitRate =\n item.cache_hit_rate_24h !== undefined ? Number(item.cache_hit_rate_24h) / 100 : 72.0;\n const lastSuccessAt = Number(item.last_success_at || item.last_test_time || 0);\n\n const blended100m = computeBlendedPrice100m(inMicros, cacheReadMicros, outMicros, cacheHitRate, rate);\n\n const ratioCny = Number(item.realtime_ratio_cny || (inMicros / 1000000) * rate || 0.0341);\n const ratioFormatted = ratioCny.toFixed(4);\n\n return {\n listing_id: item.listing_id,\n // \u5F52\u4E00\u5316\u4E3A\u6570\u5B57\uFF0C\u907F\u514D\u5B98\u65B9\u8FD4\u56DE\u5B57\u7B26\u4E32 channel_id \u5BFC\u81F4\u4E25\u683C\u76F8\u7B49\u6BD4\u8F83\u5931\u6548\uFF08\u63A5\u7BA1/\u56FA\u5B9A\u5224\u5B9A\u4F9D\u8D56\uFF09\n channel_id: item.channel_id !== undefined && item.channel_id !== null ? Number(item.channel_id) : channelId,\n channel_name: item.channel_name || `\u5546\u6237 #${channelId}`,\n supplier_name: item.supplier_name || item.supplier_nickname || 'GPT\u4F4E\u4EF7',\n supplier_id: item.supplier_id || 290,\n model_name: item.model_name || targetName,\n brand: item.brand || meta.brand || 'OpenAI',\n description: item.description || '\u9AD8\u5E76\u53D1 \u4E3B\u6253\u4FBF\u5B9C \u7A33\u5B9A',\n charge_type: item.charge_type || 'per_token',\n charge_type_text: item.charge_type === 'per_token' ? '\u6309\u91CF' : '\u6309\u91CF',\n sample_count: Number(item.sample_count || 100),\n sample_count_text: `\u8FD1 ${item.sample_count || 100} \u6B21\u6837\u672C`,\n input_price_micros: inMicros,\n output_price_micros: outMicros,\n cache_read_price_micros: cacheReadMicros,\n cache_write_price_micros: cacheWriteMicros,\n input_price_cny: formatCnyPrice(inMicros, rate),\n output_price_cny: formatCnyPrice(outMicros, rate),\n cache_read_price_cny: formatCnyPrice(cacheReadMicros, rate),\n cache_write_price_cny: formatCnyPrice(cacheWriteMicros, rate),\n official_price,\n realtime_ratio_cny: ratioCny,\n realtime_ratio_formatted: ratioFormatted,\n recent_success_rate_pct: recentSuccessRate,\n success_rate_24h_pct: successRate24h,\n success_rate_7d_pct: item.success_rate_7d !== undefined ? Number(item.success_rate_7d) / 100 : undefined,\n success_buckets: Array.isArray(item.success_buckets) ? item.success_buckets : undefined,\n b24: Array.isArray(item.b24) ? item.b24 : undefined,\n b7d: Array.isArray(item.b7d) ? item.b7d : undefined,\n sr_24h_state: item.sr_24h_state || 'rate',\n sr_7d_state: item.sr_7d_state || 'no_data',\n p50_ttft_ms: Number(item.p50_ttft_ms || 2273),\n recent_p50_ms: Number(item.recent_p50_ms || item.last_test_response_ms || 2340),\n cache_hit_rate_pct: cacheHitRate,\n blended_price_100m_cny: blended100m,\n labels,\n last_success_at: lastSuccessAt,\n last_success_text: formatRelativeTime(lastSuccessAt),\n authenticity_guaranteed: Boolean(item.authenticity_guaranteed),\n authenticity_badge: item.authenticity_guarantee_badge_key,\n // \u5B98\u65B9\u56FA\u5B9A\u72B6\u6001\u503C\u662F pin_here / pin_elsewhere\uFF08\u65E9\u671F\u4EE3\u7801\u8BEF\u7528 'pinned'\uFF0C\u5DF2\u4FEE\u6B63\uFF09\n is_pinned: item.pin_status === 'pin_here' || item.route_status === 'pin_here',\n pin_status: typeof item.pin_status === 'string' ? item.pin_status : undefined,\n user_channel_disabled: Boolean(item.user_channel_disabled || item.route_status === 'user_disabled'),\n supplier_channel_disabled: Boolean(item.supplier_channel_disabled),\n raw: item,\n };\n }\n }\n } catch (err) {\n console.warn('[dsh-a6api] fetchChannelDetails error:', err);\n }\n\n // Fallback if we have log snapshot info\n if (logSnapshot) {\n const rate = 6.7209;\n const inMicros = Number(logSnapshot.marketplace_price_input_micros || 20300);\n const outMicros = Number(logSnapshot.marketplace_price_output_micros || 101502);\n const cacheReadMicros = Number(logSnapshot.marketplace_price_cache_read_micros || 2030);\n const cacheWriteMicros = Number(logSnapshot.marketplace_price_cache_write_micros || 25375);\n\n let official_price: OfficialPrices | undefined;\n if (meta.officialPriceMicros) {\n const offIn = meta.officialPriceMicros.input;\n const offOut = meta.officialPriceMicros.output;\n const offCR = meta.officialPriceMicros.cacheRead;\n const offCW = meta.officialPriceMicros.cacheWrite;\n official_price = {\n input_price_micros: offIn,\n output_price_micros: offOut,\n cache_read_price_micros: offCR,\n cache_write_price_micros: offCW,\n input_cny: formatCnyPrice(offIn, rate),\n output_cny: formatCnyPrice(offOut, rate),\n cache_read_cny: formatCnyPrice(offCR, rate),\n cache_write_cny: formatCnyPrice(offCW, rate),\n };\n }\n\n const ratioCny = Number((inMicros / 1000000) * rate || 0.0341);\n\n return {\n listing_id: logSnapshot.marketplace_listing_id,\n channel_id: channelId,\n channel_name: logSnapshot.channel_name || `\u5546\u6237 #${channelId}`,\n supplier_name: logSnapshot.supplier_nickname || logSnapshot.channel_name || 'GPT\u4F4E\u4EF7',\n supplier_id: 290,\n model_name: targetName || logSnapshot.model_name || '',\n brand: meta.brand || 'OpenAI',\n description: '\u9AD8\u5E76\u53D1 \u4E3B\u6253\u4FBF\u5B9C \u7A33\u5B9A',\n charge_type: 'per_token',\n charge_type_text: '\u6309\u91CF',\n sample_count: 100,\n sample_count_text: '\u8FD1 100 \u6B21\u6837\u672C',\n input_price_micros: inMicros,\n output_price_micros: outMicros,\n cache_read_price_micros: cacheReadMicros,\n cache_write_price_micros: cacheWriteMicros,\n input_price_cny: formatCnyPrice(inMicros, rate),\n output_price_cny: formatCnyPrice(outMicros, rate),\n cache_read_price_cny: formatCnyPrice(cacheReadMicros, rate),\n cache_write_price_cny: formatCnyPrice(cacheWriteMicros, rate),\n official_price,\n realtime_ratio_cny: ratioCny,\n realtime_ratio_formatted: ratioCny.toFixed(4),\n recent_success_rate_pct: 100,\n success_rate_24h_pct: 99.3,\n recent_p50_ms: Number(logSnapshot.use_time ? logSnapshot.use_time * 1000 : 2340),\n p50_ttft_ms: 2273,\n cache_hit_rate_pct: 72.0,\n blended_price_100m_cny: computeBlendedPrice100m(inMicros, cacheReadMicros, outMicros, 72.0, rate),\n labels: ['\u7A33\u5B9A', '\u4F4E\u4EF7', '\u9AD8\u901F', '\u9AD8\u8D28'],\n last_success_at: Math.floor(Date.now() / 1000),\n last_success_text: '\u521A\u521A',\n authenticity_guaranteed: false,\n is_pinned: false,\n user_channel_disabled: false,\n };\n }\n\n return null;\n}\n/** \u8F7B\u91CF\u62C9\u53D6\u4EF7\u683C\u6CE2\u52A8\u6761\u6570\uFF08\u4EC5 pending/unseen\uFF09 */\nexport async function fetchPriceFluctuation(\n userId?: string,\n accessToken?: string,\n): Promise<{ pendingCount: number; unseenCount: number; totalCount: number; notices?: any[]; authError?: boolean }> {\n const token = (accessToken || '').trim();\n const uid = (userId || '').trim();\n if (!uid && !token) {\n return { pendingCount: 0, unseenCount: 0, totalCount: 0, authError: false };\n }\n const headers = buildWebHeaders(uid || undefined, token || undefined);\n const url = 'https://a6api.com/api/marketplace/price-notices';\n try {\n const res = await fetchWithNetRetry(url, { headers, timeoutMs: 8000 });\n if (res.status === 401 || res.status === 403) {\n console.warn('[dsh-a6api] fetchPriceFluctuation auth failed', res.status);\n return { pendingCount: 0, unseenCount: 0, totalCount: 0, authError: true };\n }\n if (!res.ok) {\n console.warn('[dsh-a6api] fetchPriceFluctuation HTTP', res.status);\n return { pendingCount: 0, unseenCount: 0, totalCount: 0 };\n }\n const json: any = await res.json().catch(() => null);\n if (!json) return { pendingCount: 0, unseenCount: 0, totalCount: 0 };\n if (json.success === false) return { pendingCount: 0, unseenCount: 0, totalCount: 0 };\n\n // \u517C\u5BB9\u591A\u79CD\u8FD4\u56DE\u5F62\u6001\n let arr: any[] = [];\n if (Array.isArray(json)) arr = json;\n else if (Array.isArray(json.data)) arr = json.data;\n else if (Array.isArray(json.data?.notices)) arr = json.data.notices;\n else if (Array.isArray(json.data?.items)) arr = json.data.items;\n else if (Array.isArray(json.notices)) arr = json.notices;\n else if (Array.isArray(json.items)) arr = json.items;\n\n // \u533A\u5206\u201C\u5B57\u6BB5\u7F3A\u5931\u201D vs \u201C\u663E\u5F0F\u4E3A 0\u201D\u2014\u2014\u4EC5\u7F3A\u5931\u65F6\u624D\u515C\u5E95\n const pickWithPresent = (keys: string[]): { value: number; present: boolean } => {\n for (const k of keys) {\n const v = json?.data?.[k] ?? json?.[k];\n if (v !== undefined && v !== null) {\n const n = Number(v);\n if (!Number.isNaN(n)) return { value: n, present: true };\n }\n }\n return { value: 0, present: false };\n };\n const pendingPick = pickWithPresent(['pendingCount', 'pending_count', 'pending', 'openCount']);\n const unseenPick = pickWithPresent(['unseenCount', 'unseen_count', 'unseen', 'has_unseen_count']);\n let pending = pendingPick.value;\n let unseen = unseenPick.value;\n const total = arr.length;\n\n // \u4EC5\u5728\u8BA1\u6570\u952E\u7F3A\u5931\u65F6\u624D\u4ECE\u6570\u7EC4\u515C\u5E95\uFF0C\u907F\u514D\u8986\u76D6 API \u663E\u5F0F 0\n if (!pendingPick.present && arr.length > 0) {\n // \u4E0A\u6E38\u771F\u5B9E\u5F62\u6001\uFF1Anotice.status \u2208 effective/superseded\uFF08\u4EF7\u683C\u4E8B\u4EF6\u672C\u8EAB\u7684\u72B6\u6001\uFF09\uFF0C\n // \u7528\u6237\u5BF9\u56FA\u5B9A\u6E20\u9053\u7684\u300C\u5F85\u5904\u7406\u300D\u4FE1\u53F7\u5728 relations[].state === 'open'\uFF08obsolete = \u5DF2\u88AB\u65B0\u901A\u77E5\u53D6\u4EE3\uFF09\u3002\n // \u6709 relations \u65F6\u4EE5 open \u4E3A\u51C6\uFF1B\u65E0 relations \u65F6\u9000\u56DE\u901A\u77E5\u7EA7\u72B6\u6001\uFF08\u542B effective\uFF09\u3002\n const isPendingNotice = (n: any): boolean => {\n if (n?.pending === true) return true;\n const rels = Array.isArray(n?.relations) ? n.relations : [];\n if (rels.length > 0) {\n return rels.some((r: any) => String(r?.state ?? '').toLowerCase() === 'open');\n }\n const s = String(n?.state ?? n?.status ?? '').toLowerCase();\n return s === 'open' || s === 'pending' || s === 'effective';\n };\n const counted = arr.filter(isPendingNotice).length;\n // \u4EC5\u5F53\u6570\u7EC4\u6709\u53EF\u8BC6\u522B\u7684\u72B6\u6001\u4FE1\u53F7\u65F6\u624D\u7528 counted\uFF0C\u5426\u5219\u4FDD\u6301 0\uFF08\u4E0D\u731C\u6D4B\uFF09\n const hasState = arr.some(\n (n: any) =>\n n.state !== undefined ||\n n.status !== undefined ||\n (Array.isArray(n.relations) && n.relations.length > 0),\n );\n if (hasState) pending = counted;\n // \u82E5\u65E0\u4EFB\u4F55\u72B6\u6001\u4FE1\u53F7\u4E14 pending \u7F3A\u5931\uFF0C\u4FDD\u6301 0\uFF0C\u4E0D\u518D\u9000\u5316\u4E3A total\n }\n if (!unseenPick.present && arr.length > 0) {\n unseen = arr.filter((n: any) => n.has_unseen === true || n.hasUnseen === true || n.unseen === true || n.is_unread === true).length;\n }\n\n // \u8C03\u8BD5\u65E5\u5FD7\u5DF2\u79FB\u9664\uFF08\u907F\u514D\u672A\u8131\u654F\u900F\u4F20\uFF09\uFF1B\u5982\u9700\u672C\u5730\u8C03\u8BD5\u53EF\u4E34\u65F6\u5F00\u542F DEBUG \u73AF\u5883\u53D8\u91CF\n // if (process.env.DEBUG) console.log('[dsh-a6api] price fluctuation sample', arr[0]);\n\n return { pendingCount: pending, unseenCount: unseen, totalCount: total, notices: arr };\n } catch (err) {\n console.warn('[dsh-a6api] fetchPriceFluctuation error', err);\n return { pendingCount: 0, unseenCount: 0, totalCount: 0 };\n }\n}\n\n/* ============================================================================\n * \u56FA\u5B9A / \u53D6\u6D88\u56FA\u5B9A / \u7981\u7528 \u4E00\u65CF\u63A5\u53E3\uFF08\u5E73\u53F0\u4FA7\uFF0CWeb \u4F1A\u8BDD\u9274\u6743\uFF0C\u4E0E\u5E02\u573A\u4EF7\u683C\u6CE2\u52A8\u540C\u51ED\u636E\uFF09\n * ========================================================================== */\n\ninterface MarketplaceActionResult {\n ok: boolean;\n message?: string;\n data?: any;\n}\n\n/** \u517C\u5BB9\u591A\u79CD\u8FD4\u56DE\u5F62\u6001\uFF1A{success,message} / {data:{success,message}} */\nfunction parseMarketplaceResult(json: any): MarketplaceActionResult {\n if (!json) return { ok: false, message: '\u7A7A\u54CD\u5E94' };\n const top = json.success === false ? json : null;\n const inner = json.data && json.data.success === false ? json.data : null;\n if (top) return { ok: false, message: friendlyMarketMessage(top.message) };\n if (inner) return { ok: false, message: friendlyMarketMessage(inner.message) };\n return { ok: true, data: json.data };\n}\n\n/** \u4E0A\u6E38\u901A\u7528\u9519\u8BEF\u7801\u53CB\u597D\u5316\uFF1Ainvalid_request \u7B49\u88F8\u7801\u5BF9\u7528\u6237\u4E0D\u53EF\u8BFB\uFF0C\u7ED9\u51FA\u53EF\u64CD\u4F5C\u7684\u89E3\u91CA */\nfunction friendlyMarketMessage(msg: any): string {\n const s = String(msg || '');\n if (s === 'invalid_request') {\n return '\u4E0A\u6E38\u62D2\u7EDD\u4E86\u8BE5\u64CD\u4F5C(invalid_request)\uFF1A\u53C2\u6570\u672A\u901A\u8FC7\u5E73\u53F0\u6821\u9A8C\uFF08\u53EF\u80FD\u662F\u5E73\u53F0\u63A5\u53E3\u8C03\u6574\u6216\u56FA\u5B9A\u8BB0\u5F55\u5DF2\u53D8\u5316\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5230\u5B98\u7F51\u5904\u7406';\n }\n return s || '\u64CD\u4F5C\u5931\u8D25';\n}\n\n/** \u63D0\u53D6\u6570\u7EC4\u5B57\u6BB5\uFF1A\u517C\u5BB9 data / data.data / data.items / data.data.items \u56DB\u79CD\u5F62\u6001 */\nfunction extractArray(json: any): any[] {\n if (!json) return [];\n if (Array.isArray(json)) return json;\n if (Array.isArray(json.data)) return json.data;\n if (json.data && Array.isArray(json.data.data)) return json.data.data;\n if (json.data && Array.isArray(json.data.items)) return json.data.items;\n if (json.data && json.data.data && Array.isArray(json.data.data.items)) return json.data.data.items;\n return [];\n}\n\n/** GET /api/marketplace/pins \u2014 \u5F53\u524D\u8D26\u53F7\u5168\u90E8\u56FA\u5B9A\u8BB0\u5F55\uFF08\u5361\u7247\u72B6\u6001\u8DDF\u968F\u5B98\u7F51\u7684\u771F\u76F8\u6E90\uFF09 */\nexport async function fetchMarketplacePins(\n userId?: string,\n accessToken?: string,\n): Promise<MarketplacePin[]> {\n if (!userId && !accessToken) return [];\n try {\n const res = await fetchWithNetRetry('https://a6api.com/api/marketplace/pins', {\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 8000,\n });\n if (!res.ok) {\n console.warn('[dsh-a6api] fetchMarketplacePins HTTP', res.status);\n return [];\n }\n const json: any = await res.json().catch(() => null);\n if (!json || json.success === false) return [];\n return extractArray(json)\n .filter((it: any) => it && it.model_name)\n .map((it: any) => ({\n id: it.id !== undefined ? Number(it.id) : undefined,\n token_id: Number(it.token_id || 0),\n token_name: it.token_name || undefined,\n model_name: String(it.model_name),\n channel_id: it.channel_id !== undefined && Number(it.channel_id) > 0 ? Number(it.channel_id) : undefined,\n channel_name: it.channel_name || undefined,\n supplier_name: it.supplier_name || undefined,\n supplier_nickname: it.supplier_nickname || undefined,\n fallback_to_smart_routing: it.fallback_to_smart_routing !== undefined ? Boolean(it.fallback_to_smart_routing) : undefined,\n created_at: it.created_at !== undefined ? Number(it.created_at) : undefined,\n // \u4E0D\u4E0B\u53D1 raw\uFF1A\u5BA2\u6237\u7AEF 60s \u8F6E\u8BE2\u7528 JSON \u5BF9\u6BD4\u5224\u65AD\u53D8\u5316\uFF0Craw \u542B\u6613\u53D8\u5B57\u6BB5\u4F1A\u5BFC\u81F4\u8BEF\u5224\u6574\u9875\u5237\u65B0\n }));\n } catch (err) {\n console.warn('[dsh-a6api] fetchMarketplacePins error:', err);\n return [];\n }\n}\n\n/** GET /api/token/?p=1&size=100 \u2014 \u4EE4\u724C\u5217\u8868\uFF08\u7528\u4E8E\u628A API Key \u89E3\u6790\u4E3A token_id\uFF09 */\nexport async function fetchTokens(\n userId?: string,\n accessToken?: string,\n): Promise<A6ApiTokenItem[]> {\n if (!userId && !accessToken) return [];\n try {\n const res = await fetchWithNetRetry('https://a6api.com/api/token/?p=1&size=100', {\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 8000,\n });\n if (!res.ok) return [];\n const json: any = await res.json().catch(() => null);\n if (!json || json.success === false) return [];\n return extractArray(json)\n .filter((it: any) => it && Number(it.id) > 0)\n .map((it: any) => ({\n id: Number(it.id),\n name: it.name || undefined,\n key: typeof it.key === 'string' ? it.key : undefined,\n status: it.status !== undefined ? Number(it.status) : undefined,\n raw: it,\n }));\n } catch (err) {\n console.warn('[dsh-a6api] fetchTokens error:', err);\n return [];\n }\n}\n\n/** \u53CB\u597D\u5316\u52A8\u4F5C\u7C7B\u63A5\u53E3\u9519\u8BEF\uFF08\u8D85\u65F6\u82F1\u6587\u539F\u6587\u8F6C\u4E2D\u6587\uFF0C\u4E0E probe.ts \u540C\u98CE\u683C\uFF09 */\nfunction friendlyActionError(err: any): string {\n const raw = err?.message || String(err);\n if (raw.includes('aborted due to timeout') || err?.name === 'TimeoutError') {\n return '\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5';\n }\n if (isFlakyNetworkError(err)) {\n return '\u4E0E\u4E0A\u6E38\u8FDE\u63A5\u4E0D\u7A33\u5B9A\uFF08\u5DF2\u81EA\u52A8\u91CD\u8BD5\u4ECD\u5931\u8D25\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5';\n }\n return raw;\n}\n\n/** POST /api/marketplace/pin \u2014 \u628A\u67D0\u6A21\u578B\u7684\u6D41\u91CF\u56FA\u5B9A\u5230\u6307\u5B9A\u6E20\u9053\uFF08\u7ED1\u5B9A\u4EE4\u724C\uFF09 */\nexport async function marketplacePin(\n userId: string | undefined,\n accessToken: string | undefined,\n payload: {\n token_id: number;\n channel_id: number;\n model_name: string;\n fallback_to_smart_routing: boolean;\n },\n): Promise<MarketplaceActionResult> {\n try {\n const res = await fetchWithNetRetry('https://a6api.com/api/marketplace/pin', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...buildWebHeaders(userId, accessToken),\n },\n body: JSON.stringify(payload),\n timeoutMs: 10000,\n });\n const json: any = await res.json().catch(() => null);\n const result = parseMarketplaceResult(json);\n if (!res.ok && !json) return { ok: false, message: `HTTP ${res.status}` };\n return result;\n } catch (err: any) {\n console.warn('[dsh-a6api] marketplacePin error:', err);\n return { ok: false, message: friendlyActionError(err) };\n }\n}\n\n/** POST /api/marketplace/unpin \u2014 \u53D6\u6D88\u67D0\u6A21\u578B\u7684\u56FA\u5B9A\n * \u4E0A\u6E38 pr195\uFF082026-09-08\uFF09\u8D77 payload \u5FC5\u987B\u643A\u5E26 channel_id\uFF0C\u7F3A\u5B57\u6BB5\u4E00\u5F8B 400 invalid_request */\nexport async function marketplaceUnpin(\n userId: string | undefined,\n accessToken: string | undefined,\n payload: { token_id: number; channel_id: number; model_name: string },\n): Promise<MarketplaceActionResult> {\n try {\n const res = await fetchWithNetRetry('https://a6api.com/api/marketplace/unpin', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...buildWebHeaders(userId, accessToken),\n },\n body: JSON.stringify(payload),\n timeoutMs: 10000,\n });\n const json: any = await res.json().catch(() => null);\n if (!res.ok && !json) return { ok: false, message: `HTTP ${res.status}` };\n return parseMarketplaceResult(json);\n } catch (err: any) {\n console.warn('[dsh-a6api] marketplaceUnpin error:', err);\n return { ok: false, message: friendlyActionError(err) };\n }\n}\n\n/** POST /api/marketplace/channels/:id/disable?model= \u2014 \u7981\u7528\u67D0\u6E20\u9053\u5BF9\u8BE5\u6A21\u578B\u7684\u670D\u52A1 */\nexport async function marketplaceDisableChannel(\n userId: string | undefined,\n accessToken: string | undefined,\n channelId: number,\n model: string,\n): Promise<MarketplaceActionResult> {\n try {\n const res = await fetchWithNetRetry(\n `https://a6api.com/api/marketplace/channels/${channelId}/disable?model=${encodeURIComponent(model)}`,\n {\n method: 'POST',\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 10000,\n },\n );\n const json: any = await res.json().catch(() => null);\n if (!res.ok && !json) return { ok: false, message: `HTTP ${res.status}` };\n return parseMarketplaceResult(json);\n } catch (err: any) {\n console.warn('[dsh-a6api] marketplaceDisableChannel error:', err);\n return { ok: false, message: friendlyActionError(err) };\n }\n}\n\n/** POST /api/marketplace/channels/:id/restore?model= \u2014 \u6062\u590D\u88AB\u7981\u7528\u7684\u6E20\u9053 */\nexport async function marketplaceRestoreChannel(\n userId: string | undefined,\n accessToken: string | undefined,\n channelId: number,\n model: string,\n): Promise<MarketplaceActionResult> {\n try {\n const res = await fetchWithNetRetry(\n `https://a6api.com/api/marketplace/channels/${channelId}/restore?model=${encodeURIComponent(model)}`,\n {\n method: 'POST',\n headers: buildWebHeaders(userId, accessToken),\n timeoutMs: 10000,\n },\n );\n const json: any = await res.json().catch(() => null);\n if (!res.ok && !json) return { ok: false, message: `HTTP ${res.status}` };\n return parseMarketplaceResult(json);\n } catch (err: any) {\n console.warn('[dsh-a6api] marketplaceRestoreChannel error:', err);\n return { ok: false, message: friendlyActionError(err) };\n }\n}\n", "import { cleanBaseUrl, fetchChannelDetails, fetchRecentLogs } from './a6api-client.js';\nimport { fetchWithNetRetry, isFlakyNetworkError } from './net.js';\nimport type { ApiRoutingLogItem, MerchantChannelInfo } from '../types.js';\n\nexport interface ProbeResult {\n modelName: string;\n success: boolean;\n channelId?: number;\n channelName?: string;\n /** \u8BE5\u6B21\u8BF7\u6C42\u5B9E\u9645\u4F7F\u7528\u7684\u4EE4\u724C ID\uFF08\u7528\u4E8E\u56FA\u5B9A/\u7981\u7528\u6309\u4EE4\u724C\u7ED1\u5B9A\uFF09 */\n tokenId?: number;\n merchant?: MerchantChannelInfo | null;\n error?: string;\n durationMs?: number;\n}\n\n/** Delay helper */\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Probe a single model by sending a 1-token prompt and querying logs */\nexport async function probeSingleModel(\n baseURL: string,\n apiKey: string,\n userId?: string,\n accessToken?: string,\n modelName?: string,\n): Promise<ProbeResult> {\n const targetModel = modelName || '';\n const cleanUrl = cleanBaseUrl(baseURL);\n if (!apiKey) {\n return { modelName: targetModel, success: false, error: '\u672A\u914D\u7F6E API Key' };\n }\n\n const startTime = Date.now();\n let requestOk = false;\n let requestError = '';\n\n try {\n const res = await fetchWithNetRetry(`${cleanUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey.trim()}`,\n },\n body: JSON.stringify({\n model: targetModel,\n messages: [{ role: 'user', content: '1' }],\n max_tokens: 1,\n }),\n // \u63A8\u7406\u6A21\u578B(\u5982 grok-4.6)\u5B9E\u6D4B\u5355\u6B21\u54CD\u5E94\u53EF\u8FBE 40-90s+,\u9608\u503C\u8FC7\u77ED\u4F1A\u88AB\u9891\u7E41\u6390\u65AD\u5BFC\u81F4\u63A2\u6D4B\u5931\u8D25\uFF1B\n // \u8D70 fetchWithNetRetry\uFF1A\u6BCF\u6B21\u5C1D\u8BD5\u72EC\u7ACB 180s \u7A97\u53E3\uFF0C\u4F20\u8F93\u5C42\u77AC\u65AD(ECONNRESET)\u81EA\u52A8\u91CD\u8BD5\u4E00\u6B21\n timeoutMs: 180000,\n });\n\n if (res.ok) {\n requestOk = true;\n } else {\n const errText = await res.text();\n requestError = `HTTP ${res.status}: ${errText.slice(0, 150)}`;\n }\n } catch (err: any) {\n const raw = err?.message || String(err);\n // \u8D85\u65F6\u9519\u8BEF\u82F1\u6587\u539F\u6587\u5BF9\u7528\u6237\u4E0D\u53CB\u597D,\u8F6C\u4E3A\u4E2D\u6587\u63D0\u793A\n if (raw.includes('aborted due to timeout') || err?.name === 'TimeoutError') {\n requestError = '\u63A2\u6D4B\u8D85\u65F6(\u9608\u503C180\u79D2) \u2014 \u63A8\u7406\u6A21\u578B\u54CD\u5E94\u8F83\u6162,\u5DF2\u4FDD\u7559\u4E0A\u6B21\u5546\u6237\u6570\u636E,\u8BF7\u7A0D\u540E\u91CD\u8BD5';\n } else if (isFlakyNetworkError(err)) {\n // \u5B9E\u6D4B\uFF1A\u4E0A\u6E38\u56DE\u6536\u7A7A\u95F2\u8FDE\u63A5\u540E\u9996\u53D1\u8BF7\u6C42\u7EA6 5s \u629B fetch failed(ECONNRESET)\uFF0C\u91CD\u8BD5\u5373\u6062\u590D\uFF1B\n // fetchWithNetRetry \u5DF2\u81EA\u52A8\u91CD\u8BD5\u4E00\u6B21\uFF0C\u8D70\u5230\u8FD9\u91CC\u8BF4\u660E\u91CD\u8BD5\u540E\u4ECD\u5931\u8D25\n requestError = '\u4E0E\u4E0A\u6E38\u8FDE\u63A5\u4E0D\u7A33\u5B9A(fetch failed\uFF0C\u5DF2\u81EA\u52A8\u91CD\u8BD5\u4ECD\u5931\u8D25)\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5';\n } else {\n requestError = raw;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // \u4EC5\u8BF7\u6C42\u6210\u529F\u540E\u67E5\u65E5\u5FD7,\u5931\u8D25\u65F6\u76F4\u63A5\u8FD4\u56DE\u9519\u8BEF(\u4E0D\u5728\u5361\u7247\u4E0A\u56DE\u9000\u5C55\u793A\u5386\u53F2\u5546\u6237)\n if (requestOk && (userId || accessToken)) {\n // Wait slightly for gateway log writing (\u6162\u6A21\u578B\u8BF7\u6C42\u671F\u95F4\u65E5\u5FD7\u5DF2\u843D\u76D8,\u5FEB\u6A21\u578B\u9700\u8981\u7B49\u5F85)\n await sleep(1200);\n try {\n const logs = await fetchRecentLogs(userId, accessToken, 15);\n const minTimestamp = Math.floor(startTime / 1000) - 10;\n // Find recent log entry for this model\n const log =\n logs.find(\n (it) =>\n it.model_name?.toLowerCase() === targetModel.toLowerCase() &&\n Number(it.created_at || 0) >= minTimestamp,\n ) || logs.find((it) => it.model_name?.toLowerCase() === targetModel.toLowerCase());\n\n if (log && log.channel) {\n const channelId = Number(log.channel);\n let logSnapshot: any = null;\n if (log.other) {\n try {\n logSnapshot = { ...JSON.parse(log.other), channel_name: log.channel_name, model_name: log.model_name };\n } catch {}\n }\n const merchant = await fetchChannelDetails(channelId, userId, accessToken, targetModel, logSnapshot);\n return {\n modelName: targetModel,\n success: true,\n channelId,\n channelName: log.channel_name,\n // \u8BE5\u6B21\u8BF7\u6C42\u7531 API Key \u53D1\u8D77\uFF0C\u65E5\u5FD7\u4E2D\u8BB0\u5F55\u7684 token_id \u5373\u8BE5 Key \u7684\u4EE4\u724C ID\n tokenId: log.token_id !== undefined && Number(log.token_id) > 0 ? Number(log.token_id) : undefined,\n merchant,\n durationMs,\n };\n }\n } catch (err: any) {\n console.warn(`[dsh-a6api] Log lookup error for ${targetModel}:`, err);\n }\n }\n\n return {\n modelName: targetModel,\n success: requestOk,\n durationMs,\n error: requestOk ? undefined : requestError,\n };\n}\n\n/** Pre-populate merchant cards from recent logs without triggering live probe */\nexport async function getKnownMerchantsFromLogs(\n userId?: string,\n accessToken?: string,\n modelNames: string[] = [],\n logs?: ApiRoutingLogItem[],\n): Promise<Record<string, MerchantChannelInfo>> {\n if ((!userId && !accessToken) || modelNames.length === 0) return {};\n\n const result: Record<string, MerchantChannelInfo> = {};\n try {\n const items = logs !== undefined ? logs : await fetchRecentLogs(userId, accessToken, 50);\n // \u9632\u5FA1\u6027\u6392\u5E8F\uFF1A\u4E0E /state \u7684 lastRoutedMap \u4FDD\u6301\u4E00\u81F4\n const sorted = items.slice().sort((a: any, b: any) => (Number(b.created_at) || 0) - (Number(a.created_at) || 0));\n const modelToLog = new Map<string, any>();\n\n for (const log of sorted) {\n const mName = log.model_name;\n const chId = Number(log.channel);\n if (mName && chId && !modelToLog.has(mName.toLowerCase())) {\n modelToLog.set(mName.toLowerCase(), log);\n }\n }\n\n const matchedEntries: { modelName: string; log: any }[] = [];\n for (const name of modelNames) {\n const log = modelToLog.get(name.toLowerCase());\n if (log) {\n matchedEntries.push({ modelName: name, log });\n }\n }\n\n // Fetch details with concurrency limit 4\n for (let i = 0; i < matchedEntries.length; i += 4) {\n const batch = matchedEntries.slice(i, i + 4);\n await Promise.all(\n batch.map(async ({ modelName, log }) => {\n try {\n const channelId = Number(log.channel);\n let logSnapshot: any = null;\n if (log.other) {\n try {\n logSnapshot = { ...JSON.parse(log.other), channel_name: log.channel_name, model_name: log.model_name };\n } catch {}\n }\n const card = await fetchChannelDetails(channelId, userId, accessToken, modelName, logSnapshot);\n if (card) {\n result[modelName] = card;\n }\n } catch {\n // ignore\n }\n }),\n );\n }\n } catch (err) {\n console.warn('[dsh-a6api] getKnownMerchantsFromLogs error:', err);\n }\n\n return result;\n}\n", "import * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as os from 'node:os';\nimport { getCatalogEntry } from './catalog.js';\nimport type { A6ApiConfig } from '../types.js';\n\n/**\n * DSH \u539F\u751F\u914D\u7F6E\u6574\u5408\uFF08\u6D88\u9664\u63D2\u4EF6\u72EC\u7ACB\u914D\u7F6E\u6587\u4EF6 dsh-a6api-config.json\uFF09\uFF1A\n * - \u51ED\u636E\uFF08API Key / \u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C / userId\uFF09\u2192 ~/.dsh/.credentials.yaml\uFF08refs\uFF0C0600\uFF09\n * - \u975E\u673A\u5BC6\u72B6\u6001\uFF08baseURL / \u6A21\u578B\u5217\u8868\uFF09\u2192 ~/.dsh/settings.yaml \u7684 llm-pi-ai.providers.a6api \u5757\n * - \u8BFB\u5199\u4F18\u5148\u8D70 DSH \u539F\u751F\u7F1D ctx.credentials / ctx.settings\uFF08env \u4F18\u5148\u8BED\u4E49\u3001\u4E32\u884C\u5199\u961F\u5217\u3001schema \u6821\u9A8C\u3001\n * \u70ED\u53D1\u5E03\uFF09\uFF1B\u539F\u751F\u670D\u52A1\u7F3A\u5931\u6216\u5199\u5165\u5931\u8D25\u65F6\u56DE\u9000\u5230\u76F4\u63A5\u8BFB\u5199\u4E24\u4E2A\u6587\u4EF6\uFF08\u683C\u5F0F\u4E0E DSH \u539F\u751F\u4E00\u81F4\uFF09\u3002\n * - \u65E7\u7248\u72EC\u7ACB\u914D\u7F6E\u6587\u4EF6\u5728\u542F\u52A8\u65F6\u81EA\u52A8\u8FC1\u79FB\uFF08\u53EA\u586B\u7A7A\u4E0D\u8986\u76D6\uFF09\u5E76\u5F52\u6863\u4E3A dsh-a6api-config.json.bak\u3002\n */\n\nexport const A6API_CRED_REF = 'A6API_API_KEY';\nexport const A6API_TOKEN_REF = 'A6API_ACCESS_TOKEN';\nexport const A6API_USER_REF = 'A6API_USER_ID';\n\nconst SETTINGS_NS = 'llm-pi-ai';\nconst PROVIDER_KEY = 'a6api';\nconst DEFAULT_BASE_URL = 'https://api.a6api.com';\nconst LEGACY_CONFIG_NAME = 'dsh-a6api-config.json';\n\n/** \u539F\u5B50\u5199\u5165\uFF1A\u5148\u5199\u4E34\u65F6\u6587\u4EF6\uFF080600/0644\uFF09\u518D rename\uFF0C\u907F\u514D\u5D29\u6E83\u622A\u65AD\u4E0E\u6743\u9650\u4F4D\u6CC4\u9732 */\nasync function atomicWriteFile(filePath: string, content: string, mode = 0o600): Promise<void> {\n const dir = path.dirname(filePath);\n await fsp.mkdir(dir, { recursive: true });\n const tmpPath = path.join(dir, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);\n await fsp.writeFile(tmpPath, content, { mode });\n await fsp.rename(tmpPath, filePath);\n}\n\nfunction dshHome(): string {\n return process.env.DSH_HOME || path.join(os.homedir(), '.dsh');\n}\n\nfunction legacyConfigFile(): string {\n return path.join(dshHome(), LEGACY_CONFIG_NAME);\n}\n\nfunction credentialsFile(): string {\n return path.join(dshHome(), '.credentials.yaml');\n}\n\nfunction settingsFile(): string {\n return path.join(dshHome(), 'settings.yaml');\n}\n\n/** \u53EF\u9009\u5730\u53D6 DSH \u539F\u751F\u670D\u52A1\uFF1B\u7F3A\u5931\u65F6\u8FD4\u56DE undefined\uFF08\u8C03\u7528\u65B9\u56DE\u9000\u5230\u6587\u4EF6\u76F4\u8BFB\u5199\uFF09 */\nfunction getCredentials(ctx: any) {\n try {\n if (ctx && typeof ctx.get === 'function') return ctx.get('credentials');\n } catch {}\n return undefined;\n}\n\nfunction getSettings(ctx: any) {\n try {\n if (ctx && typeof ctx.get === 'function') return ctx.get('settings');\n } catch {}\n return undefined;\n}\n\n/** \u53BB\u6389 OpenAI \u517C\u5BB9\u7AEF\u70B9\u7684 /v1 \u540E\u7F00\uFF0C\u8FD8\u539F\u63D2\u4EF6 API \u8C03\u7528\u6240\u7528\u7684\u88F8\u5730\u5740 */\nfunction stripV1(baseURL: string): string {\n return baseURL.replace(/\\/v1\\/?$/, '');\n}\n\n// ===== .credentials.yaml \u624B\u5199\u8BFB\u5199\uFF08\u539F\u751F\u7F1D\u7F3A\u5931\u65F6\u7684\u515C\u5E95\uFF0C\u683C\u5F0F\u4E0E DSH \u4E00\u81F4\uFF1Aversion:1 + refs\uFF09 =====\n\n/** Read a key from .credentials.yaml */\nexport async function readCredentialKey(refKey: string): Promise<string | null> {\n try {\n const yaml = await fsp.readFile(credentialsFile(), 'utf8');\n let inRefs = false;\n for (const line of yaml.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n if (indent === 0) {\n inRefs = trimmed.startsWith('refs:');\n continue;\n }\n if (!inRefs) continue;\n const m = /^([A-Za-z0-9_.\\-]+):\\s*(.*)$/.exec(trimmed);\n if (m && m[1] === refKey) {\n let val = m[2].trim();\n if ((val.startsWith('\"') && val.endsWith('\"')) || (val.startsWith(\"'\") && val.endsWith(\"'\"))) {\n val = val.slice(1, -1);\n }\n return val || null;\n }\n }\n } catch {}\n return null;\n}\n\n/**\n * Write/update a key in .credentials.yaml\u3002\n * DSH credentials-local \u5BF9\u7A7A ref \u503C\u6574\u4F53\u62D2\u6536\u6587\u6863\uFF08parseRefs \u629B\u9519\uFF09\uFF0C\u56E0\u6B64\n * \u7A7A\u4E32/undefined = \u5220\u9664\u8BE5\u952E\u884C\uFF08\u4E0E\u539F\u751F unset \u8BED\u4E49\u4E00\u81F4\uFF09\uFF0C\u7EDD\u4E0D\u5199\u5165\u7A7A\u503C\u3002\n */\nexport async function writeCredentialKey(refKey: string, value: string): Promise<void> {\n const cFile = credentialsFile();\n let yaml = '';\n try {\n yaml = await fsp.readFile(cFile, 'utf8');\n } catch {\n yaml = 'version: 1\\nrefs:\\n';\n }\n\n const lines = yaml.split(/\\r?\\n/);\n let inRefs = false;\n let refsLineIdx = -1;\n let foundIdx = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n if (indent === 0) {\n if (trimmed.startsWith('refs:')) {\n inRefs = true;\n refsLineIdx = i;\n } else {\n inRefs = false;\n }\n continue;\n }\n if (inRefs) {\n const m = /^([A-Za-z0-9_.\\-]+):/.exec(trimmed);\n if (m && m[1] === refKey) {\n foundIdx = i;\n break;\n }\n }\n }\n\n if (value === '') {\n // \u5220\u9664\u8BED\u4E49\uFF1A\u79FB\u9664\u8BE5\u952E\u884C\uFF08refs \u4E0B\u65E0\u5176\u4ED6\u952E\u65F6\u4FDD\u7559\u7A7A\u7684 refs: \u9AA8\u67B6\uFF0C\u662F\u5408\u6CD5\u7A7A\u5B58\u50A8\uFF09\n if (foundIdx >= 0) lines.splice(foundIdx, 1);\n } else {\n if (foundIdx >= 0) {\n lines[foundIdx] = ` ${refKey}: ${JSON.stringify(value)}`;\n } else {\n if (refsLineIdx >= 0) {\n lines.splice(refsLineIdx + 1, 0, ` ${refKey}: ${JSON.stringify(value)}`);\n } else {\n lines.push('refs:', ` ${refKey}: ${JSON.stringify(value)}`);\n }\n }\n }\n\n await atomicWriteFile(cFile, lines.join('\\n'), 0o600);\n}\n\n// ===== settings.yaml \u624B\u5199\u8BFB\u5199\uFF08\u539F\u751F\u7F1D\u7F3A\u5931/\u5199\u5165\u5931\u8D25\u65F6\u7684\u515C\u5E95\uFF09 =====\n\n/** \u89E3\u6790 settings.yaml \u4E2D llm-pi-ai.providers.a6api \u5757\u7684\u6A21\u578B ID \u5217\u8868 */\nasync function readRawConfiguredModels(): Promise<string[]> {\n try {\n const yaml = await fsp.readFile(settingsFile(), 'utf8');\n const lines = yaml.split(/\\r?\\n/);\n let inA6 = false;\n let inModels = false;\n const modelIds: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n if (indent === 4 && trimmed.startsWith('a6api:')) {\n inA6 = true;\n inModels = false;\n continue;\n }\n if (inA6 && indent <= 4 && !trimmed.startsWith('a6api:')) {\n inA6 = false;\n inModels = false;\n }\n if (inA6 && indent === 6 && trimmed.startsWith('models:')) {\n inModels = true;\n continue;\n }\n if (inModels && indent === 8 && trimmed.startsWith('- id:')) {\n const id = trimmed.replace(/^- id:\\s*/, '').trim();\n if (id) modelIds.push(id);\n }\n }\n return modelIds;\n } catch {\n return [];\n }\n}\n\n/** \u89E3\u6790 settings.yaml \u4E2D a6api \u5757\u7684 baseURL\uFF08\u542B /v1 \u540E\u7F00\uFF09 */\nasync function readRawA6apiBaseURL(): Promise<string> {\n try {\n const yaml = await fsp.readFile(settingsFile(), 'utf8');\n let inA6 = false;\n for (const line of yaml.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n if (indent === 4 && trimmed.startsWith('a6api:')) {\n inA6 = true;\n continue;\n }\n if (inA6 && indent <= 4 && !trimmed.startsWith('a6api:')) inA6 = false;\n if (inA6 && indent === 6 && trimmed.startsWith('baseURL:')) {\n return trimmed.replace(/^baseURL:\\s*/, '').trim().replace(/^[\"']|[\"']$/g, '');\n }\n }\n } catch {}\n return '';\n}\n\n/** \u5B9A\u4F4D settings.yaml \u4E2D `llm-pi-ai:` -> `providers:` -> `a6api:` \u7684\u884C\u533A\u95F4\uFF08\u4F9B\u5199\u5165/\u79FB\u9664\u5171\u7528\uFF09 */\nfunction scanA6apiBlockRange(lines: string[]): {\n a6Start: number;\n a6End: number;\n providersLineIdx: number;\n llmLineIdx: number;\n} {\n let inLlm = false;\n let inProviders = false;\n let inA6 = false;\n let a6Start = -1;\n let a6End = -1;\n let providersLineIdx = -1;\n let llmLineIdx = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n\n if (indent === 0) {\n inLlm = trimmed.startsWith('llm-pi-ai:');\n if (inLlm) llmLineIdx = i;\n inProviders = false;\n inA6 = false;\n continue;\n }\n\n if (inLlm && indent === 2 && trimmed.startsWith('providers:')) {\n inProviders = true;\n providersLineIdx = i;\n inA6 = false;\n continue;\n }\n\n if (inProviders && indent === 4) {\n if (trimmed.startsWith('a6api:')) {\n inA6 = true;\n a6Start = i;\n a6End = i + 1;\n } else {\n if (inA6) {\n a6End = i;\n inA6 = false;\n }\n }\n continue;\n }\n\n if (inA6 && indent > 4) {\n a6End = i + 1;\n } else if (inA6 && indent <= 4) {\n a6End = i;\n inA6 = false;\n }\n }\n\n return { a6Start, a6End, providersLineIdx, llmLineIdx };\n}\n\n/** \u88F8\u5199 a6api \u63D0\u4F9B\u5546\u5757\u5230 settings.yaml\uFF08\u539F\u751F\u7F1D\u5199\u5165\u5931\u8D25\u65F6\u7684\u515C\u5E95\uFF0C\u683C\u5F0F\u4E0E DSH \u539F\u751F\u4E00\u81F4\uFF09\u3002\n * \u6CE8\u610F\uFF1A\u4EC5\u4EE5\u975E\u7A7A\u6A21\u578B\u5217\u8868\u8C03\u7528\uFF08\u7A7A\u5217\u8868\u8D70\u79FB\u9664\u8DEF\u5F84\uFF09\uFF1B\u6574\u5757\u66FF\u6362\u4F1A\u4E22\u5F03\u7528\u6237\u5728\u5757\u5185\u624B\u5DE5\u6DFB\u52A0\u7684\n * \u5176\u4ED6\u5B57\u6BB5\uFF08\u5982 compat\uFF09\uFF0C\u4E0E\u539F\u751F update \u7684 merge \u8BED\u4E49\u6709\u5DEE\u5F02\uFF0C\u5C5E\u515C\u5E95\u8DEF\u5F84\u7684\u5DF2\u77E5\u53D6\u820D\u3002 */\nasync function writeRawA6apiBlock(baseURL: string, modelIds: string[]): Promise<void> {\n const sFile = settingsFile();\n let yaml = '';\n try {\n yaml = await fsp.readFile(sFile, 'utf8');\n } catch {\n yaml = 'llm-pi-ai:\\n providers:\\n';\n }\n\n const modelEntries = modelIds.map((id) => {\n // \u53C2\u6570\u4EE5\u76EE\u5F55\u4E3A\u51C6\uFF1A\u6709\u5219\u5199\u5165\uFF0C\u7F3A\u5219\u7701\u7565\uFF08llm-pi-ai \u7528\u9ED8\u8BA4\u503C\u515C\u5E95\uFF09\uFF0C\u7EDD\u4E0D\u5199\u63A8\u65AD\u503C\n const entry = getCatalogEntry(id);\n const lines = [` - id: ${id}`];\n // name \u7528 JSON \u53CC\u5F15\u53F7\u5E8F\u5217\u5316\uFF08\u9632 YAML \u6CE8\u5165\uFF1A\u5192\u53F7/#/\u6362\u884C\uFF09\uFF0C\u5E76\u53BB\u9664\u6362\u884C\n if (entry?.name) lines.push(` name: ${JSON.stringify(String(entry.name).replace(/\\r?\\n/g, ' '))}`);\n if (entry?.contextWindow != null) lines.push(` contextWindow: ${entry.contextWindow}`);\n if (entry?.maxTokens != null) lines.push(` maxTokens: ${entry.maxTokens}`);\n if (entry?.input && entry.input.length > 0) {\n lines.push(` input:`);\n for (const m of entry.input) lines.push(` - ${m}`);\n }\n if (entry?.reasoningEfforts && typeof entry.reasoningEfforts === 'object') {\n lines.push(` reasoningEfforts:`);\n for (const [k, v] of Object.entries(entry.reasoningEfforts)) {\n // null \u503C\u8F93\u51FA valueless \u952E\uFF08\u5982 `off: `\uFF0CDSH \u89E3\u6790\u4E3A supported-send-nothing\uFF0C\u4E0E native \u8DEF\u5F84\u8BED\u4E49\u4E00\u81F4\uFF09\n lines.push(v ? ` ${k}: ${v}` : ` ${k}: `);\n }\n }\n return lines.join('\\n');\n });\n\n // Ensure OpenAI compatible endpoints in DSH settings.yaml have the /v1 suffix\n const dshBaseUrl = baseURL.endsWith('/v1') ? baseURL : `${baseURL.replace(/\\/+$/, '')}/v1`;\n\n const a6apiBlockLines = [\n ` a6api:`,\n ` displayName: A6API`,\n ` apiKeyEnv: ${A6API_CRED_REF}`,\n ` api: openai-completions`,\n ` baseURL: ${dshBaseUrl}`,\n ` models:`,\n ...modelEntries,\n ];\n\n const lines = yaml.split(/\\r?\\n/);\n const { a6Start, a6End, providersLineIdx, llmLineIdx } = scanA6apiBlockRange(lines);\n\n if (a6Start >= 0) {\n // Replace existing a6api block\n lines.splice(a6Start, a6End - a6Start, ...a6apiBlockLines);\n } else if (providersLineIdx >= 0) {\n // Insert under providers:\n lines.splice(providersLineIdx + 1, 0, ...a6apiBlockLines);\n } else if (llmLineIdx >= 0) {\n // Insert providers: then a6api\n lines.splice(llmLineIdx + 1, 0, ` providers:`, ...a6apiBlockLines);\n } else {\n // Insert llm-pi-ai: providers: a6api\n lines.push(`llm-pi-ai:`, ` providers:`, ...a6apiBlockLines);\n }\n\n await atomicWriteFile(sFile, lines.join('\\n'), 0o644);\n}\n\n/**\n * \u88F8\u5199\u79FB\u9664 a6api \u5757\uFF08\u539F\u751F\u7F1D\u7F3A\u5931/\u5931\u8D25\u65F6\u7684\u515C\u5E95\uFF09\u3002\n * DSH schema \u5BF9\u624B\u5199\u8DEF\u7531\u65E0\u5408\u6CD5\u7684\u96F6\u6A21\u578B\u8868\u793A\uFF0C\u7A7A\u6A21\u578B\u5217\u8868 = \u79FB\u9664\u6574\u4E2A\u5757\uFF1B\n * \u5757\u79FB\u9664\u540E\u987A\u5E26\u6E05\u7406\u7A7A\u58F3\uFF08providers/llm-pi-ai \u4E0B\u65E0\u5176\u4ED6\u952E\u65F6\u4E00\u5E76\u5220\u9664\uFF09\uFF0C\u4FDD\u6301 YAML \u5408\u6CD5\u3002\n */\nasync function removeRawA6apiBlock(): Promise<void> {\n const sFile = settingsFile();\n let yaml = '';\n try {\n yaml = await fsp.readFile(sFile, 'utf8');\n } catch {\n return; // \u65E0\u6587\u4EF6\u6216\u4E0D\u53EF\u8BFB\uFF0C\u65E0\u4E8B\u53EF\u505A\n }\n\n const lines = yaml.split(/\\r?\\n/);\n const { a6Start, a6End, providersLineIdx, llmLineIdx } = scanA6apiBlockRange(lines);\n if (a6Start < 0) return;\n\n lines.splice(a6Start, a6End - a6Start);\n\n // \u6E05\u7406\u7A7A\u58F3\uFF1Aproviders \u4E0B\u65E0\u5176\u4ED6 indent-4 provider \u952E \u2192 \u79FB\u9664 providers \u884C\uFF1Bllm-pi-ai \u4E0B\u65E0\u5176\u4ED6 indent-2 \u952E \u2192 \u79FB\u9664 llm-pi-ai \u884C\n if (providersLineIdx >= 0) {\n let hasProvider = false;\n for (let i = providersLineIdx + 1; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = lines[i].match(/^\\s*/)?.[0].length ?? 0;\n if (indent <= 2) break;\n if (indent === 4) {\n hasProvider = true;\n break;\n }\n }\n if (!hasProvider) lines.splice(providersLineIdx, 1);\n }\n if (llmLineIdx >= 0) {\n let hasLlmKey = false;\n for (let i = llmLineIdx + 1; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const indent = lines[i].match(/^\\s*/)?.[0].length ?? 0;\n if (indent === 0) break;\n if (indent === 2) {\n hasLlmKey = true;\n break;\n }\n }\n if (!hasLlmKey) lines.splice(llmLineIdx, 1);\n }\n\n await atomicWriteFile(sFile, lines.join('\\n'), 0o644);\n}\n\n// ===== \u65E7\u7248\u72EC\u7ACB\u914D\u7F6E\u6587\u4EF6\uFF08dsh-a6api-config.json\uFF09\u8BFB\u53D6\u4E0E\u89C4\u8303\u5316 =====\n\n/** \u65E7\u5B57\u6BB5\u522B\u540D\u6536\u655B\uFF1AaccessToken / systemAccessToken / sessionCookie \u662F\u540C\u4E00\u4E2A\u51ED\u636E\u7684\u5386\u4EE3\u547D\u540D */\nfunction normalizeLegacy(parsed: any): {\n baseURL: string;\n apiKey: string;\n accessToken: string;\n userId: string;\n activeModels: string[];\n} {\n return {\n apiKey: typeof parsed?.apiKey === 'string' ? parsed.apiKey : '',\n accessToken: String(parsed?.accessToken || parsed?.systemAccessToken || parsed?.sessionCookie || ''),\n userId: String(parsed?.userId || ''),\n baseURL: typeof parsed?.baseURL === 'string' && parsed.baseURL ? parsed.baseURL : DEFAULT_BASE_URL,\n activeModels: Array.isArray(parsed?.activeModels) ? parsed.activeModels.filter((m: any) => typeof m === 'string') : [],\n };\n}\n\n/** \u65E7\u6587\u4EF6\u8BFB\u53D6\uFF08\u8FC1\u79FB\u672A\u5B8C\u6210/\u5931\u8D25\u65F6\u7684\u672B\u7EA7\u515C\u5E95\uFF1B\u522B\u540D\u53EA\u5728\u8BFB\u53D6\u94FE\u4E0A\u5B58\u5728\uFF09 */\nasync function readLegacyConfig(): Promise<A6ApiConfig | null> {\n try {\n const raw = await fsp.readFile(legacyConfigFile(), 'utf8');\n const legacy = normalizeLegacy(JSON.parse(raw));\n return {\n baseURL: legacy.baseURL,\n apiKey: legacy.apiKey,\n accessToken: legacy.accessToken || undefined,\n userId: legacy.userId || undefined,\n activeModels: legacy.activeModels,\n };\n } catch {\n return null;\n }\n}\n\n/** \u6784\u5EFA llm-pi-ai.providers.a6api \u5757\uFF08\u4E0E DSH \u539F\u751F schema \u517C\u5BB9\uFF1Aopenai-completions + /v1 \u7AEF\u70B9\uFF09\u3002\n * \u53C2\u6570\u6765\u81EA\u6A21\u578B\u76EE\u5F55\uFF08getCatalogEntry\uFF09\uFF1A\u6709\u5219\u5199\u5165\uFF0C\u7F3A\u5219\u7701\u7565\u8BE5\u5B57\u6BB5\uFF08llm-pi-ai \u9ED8\u8BA4\u503C\u515C\u5E95\uFF09\u3002 */\nfunction buildA6apiBlock(baseURL: string, modelIds: string[]): Record<string, any> {\n const models = modelIds.map((id) => {\n const entry = getCatalogEntry(id);\n const m: Record<string, any> = { id };\n if (entry?.name) m.name = entry.name;\n if (entry?.contextWindow != null) m.contextWindow = entry.contextWindow;\n if (entry?.maxTokens != null) m.maxTokens = entry.maxTokens;\n if (entry?.input && entry.input.length > 0) m.input = [...entry.input];\n if (entry?.reasoningEfforts !== undefined && entry.reasoningEfforts !== null) {\n m.reasoningEfforts = entry.reasoningEfforts;\n }\n return m;\n });\n return {\n displayName: 'A6API',\n apiKeyEnv: A6API_CRED_REF,\n api: 'openai-completions',\n baseURL: baseURL.endsWith('/v1') ? baseURL : `${baseURL.replace(/\\/+$/, '')}/v1`,\n models,\n };\n}\n\nexport interface ConfigAccess {\n /** \u89E6\u53D1\uFF08\u5E76\u7B49\u5F85\uFF09\u65E7\u914D\u7F6E\u6587\u4EF6\u7684\u81EA\u52A8\u8FC1\u79FB\uFF1B\u5E42\u7B49\uFF0C\u8FDB\u7A0B\u5185\u53EA\u6267\u884C\u4E00\u6B21\uFF0C\u5931\u8D25\u4E0D\u963B\u585E */\n ensureMigrated(): Promise<void>;\n /** \u8BFB\u53D6\u5F53\u524D\u914D\u7F6E\uFF1A\u539F\u751F\u7F1D\u4F18\u5148\uFF0C\u9010\u7EA7\u515C\u5E95\u5230\u65E7\u6587\u4EF6 */\n readConfig(): Promise<A6ApiConfig>;\n /** \u5199\u5165\u51ED\u636E\u5B57\u6BB5\uFF08\u7A7A\u4E32 = \u6E05\u9664\uFF0C\u8D70 unset\uFF09\uFF1Bsettings \u540C\u6B65\u8BF7\u7528 syncModels */\n writeConfig(parts: Partial<Pick<A6ApiConfig, 'apiKey' | 'accessToken' | 'userId'>>): Promise<void>;\n /** \u628A\u6A21\u578B\u5217\u8868\uFF08\u4E0E baseURL\uFF09\u540C\u6B65\u8FDB DSH settings.yaml \u7684 llm-pi-ai.providers.a6api \u5757 */\n syncModels(baseURL: string, modelIds: string[]): Promise<void>;\n /** \u5F53\u524D DSH \u5DF2\u914D\u7F6E\u7684 a6api \u6A21\u578B ID \u5217\u8868 */\n getDshConfiguredModels(): Promise<string[]>;\n}\n\nexport function createConfigAccess(ctx: any): ConfigAccess {\n let migration: Promise<void> | null = null;\n\n const ensureMigrated = (): Promise<void> => {\n if (!migration) {\n migration = doMigrate().catch((err: any) => {\n // \u8FC1\u79FB\u5931\u8D25\u4E0D\u963B\u585E\uFF1A\u4FDD\u7559\u65E7\u6587\u4EF6\uFF0CreadConfig \u7684\u672B\u7EA7\u515C\u5E95\u7EE7\u7EED\u5DE5\u4F5C\uFF0C\u4E0B\u6B21\u542F\u52A8\u91CD\u8BD5\n console.warn('[dsh-a6api] \u65E7\u914D\u7F6E\u8FC1\u79FB\u5931\u8D25\uFF08\u4FDD\u7559\u65E7\u6587\u4EF6\u8BFB\u53D6\u515C\u5E95\uFF09:', err?.message || err);\n });\n }\n return migration;\n };\n\n /** \u8BFB\u4E00\u4E2A\u51ED\u636E ref\uFF1A\u539F\u751F resolve\uFF08env \u4F18\u5148\uFF09\u2192 \u6587\u4EF6\u76F4\u8BFB\u515C\u5E95 */\n const resolveRef = async (creds: any, ref: string): Promise<string> => {\n try {\n if (creds && typeof creds.resolve === 'function') {\n const r = await creds.resolve(ref);\n return r && typeof r.value === 'string' ? r.value : '';\n }\n } catch (err: any) {\n console.warn(`[dsh-a6api] credentials.resolve(${ref}) failed:`, err?.message || err);\n }\n return (await readCredentialKey(ref)) || '';\n };\n\n /** \u8BFB llm-pi-ai.providers.a6api \u5757\uFF1A\u539F\u751F settings.get \u4F18\u5148 */\n const readA6apiBlock = async (\n settings: any,\n ): Promise<{ baseURL?: string; models: string[] } | null> => {\n try {\n if (settings && typeof settings.get === 'function') {\n const llm = settings.get(SETTINGS_NS);\n const block = llm && llm.providers ? llm.providers[PROVIDER_KEY] : undefined;\n if (block && typeof block === 'object') {\n return {\n baseURL: typeof block.baseURL === 'string' ? block.baseURL : undefined,\n models: Array.isArray(block.models)\n ? block.models\n .map((m: any) => (typeof m === 'string' ? m : m && typeof m.id === 'string' ? m.id : ''))\n .filter(Boolean)\n : [],\n };\n }\n }\n } catch (err: any) {\n console.warn('[dsh-a6api] settings.get(llm-pi-ai) failed:', err?.message || err);\n }\n return null;\n };\n\n const readConfig = async (): Promise<A6ApiConfig> => {\n await ensureMigrated();\n const creds = getCredentials(ctx);\n const settings = getSettings(ctx);\n\n // \u51ED\u636E\uFF1A\u539F\u751F resolve\uFF08env \u4F18\u5148\uFF09\u2192 \u6587\u4EF6\u76F4\u8BFB\u515C\u5E95\n const apiKey = await resolveRef(creds, A6API_CRED_REF);\n const accessToken = await resolveRef(creds, A6API_TOKEN_REF);\n const userId = await resolveRef(creds, A6API_USER_REF);\n\n // \u975E\u673A\u5BC6\u72B6\u6001\uFF1Allm-pi-ai.providers.a6api \u5757\uFF08\u539F\u751F\u89E3\u6790\u4F18\u5148\uFF0C\u88F8\u8BFB\u515C\u5E95\uFF09\n let baseURL = DEFAULT_BASE_URL;\n let activeModels: string[] = [];\n const block = await readA6apiBlock(settings);\n if (block) {\n if (block.baseURL) baseURL = stripV1(block.baseURL) || DEFAULT_BASE_URL;\n activeModels = block.models;\n } else {\n const rawBase = await readRawA6apiBaseURL();\n if (rawBase) baseURL = stripV1(rawBase) || DEFAULT_BASE_URL;\n activeModels = await readRawConfiguredModels();\n }\n\n // \u672B\u7EA7\u515C\u5E95\uFF1A\u539F\u751F\u51ED\u636E\u4E3A\u7A7A\u4E14\u65E7\u6587\u4EF6\u4ECD\u5728\uFF08\u8FC1\u79FB\u672A\u5B8C\u6210\u6216\u5931\u8D25\uFF09\u2192 \u65E7\u6587\u4EF6\u53EA\u586B\u7A7A\u5B57\u6BB5\uFF0C\n // \u975E\u673A\u5BC6\u72B6\u6001\u59CB\u7EC8\u4EE5\u539F\u751F settings \u4E3A\u51C6\uFF08\u907F\u514D\u65E7\u503C\u906E\u853D\u7528\u6237\u8FC1\u79FB\u5931\u8D25\u540E\u65B0\u6539\u7684\u8282\u70B9/\u6A21\u578B\uFF09\n if (!apiKey && !accessToken && fs.existsSync(legacyConfigFile())) {\n const legacy = await readLegacyConfig();\n if (legacy) {\n return {\n baseURL: baseURL || legacy.baseURL,\n apiKey: apiKey || legacy.apiKey,\n accessToken: accessToken || legacy.accessToken,\n userId: userId || legacy.userId,\n activeModels: activeModels.length > 0 ? activeModels : legacy.activeModels,\n };\n }\n }\n\n return { baseURL, apiKey, accessToken, userId, activeModels };\n };\n\n const writeConfig = async (\n parts: Partial<Pick<A6ApiConfig, 'apiKey' | 'accessToken' | 'userId'>>,\n ): Promise<void> => {\n // \u5148\u7B49\u8FC1\u79FB\u5B8C\u6210\uFF0C\u907F\u514D fillRef \u7684\u300C\u8BFB\u2192\u5199\u300D\u4E24\u6B65\u628A\u8FC1\u79FB\u503C\u8986\u76D6\u7528\u6237\u521A\u5199\u5165\u7684\u65B0\u503C\n await ensureMigrated();\n const creds = getCredentials(ctx);\n const entries: Array<[string, string | undefined]> = [\n [A6API_CRED_REF, parts.apiKey],\n [A6API_TOKEN_REF, parts.accessToken],\n [A6API_USER_REF, parts.userId],\n ];\n for (const [ref, value] of entries) {\n if (value === undefined) continue;\n const v = value.trim();\n try {\n if (creds && typeof creds.set === 'function' && typeof creds.unset === 'function') {\n if (v) await creds.set(ref, v);\n else await creds.unset(ref);\n } else {\n // \u515C\u5E95\u8DEF\u5F84\uFF1AwriteCredentialKey \u5BF9\u7A7A\u4E32\u6267\u884C\u5220\u9664\uFF08DSH credentials-local \u62D2\u6536\u7A7A ref \u503C\uFF09\n await writeCredentialKey(ref, v);\n }\n } catch (err: any) {\n // env \u906E\u853D\uFF08assertUnshadowed\uFF09\u7B49\u573A\u666F\uFF1A\u8DF3\u8FC7\u5199\u5165\uFF0Cenv \u503C\u4F18\u5148\u7B26\u5408 DSH \u539F\u751F\u8BED\u4E49\n console.warn(`[dsh-a6api] \u5199\u5165\u51ED\u636E ${ref} \u5931\u8D25\uFF08\u5DF2\u8DF3\u8FC7\uFF09:`, err?.message || err);\n }\n }\n };\n\n const syncModels = async (baseURL: string, modelIds: string[]): Promise<void> => {\n const settings = getSettings(ctx);\n if (modelIds.length === 0) {\n // DSH \u786C\u7EA6\u675F\uFF1Allm-pi-ai \u5BF9\u624B\u5199\u8DEF\u7531\uFF08a6api \u4E0D\u5728\u5185\u7F6E catalog\uFF09\u4E0D\u5B58\u5728\u5408\u6CD5\u7684\u300C\u96F6\u6A21\u578B\u300D\u8868\u793A\uFF0C\n // assertServiceable \u4F1A\u62D2\u7EDD models: []\uFF08\"resolves no models...\"\uFF09\uFF0C\u5199\u76D8\u5C06\u6BD2\u5316\u4E0B\u6B21\u542F\u52A8\u3002\n // \u7A7A\u5217\u8868 = \u79FB\u9664\u6574\u4E2A a6api \u5757\uFF08\u8DEF\u7531\u4ECE DSH \u6D88\u5931\uFF1BbaseURL \u968F\u5757\u4E00\u5E76\u79FB\u9664\uFF0C\u5C5E schema \u7EA6\u675F\u4E0B\u7684\u5FC5\u7136\uFF09\u3002\n if (settings && typeof settings.mutate === 'function') {\n try {\n await settings.mutate(SETTINGS_NS, [{ op: 'unset', path: ['providers', PROVIDER_KEY] }]);\n return;\n } catch (err: any) {\n console.warn('[dsh-a6api] settings.mutate(llm-pi-ai) \u79FB\u9664 a6api \u5757\u5931\u8D25\uFF0C\u56DE\u9000\u88F8\u5199 settings.yaml:', err?.message || err);\n }\n }\n await removeRawA6apiBlock();\n return;\n }\n\n const block = buildA6apiBlock(baseURL, modelIds);\n if (settings && typeof settings.update === 'function') {\n try {\n // \u539F\u751F\u7F1D\uFF1A\u547D\u540D\u7A7A\u95F4\u4E32\u884C\u5199\u961F\u5217 + schema \u6821\u9A8C + \u70ED\u53D1\u5E03\uFF08\u5408\u5E76\u8BED\u4E49\uFF0C\u4E0D\u5F71\u54CD\u5176\u4ED6 provider\uFF09\n await settings.update(SETTINGS_NS, { providers: { [PROVIDER_KEY]: block } });\n return;\n } catch (err: any) {\n console.warn('[dsh-a6api] settings.update(llm-pi-ai) \u5931\u8D25\uFF0C\u56DE\u9000\u88F8\u5199 settings.yaml:', err?.message || err);\n }\n }\n await writeRawA6apiBlock(baseURL, modelIds);\n };\n\n const getDshConfiguredModels = async (): Promise<string[]> => {\n const block = await readA6apiBlock(getSettings(ctx));\n if (block) return block.models;\n return readRawConfiguredModels();\n };\n\n /** \u53EA\u586B\u7A7A\uFF1A\u8FC1\u79FB\u503C\u4EC5\u5728\u5F53\u524D\u65E0\u8BE5 ref\uFF08\u542B env \u8986\u76D6\uFF09\u65F6\u5199\u5165\uFF1B\u8FD4\u56DE false = \u5199\u5165\u5931\u8D25\uFF08\u9700\u4FDD\u7559\u65E7\u6587\u4EF6\uFF09 */\n const fillRef = async (creds: any, ref: string, value: string): Promise<boolean> => {\n if (!value) return true; // \u65E0\u503C\u53EF\u8FC1 = \u65E0\u9700\u5199 = \u89C6\u4E3A\u6210\u529F\n try {\n const current = await resolveRef(creds, ref);\n if (current) return true; // \u5DF2\u6709\u503C\uFF08\u542B env \u8986\u76D6\uFF09\uFF0C\u65E0\u9700\u5199\n if (creds && typeof creds.set === 'function') await creds.set(ref, value);\n else await writeCredentialKey(ref, value);\n return true;\n } catch (err: any) {\n console.warn(`[dsh-a6api] \u8FC1\u79FB ${ref} \u5931\u8D25\uFF08\u8DF3\u8FC7\uFF0C\u4FDD\u7559\u65E7\u6587\u4EF6\uFF09:`, err?.message || err);\n return false;\n }\n };\n\n const archiveLegacy = async (filePath: string): Promise<void> => {\n try {\n await fsp.rename(filePath, `${filePath}.bak`);\n console.log('[dsh-a6api] \u65E7\u914D\u7F6E\u5DF2\u8FC1\u79FB\u81F3 DSH \u539F\u751F\u914D\u7F6E\u5E76\u5F52\u6863: dsh-a6api-config.json.bak');\n } catch (err: any) {\n console.warn('[dsh-a6api] \u65E7\u914D\u7F6E\u5F52\u6863\u5931\u8D25\uFF08\u8FC1\u79FB\u503C\u5DF2\u5199\u5165\uFF0C\u65E7\u6587\u4EF6\u4FDD\u7559\uFF0C\u4E0B\u6B21\u542F\u52A8\u91CD\u8BD5\uFF09:', err?.message || err);\n }\n };\n\n const doMigrate = async (): Promise<void> => {\n const filePath = legacyConfigFile();\n let raw = '';\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch {\n return; // \u65E0\u65E7\u6587\u4EF6\uFF0C\u65E0\u4E8B\u53EF\u505A\n }\n\n let parsed: any;\n try {\n parsed = JSON.parse(raw);\n } catch (err: any) {\n console.warn('[dsh-a6api] \u65E7\u914D\u7F6E\u6587\u4EF6\u635F\u574F\uFF0C\u8DF3\u8FC7\u8FC1\u79FB\u5E76\u5F52\u6863:', err?.message || err);\n await archiveLegacy(filePath);\n return;\n }\n\n const legacy = normalizeLegacy(parsed);\n const creds = getCredentials(ctx);\n\n // \u51ED\u636E\uFF1A\u53EA\u586B\u7A7A\u4E0D\u8986\u76D6\uFF08\u5F53\u524D\u5DF2\u6709\u503C\u6216 env \u8986\u76D6\u5219\u4E0D\u52A8\uFF09\uFF1B\n // \u4EFB\u4E00\u5199\u5165\u5931\u8D25 \u2192 \u4E0D\u5F52\u6863\uFF08\u51B3\u7B56\uFF1A\u5168\u90E8\u5199\u6210\u529F\u540E\u624D\u5F52\u6863\uFF09\uFF0C\u4FDD\u7559\u65E7\u6587\u4EF6\u8BFB\u53D6\u515C\u5E95\u4E0E\u4E0B\u6B21\u542F\u52A8\u91CD\u8BD5\u3002\n // \u987A\u5E8F\u6267\u884C\uFF1A\u515C\u5E95\u8DEF\u5F84 writeCredentialKey \u662F\u8BFB-\u6539-\u5199\u540C\u4E00\u6587\u4EF6\uFF0C\u5E76\u53D1\u4F1A\u4E92\u76F8\u8986\u76D6\u3002\n const fillResults = [\n await fillRef(creds, A6API_CRED_REF, legacy.apiKey),\n await fillRef(creds, A6API_TOKEN_REF, legacy.accessToken),\n await fillRef(creds, A6API_USER_REF, legacy.userId),\n ];\n if (fillResults.some((ok) => !ok)) {\n console.warn('[dsh-a6api] \u51ED\u636E\u8FC1\u79FB\u672A\u5168\u90E8\u6210\u529F\uFF0C\u8DF3\u8FC7\u5F52\u6863\uFF0C\u4FDD\u7559\u65E7\u6587\u4EF6\u8BFB\u53D6\u515C\u5E95\uFF08\u4E0B\u6B21\u542F\u52A8\u91CD\u8BD5\uFF09');\n return;\n }\n\n // settings\uFF1A\u4EC5\u5F53 a6api \u5757\u4E0D\u5B58\u5728\u65F6\u56DE\u586B\uFF08\u7EDD\u4E0D\u8986\u76D6\u7528\u6237\u5F53\u524D\u7684 settings.yaml\uFF09\n const block = await readA6apiBlock(getSettings(ctx));\n const blockExists = Boolean(block) || (await readRawConfiguredModels()).length > 0;\n if (!blockExists && legacy.activeModels.length > 0) {\n await syncModels(legacy.baseURL, legacy.activeModels);\n }\n\n await archiveLegacy(filePath);\n };\n\n return { ensureMigrated, readConfig, writeConfig, syncModels, getDshConfiguredModels };\n}\n", "export interface A6ApiConfig {\n baseURL: string;\n apiKey: string;\n accessToken?: string;\n userId?: string;\n activeModels: string[];\n /** \u670D\u52A1\u7AEF\u8131\u654F\u4E0B\u53D1\uFF1A\u662F\u5426\u5DF2\u914D\u7F6E API Key\uFF08\u771F\u5B9E\u5BC6\u94A5\u7EDD\u4E0D\u56DE\u4F20\u5BA2\u6237\u7AEF\uFF09 */\n hasApiKey?: boolean;\n /** \u670D\u52A1\u7AEF\u8131\u654F\u4E0B\u53D1\uFF1A\u662F\u5426\u5DF2\u914D\u7F6E\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C */\n hasToken?: boolean;\n}\n\n/**\n * \u6A21\u578B\u76EE\u5F55\u6761\u76EE\uFF08settings.yaml \u7684 llm-pi-ai \u539F\u751F\u6A21\u578B\u5B57\u6BB5 + \u5185\u90E8 brand\uFF09\u3002\n * \u53EF\u9009\u5B57\u6BB5\u7F3A\u7701 = \u53C2\u6570\u672A\u83B7\u53D6/\u672A\u586B\u5199\uFF0C\u5199 settings.yaml \u65F6\u7701\u7565\u8BE5\u5B57\u6BB5\uFF08llm-pi-ai \u9ED8\u8BA4\u503C\u515C\u5E95\uFF09\u3002\n */\nexport interface CatalogModelEntry {\n id: string;\n name?: string;\n contextWindow?: number;\n maxTokens?: number;\n input?: ('text' | 'image')[];\n /** false = \u660E\u786E\u975E\u63A8\u7406\u6A21\u578B\uFF1Bdict = \u6863\u4F4D \u2192 wire \u503C\uFF08\u503C\u53EF\u4E3A null\uFF0C\u540C llm-pi-ai \u8BED\u4E49\uFF09 */\n reasoningEfforts?: Record<string, string | null> | false;\n /** \u4EC5\u63D2\u4EF6\u5185\u90E8\u4F7F\u7528\uFF1A\u54C1\u724C\u6765\u81EA A6API \u5E02\u573A\u6E20\u9053\uFF0C\u4E0D\u5199\u5165 settings.yaml */\n brand?: string;\n /** \u6700\u8FD1\u4E00\u6B21 OpenRouter \u67E5\u8BE2/\u4EBA\u5DE5\u4FEE\u6539\u65F6\u95F4 */\n updatedAt?: number;\n}\n\n/** DSH llm-pi-ai \u652F\u6301\u7684\u5B8C\u6574\u601D\u8003\u6863\u4F4D\uFF08THINKING_LEVELS\uFF0C\u4E0E dsh-llm-pi-ai \u6E90\u7801\u4E00\u81F4\uFF09 */\nexport const THINKING_LEVEL_KEYS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const;\n\nexport type ReasoningEffortsValue = Record<string, string | null> | false;\n\n/**\n * \u6821\u9A8C reasoningEfforts\uFF08DSH llm-pi-ai \u8BED\u4E49\uFF0C\u670D\u52A1\u7AEF\u4E0E\u5BA2\u6237\u7AEF\u5171\u7528\uFF09\uFF1A\n * - false = \u975E\u63A8\u7406\u6A21\u578B\uFF0C\u5408\u6CD5\n * - \u952E\u5FC5\u987B \u2208 THINKING_LEVEL_KEYS\uFF1B\u503C\u5FC5\u987B\u975E\u7A7A\u5B57\u7B26\u4E32\uFF0C\u4EC5 off \u5141\u8BB8 null\n * - \u7A7A\u5B57\u5178\u3001\u4EC5 off \u65E0\u5176\u4ED6\u6863\u4F4D\u5747\u975E\u6CD5\n */\nexport function validateReasoningEfforts(\n value: unknown,\n): { ok: true; value: ReasoningEffortsValue } | { ok: false; error: string } {\n if (value === false) return { ok: true, value: false };\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'reasoningEfforts \u5FC5\u987B\u662F\u6863\u4F4D\u5B57\u5178\u6216 false' };\n }\n const dict = value as Record<string, unknown>;\n const keys = Object.keys(dict);\n if (keys.length === 0) return { ok: false, error: 'reasoningEfforts \u4E0D\u80FD\u4E3A\u7A7A\u5B57\u5178' };\n const out: Record<string, string | null> = {};\n for (const k of keys) {\n if (!(THINKING_LEVEL_KEYS as readonly string[]).includes(k)) {\n return { ok: false, error: `reasoningEfforts \u952E \"${k}\" \u4E0D\u662F DSH \u652F\u6301\u7684\u6863\u4F4D\uFF08off/minimal/low/medium/high/xhigh/max\uFF09` };\n }\n const v = dict[k];\n if (v === null) {\n if (k !== 'off') {\n return { ok: false, error: `reasoningEfforts.${k} \u5FC5\u987B\u63D0\u4F9B wire \u503C\uFF0C\u4EC5 off \u5141\u8BB8\u7559\u7A7A` };\n }\n out[k] = null;\n } else if (typeof v === 'string' && v.length > 0) {\n out[k] = v;\n } else {\n return { ok: false, error: `reasoningEfforts.${k} \u7684\u503C\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u6216 null` };\n }\n }\n if (!keys.some((k) => k !== 'off')) {\n return { ok: false, error: 'reasoningEfforts \u9664 off \u5916\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u601D\u8003\u6863\u4F4D\uFF08\u975E\u63A8\u7406\u6A21\u578B\u8BF7\u7528 false\uFF09' };\n }\n return { ok: true, value: out };\n}\n\nexport interface A6ApiModelMeta {\n id: string;\n name: string;\n brand: string;\n contextWindow: number;\n maxTokens: number;\n modalities: ('text' | 'image')[];\n reasoningEfforts?: Record<string, string>;\n thinkingFormat?: string;\n officialPriceMicros?: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n };\n}\n\nexport interface OfficialPrices {\n input_cny: string;\n output_cny: string;\n cache_read_cny: string;\n cache_write_cny: string;\n input_price_micros?: number;\n output_price_micros?: number;\n cache_read_price_micros?: number;\n cache_write_price_micros?: number;\n}\n\nexport interface SuccessBucketItem {\n sample_count?: number;\n success_count?: number;\n success_rate: number;\n}\n\nexport interface Bucket24hItem {\n s?: number;\n k?: number;\n r: number;\n t?: number;\n d?: number;\n f?: number;\n c?: number;\n}\n\nexport interface Bucket7dItem {\n s?: number;\n k?: number;\n r?: number;\n t?: number;\n d?: number;\n f?: number;\n c?: number;\n}\n\nexport interface MerchantChannelInfo {\n listing_id?: number;\n channel_id: number;\n channel_name: string;\n supplier_name: string;\n supplier_id?: number;\n model_name: string;\n brand: string;\n description: string;\n charge_type?: string;\n charge_type_text?: string;\n sample_count?: number;\n sample_count_text?: string;\n input_price_micros: number;\n output_price_micros: number;\n cache_read_price_micros: number;\n cache_write_price_micros: number;\n input_price_cny: string;\n output_price_cny: string;\n cache_read_price_cny: string;\n cache_write_price_cny: string;\n official_price?: OfficialPrices;\n realtime_ratio_cny: number;\n realtime_ratio_formatted: string;\n recent_success_rate_pct: number;\n success_rate_24h_pct: number;\n success_rate_7d_pct?: number;\n success_buckets?: SuccessBucketItem[];\n b24?: Bucket24hItem[];\n b7d?: Bucket7dItem[];\n sr_24h_state?: string;\n sr_7d_state?: string;\n p50_ttft_ms?: number;\n recent_p50_ms: number;\n cache_hit_rate_pct: number;\n /** \u6DF7\u5408\u4EF7\u4F30\u7B97\uFF08\u00A5 / 1\u4EBF tokens\uFF09\uFF1A\u8F93\u5165\u7C7B 99.65% \u6309 24h \u7F13\u5B58\u547D\u4E2D\u7387\u5206\u4E3A\u547D\u4E2D\uFF08\u7F13\u5B58\u8BFB\u4EF7\uFF09/\u672A\u547D\u4E2D\uFF08\u8F93\u5165\u4EF7\uFF09\uFF0C\u8F93\u51FA\u56FA\u5B9A\u5360 0.35%\uFF1B\u65E0 token \u5355\u4EF7\u65F6\u7F3A\u7701\u4E0D\u5C55\u793A */\n blended_price_100m_cny?: number;\n labels: string[];\n last_success_at: number;\n last_success_text: string;\n authenticity_guaranteed: boolean;\n authenticity_badge?: string;\n is_pinned?: boolean;\n /** \u5B98\u65B9\u6E20\u9053\u641C\u7D22\u8FD4\u56DE\u7684\u56FA\u5B9A\u72B6\u6001\uFF1Apin_here / pin_elsewhere / undefined */\n pin_status?: string;\n user_channel_disabled?: boolean;\n supplier_channel_disabled?: boolean;\n raw?: any;\n}\n\n/** \u5E73\u53F0\u4FA7\u56FA\u5B9A\u8BB0\u5F55\uFF08GET /api/marketplace/pins\uFF09 */\nexport interface MarketplacePin {\n id?: number;\n token_id: number;\n token_name?: string;\n model_name: string;\n channel_id?: number;\n channel_name?: string;\n supplier_name?: string;\n supplier_nickname?: string;\n /** \u5F02\u5E38\u65F6\u662F\u5426\u81EA\u52A8\u5207\u6362\u667A\u80FD\u4F18\u9009\uFF08false = \u4E25\u683C\u56FA\u5B9A\uFF09 */\n fallback_to_smart_routing?: boolean;\n created_at?: number;\n raw?: any;\n}\n\n/** \u4EE4\u724C\u5217\u8868\u6761\u76EE\uFF08GET /api/token/\uFF0C\u7528\u4E8E\u628A API Key \u89E3\u6790\u4E3A token_id\uFF09 */\nexport interface A6ApiTokenItem {\n id: number;\n name?: string;\n key?: string;\n status?: number;\n raw?: any;\n}\n\nexport interface ModelCardData {\n model_name: string;\n brand: string;\n contextWindow: number;\n maxTokens: number;\n modalities: ('text' | 'image')[];\n hasReasoning: boolean;\n inDsh: boolean;\n merchant?: MerchantChannelInfo;\n probeStatus: 'idle' | 'queued' | 'probing' | 'success' | 'error';\n probeError?: string;\n probeLatencyMs?: number;\n lastProbedAt?: number;\n /** \u8DEF\u7531\u5FEB\u7167\u65F6\u6548\uFF1A\u8BE5\u6A21\u578B\u6700\u65B0\u4E00\u6761\u300C\u5E26 channel \u7684\u8C03\u7528\u65E5\u5FD7\u300D\u65F6\u95F4\uFF08\u79D2\uFF09\uFF0C\u5373\u5361\u7247\u5546\u6237\u6570\u636E\u6765\u6E90\u8BF7\u6C42\u7684\u65F6\u523B */\n lastRoutedAt?: number;\n /** \u670D\u52A1\u7AEF\u7B97\u597D\u7684\u76F8\u5BF9\u65F6\u95F4\u6587\u6848\uFF08\u5982\u300C3 \u5C0F\u65F6\u524D\u300D\uFF09\uFF0C\u65E0\u8BB0\u5F55\u65F6\u5BA2\u6237\u7AEF\u663E\u793A\u300C\u4ECE\u672A\u8DEF\u7531\u300D */\n lastRoutedText?: string;\n /** \u5E73\u53F0\u56FA\u5B9A\u72B6\u6001\uFF08\u6309\u5F53\u524D API Key \u4EE4\u724C\uFF09\uFF1A\u56FA\u5B9A\u5230\u5361\u7247\u5546\u5BB6 / \u56FA\u5B9A\u5230\u5176\u4ED6\u5546\u5BB6 / \u672A\u56FA\u5B9A */\n pinStatus?: 'pin_here' | 'pin_elsewhere';\n /** \u56FA\u5B9A\u7684\u6E20\u9053 ID\uFF08pin_elsewhere \u65F6\u7528\u4E8E\u5C55\u793A\u56FA\u5B9A\u5230\u4E86\u54EA\u5BB6\uFF09 */\n pinnedChannelId?: number;\n pinnedSupplierName?: string;\n pinnedFallback?: boolean;\n /** \u8BE5\u6A21\u578B\u5BF9\u5E94\u7684\u56FA\u5B9A\u8BB0\u5F55\u5F52\u5C5E\uFF08\u76F8\u5BF9\u5F53\u524D API Key \u4EE4\u724C\uFF09\uFF1A\n * true = \u5C5E\u4E8E\u5F53\u524D\u4EE4\u724C\uFF1Bfalse = \u5C5E\u4E8E\u5176\u4ED6\u4EE4\u724C\uFF08\u4EC5\u4F9B\u53C2\u8003\uFF0C\u4E0D\u53EF\u5728\u6B64\u53D6\u6D88\uFF09\uFF1B\n * undefined = \u5F53\u524D\u4EE4\u724C\u672A\u80FD\u89E3\u6790\uFF08\u5F52\u5C5E\u672A\u77E5\uFF0C\u4EC5\u4F9B\u53C2\u8003\u4F46\u4E0D\u7981\u7528\u64CD\u4F5C\uFF09 */\n pinTokenMatched?: boolean;\n}\n\nexport interface BalanceInfo {\n hasAccountAuth: boolean;\n accountBalanceUsd: number;\n accountBalanceFormatted: string;\n accountBalanceCnyFormatted: string;\n usedUsd: number;\n usedFormatted: string;\n requestCount: number;\n username?: string;\n userId?: string | number;\n isLow: boolean;\n updatedAt: number;\n}\n\nexport interface ApiRoutingLogItem {\n id: number | string;\n created_at: number;\n model_name: string;\n channel?: number | string;\n channel_name?: string;\n /** \u53D1\u8D77\u8BE5\u8BF7\u6C42\u7684\u4EE4\u724C ID\uFF08\u7528\u4E8E\u628A API Key \u89E3\u6790\u4E3A\u56FA\u5B9A/\u7981\u7528\u6240\u9700\u7684 token_id\uFF09 */\n token_id?: number;\n prompt_tokens?: number;\n completion_tokens?: number;\n use_time?: number;\n quota?: number;\n cost_usd?: number;\n cost_formatted?: string;\n token_name?: string;\n status: 'success' | 'error';\n other?: string;\n raw?: any;\n}\n\nexport interface A6ApiStateResponse {\n config: A6ApiConfig;\n balance: BalanceInfo | null;\n models: ModelCardData[];\n dshConfiguredModels: string[];\n recentLogs?: ApiRoutingLogItem[];\n /** \u5E73\u53F0\u56FA\u5B9A\u8BB0\u5F55\u5217\u8868\uFF08\u7528\u4E8E\u5361\u7247\u72B6\u6001\u8DDF\u968F\u5B98\u7F51\uFF09 */\n pins?: MarketplacePin[];\n}\n// \u4EF7\u683C\u6CE2\u52A8\u80F6\u56CA\uFF08\u8F7B\u91CF\u76D1\u542C\uFF09\nexport interface PriceFluctuationState {\n pendingCount: number;\n unseenCount: number;\n totalCount: number;\n updatedAt: number | null;\n hasAuth?: boolean;\n authError?: boolean;\n}\n", "import { fetchBalance, fetchTokenModels, fetchRecentLogs, fetchPriceFluctuation, formatRelativeTime, fetchMarketplacePins, fetchTokens, fetchChannelDetails, marketplacePin, marketplaceUnpin, marketplaceDisableChannel, marketplaceRestoreChannel } from './server/a6api-client.js';\nimport { getKnownMerchantsFromLogs, probeSingleModel } from './server/probe.js';\nimport { resolveModelMeta, getCatalog, upsertCatalogEntries, clearCatalog, queryOpenRouter, fetchMarketplaceModels, updateCatalogEntry } from './server/catalog.js';\nimport { createConfigAccess } from './server/sync.js';\nimport type { ConfigAccess } from './server/sync.js';\nimport type { A6ApiConfig, A6ApiStateResponse, MarketplacePin, MerchantChannelInfo, ModelCardData } from './types.js';\nimport { validateReasoningEfforts } from './types.js';\n\nexport const name = '@lynn123411/dsh-a6api';\nexport const inject = ['webServer'];\n\nexport {\n fetchBalance,\n fetchTokenModels,\n fetchRecentLogs,\n fetchChannelDetails,\n fetchMarketplacePins,\n} from './server/a6api-client.js';\nexport { probeSingleModel, getKnownMerchantsFromLogs } from './server/probe.js';\nexport {\n resolveModelMeta,\n inferBrand,\n getCatalog,\n getCatalogEntry,\n clearCatalog,\n queryOpenRouter,\n fetchMarketplaceModels,\n updateCatalogEntry,\n} from './server/catalog.js';\nexport { createConfigAccess, A6API_CRED_REF, A6API_TOKEN_REF, A6API_USER_REF } from './server/sync.js';\n\nconst PREFIX = '/api/dsh-a6api';\n\n/** \u5BA2\u6237\u7AEF\u8131\u654F\u5360\u4F4D\u7B26\uFF1A\u670D\u52A1\u7AEF\u7EDD\u4E0D\u56DE\u4F20\u771F\u5B9E\u5BC6\u94A5 */\nconst MASK = '\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022';\n\n/** \u8131\u654F\u914D\u7F6E\uFF1AAPI Key / \u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C / userId \u4EC5\u4EE5\u5360\u4F4D\u7B26\u5F62\u5F0F\u4E0B\u53D1\uFF0C\u771F\u5B9E\u503C\u53EA\u5B58\u5728\u4E8E\u670D\u52A1\u7AEF */\nfunction maskConfig(c: A6ApiConfig): A6ApiConfig {\n return {\n ...c,\n apiKey: c.apiKey ? MASK : '',\n accessToken: c.accessToken ? MASK : '',\n userId: c.userId ? MASK : '',\n hasApiKey: Boolean(c.apiKey),\n hasToken: Boolean(c.accessToken),\n };\n}\n\nfunction sendJson(res: any, status: number, body: any) {\n res.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-cache',\n // \u4E0D\u8BBE access-control-allow-origin\uFF1A\u4EC5\u5141\u8BB8\u540C\u6E90\u8C03\u7528\uFF0C\u963B\u65AD\u8DE8\u7AD9\u8BFB\u53D6\u4E0E CSRF \u9884\u68C0\n });\n res.end(JSON.stringify(body));\n}\n\nfunction readBody(req: any): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = '';\n req.on('data', (chunk: any) => {\n data += chunk;\n if (data.length > 2 * 1024 * 1024) {\n req.destroy();\n reject(new Error('Body too large'));\n }\n });\n req.on('end', () => resolve(data.trim()));\n req.on('error', reject);\n });\n}\n\nasync function parseJsonBody(req: any): Promise<any> {\n const text = await readBody(req);\n if (!text) return {};\n try {\n return JSON.parse(text);\n } catch {\n throw new Error('Invalid JSON body');\n }\n}\n\n// In-memory cache for merchant cards to avoid duplicate log calls\nconst merchantCardCache = new Map<string, { card: MerchantChannelInfo; at: number }>();\n/** \u5361\u7247\u7F13\u5B58\u6709\u6548\u671F:\u8FC7\u671F\u540E /state \u4ECE\u6700\u65B0\u65E5\u5FD7\u91CD\u65B0\u63A8\u5BFC,\u907F\u514D\u6C38\u8FDC\u5C55\u793A\u9648\u65E7\u5546\u6237 */\nconst MERCHANT_CARD_TTL_MS = 15 * 60 * 1000;\n\n/** \u4EE4\u724C\u89E3\u6790\u7ED3\u679C\u7F13\u5B58\uFF08\u907F\u514D /state \u6BCF\u6B21\u91CD\u590D\u8C03\u4EE4\u724C\u5217\u8868\uFF09 */\nlet tokenResolveCache: { tokenId: number; at: number } | null = null;\nconst TOKEN_RESOLVE_TTL_MS = 10 * 60 * 1000;\n\n/**\n * \u628A\u914D\u7F6E\u7684 API Key \u89E3\u6790\u4E3A\u5E73\u53F0 token_id\uFF08\u56FA\u5B9A/\u53D6\u6D88\u56FA\u5B9A/\u7981\u7528\u6309\u4EE4\u724C\u7ED1\u5B9A\uFF09\u3002\n * \u89E3\u6790\u94FE\uFF1A\u5185\u5B58\u7F13\u5B58\uFF08TTL\uFF09\u2192 \u4EE4\u724C\u5217\u8868\u6309 key \u7CBE\u786E\u5339\u914D \u2192 \u552F\u4E00\u4EE4\u724C\u515C\u5E95\u3002\n * \u8FD4\u56DE null \u8868\u793A\u65E0\u6CD5\u89E3\u6790\uFF08\u8C03\u7528\u65B9\u53EF\u518D\u7528\u300C\u63A2\u6D4B\u65E5\u5FD7 token_id\u300D\u515C\u5E95\uFF09\u3002\n * \u8BF4\u660E\uFF1AtokenId \u662F\u6D3E\u751F\u6570\u636E\uFF0C\u4E0D\u518D\u6301\u4E45\u5316\uFF1B\u6BCF\u6B21\u8FDB\u7A0B\u51B7\u542F\u52A8\u540E\u9996\u6B21\u56FA\u5B9A/\u53D6\u6D88\u56FA\u5B9A\u591A\u4E00\u6B21\u4EE4\u724C\u5217\u8868\u8BF7\u6C42\u3002\n */\nasync function resolveTokenId(config: A6ApiConfig): Promise<number | null> {\n if (tokenResolveCache && Date.now() - tokenResolveCache.at < TOKEN_RESOLVE_TTL_MS) {\n return tokenResolveCache.tokenId;\n }\n const token = config.accessToken || '';\n if (!config.userId || !token) return null;\n try {\n const tokens = await fetchTokens(config.userId, token);\n let tokenId: number | null = null;\n const key = (config.apiKey || '').trim();\n if (key) {\n const hit = tokens.find((t) => t.key && t.key === key);\n if (hit) tokenId = hit.id;\n }\n if (!tokenId && tokens.length === 1) tokenId = tokens[0].id;\n if (tokenId && tokenId > 0) {\n tokenResolveCache = { tokenId, at: Date.now() };\n return tokenId;\n }\n } catch (err) {\n console.warn('[dsh-a6api] resolveTokenId error:', err);\n }\n return null;\n}\n\n/** \u53D6\u5F53\u524D Web \u4F1A\u8BDD\u51ED\u636E\uFF08\u56FA\u5B9A\u65CF\u63A5\u53E3\u9274\u6743\uFF0C\u4E0E\u5E02\u573A\u4EF7\u683C\u6CE2\u52A8\u540C\u6E90\uFF09 */\nfunction webAuthOf(config: A6ApiConfig): { userId?: string; token?: string } {\n return { userId: config.userId || undefined, token: config.accessToken || undefined };\n}\n\n/** \u4ECE\u7F13\u5B58\u53D6\u6A21\u578B\u5546\u5BB6\u5361\u7247\uFF08TTL \u5185\u6709\u6548\uFF09 */\nfunction cachedMerchantOf(modelName: string): MerchantChannelInfo | undefined {\n const entry = merchantCardCache.get(modelName.toLowerCase());\n return entry && Date.now() - entry.at < MERCHANT_CARD_TTL_MS ? entry.card : undefined;\n}\n\n/** \u628A\u56FA\u5B9A\u8BB0\u5F55\u53E0\u52A0\u5230\u6A21\u578B\u5361\u7247\u4E0A\uFF08pin_here / pin_elsewhere / \u7981\u7528\u7B49\u5C55\u793A\u5B57\u6BB5\uFF09 */\nfunction overlayPinsOnModels(models: ModelCardData[], pins: MarketplacePin[], tokenId?: number | null): ModelCardData[] {\n const byModel = new Map<string, MarketplacePin[]>();\n for (const p of pins) {\n const key = (p.model_name || '').toLowerCase();\n if (!key) continue;\n const list = byModel.get(key);\n if (list) list.push(p);\n else byModel.set(key, [p]);\n }\n // \u540C\u4E00\u6A21\u578B\u88AB\u591A\u4E2A\u4EE4\u724C\u56FA\u5B9A\u65F6\u6309\u521B\u5EFA\u65F6\u95F4\u5012\u5E8F\uFF0C\u4FDD\u8BC1\u5C55\u793A\u786E\u5B9A\u6027\uFF08\u6700\u65B0\u4E00\u6761\u4F18\u5148\uFF09\n const latestFirst = (list: MarketplacePin[]): MarketplacePin[] =>\n [...list].sort((a, b) => (Number(b.created_at) || 0) - (Number(a.created_at) || 0));\n return models.map((m) => {\n const list = byModel.get(m.model_name.toLowerCase());\n if (!list || list.length === 0) return m;\n const sorted = latestFirst(list);\n // \u4F18\u5148\u53D6\u5F53\u524D\u4EE4\u724C\u7684\u56FA\u5B9A\u8BB0\u5F55\uFF1B\u89E3\u6790\u4E0D\u51FA\u4EE4\u724C\u65F6\u53D6\u6700\u65B0\u4E00\u6761\u5E76\u6807\u8BB0\u5F52\u5C5E\u672A\u77E5\uFF08undefined\uFF09\uFF0C\n // \u8C03\u7528\u65B9\u4E0D\u5F97\u5C06\u5176\u4E0E\u300C\u5C5E\u4E8E\u5176\u4ED6\u4EE4\u724C\uFF08false\uFF09\u300D\u6DF7\u4E3A\u4E00\u8C08\n const pick =\n (tokenId ? sorted.find((p) => Number(p.token_id) === tokenId) : undefined) || sorted[0];\n const cardChannel = m.merchant?.channel_id;\n const pinChannel = pick.channel_id;\n return {\n ...m,\n // Number() \u5F52\u4E00\u5316\uFF1A\u5B98\u65B9\u63A5\u53E3\u53EF\u80FD\u8FD4\u56DE\u5B57\u7B26\u4E32\u6E20\u9053 ID\uFF0C\u4E25\u683C\u76F8\u7B49\u4F1A\u8BEF\u5224\n pinStatus: pinChannel\n ? cardChannel && Number(cardChannel) === Number(pinChannel)\n ? 'pin_here'\n : 'pin_elsewhere'\n : undefined,\n pinnedChannelId: pinChannel,\n pinnedSupplierName: pick.supplier_nickname || pick.supplier_name,\n pinnedFallback: pick.fallback_to_smart_routing,\n // \u4E09\u6001\uFF1Atrue=\u5C5E\u4E8E\u5F53\u524D\u4EE4\u724C\uFF0Cfalse=\u5C5E\u4E8E\u5176\u4ED6\u4EE4\u724C\uFF0Cundefined=\u5F53\u524D\u4EE4\u724C\u672A\u89E3\u6790\uFF08\u672A\u77E5\uFF09\n pinTokenMatched: tokenId ? Number(pick.token_id) === tokenId : undefined,\n };\n });\n}\n\n// ===== /state \u4E0E /price-fluctuation \u7684\u4E0A\u6E38\u77ED\u7F13\u5B58 + \u5E76\u53D1\u53BB\u91CD =====\n//\n// \u5BA2\u6237\u7AEF\u6BCF 60s\uFF08\u6BCF\u4E2A\u6807\u7B7E\u9875\u4E00\u4EFD\u5B9A\u65F6\u5668\uFF09\u8F6E\u8BE2 /state\uFF0C\u9875\u9762\u5237\u65B0/\u6253\u5F00\u8BBE\u7F6E\u9762\u677F\u8FD8\u4F1A\u989D\u5916\u89E6\u53D1\uFF1B\n// \u65E0\u72B6\u6001\u5B9E\u73B0\u4E0B\u6BCF\u6765\u4E00\u4E2A /state \u90FD\u5B8C\u6574\u91CD\u62C9\u4E0A\u6E38\uFF08\u4F59\u989D/\u4EE4\u724C\u6A21\u578B/\u65E5\u5FD7/\u56FA\u5B9A\u8BB0\u5F55\uFF09\uFF0C\u591A\u6807\u7B7E\u9875\u5404\u81EA\u4E3A\u653F\uFF0C\n// \u4E0A\u6E38\u6D41\u91CF = \u6807\u7B7E\u9875\u6570 \u00D7 \u89E6\u53D1\u6B21\u6570\u3002\u8FD9\u91CC\u628A\u300C\u6700\u8FD1\u4E00\u6B21\u7EC4\u88C5\u7ED3\u679C\u300D\u6309\u51ED\u636E\u77ED\u7F13\u5B58\uFF08TTL\uFF09\uFF0C\n// \u5E76\u628A\u5E76\u53D1\u5230\u8FBE\u7684\u8BF7\u6C42\u5408\u5E76\u5230\u540C\u4E00\u4EFD\u5728\u9014\u6784\u5EFA\uFF1A\u4E0A\u6E38\u8BF7\u6C42\u9891\u7387\u4ECE\u300C\u6BCF 60s \u00D7 \u6807\u7B7E\u9875\u6570\u300D\u964D\u4E3A\u300C\u6BCF TTL \u4E00\u6B21\u300D\u3002\n// \u6570\u636E\u53D8\u66F4\u7C7B\u64CD\u4F5C\uFF08\u4FDD\u5B58\u914D\u7F6E/\u540C\u6B65\u6A21\u578B/\u63A2\u6D4B/\u56FA\u5B9A/\u53D6\u6D88\u56FA\u5B9A/\u7981\u7528/\u6062\u590D\uFF09\u8C03\u7528 stateMemo.invalidate()\n// \u63D0\u5347\u4EE3\u9645\u5E76\u6E05\u7A7A\u7F13\u5B58\uFF1B\u53D8\u66F4\u524D\u5DF2\u5F00\u59CB\u7684\u5728\u9014\u6784\u5EFA\u5B8C\u6210\u65F6\u56E0\u4EE3\u9645\u4E0D\u7B26\u4E0D\u4F1A\u5199\u5165\u7F13\u5B58\uFF08\u4EC5\u670D\u52A1\u672C\u6B21\u8BF7\u6C42\uFF09\u3002\n\n/**\n * \u901A\u7528\u4E0A\u6E38\u8BB0\u5FC6\uFF1ATTL \u77ED\u7F13\u5B58 + \u540C\u952E\u5728\u9014\u6784\u5EFA\u5408\u5E76 + \u4EE3\u9645\u5931\u6548\u3002\n * shouldCache \u53EF\u9009\uFF1A\u5BF9\u4E0D\u5E94\u88AB\u7F13\u5B58\u7684\u7ED3\u679C\uFF08\u5982\u9274\u6743\u5931\u8D25\u6001\uFF09\u8FD4\u56DE false\uFF0C\u8BE5\u7ED3\u679C\u4EC5\u670D\u52A1\u672C\u6B21\u8BF7\u6C42\u3002\n */\nfunction createUpstreamMemo<T>(ttlMs: number, shouldCache?: (value: T) => boolean): {\n get(key: string, fetcher: () => Promise<T>, opts?: { force?: boolean }): Promise<T>;\n invalidate(): void;\n} {\n let cache = new Map<string, { data: T; at: number; epoch: number }>();\n const inflight = new Map<string, Promise<T>>();\n let epoch = 0;\n\n return {\n /**\n * \u6570\u636E\u53D8\u66F4\u540E\u8C03\u7528\uFF1A\u65E7\u7ED3\u679C\u7ACB\u5373\u4E0D\u53EF\u7528\u3002\n * \u540C\u65F6\u6E05\u7A7A\u5728\u9014\u6784\u5EFA\u8868\uFF1A\u53D8\u66F4\u5B8C\u6210\u540E\u624D\u5230\u8FBE\u7684\u8BF7\u6C42\u4E0D\u4F1A\u300C\u52A0\u5165\u300D\u53D8\u66F4\u524D\u5DF2\u5F00\u59CB\u7684\u65E7\u6784\u5EFA\n * \uFF08\u65E7\u6784\u5EFA\u7684\u5199\u7F13\u5B58\u4ECD\u6709\u4EE3\u9645\u6821\u9A8C\u515C\u5E95\uFF09\uFF0C\u800C\u662F\u5FC5\u7136\u53D1\u8D77\u4E00\u6B21\u65B0\u6784\u5EFA\u62FF\u5230\u6700\u65B0\u6570\u636E\u3002\n */\n invalidate() {\n epoch += 1;\n cache.clear();\n inflight.clear();\n },\n\n async get(key, fetcher, opts?: { force?: boolean }) {\n // force\uFF08\u624B\u52A8\u300C\u5237\u65B0\u5217\u8868\u300D\uFF09\uFF1A\u8DF3\u8FC7 TTL \u7F13\u5B58\u8BFB\u53D6\uFF0C\u52A0\u5165/\u53D1\u8D77\u65B0\u6784\u5EFA\u62FF\u6700\u65B0\u4E0A\u6E38\u6570\u636E\uFF1B\n // \u5728\u9014\u6784\u5EFA\u672C\u8EAB\u5C31\u662F\u65B0\u62C9\u53D6\uFF0C\u52A0\u5165\u5B83\u540C\u6837\u65B0\u9C9C\u4E14\u907F\u514D\u5E76\u53D1\u91CD\u590D\u6253\u4E0A\u6E38\n const hit = opts?.force ? undefined : cache.get(key);\n if (hit && hit.epoch === epoch && Date.now() - hit.at < ttlMs) return hit.data;\n\n let pending = inflight.get(key);\n if (!pending) {\n const buildEpoch = epoch;\n const run = Promise.resolve()\n .then(fetcher)\n .then((data) => {\n // \u6784\u5EFA\u671F\u95F4\u53D1\u751F\u6570\u636E\u53D8\u66F4 \u2192 \u4E0D\u5199\u7F13\u5B58\uFF1BshouldCache \u62D2\u7EDD\uFF08\u5982 authError\uFF09\u2192 \u4E0D\u5199\u7F13\u5B58\n if (buildEpoch === epoch && (!shouldCache || shouldCache(data))) {\n cache.set(key, { data, at: Date.now(), epoch: buildEpoch });\n }\n return data;\n })\n .finally(() => {\n if (inflight.get(key) === run) inflight.delete(key);\n });\n inflight.set(key, run);\n pending = run;\n }\n return pending;\n },\n };\n}\n\n/** /state \u5168\u91CF\u54CD\u5E94\u7F13\u5B58 TTL\uFF1A\u7565\u5927\u4E8E\u5BA2\u6237\u7AEF 60s \u8F6E\u8BE2\u5468\u671F \u2192 \u5355\u6807\u7B7E\u9875\u7A33\u6001\u4E0A\u6E38\u7EA6\u6BCF 2 \u5206\u949F\u4E00\u6B21\uFF0C\u591A\u6807\u7B7E\u9875\u5171\u4EAB */\nconst stateMemo = createUpstreamMemo<A6ApiStateResponse>(120_000);\n/** \u4EF7\u683C\u6CE2\u52A8\u8BA1\u6570\u7F13\u5B58\uFF08\u540C\u4E00\u4E0A\u6E38\u4EF7\u683C\u901A\u77E5\u63A5\u53E3\u7684\u5408\u5E76\u7A97\u53E3\uFF09\uFF1B\u9274\u6743\u5931\u8D25\u6001\u4E0D\u7F13\u5B58\uFF0C\u4FDD\u8BC1\u5931\u6548\u4FE1\u53F7\u5373\u65F6\u53EF\u89C1 */\nconst priceCountsMemo = createUpstreamMemo<{\n pendingCount: number;\n unseenCount: number;\n totalCount: number;\n authError?: boolean;\n}>(120_000, (counts) => !counts.authError);\n\n/** \u7F13\u5B58\u952E\uFF1A\u6309\u8282\u70B9\u4E0E\u51ED\u636E\u9694\u79BB\uFF1BuserId / apiKey / accessToken \u4EFB\u4E00\u53D8\u5316 \u2192 \u952E\u53D8\u5316 \u2192 \u81EA\u52A8\u9519\u8FC7\u65E7\u7F13\u5B58 */\nfunction stateCacheKeyOf(config: A6ApiConfig): string {\n const fingerprint = (s: string): string => {\n let h = 0;\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0;\n return (h >>> 0).toString(36);\n };\n return `${config.baseURL || ''}|${config.userId || ''}|${fingerprint(config.apiKey || '')}|${fingerprint(config.accessToken || '')}`;\n}\n\n/** /state \u5165\u53E3\uFF1A\u77ED\u7F13\u5B58\u4F18\u5148\uFF08force=true \u7ED5\u8FC7 TTL \u76F4\u63A5\u91CD\u5EFA\uFF09\uFF1B\u672A\u547D\u4E2D\u5219\u5408\u5E76\u5230\u5728\u9014\u6784\u5EFA\uFF08\u5E76\u53D1 /state \u5171\u4EAB\u540C\u4E00\u6B21\u4E0A\u6E38\u62C9\u53D6\uFF09 */\nasync function getCachedStateResponse(config: A6ApiConfig, configAccess: ConfigAccess, force = false): Promise<A6ApiStateResponse> {\n return stateMemo.get(stateCacheKeyOf(config), () => buildStateResponse(config, configAccess), { force });\n}\n\n/** \u7EC4\u88C5\u4E00\u6B21\u5B8C\u6574\u7684 /state \u54CD\u5E94\uFF08\u539F /state \u8DEF\u7531\u5185\u8054\u903B\u8F91\u539F\u6837\u63D0\u53D6\uFF1A\u4E0A\u6E38\u62C9\u53D6 + \u5546\u6237\u5361\u7247\u63A8\u5BFC + \u56FA\u5B9A\u53E0\u52A0\uFF09 */\nasync function buildStateResponse(config: A6ApiConfig, configAccess: ConfigAccess): Promise<A6ApiStateResponse> {\n const token = config.accessToken || '';\n // \u5E76\u884C\u62C9\u53D6\u4E92\u76F8\u72EC\u7ACB\u7684\u4E0A\u6E38\u6570\u636E\uFF1A\u4F59\u989D / \u672C\u5730\u914D\u7F6E\u6A21\u578B / \u4EE4\u724C\u6A21\u578B\u5217\u8868 / \u6700\u8FD1\u65E5\u5FD7 / \u5E73\u53F0\u56FA\u5B9A\u8BB0\u5F55\u3002\n // \u539F\u4E32\u884C 5 \u6B21\u4E0A\u6E38 RTT \u2192 1 \u6B21\uFF0C\u51B7\u8DEF\u5F84 3~10s \u2192 \u7EA6 1~2s\uFF08\u542F\u52A8\u9884\u70ED + 60s \u8F6E\u8BE2\u4F9D\u8D56\u6B64\u63D0\u901F\uFF09\u3002\n // \u9519\u8BEF\u8BED\u4E49\u4E0E\u539F\u5148\u4E00\u81F4\uFF1A\u4F59\u989D/\u6A21\u578B\u5217\u8868/\u65E5\u5FD7\u5931\u8D25\u5219\u6574\u4F53 500\uFF0C\u56FA\u5B9A\u8BB0\u5F55\u5931\u8D25\u964D\u7EA7\u4E3A\u7A7A\u3002\n const [balance, dshConfiguredModels, modelIdsRaw, allLogs, pins] = await Promise.all([\n fetchBalance(config.baseURL, config.apiKey, config.userId, token),\n configAccess.getDshConfiguredModels(),\n config.apiKey ? fetchTokenModels(config.baseURL, config.apiKey) : Promise.resolve([] as string[]),\n fetchRecentLogs(config.userId, token, 100),\n config.userId && token\n ? fetchMarketplacePins(config.userId, token).catch(() => [] as MarketplacePin[])\n : Promise.resolve([] as MarketplacePin[]),\n ]);\n\n // Auto-persist discovered userId\n if (balance?.userId && String(balance.userId) !== config.userId) {\n // \u8D26\u53F7\u53D8\u5316\uFF1A\u65E7 tokenId \u4E0D\u518D\u5BF9\u5E94\u5F53\u524D\u8D26\u53F7\uFF0C\u4F5C\u5E9F\u5E76\u91CD\u7F6E\u89E3\u6790\u7F13\u5B58\n tokenResolveCache = null;\n config.userId = String(balance.userId);\n await configAccess.writeConfig({ userId: config.userId });\n }\n\n // Fallback to DSH-configured / default models if token query returned empty\n let modelIds = modelIdsRaw;\n if (modelIds.length === 0) {\n modelIds = [\n ...new Set([\n ...dshConfiguredModels,\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'gpt-5.6-luna',\n 'claude-fable-5',\n 'claude-opus-5',\n 'grok-4.6',\n ]),\n ];\n }\n\n // \u4E00\u6B21\u62C9\u53D6\u65E5\u5FD7(\u63A5\u53E3\u5B9E\u6D4B\u4E0A\u9650 100 \u6761),\u540C\u4E00\u4EFD\u6570\u636E\u7528\u4E8E: \u2460\u5546\u6237\u5361\u7247\u9884\u586B\u5145 \u2461\u8DEF\u7531\u5FEB\u7167\u65F6\u6548\u6620\u5C04 \u2462Account \u9875\u6700\u8FD1\u660E\u7EC6\n // \u9632\u5FA1\u6027\u6392\u5E8F\uFF1A\u4F9D\u8D56\u201C\u6700\u65B0\u5728\u524D\u201D\uFF0C\u82E5\u7F51\u5173\u6392\u5E8F\u53D8\u66F4\u4ECD\u80FD\u6B63\u786E\u53D6\u9996\u6761\n allLogs.sort((a, b) => (Number(b.created_at) || 0) - (Number(a.created_at) || 0));\n\n // Match known merchant cards from recent logs if not yet in cache (with 10s total timeout to avoid /state hang)\n if (config.userId || token) {\n const missing = modelIds.filter((m) => {\n const entry = merchantCardCache.get(m.toLowerCase());\n return !entry || Date.now() - entry.at >= MERCHANT_CARD_TTL_MS;\n });\n if (missing.length > 0) {\n let found: Record<string, MerchantChannelInfo> = {};\n try {\n found = await Promise.race([\n getKnownMerchantsFromLogs(config.userId, token, missing, allLogs),\n new Promise<Record<string, MerchantChannelInfo>>((resolve) => setTimeout(() => resolve({}), 10000)),\n ]);\n } catch {\n found = {};\n }\n for (const [mName, card] of Object.entries(found)) {\n merchantCardCache.set(mName.toLowerCase(), { card, at: Date.now() });\n }\n }\n }\n\n // \u8DEF\u7531\u5FEB\u7167\u65F6\u6548: \u6BCF\u4E2A\u6A21\u578B\u6700\u65B0\u4E00\u6761\u300C\u5E26 channel \u7684\u8C03\u7528\u65E5\u5FD7\u300D\u65F6\u95F4 \u2014\u2014 \u4E0E\u9884\u586B\u5145\u5361\u7247\u5546\u6237\u6570\u636E\u540C\u4E00\u6761\u89C4\u5219(\u53D6\u6700\u65B0\u547D\u4E2D\u5546\u6237\u8DEF\u7531\u7684\u8BF7\u6C42)\n const lastRoutedMap = new Map<string, number>();\n for (const log of allLogs) {\n const mName = log.model_name;\n const chId = Number(log.channel);\n const ts = Number(log.created_at) || 0;\n if (mName && chId > 0 && ts > 0 && !lastRoutedMap.has(mName.toLowerCase())) {\n lastRoutedMap.set(mName.toLowerCase(), ts);\n }\n }\n\n const dshSet = new Set(dshConfiguredModels);\n let models: ModelCardData[] = modelIds.map((mId) => {\n const meta = resolveModelMeta(mId);\n const cacheEntry = merchantCardCache.get(mId.toLowerCase());\n const cachedCard =\n cacheEntry && Date.now() - cacheEntry.at < MERCHANT_CARD_TTL_MS\n ? cacheEntry.card\n : undefined;\n const routedAt = lastRoutedMap.get(mId.toLowerCase());\n return {\n model_name: mId,\n brand: meta.brand,\n contextWindow: meta.contextWindow,\n maxTokens: meta.maxTokens,\n modalities: meta.modalities,\n hasReasoning: Boolean(meta.reasoningEfforts || meta.thinkingFormat),\n inDsh: dshSet.has(mId),\n merchant: cachedCard,\n probeStatus: cachedCard ? 'success' : 'idle',\n lastRoutedAt: routedAt,\n lastRoutedText: routedAt ? formatRelativeTime(routedAt) : undefined,\n };\n });\n\n // \u56FA\u5B9A\u72B6\u6001\u53E0\u52A0\uFF1Apins \u5DF2\u5728\u5E76\u884C\u6279\u6B21\u62C9\u53D6\uFF08\u5931\u8D25\u964D\u7EA7\u4E3A\u7A7A\u6570\u7EC4\uFF09\uFF0C\u8BA9\u5361\u7247\u72B6\u6001\u8DDF\u968F\u5B98\u7F51\n // \uFF08\u5B98\u7F51\u4FA7\u89E3\u9664\u56FA\u5B9A/\u6DA8\u4EF7\u81EA\u52A8\u89E3\u9664\u90FD\u4F1A\u53CD\u6620\u8FC7\u6765\uFF09\n const resolvedTokenId = pins.length > 0 ? await resolveTokenId(config) : null;\n models = overlayPinsOnModels(models, pins, resolvedTokenId);\n\n // \u56FA\u5B9A\u5546\u5BB6\u81EA\u52A8\u63A5\u7BA1\u5361\u7247\uFF1A\u6A21\u578B\u5DF2\u56FA\u5B9A\u5230\u300C\u975E\u5F53\u524D\u5361\u7247\u300D\u7684\u5546\u5BB6\u65F6\uFF08\u5F53\u524D\u4EE4\u724C\u7684\u56FA\u5B9A\uFF09\uFF0C\n // \u62C9\u53D6\u8BE5\u56FA\u5B9A\u5546\u5BB6\u7684\u6E20\u9053\u8BE6\u60C5\u66FF\u6362\u5361\u7247\uFF0C\u800C\u4E0D\u662F\u63D0\u793A\u300C\u5DF2\u56FA\u5B9A\u5230\u5176\u4ED6\u5546\u5BB6\u300D\u3002\n // \u62C9\u53D6\u5931\u8D25 / \u56FA\u5B9A\u5C5E\u4E8E\u5176\u4ED6\u4EE4\u724C / \u5F52\u5C5E\u672A\u77E5\u65F6\u4FDD\u6301\u539F\u5361\u7247\u5E76\u56DE\u9000\u5230\u63D0\u793A\u5FBD\u6807\u3002\n const rePointTargets = models\n .filter(\n (m) =>\n m.pinStatus === 'pin_elsewhere' &&\n m.pinTokenMatched === true &&\n m.pinnedChannelId &&\n m.pinnedChannelId > 0,\n )\n .map((m) => ({ modelName: m.model_name, channelId: m.pinnedChannelId as number }));\n if (rePointTargets.length > 0 && config.userId && token) {\n try {\n await Promise.race([\n (async () => {\n for (let i = 0; i < rePointTargets.length; i += 4) {\n const batch = rePointTargets.slice(i, i + 4);\n await Promise.all(\n batch.map(async ({ modelName, channelId }) => {\n try {\n const pinnedCard = await fetchChannelDetails(\n channelId,\n config.userId,\n token,\n modelName,\n );\n // \u6821\u9A8C\u8FD4\u56DE\u5361\u7247\u786E\u5B9E\u5C5E\u4E8E\u76EE\u6807\u56FA\u5B9A\u6E20\u9053\uFF0C\u907F\u514D\u5B98\u65B9\u641C\u7D22\u8FD4\u56DE\u5176\u4ED6\u6761\u76EE\u6C61\u67D3\u7F13\u5B58\n if (pinnedCard && Number(pinnedCard.channel_id) === Number(channelId)) {\n merchantCardCache.set(modelName.toLowerCase(), { card: pinnedCard, at: Date.now() });\n }\n } catch {}\n }),\n );\n }\n })(),\n new Promise<void>((resolve) => setTimeout(() => resolve(), 10000)),\n ]);\n } catch {}\n // \u7528\u56DE\u586B\u540E\u7684\u7F13\u5B58\u91CD\u5EFA\u5361\u7247\uFF08\u56FA\u5B9A\u5546\u5BB6\u5373\u5361\u7247\u5546\u5BB6 \u2192 \u72B6\u6001\u5347\u7EA7\u4E3A pin_here\uFF09\n models = models.map((m) => {\n if (m.pinStatus !== 'pin_elsewhere' || m.pinTokenMatched !== true) return m;\n const entry = merchantCardCache.get(m.model_name.toLowerCase());\n const card = entry && Date.now() - entry.at < MERCHANT_CARD_TTL_MS ? entry.card : undefined;\n if (card && Number(card.channel_id) === Number(m.pinnedChannelId)) {\n // \u8DEF\u7531\u5FEB\u7167\u53E3\u5F84\u5BF9\u9F50\uFF1A\u53D6\u300C\u8BE5\u5546\u5BB6\u7684\u8BE5\u6A21\u578B\u300D\u6700\u8FD1\u4E00\u6B21\u8BF7\u6C42\uFF08\u5361\u7247\u5DF2\u5207\u6362\u5230\u56FA\u5B9A\u5546\u5BB6\uFF0C\u65F6\u95F4\u4E0D\u80FD\u518D\u6309\u4EFB\u610F\u5546\u5BB6\u53D6\uFF09\n const pinnedLog = allLogs.find(\n (l) =>\n l.model_name?.toLowerCase() === m.model_name.toLowerCase() &&\n Number(l.channel) === m.pinnedChannelId,\n );\n const pinnedAt = pinnedLog ? Number(pinnedLog.created_at) || 0 : undefined;\n return {\n ...m,\n merchant: card,\n pinStatus: 'pin_here' as const,\n probeStatus: 'success' as const,\n lastRoutedAt: pinnedAt,\n lastRoutedText: pinnedAt ? formatRelativeTime(pinnedAt) : undefined,\n };\n }\n return m;\n });\n }\n\n // Account \u9875\u660E\u7EC6\u4FDD\u6301\u539F\u6709\u7A97\u53E3 (20 \u6761)\n const recentLogs = allLogs.slice(0, 20);\n\n return {\n config: maskConfig(config),\n balance,\n models,\n dshConfiguredModels,\n recentLogs,\n pins,\n };\n}\n\nexport function apply(ctx: any): void {\n // DSH \u539F\u751F\u914D\u7F6E\u8BBF\u95EE\u5668\uFF1A\u542F\u52A8\u5373\u89E6\u53D1\u65E7\u914D\u7F6E\u6587\u4EF6\u81EA\u52A8\u8FC1\u79FB\uFF08\u5E42\u7B49\uFF0C\u9996\u6B21\u8BFB\u53D6\u4F1A\u7B49\u5F85\u5176\u5B8C\u6210\uFF09\n const configAccess = createConfigAccess(ctx);\n void configAccess.ensureMigrated();\n\n // Register Web API routes\n const webServer = ctx.webServer || (ctx.get ? ctx.get('webServer') : null);\n if (webServer && typeof webServer.register === 'function') {\n ctx.effect(() => {\n const unregister = webServer.register({\n kind: 'prefix',\n path: PREFIX,\n handler: async (req: any, res: any) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const pathname = url.pathname.replace(PREFIX, '') || '/';\n\n // CORS preflight\uFF1A\u540C\u6E90\u7B56\u7565\u4E0B\u65E0\u9700\u653E\u884C\u8DE8\u6E90\uFF08\u79FB\u9664 ACAO \u540E\u8DE8\u6E90\u9884\u68C0\u5929\u7136\u5931\u8D25\uFF09\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n return res.end();\n }\n\n // CSRF \u9762\uFF1A\u540C\u6E90 POST \u4E00\u5F8B\u8981\u6C42 JSON Content-Type\uFF08\u8DE8\u7AD9\u8868\u5355\u65E0\u6CD5\u4F2A\u9020\u8BE5\u5934\uFF09\uFF1B\n // \u5BA2\u6237\u7AEF\u5168\u90E8 POST \u5DF2\u5E26 application/json\uFF08\u542B\u65E0 body \u7684 fetch-models/clear\uFF09\n if (req.method === 'POST' && !String(req.headers['content-type'] || '').toLowerCase().includes('application/json')) {\n return sendJson(res, 415, { ok: false, error: 'Content-Type must be application/json' });\n }\n\n try {\n // GET /state \u2014 \u77ED\u7F13\u5B58 + \u5E76\u53D1\u53BB\u91CD\uFF1ATTL \u5185\u91CD\u590D/\u5E76\u53D1\u8BF7\u6C42\u5171\u4EAB\u540C\u4E00\u4EFD\u4E0A\u6E38\u7ED3\u679C\uFF0C\n // \u591A\u6807\u7B7E\u9875\u8F6E\u8BE2\u3001\u9875\u9762\u5237\u65B0\u3001\u9762\u677F\u6253\u5F00\u4E0E\u64CD\u4F5C\u540E\u7684\u81EA\u52A8\u5237\u65B0\u4E0D\u518D\u5404\u81EA\u91CD\u590D\u62C9\u53D6\u4E0A\u6E38\n if (pathname === '/state' && (req.method === 'GET' || req.method === 'HEAD')) {\n const config = await configAccess.readConfig();\n // \u300C\u5237\u65B0\u5217\u8868\u300D\u6309\u94AE\u5E26 force=1\uFF1A\u7ED5\u8FC7 120s \u77ED\u7F13\u5B58\u7ACB\u5373\u91CD\u5EFA\uFF08\u540E\u53F0\u8F6E\u8BE2\u4E0D\u5E26\u53C2\u6570\uFF0C\u7EE7\u7EED\u5403\u7F13\u5B58\uFF09\n const force = url.searchParams.get('force') === '1';\n const response = await getCachedStateResponse(config, configAccess, force);\n return sendJson(res, 200, { ok: true, data: response });\n }\n\n // POST /config\n if (pathname === '/config' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const current = await configAccess.readConfig();\n // \u517C\u5BB9\u65E7\u5BA2\u6237\u7AEF bundle \u4ECD\u4F1A\u53D1\u9001 sessionCookie\uFF1A\u540C\u4E00\u51ED\u636E\uFF0C\u53D6\u4EFB\u4E00\u975E\u5360\u4F4D\u503C\n const rawToken =\n body.accessToken !== undefined && body.accessToken !== MASK\n ? body.accessToken\n : body.sessionCookie !== undefined && body.sessionCookie !== MASK\n ? body.sessionCookie\n : current.accessToken;\n const newApiKey =\n body.apiKey !== undefined && body.apiKey !== MASK ? body.apiKey : current.apiKey;\n // API Key / \u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\uFF08\u8D26\u53F7\uFF09/ userId \u4EFB\u4E00\u53D8\u66F4\u540E\uFF0C\u65E7 tokenId \u4E0D\u518D\u5BF9\u5E94\u5F53\u524D\u8D26\u53F7\u7684\u4EE4\u724C\uFF0C\n // \u6E05\u9664\u5E76\u91CD\u7F6E\u89E3\u6790\u7F13\u5B58\uFF0C\u4E0B\u6B21\u56FA\u5B9A/\u53D6\u6D88\u56FA\u5B9A\u65F6\u91CD\u65B0\u89E3\u6790\n const credChanged =\n newApiKey !== current.apiKey ||\n rawToken !== (current.accessToken || '') ||\n (body.userId !== undefined && body.userId !== MASK && body.userId !== current.userId);\n if (credChanged) {\n tokenResolveCache = null;\n }\n\n const updated: A6ApiConfig = {\n baseURL: body.baseURL !== undefined ? body.baseURL : current.baseURL,\n apiKey: newApiKey,\n accessToken: rawToken,\n userId: body.userId !== undefined && body.userId !== MASK ? body.userId : current.userId,\n activeModels: Array.isArray(body.activeModels) ? body.activeModels : current.activeModels,\n };\n\n // Validate access token and auto-fetch balance & userId\n const balance = await fetchBalance(updated.baseURL, updated.apiKey, updated.userId, updated.accessToken);\n if (balance?.userId) {\n updated.userId = String(balance.userId);\n }\n\n // \u51ED\u636E\u5199\u5165\u539F\u751F\u5B58\u50A8\uFF08credentials refs\uFF1B\u7A7A\u4E32 = \u6E05\u9664\uFF09\uFF1B\u4EC5\u5199\u6709\u53D8\u5316\u7684\u5B57\u6BB5\n const credWrites: Partial<Pick<A6ApiConfig, 'apiKey' | 'accessToken' | 'userId'>> = {};\n if (updated.apiKey !== current.apiKey) credWrites.apiKey = updated.apiKey;\n if ((updated.accessToken || '') !== (current.accessToken || '')) credWrites.accessToken = updated.accessToken;\n if ((updated.userId || '') !== (current.userId || '')) credWrites.userId = updated.userId;\n if (Object.keys(credWrites).length > 0) {\n await configAccess.writeConfig(credWrites);\n }\n\n // \u540C\u6B65 DSH settings\uFF08\u4E0E\u65E7\u884C\u4E3A\u4E00\u81F4\uFF1A\u4EC5\u5F53\u6709\u6D3B\u52A8\u6A21\u578B\u65F6\uFF09\u3002\n // \u6CE8\uFF1A\u96F6\u6A21\u578B\u65F6\u65E0\u6CD5\u6301\u4E45\u5316 baseURL\u2014\u2014llm-pi-ai \u5BF9\u624B\u5199\u8DEF\u7531\u65E0\u5408\u6CD5\u7684\u96F6\u6A21\u578B\u8868\u793A\n // \uFF08models: [] \u4F1A\u88AB assertServiceable \u62D2\u7EDD\u5E76\u6BD2\u5316\u4E0B\u6B21\u542F\u52A8\uFF09\uFF0Ca6api \u5757\u6B64\u65F6\u4E0D\u5B58\u5728\uFF0C\n // \u8282\u70B9\u8BBE\u7F6E\u5C5E\u60F0\u6027\u72B6\u6001\uFF0C\u5F85\u7528\u6237\u542F\u7528\u6A21\u578B\u65F6\u968F\u5757\u4E00\u5E76\u843D\u76D8\u3002\n if (updated.activeModels.length > 0) {\n await configAccess.syncModels(updated.baseURL, updated.activeModels);\n }\n // \u914D\u7F6E\uFF08\u542B\u51ED\u636E/\u8282\u70B9/\u6A21\u578B\u5217\u8868\uFF09\u5DF2\u53D8\u66F4\uFF1A\u4F5C\u5E9F /state \u77ED\u7F13\u5B58\uFF0C\u4E0B\u6B21\u62C9\u53D6\u7ACB\u5373\u91CD\u5EFA\uFF1B\n // \u4EF7\u683C\u6CE2\u52A8\u7F13\u5B58\u540C\u6837\u6309\u51ED\u636E\u952E\u63A7\uFF0C\u4E00\u5E76\u4F5C\u5E9F\uFF08\u907F\u514D\u65E7\u8BA1\u6570/\u65E7\u9274\u6743\u5931\u8D25\u6001\u6B8B\u7559\uFF09\n stateMemo.invalidate();\n priceCountsMemo.invalidate();\n return sendJson(res, 200, { ok: true, config: maskConfig(updated), balance });\n }\n\n // GET /balance\n if (pathname === '/balance' && (req.method === 'GET' || req.method === 'HEAD')) {\n const config = await configAccess.readConfig();\n const token = config.accessToken || '';\n const balance = await fetchBalance(config.baseURL, config.apiKey, config.userId, token);\n const recentLogs = await fetchRecentLogs(config.userId, token, 20);\n return sendJson(res, 200, { ok: true, balance, recentLogs });\n }\n\n // GET /logs\n if (pathname === '/logs' && (req.method === 'GET' || req.method === 'HEAD')) {\n const config = await configAccess.readConfig();\n const token = config.accessToken || '';\n const recentLogs = await fetchRecentLogs(config.userId, token, 30);\n return sendJson(res, 200, { ok: true, logs: recentLogs });\n }\n\n // POST /probe\n if (pathname === '/probe' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const config = await configAccess.readConfig();\n const token = config.accessToken || '';\n const modelName = body.modelName;\n\n if (modelName && modelName !== 'all') {\n const result = await probeSingleModel(config.baseURL, config.apiKey, config.userId, token, modelName);\n if (result.merchant) {\n merchantCardCache.set(modelName.toLowerCase(), { card: result.merchant, at: Date.now() });\n }\n // \u63A2\u6D4B\u4F1A\u5199\u5165\u8DEF\u7531\u65E5\u5FD7/\u66F4\u65B0\u5546\u6237\u5361\u7247\uFF1A\u4F5C\u5E9F /state \u77ED\u7F13\u5B58\uFF0C\u8BA9\u5361\u7247\u5373\u65F6\u53CD\u6620\u65B0\u63A2\u6D4B\u7ED3\u679C\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, result });\n }\n\n // Probe all models in token\n let modelIds: string[] = body.modelNames;\n if (!Array.isArray(modelIds) || modelIds.length === 0) {\n modelIds = await fetchTokenModels(config.baseURL, config.apiKey);\n }\n if (modelIds.length === 0) {\n modelIds = await configAccess.getDshConfiguredModels();\n }\n\n const results = [];\n for (const m of modelIds) {\n const r = await probeSingleModel(config.baseURL, config.apiKey, config.userId, token, m);\n if (r.merchant) {\n merchantCardCache.set(m.toLowerCase(), { card: r.merchant, at: Date.now() });\n }\n results.push(r);\n }\n\n // \u5168\u91CF\u63A2\u6D4B\u540C\u6837\u4F1A\u5237\u65B0\u65E5\u5FD7\u4E0E\u5546\u6237\u5361\u7247\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, results });\n }\n\n // POST /sync-models\n if (pathname === '/sync-models' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n await configAccess.ensureMigrated();\n const config = await configAccess.readConfig();\n const modelIds = Array.isArray(body.modelIds) ? body.modelIds : [];\n const baseURL = body.baseURL || config.baseURL;\n\n // \u6A21\u578B\u5217\u8868\u552F\u4E00\u771F\u76F8\u6E90 = DSH settings.yaml \u7684 llm-pi-ai.providers.a6api.models\n await configAccess.syncModels(baseURL, modelIds);\n\n const dshConfiguredModels = await configAccess.getDshConfiguredModels();\n // DSH \u5DF2\u542F\u7528\u6A21\u578B\u5217\u8868\u5DF2\u53D8\u66F4\uFF08\u54CD\u5E94\u542B dshConfiguredModels/\u56DE\u9000\u6A21\u578B\u5217\u8868\uFF09\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, dshConfiguredModels });\n }\n\n // POST /pin \u2014 \u628A\u5361\u7247\u5F53\u524D\u5546\u5BB6\u56FA\u5B9A\u4E3A\u8BE5\u6A21\u578B\u7684\u670D\u52A1\u6E20\u9053\uFF08\u5E73\u53F0\u4FA7\uFF0C\u6309 API Key \u4EE4\u724C\u7ED1\u5B9A\uFF09\n if (pathname === '/pin' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const config = await configAccess.readConfig();\n const modelName = String(body.modelName || '').trim();\n if (!modelName) return sendJson(res, 400, { ok: false, error: '\u7F3A\u5C11\u6A21\u578B\u540D\u79F0' });\n const { userId, token } = webAuthOf(config);\n if (!userId || !token) {\n return sendJson(res, 400, { ok: false, error: '\u9700\u5728\u300C\u57FA\u7840\u914D\u7F6E\u300D\u586B\u5199\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C/\u4F1A\u8BDD\u540E\u624D\u80FD\u56FA\u5B9A\u5546\u5BB6' });\n }\n // \u56FA\u5B9A\u7684\u662F\u5361\u7247\u5F53\u524D\u5C55\u793A\u7684\u5546\u5BB6\uFF08\u65E0\u5546\u5BB6\u9009\u62E9\u5668\uFF09\n let card = cachedMerchantOf(modelName);\n // token_id \u89E3\u6790\u94FE\uFF1A\u914D\u7F6E\u7F13\u5B58 \u2192 \u4EE4\u724C\u5217\u8868 \u2192 \u63A2\u6D4B\u65E5\u5FD7\uFF081-token\uFF09\n let tokenId = await resolveTokenId(config);\n // \u5361\u7247\u7F3A\u5931\u6216\u4EE4\u724C\u672A\u89E3\u6790\u65F6\uFF0C\u7528\u4E00\u6B21\u63A2\u6D4B\u540C\u65F6\u56DE\u586B\u4E24\u8005\uFF08\u63A2\u6D4B\u8BF7\u6C42\u672C\u8EAB\u4F1A\u5199\u8DEF\u7531\u65E5\u5FD7\uFF09\n if ((!card || !tokenId) && config.apiKey) {\n let probedOk = false;\n try {\n const probe = await probeSingleModel(config.baseURL, config.apiKey, userId, token, modelName);\n probedOk = Boolean(probe && probe.success);\n if (!tokenId && probe.tokenId && Number(probe.tokenId) > 0) tokenId = Number(probe.tokenId);\n if (!card && probe.merchant) {\n card = probe.merchant;\n merchantCardCache.set(modelName.toLowerCase(), { card, at: Date.now() });\n }\n } catch {}\n // \u63A2\u6D4B\u5DF2\u5199\u8DEF\u7531\u65E5\u5FD7/\u53EF\u80FD\u66F4\u65B0\u5546\u6237\u5361\u7247\uFF1A\u5373\u4F7F\u4E3B\u64CD\u4F5C\u968F\u540E\u5931\u8D25\u4E5F\u5148\u5931\u6548\uFF0C\u907F\u514D\u65E7\u5361\u7247\u88AB\u7F13\u5B58\u957F\u671F\u670D\u52A1\n if (probedOk) stateMemo.invalidate();\n }\n if (!card) {\n return sendJson(res, 400, { ok: false, error: '\u8BE5\u6A21\u578B\u6682\u65E0\u5546\u5BB6\u6570\u636E\uFF0C\u8BF7\u5148\u300C\u63A2\u6D4B\u5546\u5BB6\u300D' });\n }\n if (!tokenId) {\n return sendJson(res, 400, { ok: false, error: '\u65E0\u6CD5\u81EA\u52A8\u89E3\u6790 API Key \u5BF9\u5E94\u7684\u4EE4\u724C ID\uFF0C\u8BF7\u68C0\u67E5\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\u662F\u5426\u6709\u6548\uFF0C\u6216\u5230\u5B98\u7F51\u300C\u4EE4\u724C\u300D\u9875\u624B\u52A8\u56FA\u5B9A' });\n }\n if (!card.channel_id) {\n return sendJson(res, 400, { ok: false, error: '\u5546\u5BB6\u5361\u7247\u7F3A\u5C11\u6E20\u9053 ID\uFF0C\u8BF7\u91CD\u65B0\u63A2\u6D4B' });\n }\n const pinResult = await marketplacePin(userId, token, {\n token_id: tokenId,\n channel_id: card.channel_id,\n model_name: modelName,\n // \u5E73\u53F0\u9ED8\u8BA4\u515C\u5E95\uFF1A\u6E20\u9053\u5F02\u5E38\u65F6\u81EA\u52A8\u5207\u6362\u667A\u80FD\u4F18\u9009\uFF08\u4E0D\u66B4\u9732 UI \u5F00\u5173\uFF09\n fallback_to_smart_routing: true,\n });\n if (!pinResult.ok) {\n return sendJson(res, 400, { ok: false, error: pinResult.message || '\u56FA\u5B9A\u5931\u8D25' });\n }\n // \u66F4\u65B0\u5185\u5B58\u4EE4\u724C\u89E3\u6790\u7F13\u5B58\uFF08tokenId \u4E3A\u6D3E\u751F\u6570\u636E\uFF0C\u4E0D\u6301\u4E45\u5316\uFF09\n tokenResolveCache = { tokenId, at: Date.now() };\n merchantCardCache.set(modelName.toLowerCase(), {\n card: { ...card, is_pinned: true, pin_status: 'pin_here' },\n at: Date.now(),\n });\n const pinList = await fetchMarketplacePins(userId, token);\n // \u56FA\u5B9A\u72B6\u6001\u5DF2\u53D8\u66F4\uFF1A\u4F5C\u5E9F /state \u77ED\u7F13\u5B58\uFF0C\u968F\u540E\u7684 fetchState \u7ACB\u5373\u91CD\u5EFA\uFF08\u542B\u65B0\u7684 pin \u53E0\u52A0\uFF09\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, message: `\u5DF2\u56FA\u5B9A ${modelName} \u81F3\u5546\u6237 #${card.channel_id}`, pins: pinList, tokenId });\n }\n\n // POST /unpin \u2014 \u53D6\u6D88\u8BE5\u6A21\u578B\u7684\u56FA\u5B9A\uFF08\u53D6\u6D88\u540E\u91CD\u65B0\u63A2\u6D4B\u5373\u53EF\u8DEF\u7531\u5230\u65B0\u5546\u5BB6\uFF09\n if (pathname === '/unpin' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const config = await configAccess.readConfig();\n const modelName = String(body.modelName || '').trim();\n if (!modelName) return sendJson(res, 400, { ok: false, error: '\u7F3A\u5C11\u6A21\u578B\u540D\u79F0' });\n const { userId, token } = webAuthOf(config);\n if (!userId || !token) {\n return sendJson(res, 400, { ok: false, error: '\u9700\u5728\u300C\u57FA\u7840\u914D\u7F6E\u300D\u586B\u5199\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C/\u4F1A\u8BDD\u540E\u624D\u80FD\u53D6\u6D88\u56FA\u5B9A' });\n }\n const tokenId = await resolveTokenId(config);\n if (!tokenId) {\n return sendJson(res, 400, { ok: false, error: '\u65E0\u6CD5\u89E3\u6790 API Key \u5BF9\u5E94\u7684\u4EE4\u724C ID\uFF08\u591A\u4EE4\u724C\u8D26\u53F7\u9700\u4FDD\u8BC1\u4EE4\u724C\u5217\u8868\u53EF\u8BFB\uFF09\uFF1B\u53EF\u5148\u300C\u63A2\u6D4B\u5546\u5BB6\u300D\u4E00\u6B21\u540E\u91CD\u8BD5\uFF0C\u6216\u5230\u5B98\u7F51\u624B\u52A8\u53D6\u6D88' });\n }\n // \u4E0A\u6E38 pr195 \u8D77 unpin \u5FC5\u987B\u643A\u5E26 channel_id\uFF08\u56FA\u5B9A\u6240\u5C5E\u6E20\u9053\uFF09\uFF1A\n // \u4F18\u5148\u53D6\u5BA2\u6237\u7AEF\u5361\u7247\u4E0A\u7684\u56FA\u5B9A\u6E20\u9053\uFF08pinnedChannelId / \u5361\u7247\u5546\u5BB6\uFF09\uFF0C\u515C\u5E95\u670D\u52A1\u7AEF\u5546\u6237\u5361\u7247\u7F13\u5B58\n let channelId = Number(body.channelId) > 0 ? Number(body.channelId) : 0;\n if (!channelId) {\n const card = cachedMerchantOf(modelName);\n if (card?.channel_id) channelId = Number(card.channel_id);\n }\n if (!channelId) {\n return sendJson(res, 400, { ok: false, error: '\u672A\u80FD\u786E\u5B9A\u8BE5\u6A21\u578B\u56FA\u5B9A\u6240\u5C5E\u7684\u5546\u5BB6\u6E20\u9053\uFF08\u4E0A\u6E38\u53D6\u6D88\u56FA\u5B9A\u9700\u8981\u6E20\u9053 ID\uFF09\uFF1B\u8BF7\u5148\u5237\u65B0\u5217\u8868\u6216\u300C\u63A2\u6D4B\u5546\u5BB6\u300D\u4E00\u6B21\u540E\u91CD\u8BD5\uFF0C\u6216\u5230\u5B98\u7F51\u624B\u52A8\u53D6\u6D88' });\n }\n const unpinResult = await marketplaceUnpin(userId, token, { token_id: tokenId, channel_id: channelId, model_name: modelName });\n if (!unpinResult.ok) {\n return sendJson(res, 400, { ok: false, error: unpinResult.message || '\u53D6\u6D88\u56FA\u5B9A\u5931\u8D25' });\n }\n const card = cachedMerchantOf(modelName);\n if (card) {\n merchantCardCache.set(modelName.toLowerCase(), {\n card: { ...card, is_pinned: false, pin_status: undefined },\n at: Date.now(),\n });\n }\n const pinList = await fetchMarketplacePins(userId, token);\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, message: `\u5DF2\u53D6\u6D88\u56FA\u5B9A ${modelName}`, pins: pinList, tokenId });\n }\n\n // POST /disable \u2014 \u7981\u7528\u5361\u7247\u5F53\u524D\u5546\u5BB6\u5BF9\u8BE5\u6A21\u578B\u7684\u670D\u52A1\uFF08\u5E73\u53F0\u4FA7\uFF0C\u6309 \u6E20\u9053\u00D7\u6A21\u578B\uFF09\n if (pathname === '/disable' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const config = await configAccess.readConfig();\n const modelName = String(body.modelName || '').trim();\n if (!modelName) return sendJson(res, 400, { ok: false, error: '\u7F3A\u5C11\u6A21\u578B\u540D\u79F0' });\n let card = cachedMerchantOf(modelName);\n // \u5361\u7247\u7F13\u5B58\u8FC7\u671F\u65F6\u7528\u4E00\u6B21\u63A2\u6D4B\u56DE\u586B\uFF08\u4E0E /pin \u4E00\u81F4\uFF0C\u907F\u514D\u300C\u6309\u94AE\u53EF\u7528\u4F46\u63A5\u53E3 400\u300D\uFF09\n if (!card && config.apiKey) {\n let probedOk = false;\n try {\n const probe = await probeSingleModel(config.baseURL, config.apiKey, config.userId, config.accessToken || '', modelName);\n probedOk = Boolean(probe && probe.success);\n if (probe.merchant) {\n card = probe.merchant;\n merchantCardCache.set(modelName.toLowerCase(), { card, at: Date.now() });\n }\n } catch {}\n // \u63A2\u6D4B\u5DF2\u5199\u8DEF\u7531\u65E5\u5FD7/\u53EF\u80FD\u66F4\u65B0\u5546\u6237\u5361\u7247\uFF1A\u5373\u4F7F\u4E3B\u64CD\u4F5C\u968F\u540E\u5931\u8D25\u4E5F\u5148\u5931\u6548\n if (probedOk) stateMemo.invalidate();\n }\n if (!card || !card.channel_id) {\n return sendJson(res, 400, { ok: false, error: '\u8BE5\u6A21\u578B\u6682\u65E0\u5546\u5BB6\u6570\u636E\uFF0C\u8BF7\u5148\u300C\u63A2\u6D4B\u5546\u5BB6\u300D' });\n }\n const { userId, token } = webAuthOf(config);\n if (!userId || !token) {\n return sendJson(res, 400, { ok: false, error: '\u9700\u5728\u300C\u57FA\u7840\u914D\u7F6E\u300D\u586B\u5199\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C/\u4F1A\u8BDD\u540E\u624D\u80FD\u7981\u7528\u5546\u5BB6' });\n }\n const disableResult = await marketplaceDisableChannel(userId, token, card.channel_id, modelName);\n if (!disableResult.ok) {\n return sendJson(res, 400, { ok: false, error: disableResult.message || '\u7981\u7528\u5931\u8D25' });\n }\n merchantCardCache.set(modelName.toLowerCase(), {\n card: { ...card, user_channel_disabled: true },\n at: Date.now(),\n });\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, message: `\u5DF2\u7981\u7528\u5546\u6237 #${card.channel_id} \u5BF9\u8BE5\u6A21\u578B\u7684\u670D\u52A1` });\n }\n\n // POST /restore \u2014 \u6062\u590D\u88AB\u7981\u7528\u7684\u5546\u5BB6\n if (pathname === '/restore' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const config = await configAccess.readConfig();\n const modelName = String(body.modelName || '').trim();\n if (!modelName) return sendJson(res, 400, { ok: false, error: '\u7F3A\u5C11\u6A21\u578B\u540D\u79F0' });\n let card = cachedMerchantOf(modelName);\n if (!card && config.apiKey) {\n let probedOk = false;\n try {\n const probe = await probeSingleModel(config.baseURL, config.apiKey, config.userId, config.accessToken || '', modelName);\n probedOk = Boolean(probe && probe.success);\n if (probe.merchant) {\n card = probe.merchant;\n merchantCardCache.set(modelName.toLowerCase(), { card, at: Date.now() });\n }\n } catch {}\n // \u63A2\u6D4B\u5DF2\u5199\u8DEF\u7531\u65E5\u5FD7/\u53EF\u80FD\u66F4\u65B0\u5546\u6237\u5361\u7247\uFF1A\u5373\u4F7F\u4E3B\u64CD\u4F5C\u968F\u540E\u5931\u8D25\u4E5F\u5148\u5931\u6548\n if (probedOk) stateMemo.invalidate();\n }\n if (!card || !card.channel_id) {\n return sendJson(res, 400, { ok: false, error: '\u8BE5\u6A21\u578B\u6682\u65E0\u5546\u5BB6\u6570\u636E\uFF0C\u8BF7\u5148\u300C\u63A2\u6D4B\u5546\u5BB6\u300D' });\n }\n const { userId, token } = webAuthOf(config);\n if (!userId || !token) {\n return sendJson(res, 400, { ok: false, error: '\u9700\u5728\u300C\u57FA\u7840\u914D\u7F6E\u300D\u586B\u5199\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C/\u4F1A\u8BDD\u540E\u624D\u80FD\u6062\u590D\u5546\u5BB6' });\n }\n const restoreResult = await marketplaceRestoreChannel(userId, token, card.channel_id, modelName);\n if (!restoreResult.ok) {\n return sendJson(res, 400, { ok: false, error: restoreResult.message || '\u6062\u590D\u5931\u8D25' });\n }\n merchantCardCache.set(modelName.toLowerCase(), {\n card: { ...card, user_channel_disabled: false },\n at: Date.now(),\n });\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, message: `\u5DF2\u6062\u590D\u5546\u6237 #${card.channel_id} \u5BF9\u8BE5\u6A21\u578B\u7684\u670D\u52A1` });\n }\n\n // GET /price-fluctuation \u2014 \u8F7B\u91CF\u4EF7\u683C\u6CE2\u52A8\u6761\u6570\uFF08\u5F85\u5904\u7406 n\uFF09\uFF0C\u4EC5\u56DE\u4F20\u8BA1\u6570\uFF1B\n // \u670D\u52A1\u7AEF\u77ED\u7F13\u5B58 + \u5E76\u53D1\u53BB\u91CD\uFF1A\u591A\u6807\u7B7E\u9875/\u8F6E\u8BE2\u5171\u4EAB\u540C\u4E00\u4EFD\u4EF7\u683C\u901A\u77E5\u4E0A\u6E38\u7ED3\u679C\n if (pathname === '/price-fluctuation' && (req.method === 'GET' || req.method === 'HEAD')) {\n const config = await configAccess.readConfig();\n const token = config.accessToken || '';\n if (!token || !config.userId) {\n return sendJson(res, 200, { ok: true, data: { pendingCount: 0, unseenCount: 0, totalCount: 0, hasAuth: false, authError: false, updatedAt: Date.now() } });\n }\n const counts = await priceCountsMemo.get(stateCacheKeyOf(config), async () => {\n const result = await fetchPriceFluctuation(config.userId, token);\n // \u4EC5\u7F13\u5B58\u8BA1\u6570\uFF08notices \u4F53\u91CF\u5927\u4E14\u65E0\u8DE8\u8BF7\u6C42\u590D\u7528\u4EF7\u503C\uFF0C\u4E0D\u4E0B\u53D1\u4E5F\u4E0D\u7F13\u5B58\uFF09\n const { notices, ...rest } = result as any;\n return rest as any;\n });\n // 401/403 \u65F6 authError=true\uFF0C\u5BA2\u6237\u7AEF\u53EF\u533A\u5206\u201C\u672A\u914D\u7F6E\u201D\u4E0E\u201C\u5931\u6548\u201D\n const hasAuth = !counts.authError;\n return sendJson(res, 200, { ok: true, data: { pendingCount: counts.pendingCount, unseenCount: counts.unseenCount, totalCount: counts.totalCount, hasAuth, authError: Boolean(counts.authError), updatedAt: Date.now() } });\n }\n\n // GET /pins \u2014 \u8F7B\u91CF\u56FA\u5B9A\u8BB0\u5F55\uFF08\u5BA2\u6237\u7AEF 60s \u8F6E\u8BE2\uFF0C\u8BA9\u5361\u7247\u72B6\u6001\u8DDF\u968F\u5B98\u7F51\u4FA7\u89E3\u9664/\u65B0\u589E\u56FA\u5B9A\uFF09\n if (pathname === '/pins' && (req.method === 'GET' || req.method === 'HEAD')) {\n const config = await configAccess.readConfig();\n const { userId, token } = webAuthOf(config);\n if (!userId || !token) {\n return sendJson(res, 200, { ok: true, pins: [] });\n }\n try {\n const pins = await fetchMarketplacePins(userId, token);\n return sendJson(res, 200, { ok: true, pins });\n } catch (err: any) {\n console.warn('[dsh-a6api] GET /pins error:', err);\n return sendJson(res, 200, { ok: true, pins: [] });\n }\n }\n\n // GET /catalog \u2014 \u6A21\u578B\u76EE\u5F55\u5168\u91CF\uFF08\u8FD0\u884C\u65F6 JSON\uFF0C\u5B57\u6BB5 = settings.yaml \u539F\u751F\u6A21\u578B\u5B57\u6BB5 + brand\uFF09\n if (pathname === '/catalog' && (req.method === 'GET' || req.method === 'HEAD')) {\n return sendJson(res, 200, { ok: true, catalog: getCatalog() });\n }\n\n // POST /catalog/clear \u2014 \u6E05\u7A7A\u6A21\u578B\u76EE\u5F55\uFF08\u91CD\u65B0\u62C9\u53D6/\u586B\u5145\u524D\u4F7F\u7528\uFF1Bsettings.yaml \u5DF2\u542F\u7528\u6761\u76EE\u4E0D\u53D7\u5F71\u54CD\uFF09\n if (pathname === '/catalog/clear' && req.method === 'POST') {\n await clearCatalog();\n // \u76EE\u5F55\u54C1\u724C/\u53C2\u6570\u53C2\u4E0E /state \u5361\u7247\u5143\u6570\u636E\uFF08resolveModelMeta\uFF09\uFF1A\u4F5C\u5E9F\u77ED\u7F13\u5B58\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true });\n }\n\n // POST /catalog/fetch-models \u2014 \u4ECE A6API \u5E02\u573A\u7FFB\u9875\u62C9\u53D6\u5168\u90E8\u6A21\u578B ID\uFF08\u542B\u54C1\u724C\uFF09\uFF0C\u5408\u5E76\u5165\u76EE\u5F55\u3002\n // \u4EC5\u65B0\u589E\u7F3A\u5931\u6761\u76EE/\u8865\u54C1\u724C/\u8865\u9ED8\u8BA4\u63A8\u7406\u6863\u4F4D\uFF0C\u4E0D\u8986\u76D6\u4EFB\u4F55\u5DF2\u5B58\u5728\u6761\u76EE\u7684\u53C2\u6570\u3002\n if (pathname === '/catalog/fetch-models' && req.method === 'POST') {\n const config = await configAccess.readConfig();\n const { userId, token } = webAuthOf(config);\n let result;\n try {\n result = await fetchMarketplaceModels(userId, token);\n } catch (err: any) {\n // \u672A\u914D\u7F6E\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\u7B49\u9274\u6743\u7C7B\u9519\u8BEF \u2192 400 + \u5F15\u5BFC\u6587\u6848\uFF08\u4E0E /pin \u98CE\u683C\u4E00\u81F4\uFF09\n return sendJson(res, 400, { ok: false, error: err?.message || '\u83B7\u53D6\u5E02\u573A\u6A21\u578B\u5931\u8D25' });\n }\n const models = result.models;\n const before = new Set(getCatalog().map((e) => e.id.toLowerCase()));\n let added = 0;\n for (const m of models) {\n if (!before.has(m.id.toLowerCase())) added++;\n }\n // reasoningEfforts \u9ED8\u8BA4 = DSH \u5168\u90E8\u601D\u8003\u6863\u4F4D\uFF08upsert \u53EA\u8865\u7F3A\u5931\u5B57\u6BB5\uFF0C\u5DF2\u6709\u81EA\u5B9A\u4E49\u4E0D\u53D7\u5F71\u54CD\uFF09\n await upsertCatalogEntries(\n models.map((m) => ({ id: m.id, brand: m.brand, reasoningEfforts: m.reasoningEfforts })),\n );\n // \u76EE\u5F55\u54C1\u724C\u53C2\u4E0E /state \u5361\u7247\u5143\u6570\u636E\uFF1A\u4F5C\u5E9F\u77ED\u7F13\u5B58\n stateMemo.invalidate();\n return sendJson(res, 200, {\n ok: true,\n total: models.length,\n added,\n failedPages: result.failedPages,\n });\n }\n\n // POST /catalog/query-openrouter \u2014 \u5BF9\u5168\u90E8\uFF08\u6216\u6307\u5B9A\uFF09\u76EE\u5F55\u6A21\u578B\u67E5 OpenRouter \u5E76\u586B\u5145\u53C2\u6570\u3002\n // \u80FD\u67E5\u5230\u7684\u586B\u5145 contextWindow/maxTokens/input/name\uFF1B\u67E5\u4E0D\u5230\u7684\u4FDD\u6301\u539F\u5B57\u6BB5\u4E0D\u53D8\u3002\n if (pathname === '/catalog/query-openrouter' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const catalog = getCatalog();\n const modelIds =\n Array.isArray(body.modelIds) && body.modelIds.length > 0\n ? body.modelIds.map((s: any) => String(s))\n : catalog.map((e) => e.id);\n if (modelIds.length === 0) {\n return sendJson(res, 400, { ok: false, error: '\u76EE\u5F55\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u300C\u4ECE A6API \u83B7\u53D6\u5E02\u573A\u6A21\u578B\u300D' });\n }\n const result = await queryOpenRouter(modelIds);\n // \u5DF2\u542F\u7528\u6A21\u578B\u53C2\u6570\u53EF\u80FD\u88AB\u672C\u6B21\u67E5\u8BE2\u586B\u5145\uFF1A\u4E0E /catalog/update \u540C\u4E00\u6570\u636E\u6D41\uFF08\u76EE\u5F55 \u2192 settings.yaml\uFF09\uFF0C\n // \u547D\u4E2D\u5DF2\u542F\u7528\u6A21\u578B\u65F6\u7ACB\u5373\u91CD\u5199 settings.yaml\uFF0C\u53C2\u6570\u5373\u65F6\u751F\u6548\n if (result.updated.length > 0) {\n try {\n const config = await configAccess.readConfig();\n const dshModels = await configAccess.getDshConfiguredModels();\n const dshSet = new Set(dshModels.map((m) => m.toLowerCase()));\n if (config.activeModels.length > 0 && result.updated.some((u) => dshSet.has(u.id.toLowerCase()))) {\n await configAccess.syncModels(config.baseURL, config.activeModels);\n }\n } catch (err: any) {\n console.warn('[dsh-a6api] query-openrouter: resync settings failed:', err?.message || err);\n }\n }\n // contextWindow/maxTokens \u7B49\u76EE\u5F55\u5B57\u6BB5\u53C2\u4E0E /state \u5361\u7247\u5143\u6570\u636E\uFF1A\u4F5C\u5E9F\u77ED\u7F13\u5B58\n stateMemo.invalidate();\n return sendJson(res, 200, {\n ok: true,\n updated: result.updated.length,\n notFound: result.notFound,\n });\n }\n\n // POST /catalog/update \u2014 \u4FEE\u6539\u5355\u4E2A\u76EE\u5F55\u6761\u76EE\u53C2\u6570\uFF08name/contextWindow/maxTokens/input/reasoningEfforts\uFF09\u3002\n // \u82E5\u8BE5\u6A21\u578B\u5DF2\u5728 DSH \u542F\u7528\uFF0C\u7ACB\u5373\u91CD\u5199 settings.yaml \u5BF9\u5E94\u6761\u76EE\u4F7F\u53C2\u6570\u5373\u65F6\u751F\u6548\u3002\n if (pathname === '/catalog/update' && req.method === 'POST') {\n const body = await parseJsonBody(req);\n const id = String(body.id || '').trim();\n if (!id) return sendJson(res, 400, { ok: false, error: '\u7F3A\u5C11\u6A21\u578B ID' });\n const patch: Record<string, any> = {};\n // null = \u5220\u9664\u8BE5\u5B57\u6BB5\uFF08\u6E05\u7A7A\u8BED\u4E49\uFF09\uFF1Bundefined = \u4E0D\u4FEE\u6539\n if (body.name !== undefined) {\n if (body.name === null) {\n patch.name = null;\n } else if (typeof body.name !== 'string') {\n return sendJson(res, 400, { ok: false, error: 'name \u5FC5\u987B\u662F\u5B57\u7B26\u4E32' });\n } else {\n const name = body.name.trim();\n patch.name = name || null;\n }\n }\n for (const key of ['contextWindow', 'maxTokens'] as const) {\n if (body[key] === null) {\n patch[key] = null;\n } else if (body[key] !== undefined) {\n const n = Number(body[key]);\n if (!Number.isInteger(n) || n < 1) {\n return sendJson(res, 400, { ok: false, error: `${key} \u5FC5\u987B\u662F\u6B63\u6574\u6570` });\n }\n patch[key] = n;\n }\n }\n if (body.input !== undefined) {\n if (body.input === null) {\n patch.input = null;\n } else if (!Array.isArray(body.input)) {\n return sendJson(res, 400, { ok: false, error: 'input \u5FC5\u987B\u662F\u6570\u7EC4' });\n } else {\n const mods = body.input.filter((m: any) => m === 'text' || m === 'image');\n // \u7A7A\u6570\u7EC4 = \u6E05\u7A7A\u8BE5\u5B57\u6BB5\uFF08null \u8BED\u4E49\u5220\u9664\uFF09\n patch.input = mods.length > 0 ? mods : null;\n }\n }\n if (body.reasoningEfforts !== undefined) {\n if (body.reasoningEfforts === null) {\n patch.reasoningEfforts = null; // \u5220\u9664\u8BE5\u5B57\u6BB5\n } else {\n // DSH \u8BED\u4E49\u4E25\u683C\u6821\u9A8C\uFF1A\u952E \u2208 THINKING_LEVELS\u3001\u503C\u975E\u7A7A\uFF08\u4EC5 off \u53EF null\uFF09\u3001\u975E\u7A7A\u5B57\u5178\u3001\u81F3\u5C11\u4E00\u4E2A\u975E off \u6863\u4F4D\n const v = validateReasoningEfforts(body.reasoningEfforts);\n if (!v.ok) return sendJson(res, 400, { ok: false, error: v.error });\n patch.reasoningEfforts = v.value;\n }\n }\n const entry = await updateCatalogEntry(id, patch);\n if (!entry) return sendJson(res, 404, { ok: false, error: '\u76EE\u5F55\u4E2D\u4E0D\u5B58\u5728\u8BE5\u6A21\u578B' });\n\n // \u5DF2\u542F\u7528\u6A21\u578B\uFF1A\u7ACB\u5373\u91CD\u5199 settings.yaml \u5BF9\u5E94\u6761\u76EE\uFF08\u53C2\u6570\u5373\u65F6\u751F\u6548\uFF0C\u5355\u4E00\u6570\u636E\u6D41\uFF1A\u76EE\u5F55 \u2192 settings.yaml\uFF09\n try {\n const config = await configAccess.readConfig();\n const dshModels = await configAccess.getDshConfiguredModels();\n if (dshModels.some((m) => m.toLowerCase() === entry.id.toLowerCase()) && config.activeModels.length > 0) {\n await configAccess.syncModels(config.baseURL, config.activeModels);\n }\n } catch (err: any) {\n console.warn('[dsh-a6api] catalog update: resync settings failed:', err?.message || err);\n }\n // \u76EE\u5F55\u6761\u76EE\u5DF2\u53D8\u66F4\uFF08\u5361\u7247\u5143\u6570\u636E/\u5DF2\u542F\u7528\u6A21\u578B\u53C2\u6570\u5747\u53D7\u5F71\u54CD\uFF09\uFF1A\u4F5C\u5E9F\u77ED\u7F13\u5B58\n stateMemo.invalidate();\n return sendJson(res, 200, { ok: true, entry });\n }\n\n return sendJson(res, 404, { ok: false, error: 'Not found' });\n } catch (err: any) {\n console.error('[dsh-a6api] API error:', err);\n return sendJson(res, 500, { ok: false, error: err?.message || String(err) });\n }\n },\n });\n\n return () => {\n if (typeof unregister === 'function') unregister();\n };\n }, 'dsh-a6api: web API router');\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["path", "name", "buildWebHeaders", "sleep", "resolve", "name", "fs", "fsp", "path", "lines", "resolve", "card", "name"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynn123411/dsh-a6api",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"description": "A6API 多模型聚合站接入插件:原生 LLM 提供商注册、账户实时余额与价格波动监控、Token 白名单同步、商户线路探测与全景指标卡片",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "lynn123411",
|
|
@@ -64,12 +64,13 @@
|
|
|
64
64
|
"node": "^22.19 || >=24"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
+
"@deepseek-ai/dsh-home-paths": "0.1.3-alpha.2",
|
|
67
68
|
"@types/node": "^22.19.0",
|
|
68
69
|
"@types/react": "^19.2.18",
|
|
69
70
|
"esbuild": "^0.25.0",
|
|
70
71
|
"typescript": "^6.0.0"
|
|
71
72
|
},
|
|
72
|
-
"
|
|
73
|
-
"@deepseek-ai/dsh-home-paths": "0.1.3-alpha.2"
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.3-alpha.2"
|
|
74
75
|
}
|
|
75
76
|
}
|