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 +17 -5
- package/package.json +1 -1
- package/src/routes.js +21 -1
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
|
|
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
|
-
|
|
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
|
|
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
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) {
|