mslxdff 0.1.7 → 0.1.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/bin/mslxdff.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { execFile } from "node:child_process";
3
3
  import { readFileSync, existsSync, statSync, watch, openSync, closeSync, mkdirSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
- import { dirname, join } from "node:path";
5
+ import { dirname, join, basename } from "node:path";
6
6
  import { startServer, resolvePort } from "../src/server.js";
7
7
  import { createRouter } from "../src/routes.js";
8
8
  import { createUpstreamClient } from "../src/upstream.js";
@@ -656,13 +656,18 @@ function fmtStatus(id, statuses) {
656
656
  return `${e.status}${when}${code}`;
657
657
  }
658
658
 
659
+ function fmtDur(ms) {
660
+ if (!Number.isFinite(ms)) return "?";
661
+ return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
662
+ }
663
+
659
664
  function fmtEvent(e) {
660
665
  const t = e?.ts ? new Date(e.ts).toISOString().slice(11, 19) : "--:--:--";
661
666
  const head = `[${t}]`;
662
667
  const m = (x) => x || "-";
663
668
  switch (e?.type) {
664
669
  case "request":
665
- return `${head} request ${m(e.model)}${e.auto ? " (auto)" : ""} hops=${e.hops} from ${e.ip || "?"}${e.stream ? " stream" : ""}`;
670
+ return `${head} request ${m(e.model)}${e.auto ? " (auto)" : ""} hops=${e.hops} from ${e.ip || "?"}${e.stream ? " stream" : ""}${e.prompt ? ` content="${e.prompt}"` : ""}`;
666
671
  case "upstream-error":
667
672
  return `${head} upstream err ${m(e.model)} ${e.status ? `HTTP ${e.status}` : "network"}: ${m(e.message)}`;
668
673
  case "peer-health":
@@ -672,7 +677,7 @@ function fmtEvent(e) {
672
677
  case "peer-error":
673
678
  return `${head} peer err ${e.peer} ${e.status ? `HTTP ${e.status}` : "network"}: ${m(e.message)}`;
674
679
  case "result":
675
- return `${head} result ${e.status} ${m(e.model)} via=${e.via} ${e.durationMs ?? "?"}ms`;
680
+ return `${head} result ${e.status} ${m(e.model)} via=${e.via} 响应耗时 ${fmtDur(e.durationMs)}`;
676
681
  default:
677
682
  return `${head} ${e?.type || "?"} ${JSON.stringify(e || {})}`;
678
683
  }
@@ -728,11 +733,18 @@ async function liveDebug() {
728
733
  }
729
734
  };
730
735
  try {
731
- watch(file, { persistent: true }, pump);
736
+ mkdirSync(dirname(file), { recursive: true });
737
+ watch(dirname(file), (_evt, filename) => {
738
+ if (!filename || basename(String(filename)) !== basename(file)) return;
739
+ pump();
740
+ });
732
741
  } catch {
733
- console.error(`cannot watch event file: ${file}`);
742
+ console.error(`cannot watch event dir: ${dirname(file)}`);
734
743
  process.exit(1);
735
744
  }
745
+ // fs.watch is unreliable for freshly-created files on Windows — poll as a
746
+ // safety net so events are never missed.
747
+ setInterval(pump, 250);
736
748
  pump();
737
749
  await new Promise(() => {}); // run until Ctrl+C
738
750
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {
package/src/routes.js CHANGED
@@ -117,6 +117,26 @@ export async function peerHealthyModels(peer, { timeoutMs = PEER_STATUS_TIMEOUT_
117
117
  }
118
118
  }
119
119
 
120
+ export const PROMPT_MAX_LEN = 160;
121
+
122
+ // Human-debuggable summary of the request body: the last non-empty message
123
+ // text (multi-modal parts joined), whitespace-flattened and truncated.
124
+ export function summarizePrompt(body) {
125
+ const msgs = body?.messages;
126
+ if (!Array.isArray(msgs) || !msgs.length) return "";
127
+ const msg = msgs[msgs.length - 1];
128
+ const c = msg?.content;
129
+ let text = "";
130
+ if (typeof c === "string") text = c;
131
+ else if (Array.isArray(c)) {
132
+ text = c
133
+ .map((p) => (typeof p === "string" ? p : p && typeof p.text === "string" ? p.text : ""))
134
+ .join(" ");
135
+ }
136
+ text = String(text || "").replace(/\s+/g, " ").trim();
137
+ return text.length > PROMPT_MAX_LEN ? text.slice(0, PROMPT_MAX_LEN) + "…" : text;
138
+ }
139
+
120
140
  function parseHops(header) {
121
141
  const n = Number(header);
122
142
  return Number.isInteger(n) && n >= 0 ? n : 0;
@@ -186,7 +206,7 @@ const ROUTES = [
186
206
  const logError = (model, status, message) =>
187
207
  logs?.appendError({ model, auto: useAuto, status, message });
188
208
  const evt = (type, data) => logs?.appendEvent?.({ type, ...data, model: data.model ?? requested, auto: useAuto, durationMs: Date.now() - startedAt });
189
- evt("request", { hops, ip: clientIp(req), stream: Boolean(body.stream) });
209
+ evt("request", { hops, ip: clientIp(req), stream: Boolean(body.stream), prompt: summarizePrompt(body) });
190
210
 
191
211
  let lastErr = null;
192
212
  for (const model of order) {