@lynn123411/dsh-a6api 1.5.8 → 1.5.9

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 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.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-home-paths/lib/index.js
6
+ // node_modules/.pnpm/@deepseek-ai+dsh-home-paths@0.1.5-rc.1_@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";
@@ -1758,6 +1758,8 @@ function validateReasoningEfforts(value) {
1758
1758
  var name = "@lynn123411/dsh-a6api";
1759
1759
  var inject = ["webServer"];
1760
1760
  var PREFIX = "/api/dsh-a6api";
1761
+ var PROBE_ALL_DEADLINE_MS = 5 * 60 * 1e3;
1762
+ var PROBE_ALL_CONCURRENCY = 4;
1761
1763
  var MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
1762
1764
  function maskConfig(c) {
1763
1765
  return {
@@ -1800,6 +1802,10 @@ async function parseJsonBody(req) {
1800
1802
  throw new Error("Invalid JSON body");
1801
1803
  }
1802
1804
  }
1805
+ var LOOPBACK_ADDRESSES = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "::ffff:127.0.0.1"]);
1806
+ function isLoopbackRequest(req) {
1807
+ return LOOPBACK_ADDRESSES.has(String(req?.socket?.remoteAddress || ""));
1808
+ }
1803
1809
  var merchantCardCache = /* @__PURE__ */ new Map();
1804
1810
  var MERCHANT_CARD_TTL_MS = 15 * 60 * 1e3;
1805
1811
  var tokenResolveCache = null;
@@ -2074,6 +2080,9 @@ function apply(ctx) {
2074
2080
  if (req.method === "POST" && !String(req.headers["content-type"] || "").toLowerCase().includes("application/json")) {
2075
2081
  return sendJson(res, 415, { ok: false, error: "Content-Type must be application/json" });
2076
2082
  }
2083
+ if (req.method === "POST" && !isLoopbackRequest(req)) {
2084
+ return sendJson(res, 403, { ok: false, error: "Forbidden: \u5199\u64CD\u4F5C\u4EC5\u5141\u8BB8\u672C\u673A\u56DE\u73AF\u8C03\u7528" });
2085
+ }
2077
2086
  try {
2078
2087
  if (pathname === "/state" && (req.method === "GET" || req.method === "HEAD")) {
2079
2088
  const config = await configAccess.readConfig();
@@ -2148,16 +2157,52 @@ function apply(ctx) {
2148
2157
  if (modelIds.length === 0) {
2149
2158
  modelIds = await configAccess.getDshConfiguredModels();
2150
2159
  }
2151
- const results = [];
2152
- for (const m of modelIds) {
2153
- const r = await probeSingleModel(config.baseURL, config.apiKey, config.userId, token, m);
2154
- if (r.merchant) {
2155
- merchantCardCache.set(m.toLowerCase(), { card: r.merchant, at: Date.now() });
2160
+ const deadlineAt = Date.now() + PROBE_ALL_DEADLINE_MS;
2161
+ const results = new Array(modelIds.length);
2162
+ let nextIndex = 0;
2163
+ const worker = async () => {
2164
+ for (; ; ) {
2165
+ if (Date.now() >= deadlineAt) return;
2166
+ const i = nextIndex++;
2167
+ if (i >= modelIds.length) return;
2168
+ const m = modelIds[i];
2169
+ try {
2170
+ const r = await probeSingleModel(config.baseURL, config.apiKey, config.userId, token, m);
2171
+ if (r.merchant) {
2172
+ merchantCardCache.set(m.toLowerCase(), { card: r.merchant, at: Date.now() });
2173
+ }
2174
+ results[i] = r;
2175
+ } catch (err) {
2176
+ results[i] = { modelName: m, success: false, error: err?.message || String(err) };
2177
+ }
2156
2178
  }
2157
- results.push(r);
2179
+ };
2180
+ let deadlineTimer = null;
2181
+ try {
2182
+ await Promise.race([
2183
+ Promise.all(
2184
+ Array.from({ length: Math.min(PROBE_ALL_CONCURRENCY, modelIds.length) }, () => worker())
2185
+ ),
2186
+ // 到点即返回:在途探测不取消(各自仍有 180s 上限,其结果照常回填卡片缓存),
2187
+ // 但响应不再等待它们 —— 总墙钟时间被钉在预算内。
2188
+ new Promise((resolve2) => {
2189
+ deadlineTimer = setTimeout(resolve2, PROBE_ALL_DEADLINE_MS);
2190
+ })
2191
+ ]);
2192
+ } finally {
2193
+ if (deadlineTimer) clearTimeout(deadlineTimer);
2158
2194
  }
2195
+ const done = results.filter((r) => Boolean(r));
2196
+ const timedOut = done.length < modelIds.length;
2159
2197
  stateMemo.invalidate();
2160
- return sendJson(res, 200, { ok: true, results });
2198
+ return sendJson(res, 200, {
2199
+ ok: true,
2200
+ results: done,
2201
+ completed: done.length,
2202
+ total: modelIds.length,
2203
+ timedOut,
2204
+ error: timedOut ? `\u5168\u91CF\u63A2\u6D4B\u8D85\u51FA\u603B\u9884\u7B97 ${PROBE_ALL_DEADLINE_MS / 1e3}s\uFF0C\u5DF2\u8FD4\u56DE ${done.length}/${modelIds.length} \u4E2A\u5DF2\u5B8C\u6210\u7ED3\u679C` : void 0
2205
+ });
2161
2206
  }
2162
2207
  if (pathname === "/sync-models" && req.method === "POST") {
2163
2208
  const body = await parseJsonBody(req);