reasonix 0.43.0 → 0.44.0
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/README.md +49 -11
- package/README.zh-CN.md +35 -7
- package/dashboard/app.css +225 -4
- package/dashboard/dist/app.js +6441 -6080
- package/dashboard/dist/app.js.map +1 -1
- package/data/deepseek-tokenizer.json.gz +0 -0
- package/dist/cli/{acp-DAGPCVFZ.js → acp-TYZ2CTDL.js} +28 -30
- package/dist/cli/acp-TYZ2CTDL.js.map +1 -0
- package/dist/cli/chat-TH7VNNCJ.js +51 -0
- package/dist/cli/chunk-2425HK6U.js +0 -0
- package/dist/cli/chunk-25T6CVUP.js +0 -0
- package/dist/cli/chunk-2UQP6H6T.js +0 -0
- package/dist/cli/{chunk-3Z6IBU3D.js → chunk-2V6EAEUW.js} +95 -31
- package/dist/cli/chunk-2V6EAEUW.js.map +1 -0
- package/dist/cli/{chunk-XCGGEJTI.js → chunk-4CTDEJUF.js} +2 -2
- package/dist/cli/chunk-4QUNBQQ2.js +0 -0
- package/dist/cli/{chunk-74EX7SUH.js → chunk-5QCB62C4.js} +33 -7
- package/dist/cli/{chunk-74EX7SUH.js.map → chunk-5QCB62C4.js.map} +1 -1
- package/dist/cli/chunk-6OWJV3YW.js +390 -0
- package/dist/cli/chunk-6OWJV3YW.js.map +1 -0
- package/dist/cli/chunk-6PBZN4VI.js +0 -0
- package/dist/cli/{chunk-7O5ALB4C.js → chunk-7CIGMZT3.js} +2 -2
- package/dist/cli/{chunk-H6PS7IUE.js → chunk-7UCMM425.js} +7 -3
- package/dist/cli/chunk-7UCMM425.js.map +1 -0
- package/dist/cli/{chunk-TJX6BFZZ.js → chunk-AB2RED3C.js} +3 -3
- package/dist/cli/{chunk-XPDVG52A.js → chunk-AVFXO2EZ.js} +361 -13
- package/dist/cli/chunk-AVFXO2EZ.js.map +1 -0
- package/dist/cli/{chunk-FHOGSSCH.js → chunk-C53JQES5.js} +3 -3
- package/dist/cli/{chunk-RE4RAVFF.js → chunk-CGDR2ELH.js} +92 -30
- package/dist/cli/chunk-CGDR2ELH.js.map +1 -0
- package/dist/cli/{chunk-OSZC7C6F.js → chunk-CWZKQ5FE.js} +7 -4
- package/dist/cli/chunk-CWZKQ5FE.js.map +1 -0
- package/dist/cli/{devtools-YECO25QO.js → chunk-FEZK652I.js} +10 -85
- package/dist/cli/chunk-FEZK652I.js.map +1 -0
- package/dist/cli/{chunk-45U62RI3.js → chunk-HNXDZGC6.js} +104 -2
- package/dist/cli/chunk-HNXDZGC6.js.map +1 -0
- package/dist/cli/chunk-J5XJHLWM.js +0 -0
- package/dist/cli/chunk-JMBMLOBP.js +0 -0
- package/dist/cli/{chunk-5JJRUIPA.js → chunk-JNAQYELD.js} +16 -8
- package/dist/cli/{chunk-5JJRUIPA.js.map → chunk-JNAQYELD.js.map} +1 -1
- package/dist/cli/{chunk-YFGF5NKA.js → chunk-KGBG6M2X.js} +19 -15
- package/dist/cli/chunk-KGBG6M2X.js.map +1 -0
- package/dist/cli/{chunk-3BXRZFWS.js → chunk-KLQTAZIY.js} +12 -4
- package/dist/cli/chunk-KLQTAZIY.js.map +1 -0
- package/dist/cli/{chunk-VK5HG73G.js → chunk-KM465GST.js} +9 -9
- package/dist/cli/{chunk-DOYHN4KB.js → chunk-LIR2HBQH.js} +2 -2
- package/dist/cli/{chunk-YYQAUTTN.js → chunk-MJ6W5UN3.js} +2 -2
- package/dist/cli/{chunk-6PZ3CXBP.js → chunk-MRHHQJAQ.js} +5 -4
- package/dist/cli/chunk-MRHHQJAQ.js.map +1 -0
- package/dist/cli/{chunk-PQXPXJBJ.js → chunk-NVURFF27.js} +16 -5
- package/dist/cli/chunk-NVURFF27.js.map +1 -0
- package/dist/cli/{chunk-2R4QCDOZ.js → chunk-OPFUUYHL.js} +540 -287
- package/dist/cli/chunk-OPFUUYHL.js.map +1 -0
- package/dist/cli/chunk-PLHAZOLZ.js +0 -0
- package/dist/cli/{chunk-HFEAY5DT.js → chunk-R3CTO2HM.js} +2 -2
- package/dist/cli/{chunk-O52OLQL3.js → chunk-RDRC3XDT.js} +136 -38
- package/dist/cli/chunk-RDRC3XDT.js.map +1 -0
- package/dist/cli/chunk-S4XVGLRW.js +0 -0
- package/dist/cli/chunk-SZ5XES2N.js +0 -0
- package/dist/cli/{chunk-2K65GZBT.js → chunk-TEUDEGX2.js} +64 -19
- package/dist/cli/chunk-TEUDEGX2.js.map +1 -0
- package/dist/cli/{chunk-2Z35JOA4.js → chunk-TKVXTQ3T.js} +4 -4
- package/dist/cli/{chunk-2Z35JOA4.js.map → chunk-TKVXTQ3T.js.map} +1 -1
- package/dist/cli/chunk-TUK7OWJA.js +0 -0
- package/dist/cli/{chunk-32TIKD5U.js → chunk-TXJMRPIL.js} +3 -3
- package/dist/cli/{chunk-2KDUS647.js → chunk-V26WPN3J.js} +7 -4
- package/dist/cli/chunk-V26WPN3J.js.map +1 -0
- package/dist/cli/{chunk-F3PXYSNN.js → chunk-WK3UFQY3.js} +2 -2
- package/dist/cli/{chunk-6G3CUUFG.js → chunk-X53B3JIX.js} +3 -3
- package/dist/cli/{chunk-6G3CUUFG.js.map → chunk-X53B3JIX.js.map} +1 -1
- package/dist/cli/chunk-XJXDHAES.js +0 -0
- package/dist/cli/{chunk-6AK4EY3D.js → chunk-XSU4QVFW.js} +1 -81
- package/dist/cli/chunk-XSU4QVFW.js.map +1 -0
- package/dist/cli/chunk-XXC2BYTV.js +0 -0
- package/dist/cli/{chunk-P7EKE5ZQ.js → chunk-Z4S7EYXG.js} +4482 -1310
- package/dist/cli/chunk-Z4S7EYXG.js.map +1 -0
- package/dist/cli/chunk-ZZM6QJ4W.js +0 -0
- package/dist/cli/{chunk-YQ6NTIIE.js → chunk-ZZYBBX5N.js} +13 -5
- package/dist/cli/chunk-ZZYBBX5N.js.map +1 -0
- package/dist/cli/{code-SMKEW6CD.js → code-PSVJ3KEN.js} +48 -36
- package/dist/cli/code-PSVJ3KEN.js.map +1 -0
- package/dist/cli/{commands-FVVB5FZF.js → commands-OCU42XG4.js} +4 -4
- package/dist/cli/{commit-HE4VSPZ7.js → commit-XCQIQCYG.js} +3 -3
- package/dist/cli/{desktop-Q7NDXCON.js → desktop-KWGR4BNE.js} +210 -69
- package/dist/cli/desktop-KWGR4BNE.js.map +1 -0
- package/dist/cli/devtools-HW3WDT3Q.js +91 -0
- package/dist/cli/devtools-HW3WDT3Q.js.map +1 -0
- package/dist/cli/{diff-435UTPC5.js → diff-NHANTNC3.js} +9 -9
- package/dist/cli/{doctor-OT7KH75K.js → doctor-CC5CLOGG.js} +10 -10
- package/dist/cli/events-XEFAD5VX.js +0 -0
- package/dist/cli/index.js +132 -94
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-WUL2WO75.js → mcp-MPVGBBJF.js} +2 -2
- package/dist/cli/{mcp-browse-RR7R4XET.js → mcp-browse-4XOTC3FJ.js} +3 -3
- package/dist/cli/{mcp-inspect-REGLYBWT.js → mcp-inspect-CEMGKKAH.js} +14 -9
- package/dist/cli/mcp-inspect-CEMGKKAH.js.map +1 -0
- package/dist/cli/{prompt-UW6EFLVR.js → prompt-2D7ID24X.js} +4 -4
- package/dist/cli/prune-sessions-3RWUBYRS.js +0 -0
- package/dist/cli/{replay-YOURXV4C.js → replay-SR44E6RS.js} +10 -10
- package/dist/cli/{run-Q6BUXV66.js → run-MDGL27WL.js} +35 -36
- package/dist/cli/run-MDGL27WL.js.map +1 -0
- package/dist/cli/{server-XGDBRWMB.js → server-27ARQXIZ.js} +67 -24
- package/dist/cli/server-27ARQXIZ.js.map +1 -0
- package/dist/cli/{sessions-FH7QVYSY.js → sessions-CKQXCYGP.js} +18 -18
- package/dist/cli/sessions-CKQXCYGP.js.map +1 -0
- package/dist/cli/{setup-VDS6SVEP.js → setup-TPAGSVXO.js} +6 -6
- package/dist/cli/{stats-MQVI2XQH.js → stats-DPUBZNVX.js} +6 -4
- package/dist/cli/update-6ITLPRDV.js +0 -0
- package/dist/cli/{version-DAHGZY5N.js → version-2X3BHVVK.js} +15 -15
- package/dist/index.d.ts +181 -53
- package/dist/index.js +1322 -533
- package/dist/index.js.map +1 -1
- package/package.json +21 -8
- package/dist/cli/.-3G6VX5S7.js +0 -327
- package/dist/cli/.-6YRPB2C7.js +0 -329
- package/dist/cli/.-EYSVINK3.js +0 -317
- package/dist/cli/acp-DAGPCVFZ.js.map +0 -1
- package/dist/cli/chat-7ES4IBNH.js +0 -50
- package/dist/cli/chunk-2K65GZBT.js.map +0 -1
- package/dist/cli/chunk-2KDUS647.js.map +0 -1
- package/dist/cli/chunk-2R4QCDOZ.js.map +0 -1
- package/dist/cli/chunk-3BXRZFWS.js.map +0 -1
- package/dist/cli/chunk-3Z6IBU3D.js.map +0 -1
- package/dist/cli/chunk-45U62RI3.js.map +0 -1
- package/dist/cli/chunk-6AK4EY3D.js.map +0 -1
- package/dist/cli/chunk-6PZ3CXBP.js.map +0 -1
- package/dist/cli/chunk-H6PS7IUE.js.map +0 -1
- package/dist/cli/chunk-O52OLQL3.js.map +0 -1
- package/dist/cli/chunk-OSZC7C6F.js.map +0 -1
- package/dist/cli/chunk-P7EKE5ZQ.js.map +0 -1
- package/dist/cli/chunk-PQXPXJBJ.js.map +0 -1
- package/dist/cli/chunk-PV55UMTO.js +0 -200
- package/dist/cli/chunk-PV55UMTO.js.map +0 -1
- package/dist/cli/chunk-RE4RAVFF.js.map +0 -1
- package/dist/cli/chunk-XPDVG52A.js.map +0 -1
- package/dist/cli/chunk-YFGF5NKA.js.map +0 -1
- package/dist/cli/chunk-YQ6NTIIE.js.map +0 -1
- package/dist/cli/code-SMKEW6CD.js.map +0 -1
- package/dist/cli/desktop-Q7NDXCON.js.map +0 -1
- package/dist/cli/devtools-YECO25QO.js.map +0 -1
- package/dist/cli/doctor-OT7KH75K.js.map +0 -1
- package/dist/cli/mcp-inspect-REGLYBWT.js.map +0 -1
- package/dist/cli/prompt-UW6EFLVR.js.map +0 -1
- package/dist/cli/run-Q6BUXV66.js.map +0 -1
- package/dist/cli/server-XGDBRWMB.js.map +0 -1
- package/dist/cli/sessions-FH7QVYSY.js.map +0 -1
- package/dist/cli/stats-MQVI2XQH.js.map +0 -1
- /package/dist/cli/{.-3G6VX5S7.js.map → chat-TH7VNNCJ.js.map} +0 -0
- /package/dist/cli/{chunk-XCGGEJTI.js.map → chunk-4CTDEJUF.js.map} +0 -0
- /package/dist/cli/{chunk-7O5ALB4C.js.map → chunk-7CIGMZT3.js.map} +0 -0
- /package/dist/cli/{chunk-TJX6BFZZ.js.map → chunk-AB2RED3C.js.map} +0 -0
- /package/dist/cli/{chunk-FHOGSSCH.js.map → chunk-C53JQES5.js.map} +0 -0
- /package/dist/cli/{chunk-VK5HG73G.js.map → chunk-KM465GST.js.map} +0 -0
- /package/dist/cli/{chunk-DOYHN4KB.js.map → chunk-LIR2HBQH.js.map} +0 -0
- /package/dist/cli/{chunk-YYQAUTTN.js.map → chunk-MJ6W5UN3.js.map} +0 -0
- /package/dist/cli/{chunk-HFEAY5DT.js.map → chunk-R3CTO2HM.js.map} +0 -0
- /package/dist/cli/{chunk-32TIKD5U.js.map → chunk-TXJMRPIL.js.map} +0 -0
- /package/dist/cli/{chunk-F3PXYSNN.js.map → chunk-WK3UFQY3.js.map} +0 -0
- /package/dist/cli/{commands-FVVB5FZF.js.map → commands-OCU42XG4.js.map} +0 -0
- /package/dist/cli/{commit-HE4VSPZ7.js.map → commit-XCQIQCYG.js.map} +0 -0
- /package/dist/cli/{diff-435UTPC5.js.map → diff-NHANTNC3.js.map} +0 -0
- /package/dist/cli/{.-6YRPB2C7.js.map → doctor-CC5CLOGG.js.map} +0 -0
- /package/dist/cli/{mcp-WUL2WO75.js.map → mcp-MPVGBBJF.js.map} +0 -0
- /package/dist/cli/{mcp-browse-RR7R4XET.js.map → mcp-browse-4XOTC3FJ.js.map} +0 -0
- /package/dist/cli/{.-EYSVINK3.js.map → prompt-2D7ID24X.js.map} +0 -0
- /package/dist/cli/{replay-YOURXV4C.js.map → replay-SR44E6RS.js.map} +0 -0
- /package/dist/cli/{setup-VDS6SVEP.js.map → setup-TPAGSVXO.js.map} +0 -0
- /package/dist/cli/{chat-7ES4IBNH.js.map → stats-DPUBZNVX.js.map} +0 -0
- /package/dist/cli/{version-DAHGZY5N.js.map → version-2X3BHVVK.js.map} +0 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
|
+
|
|
4
|
+
// src/tokenizer.ts
|
|
5
|
+
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
import { createRequire } from "module";
|
|
7
|
+
import { dirname, join } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import { gunzipSync } from "zlib";
|
|
10
|
+
function buildByteToChar() {
|
|
11
|
+
const result = new Array(256);
|
|
12
|
+
const bs = [];
|
|
13
|
+
for (let b = 33; b <= 126; b++) bs.push(b);
|
|
14
|
+
for (let b = 161; b <= 172; b++) bs.push(b);
|
|
15
|
+
for (let b = 174; b <= 255; b++) bs.push(b);
|
|
16
|
+
const cs = bs.slice();
|
|
17
|
+
let n = 0;
|
|
18
|
+
for (let b = 0; b < 256; b++) {
|
|
19
|
+
if (!bs.includes(b)) {
|
|
20
|
+
bs.push(b);
|
|
21
|
+
cs.push(256 + n);
|
|
22
|
+
n++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (let i = 0; i < bs.length; i++) {
|
|
26
|
+
result[bs[i]] = String.fromCodePoint(cs[i]);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
var cached = null;
|
|
31
|
+
function resolveDataPath() {
|
|
32
|
+
if (process.env.REASONIX_TOKENIZER_PATH) return process.env.REASONIX_TOKENIZER_PATH;
|
|
33
|
+
const candidates = [];
|
|
34
|
+
try {
|
|
35
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
candidates.push(join(here, "..", "data", "deepseek-tokenizer.json.gz"));
|
|
37
|
+
candidates.push(join(here, "..", "..", "data", "deepseek-tokenizer.json.gz"));
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const req = createRequire(import.meta.url);
|
|
42
|
+
candidates.push(
|
|
43
|
+
join(dirname(req.resolve("reasonix/package.json")), "data", "deepseek-tokenizer.json.gz")
|
|
44
|
+
);
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
for (const p of candidates) {
|
|
48
|
+
if (existsSync(p)) return p;
|
|
49
|
+
}
|
|
50
|
+
return candidates[0] ?? join(process.cwd(), "data", "deepseek-tokenizer.json.gz");
|
|
51
|
+
}
|
|
52
|
+
function loadTokenizer() {
|
|
53
|
+
if (cached) return cached;
|
|
54
|
+
const buf = readFileSync(resolveDataPath());
|
|
55
|
+
const json = gunzipSync(buf).toString("utf8");
|
|
56
|
+
const data = JSON.parse(json);
|
|
57
|
+
const mergeRank = /* @__PURE__ */ new Map();
|
|
58
|
+
for (let i = 0; i < data.model.merges.length; i++) {
|
|
59
|
+
mergeRank.set(data.model.merges[i], i);
|
|
60
|
+
}
|
|
61
|
+
const splitRegexes = [];
|
|
62
|
+
for (const p of data.pre_tokenizer.pretokenizers) {
|
|
63
|
+
if (p.type === "Split") {
|
|
64
|
+
splitRegexes.push(new RegExp(p.pattern.Regex, "gu"));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const addedMap = /* @__PURE__ */ new Map();
|
|
68
|
+
const addedContents = [];
|
|
69
|
+
for (const t of data.added_tokens) {
|
|
70
|
+
if (!t.special) {
|
|
71
|
+
addedMap.set(t.content, t.id);
|
|
72
|
+
addedContents.push(t.content);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
addedContents.sort((a, b) => b.length - a.length);
|
|
76
|
+
const addedPattern = addedContents.length ? new RegExp(addedContents.map(escapeRegex).join("|"), "g") : null;
|
|
77
|
+
cached = {
|
|
78
|
+
vocab: data.model.vocab,
|
|
79
|
+
mergeRank,
|
|
80
|
+
splitRegexes,
|
|
81
|
+
byteToChar: buildByteToChar(),
|
|
82
|
+
addedPattern,
|
|
83
|
+
addedMap
|
|
84
|
+
};
|
|
85
|
+
return cached;
|
|
86
|
+
}
|
|
87
|
+
function escapeRegex(s) {
|
|
88
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
89
|
+
}
|
|
90
|
+
function applySplit(chunks, re) {
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const chunk of chunks) {
|
|
93
|
+
if (!chunk) continue;
|
|
94
|
+
re.lastIndex = 0;
|
|
95
|
+
let last = 0;
|
|
96
|
+
for (const m of chunk.matchAll(re)) {
|
|
97
|
+
const idx = m.index ?? 0;
|
|
98
|
+
if (idx > last) out.push(chunk.slice(last, idx));
|
|
99
|
+
if (m[0].length > 0) out.push(m[0]);
|
|
100
|
+
last = idx + m[0].length;
|
|
101
|
+
}
|
|
102
|
+
if (last < chunk.length) out.push(chunk.slice(last));
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function byteLevelEncode(s, byteToChar) {
|
|
107
|
+
const bytes = new TextEncoder().encode(s);
|
|
108
|
+
let out = "";
|
|
109
|
+
for (let i = 0; i < bytes.length; i++) out += byteToChar[bytes[i]];
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
function bpeEncode(piece, mergeRank) {
|
|
113
|
+
if (piece.length <= 1) return piece ? [piece] : [];
|
|
114
|
+
let word = Array.from(piece);
|
|
115
|
+
while (true) {
|
|
116
|
+
let bestIdx = -1;
|
|
117
|
+
let bestRank = Number.POSITIVE_INFINITY;
|
|
118
|
+
for (let i = 0; i < word.length - 1; i++) {
|
|
119
|
+
const pair = `${word[i]} ${word[i + 1]}`;
|
|
120
|
+
const rank = mergeRank.get(pair);
|
|
121
|
+
if (rank !== void 0 && rank < bestRank) {
|
|
122
|
+
bestRank = rank;
|
|
123
|
+
bestIdx = i;
|
|
124
|
+
if (rank === 0) break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (bestIdx < 0) break;
|
|
128
|
+
word = [
|
|
129
|
+
...word.slice(0, bestIdx),
|
|
130
|
+
word[bestIdx] + word[bestIdx + 1],
|
|
131
|
+
...word.slice(bestIdx + 2)
|
|
132
|
+
];
|
|
133
|
+
if (word.length === 1) break;
|
|
134
|
+
}
|
|
135
|
+
return word;
|
|
136
|
+
}
|
|
137
|
+
function encode(text) {
|
|
138
|
+
if (!text) return [];
|
|
139
|
+
const t = loadTokenizer();
|
|
140
|
+
const ids = [];
|
|
141
|
+
const process2 = (segment) => {
|
|
142
|
+
if (!segment) return;
|
|
143
|
+
let chunks = [segment];
|
|
144
|
+
for (const re of t.splitRegexes) chunks = applySplit(chunks, re);
|
|
145
|
+
for (const chunk of chunks) {
|
|
146
|
+
if (!chunk) continue;
|
|
147
|
+
const byteLevel = byteLevelEncode(chunk, t.byteToChar);
|
|
148
|
+
const pieces = bpeEncode(byteLevel, t.mergeRank);
|
|
149
|
+
for (const p of pieces) {
|
|
150
|
+
const id = t.vocab[p];
|
|
151
|
+
if (id !== void 0) ids.push(id);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
if (t.addedPattern) {
|
|
156
|
+
t.addedPattern.lastIndex = 0;
|
|
157
|
+
let last = 0;
|
|
158
|
+
for (const m of text.matchAll(t.addedPattern)) {
|
|
159
|
+
const idx = m.index ?? 0;
|
|
160
|
+
if (idx > last) process2(text.slice(last, idx));
|
|
161
|
+
const id = t.addedMap.get(m[0]);
|
|
162
|
+
if (id !== void 0) ids.push(id);
|
|
163
|
+
last = idx + m[0].length;
|
|
164
|
+
}
|
|
165
|
+
if (last < text.length) process2(text.slice(last));
|
|
166
|
+
} else {
|
|
167
|
+
process2(text);
|
|
168
|
+
}
|
|
169
|
+
return ids;
|
|
170
|
+
}
|
|
171
|
+
function countTokens(text) {
|
|
172
|
+
return encode(text).length;
|
|
173
|
+
}
|
|
174
|
+
var DEFAULT_BOUNDED_TOKENIZE_CHARS = 2 * 1024;
|
|
175
|
+
function countTokensBounded(text, maxChars = DEFAULT_BOUNDED_TOKENIZE_CHARS) {
|
|
176
|
+
if (text.length === 0) return 0;
|
|
177
|
+
const cap = Math.floor(maxChars);
|
|
178
|
+
if (cap > 0 && text.length <= cap) return countTokens(text);
|
|
179
|
+
if (cap <= 0) return Math.max(1, Math.ceil(text.length * 0.3));
|
|
180
|
+
const headChars = Math.ceil(cap / 2);
|
|
181
|
+
const tailChars = Math.floor(cap / 2);
|
|
182
|
+
const head = text.slice(0, headChars);
|
|
183
|
+
const tail = tailChars > 0 ? text.slice(-tailChars) : "";
|
|
184
|
+
const sampleChars = head.length + tail.length;
|
|
185
|
+
const sampleTokens = countTokens(head) + countTokens(tail);
|
|
186
|
+
const ratio = sampleChars > 0 ? sampleTokens / sampleChars : 0.3;
|
|
187
|
+
return Math.max(1, Math.ceil(text.length * ratio));
|
|
188
|
+
}
|
|
189
|
+
var BOS = "<\uFF5Cbegin\u2581of\u2581sentence\uFF5C>";
|
|
190
|
+
var EOS = "<\uFF5Cend\u2581of\u2581sentence\uFF5C>";
|
|
191
|
+
var USER_SP = "<\uFF5CUser\uFF5C>";
|
|
192
|
+
var ASSISTANT_SP = "<\uFF5CAssistant\uFF5C>";
|
|
193
|
+
var THINK_START = "<think>";
|
|
194
|
+
var THINK_END = "</think>";
|
|
195
|
+
var DSML = "\uFF5CDSML\uFF5C";
|
|
196
|
+
var TC_BEGIN = `<${DSML}tool_calls>`;
|
|
197
|
+
var TC_END = `</${DSML}tool_calls>`;
|
|
198
|
+
var INVOKE_BEGIN = `<${DSML}invoke name="`;
|
|
199
|
+
var INVOKE_END = `</${DSML}invoke>`;
|
|
200
|
+
var PARAM_TEMPLATE = `<${DSML}parameter name="{key}" string="{is_str}">{value}</${DSML}parameter>`;
|
|
201
|
+
var TOOL_RESULT_TEMPLATE = "<tool_result>{content}</tool_result>";
|
|
202
|
+
var toolsTemplateCache = /* @__PURE__ */ new WeakMap();
|
|
203
|
+
function renderTools(tools) {
|
|
204
|
+
const cached2 = toolsTemplateCache.get(tools);
|
|
205
|
+
if (cached2 !== void 0) return cached2;
|
|
206
|
+
const schemas = tools.map((t) => {
|
|
207
|
+
const fn = t.function ?? t;
|
|
208
|
+
return JSON.stringify(fn);
|
|
209
|
+
}).join("\n");
|
|
210
|
+
const rendered = `## Tools
|
|
211
|
+
|
|
212
|
+
You have access to a set of tools to help answer the user's question. You can invoke tools by writing a "<${DSML}tool_calls>" block like the following:
|
|
213
|
+
|
|
214
|
+
<${DSML}tool_calls>
|
|
215
|
+
<${DSML}invoke name="$TOOL_NAME">
|
|
216
|
+
<${DSML}parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</${DSML}parameter>
|
|
217
|
+
...
|
|
218
|
+
</${DSML}invoke>
|
|
219
|
+
<${DSML}invoke name="$TOOL_NAME2">
|
|
220
|
+
...
|
|
221
|
+
</${DSML}invoke>
|
|
222
|
+
</${DSML}tool_calls>
|
|
223
|
+
|
|
224
|
+
String parameters should be specified as is and set \`string="true"\`. For all other types (numbers, booleans, arrays, objects), pass the value in JSON format and set \`string="false"\`.
|
|
225
|
+
|
|
226
|
+
If thinking_mode is enabled (triggered by ${THINK_START}), you MUST output your complete reasoning inside ${THINK_START}...${THINK_END} BEFORE any tool calls or final response.
|
|
227
|
+
|
|
228
|
+
Otherwise, output directly after ${THINK_END} with tool calls or final response.
|
|
229
|
+
|
|
230
|
+
### Available Tool Schemas
|
|
231
|
+
|
|
232
|
+
${schemas}
|
|
233
|
+
|
|
234
|
+
You MUST strictly follow the above defined tool name and parameter schemas to invoke tool calls.`;
|
|
235
|
+
toolsTemplateCache.set(tools, rendered);
|
|
236
|
+
return rendered;
|
|
237
|
+
}
|
|
238
|
+
function encodeArgumentsToDsml(argsJson) {
|
|
239
|
+
let args;
|
|
240
|
+
try {
|
|
241
|
+
args = JSON.parse(argsJson);
|
|
242
|
+
} catch {
|
|
243
|
+
args = { arguments: argsJson };
|
|
244
|
+
}
|
|
245
|
+
return Object.entries(args).map(
|
|
246
|
+
([k, v]) => PARAM_TEMPLATE.replace("{key}", k).replace("{is_str}", typeof v === "string" ? "true" : "false").replace("{value}", typeof v === "string" ? v : JSON.stringify(v))
|
|
247
|
+
).join("\n");
|
|
248
|
+
}
|
|
249
|
+
function renderToolCallsDsml(toolCalls) {
|
|
250
|
+
const invokes = toolCalls.map((tc) => {
|
|
251
|
+
const name = tc.function?.name ?? "";
|
|
252
|
+
const argsJson = tc.function?.arguments ?? "{}";
|
|
253
|
+
return `${INVOKE_BEGIN + name}">
|
|
254
|
+
${encodeArgumentsToDsml(argsJson)}
|
|
255
|
+
${INVOKE_END}`;
|
|
256
|
+
}).join("\n");
|
|
257
|
+
return `
|
|
258
|
+
|
|
259
|
+
${TC_BEGIN}
|
|
260
|
+
${invokes}
|
|
261
|
+
${TC_END}`;
|
|
262
|
+
}
|
|
263
|
+
function mergeToolMessages(messages) {
|
|
264
|
+
const merged = [];
|
|
265
|
+
for (const msg of messages) {
|
|
266
|
+
const role = msg.role ?? "user";
|
|
267
|
+
if (role === "tool") {
|
|
268
|
+
const toolBlock = TOOL_RESULT_TEMPLATE.replace("{content}", msg.content ?? "");
|
|
269
|
+
const last = merged[merged.length - 1];
|
|
270
|
+
if (last && last.role === "user" && Array.isArray(last._toolBlocks) && Array.isArray(last._textParts)) {
|
|
271
|
+
last._toolBlocks.push(toolBlock);
|
|
272
|
+
last.content = `${last._textParts.join("\n\n")}
|
|
273
|
+
|
|
274
|
+
${last._toolBlocks.join("\n")}`.replace(
|
|
275
|
+
/^\n\n/,
|
|
276
|
+
""
|
|
277
|
+
);
|
|
278
|
+
} else {
|
|
279
|
+
merged.push({
|
|
280
|
+
role: "user",
|
|
281
|
+
content: toolBlock,
|
|
282
|
+
_textParts: [],
|
|
283
|
+
_toolBlocks: [toolBlock]
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
} else if (role === "user") {
|
|
287
|
+
const text = msg.content ?? "";
|
|
288
|
+
const last = merged[merged.length - 1];
|
|
289
|
+
if (last && last.role === "user" && Array.isArray(last._toolBlocks) && Array.isArray(last._textParts)) {
|
|
290
|
+
last._textParts.push(text);
|
|
291
|
+
last.content = `${last._textParts.join("\n\n")}
|
|
292
|
+
|
|
293
|
+
${last._toolBlocks.join("\n\n")}`.replace(
|
|
294
|
+
/^\n\n/,
|
|
295
|
+
""
|
|
296
|
+
);
|
|
297
|
+
} else {
|
|
298
|
+
merged.push({
|
|
299
|
+
...msg,
|
|
300
|
+
role: "user",
|
|
301
|
+
content: text,
|
|
302
|
+
_textParts: [text],
|
|
303
|
+
_toolBlocks: []
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
merged.push({ ...msg });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
for (const m of merged) {
|
|
311
|
+
m._textParts = void 0;
|
|
312
|
+
m._toolBlocks = void 0;
|
|
313
|
+
}
|
|
314
|
+
return merged;
|
|
315
|
+
}
|
|
316
|
+
function dropThinkingMessages(messages) {
|
|
317
|
+
let lastUserIdx = -1;
|
|
318
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
319
|
+
const role = messages[i].role;
|
|
320
|
+
if (role === "user" || role === "developer") {
|
|
321
|
+
lastUserIdx = i;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (lastUserIdx < 0) return messages;
|
|
326
|
+
const result = [];
|
|
327
|
+
for (let i = 0; i < messages.length; i++) {
|
|
328
|
+
const msg = messages[i];
|
|
329
|
+
if (i < lastUserIdx && msg.role === "developer") continue;
|
|
330
|
+
if (i < lastUserIdx && msg.role === "assistant") {
|
|
331
|
+
result.push({ ...msg, reasoning_content: null });
|
|
332
|
+
} else {
|
|
333
|
+
result.push(msg);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
function formatDeepSeekPrompt(messages, drop_thinking = false) {
|
|
339
|
+
if (messages.length === 0) return ASSISTANT_SP + THINK_END;
|
|
340
|
+
let msgs = messages;
|
|
341
|
+
if (drop_thinking) {
|
|
342
|
+
msgs = dropThinkingMessages(msgs);
|
|
343
|
+
}
|
|
344
|
+
const merged = mergeToolMessages(msgs);
|
|
345
|
+
let prompt = BOS;
|
|
346
|
+
for (let i = 0; i < merged.length; i++) {
|
|
347
|
+
const msg = merged[i];
|
|
348
|
+
const role = msg.role ?? "user";
|
|
349
|
+
const nextRole = i + 1 < merged.length ? merged[i + 1].role ?? "user" : null;
|
|
350
|
+
if (role === "system") {
|
|
351
|
+
prompt += msg.content ?? "";
|
|
352
|
+
} else if (role === "user") {
|
|
353
|
+
prompt += USER_SP + (msg.content ?? "");
|
|
354
|
+
if (nextRole === "assistant" || nextRole === null) {
|
|
355
|
+
prompt += ASSISTANT_SP + THINK_END;
|
|
356
|
+
}
|
|
357
|
+
} else if (role === "assistant") {
|
|
358
|
+
if (msg.reasoning_content) {
|
|
359
|
+
prompt += THINK_START + msg.reasoning_content + THINK_END;
|
|
360
|
+
}
|
|
361
|
+
if (msg.content) prompt += msg.content;
|
|
362
|
+
const tcs = msg.tool_calls;
|
|
363
|
+
if (Array.isArray(tcs) && tcs.length > 0) {
|
|
364
|
+
prompt += renderToolCallsDsml(tcs);
|
|
365
|
+
}
|
|
366
|
+
prompt += EOS;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return prompt;
|
|
370
|
+
}
|
|
371
|
+
function estimateConversationTokens(messages, drop_thinking = false) {
|
|
372
|
+
if (messages.length === 0) return 0;
|
|
373
|
+
return countTokensBounded(formatDeepSeekPrompt(messages, drop_thinking));
|
|
374
|
+
}
|
|
375
|
+
function estimateRequestTokens(messages, toolSpecs, drop_thinking = false) {
|
|
376
|
+
let total = estimateConversationTokens(messages, drop_thinking);
|
|
377
|
+
if (toolSpecs && toolSpecs.length > 0) {
|
|
378
|
+
total += countTokensBounded(renderTools(toolSpecs));
|
|
379
|
+
}
|
|
380
|
+
return total;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export {
|
|
384
|
+
resolveDataPath,
|
|
385
|
+
countTokens,
|
|
386
|
+
countTokensBounded,
|
|
387
|
+
estimateConversationTokens,
|
|
388
|
+
estimateRequestTokens
|
|
389
|
+
};
|
|
390
|
+
//# sourceMappingURL=chunk-6OWJV3YW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tokenizer.ts"],"sourcesContent":["/** Encode-only DeepSeek V4 tokenizer port. Applies V4 chat template so token count tracks API `prompt_tokens`. */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { gunzipSync } from \"node:zlib\";\n\ninterface AddedToken {\n id: number;\n content: string;\n special: boolean;\n normalized: boolean;\n}\n\ninterface SplitPretokenizer {\n type: \"Split\";\n pattern: { Regex: string };\n behavior: \"Isolated\" | \"Removed\" | string;\n invert: boolean;\n}\n\ninterface ByteLevelPretokenizer {\n type: \"ByteLevel\";\n add_prefix_space: boolean;\n trim_offsets: boolean;\n use_regex: boolean;\n}\n\ntype Pretokenizer = SplitPretokenizer | ByteLevelPretokenizer;\n\ninterface TokenizerData {\n added_tokens: AddedToken[];\n pre_tokenizer: {\n type: \"Sequence\";\n pretokenizers: Pretokenizer[];\n };\n model: {\n type: \"BPE\";\n vocab: Record<string, number>;\n merges: string[];\n };\n}\n\ninterface LoadedTokenizer {\n vocab: Record<string, number>;\n mergeRank: Map<string, number>;\n splitRegexes: RegExp[];\n byteToChar: string[];\n /** Non-special added tokens only — special tokens in user text tokenize byte-by-byte (HF default). */\n addedPattern: RegExp | null;\n addedMap: Map<string, number>;\n}\n\n/** GPT-2 byte→unicode map; lets byte-level BPE vocab serialize as readable JSON strings. */\nfunction buildByteToChar(): string[] {\n const result: string[] = new Array(256);\n const bs: number[] = [];\n for (let b = 33; b <= 126; b++) bs.push(b);\n for (let b = 161; b <= 172; b++) bs.push(b);\n for (let b = 174; b <= 255; b++) bs.push(b);\n const cs = bs.slice();\n let n = 0;\n for (let b = 0; b < 256; b++) {\n if (!bs.includes(b)) {\n bs.push(b);\n cs.push(256 + n);\n n++;\n }\n }\n for (let i = 0; i < bs.length; i++) {\n result[bs[i]!] = String.fromCodePoint(cs[i]!);\n }\n return result;\n}\n\nlet cached: LoadedTokenizer | null = null;\n\n/** Two ../data candidates needed: dist/index.js AND dist/cli/index.js resolve to different roots. */\nexport function resolveDataPath(): string {\n if (process.env.REASONIX_TOKENIZER_PATH) return process.env.REASONIX_TOKENIZER_PATH;\n const candidates: string[] = [];\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n candidates.push(join(here, \"..\", \"data\", \"deepseek-tokenizer.json.gz\"));\n candidates.push(join(here, \"..\", \"..\", \"data\", \"deepseek-tokenizer.json.gz\"));\n } catch {\n /* import.meta.url unavailable — skip to the package resolution step. */\n }\n try {\n const req = createRequire(import.meta.url);\n candidates.push(\n join(dirname(req.resolve(\"reasonix/package.json\")), \"data\", \"deepseek-tokenizer.json.gz\"),\n );\n } catch {\n /* Not installed as `reasonix/` — the earlier candidates still may hit. */\n }\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n // Nothing exists — return the first candidate anyway so readFileSync\n // surfaces a concrete path in the ENOENT message (better than silent miss).\n return candidates[0] ?? join(process.cwd(), \"data\", \"deepseek-tokenizer.json.gz\");\n}\n\nfunction loadTokenizer(): LoadedTokenizer {\n if (cached) return cached;\n const buf = readFileSync(resolveDataPath());\n const json = gunzipSync(buf).toString(\"utf8\");\n const data = JSON.parse(json) as TokenizerData;\n\n const mergeRank = new Map<string, number>();\n for (let i = 0; i < data.model.merges.length; i++) {\n mergeRank.set(data.model.merges[i]!, i);\n }\n\n const splitRegexes: RegExp[] = [];\n for (const p of data.pre_tokenizer.pretokenizers) {\n if (p.type === \"Split\") {\n // All three Split rules use Isolated — matches become their own\n // pre-tokens and so do the in-between stretches. The ByteLevel\n // stage in the Sequence does no extra splitting here\n // (use_regex:false), so our 3 Split regexes are the whole story.\n splitRegexes.push(new RegExp(p.pattern.Regex, \"gu\"));\n }\n }\n\n const addedMap = new Map<string, number>();\n const addedContents: string[] = [];\n for (const t of data.added_tokens) {\n if (!t.special) {\n addedMap.set(t.content, t.id);\n addedContents.push(t.content);\n }\n }\n // Longest-first ensures greedy matching doesn't lose a longer token\n // to a shorter prefix (e.g. `<think>` before `<`).\n addedContents.sort((a, b) => b.length - a.length);\n const addedPattern = addedContents.length\n ? new RegExp(addedContents.map(escapeRegex).join(\"|\"), \"g\")\n : null;\n\n cached = {\n vocab: data.model.vocab,\n mergeRank,\n splitRegexes,\n byteToChar: buildByteToChar(),\n addedPattern,\n addedMap,\n };\n return cached;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction applySplit(chunks: string[], re: RegExp): string[] {\n const out: string[] = [];\n for (const chunk of chunks) {\n if (!chunk) continue;\n // Reset lastIndex — reusing a /g regex across matchAll iterations\n // is safe (matchAll internally advances), but across different\n // input strings we want a clean start.\n re.lastIndex = 0;\n let last = 0;\n for (const m of chunk.matchAll(re)) {\n const idx = m.index ?? 0;\n if (idx > last) out.push(chunk.slice(last, idx));\n if (m[0].length > 0) out.push(m[0]);\n last = idx + m[0].length;\n }\n if (last < chunk.length) out.push(chunk.slice(last));\n }\n return out;\n}\n\n/** UTF-8 bytes of `s`, each mapped to its byte-level visible char. */\nfunction byteLevelEncode(s: string, byteToChar: string[]): string {\n const bytes = new TextEncoder().encode(s);\n let out = \"\";\n for (let i = 0; i < bytes.length; i++) out += byteToChar[bytes[i]!];\n return out;\n}\n\nfunction bpeEncode(piece: string, mergeRank: Map<string, number>): string[] {\n if (piece.length <= 1) return piece ? [piece] : [];\n let word: string[] = Array.from(piece);\n while (true) {\n let bestIdx = -1;\n let bestRank = Number.POSITIVE_INFINITY;\n for (let i = 0; i < word.length - 1; i++) {\n const pair = `${word[i]} ${word[i + 1]}`;\n const rank = mergeRank.get(pair);\n if (rank !== undefined && rank < bestRank) {\n bestRank = rank;\n bestIdx = i;\n if (rank === 0) break; // 0 is already the best possible\n }\n }\n if (bestIdx < 0) break;\n word = [\n ...word.slice(0, bestIdx),\n word[bestIdx]! + word[bestIdx + 1]!,\n ...word.slice(bestIdx + 2),\n ];\n if (word.length === 1) break;\n }\n return word;\n}\n\nexport function encode(text: string): number[] {\n if (!text) return [];\n const t = loadTokenizer();\n const ids: number[] = [];\n\n const process = (segment: string) => {\n if (!segment) return;\n let chunks: string[] = [segment];\n for (const re of t.splitRegexes) chunks = applySplit(chunks, re);\n for (const chunk of chunks) {\n if (!chunk) continue;\n const byteLevel = byteLevelEncode(chunk, t.byteToChar);\n const pieces = bpeEncode(byteLevel, t.mergeRank);\n for (const p of pieces) {\n const id = t.vocab[p];\n // If not in vocab we silently skip: shouldn't happen for\n // byte-level BPE (every single byte has its own vocab entry),\n // but if a future tokenizer update breaks that invariant we'd\n // rather under-count than throw from a UI gauge.\n if (id !== undefined) ids.push(id);\n }\n }\n };\n\n if (t.addedPattern) {\n t.addedPattern.lastIndex = 0;\n let last = 0;\n for (const m of text.matchAll(t.addedPattern)) {\n const idx = m.index ?? 0;\n if (idx > last) process(text.slice(last, idx));\n const id = t.addedMap.get(m[0]);\n if (id !== undefined) ids.push(id);\n last = idx + m[0].length;\n }\n if (last < text.length) process(text.slice(last));\n } else {\n process(text);\n }\n return ids;\n}\n\nexport function countTokens(text: string): number {\n return encode(text).length;\n}\n\nexport const DEFAULT_BOUNDED_TOKENIZE_CHARS = 2 * 1024;\n\nexport function countTokensBounded(\n text: string,\n maxChars = DEFAULT_BOUNDED_TOKENIZE_CHARS,\n): number {\n if (text.length === 0) return 0;\n const cap = Math.floor(maxChars);\n if (cap > 0 && text.length <= cap) return countTokens(text);\n if (cap <= 0) return Math.max(1, Math.ceil(text.length * 0.3));\n\n const headChars = Math.ceil(cap / 2);\n const tailChars = Math.floor(cap / 2);\n const head = text.slice(0, headChars);\n const tail = tailChars > 0 ? text.slice(-tailChars) : \"\";\n const sampleChars = head.length + tail.length;\n const sampleTokens = countTokens(head) + countTokens(tail);\n const ratio = sampleChars > 0 ? sampleTokens / sampleChars : 0.3;\n return Math.max(1, Math.ceil(text.length * ratio));\n}\n\nconst BOS = \"<|begin▁of▁sentence|>\";\nconst EOS = \"<|end▁of▁sentence|>\";\nconst USER_SP = \"<|User|>\";\nconst ASSISTANT_SP = \"<|Assistant|>\";\nconst THINK_START = \"<think>\";\nconst THINK_END = \"</think>\";\n\nconst DSML = \"|DSML|\";\nconst TC_BEGIN = `<${DSML}tool_calls>`;\nconst TC_END = `</${DSML}tool_calls>`;\nconst INVOKE_BEGIN = `<${DSML}invoke name=\"`;\nconst INVOKE_END = `</${DSML}invoke>`;\nconst PARAM_TEMPLATE = `<${DSML}parameter name=\"{key}\" string=\"{is_str}\">{value}</${DSML}parameter>`;\nconst TOOL_RESULT_TEMPLATE = \"<tool_result>{content}</tool_result>\";\n\n/** Keyed by `ImmutablePrefix._toolSpecs` identity — stable for the prefix's lifetime. */\nconst toolsTemplateCache = new WeakMap<ReadonlyArray<unknown>, string>();\n\nfunction renderTools(tools: ReadonlyArray<unknown>): string {\n const cached = toolsTemplateCache.get(tools);\n if (cached !== undefined) return cached;\n\n const schemas = tools\n .map((t) => {\n const fn = (t as { function?: unknown }).function ?? t;\n return JSON.stringify(fn);\n })\n .join(\"\\n\");\n const rendered = `## Tools\\n\\nYou have access to a set of tools to help answer the user's question. You can invoke tools by writing a \\\"<${DSML}tool_calls>\" block like the following:\\n\\n<${DSML}tool_calls>\\n<${DSML}invoke name=\"$TOOL_NAME\">\\n<${DSML}parameter name=\"$PARAMETER_NAME\" string=\"true|false\">$PARAMETER_VALUE</${DSML}parameter>\\n...\\n</${DSML}invoke>\\n<${DSML}invoke name=\"$TOOL_NAME2\">\\n...\\n</${DSML}invoke>\\n</${DSML}tool_calls>\\n\\nString parameters should be specified as is and set \\`string=\"true\"\\`. For all other types (numbers, booleans, arrays, objects), pass the value in JSON format and set \\`string=\"false\"\\`.\\n\\nIf thinking_mode is enabled (triggered by ${THINK_START}), you MUST output your complete reasoning inside ${THINK_START}...${THINK_END} BEFORE any tool calls or final response.\\n\\nOtherwise, output directly after ${THINK_END} with tool calls or final response.\\n\\n### Available Tool Schemas\\n\\n${schemas}\\n\\nYou MUST strictly follow the above defined tool name and parameter schemas to invoke tool calls.`;\n\n toolsTemplateCache.set(tools, rendered);\n return rendered;\n}\n\ninterface ToolCall {\n function?: { name?: string; arguments?: string };\n [k: string]: unknown;\n}\n\ninterface V4Message {\n role?: string;\n content?: string | null;\n tool_calls?: ToolCall[];\n tool_call_id?: string;\n reasoning_content?: string | null;\n _toolBlocks?: string[];\n _textParts?: string[];\n}\n\nfunction encodeArgumentsToDsml(argsJson: string): string {\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(argsJson) as Record<string, unknown>;\n } catch {\n args = { arguments: argsJson };\n }\n return Object.entries(args)\n .map(([k, v]) =>\n PARAM_TEMPLATE.replace(\"{key}\", k)\n .replace(\"{is_str}\", typeof v === \"string\" ? \"true\" : \"false\")\n .replace(\"{value}\", typeof v === \"string\" ? v : JSON.stringify(v)),\n )\n .join(\"\\n\");\n}\n\nfunction renderToolCallsDsml(toolCalls: ToolCall[]): string {\n const invokes = toolCalls\n .map((tc) => {\n const name = tc.function?.name ?? \"\";\n const argsJson = tc.function?.arguments ?? \"{}\";\n return `${INVOKE_BEGIN + name}\">\\n${encodeArgumentsToDsml(argsJson)}\\n${INVOKE_END}`;\n })\n .join(\"\\n\");\n return `\\n\\n${TC_BEGIN}\\n${invokes}\\n${TC_END}`;\n}\n\nfunction mergeToolMessages(messages: V4Message[]): V4Message[] {\n const merged: V4Message[] = [];\n for (const msg of messages) {\n const role = msg.role ?? \"user\";\n if (role === \"tool\") {\n const toolBlock = TOOL_RESULT_TEMPLATE.replace(\"{content}\", msg.content ?? \"\");\n const last = merged[merged.length - 1];\n if (\n last &&\n last.role === \"user\" &&\n Array.isArray(last._toolBlocks) &&\n Array.isArray(last._textParts)\n ) {\n last._toolBlocks.push(toolBlock);\n last.content = `${last._textParts.join(\"\\n\\n\")}\\n\\n${last._toolBlocks.join(\"\\n\")}`.replace(\n /^\\n\\n/,\n \"\",\n );\n } else {\n merged.push({\n role: \"user\",\n content: toolBlock,\n _textParts: [],\n _toolBlocks: [toolBlock],\n });\n }\n } else if (role === \"user\") {\n const text = msg.content ?? \"\";\n const last = merged[merged.length - 1];\n if (\n last &&\n last.role === \"user\" &&\n Array.isArray(last._toolBlocks) &&\n Array.isArray(last._textParts)\n ) {\n last._textParts.push(text);\n last.content =\n `${last._textParts.join(\"\\n\\n\")}\\n\\n${last._toolBlocks.join(\"\\n\\n\")}`.replace(\n /^\\n\\n/,\n \"\",\n );\n } else {\n merged.push({\n ...msg,\n role: \"user\",\n content: text,\n _textParts: [text],\n _toolBlocks: [],\n });\n }\n } else {\n merged.push({ ...msg });\n }\n }\n for (const m of merged) {\n m._textParts = undefined;\n m._toolBlocks = undefined;\n }\n return merged;\n}\n\n/** Drop `reasoning_content` from assistant messages before the last user/developer message. Matches Python `_drop_thinking_messages`. */\nfunction dropThinkingMessages(messages: V4Message[]): V4Message[] {\n let lastUserIdx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n const role = messages[i]!.role;\n if (role === \"user\" || role === \"developer\") {\n lastUserIdx = i;\n break;\n }\n }\n if (lastUserIdx < 0) return messages;\n\n // Match Python `_drop_thinking_messages`:\n // - developer messages before lastUserIdx are dropped entirely\n // - assistant messages before lastUserIdx keep content & tool_calls\n // but have reasoning_content stripped\n const result: V4Message[] = [];\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n if (i < lastUserIdx && msg.role === \"developer\") continue;\n if (i < lastUserIdx && msg.role === \"assistant\") {\n result.push({ ...msg, reasoning_content: null });\n } else {\n result.push(msg);\n }\n }\n return result;\n}\n\n/** Apply DeepSeek V4 chat template. Matches `encoding_dsv4.py`: tool results merged into user messages, assistant tool_calls in DSML, generation suffix appended. */\nexport function formatDeepSeekPrompt(\n messages: Array<{\n role?: string;\n content?: string | null;\n tool_calls?: unknown;\n tool_call_id?: string;\n reasoning_content?: string | null;\n }>,\n drop_thinking = false,\n): string {\n if (messages.length === 0) return ASSISTANT_SP + THINK_END;\n\n let msgs = messages as V4Message[];\n if (drop_thinking) {\n msgs = dropThinkingMessages(msgs);\n }\n const merged = mergeToolMessages(msgs);\n\n let prompt = BOS;\n\n for (let i = 0; i < merged.length; i++) {\n const msg = merged[i]!;\n const role = msg.role ?? \"user\";\n const nextRole = i + 1 < merged.length ? (merged[i + 1]!.role ?? \"user\") : null;\n\n if (role === \"system\") {\n prompt += msg.content ?? \"\";\n } else if (role === \"user\") {\n prompt += USER_SP + (msg.content ?? \"\");\n if (nextRole === \"assistant\" || nextRole === null) {\n prompt += ASSISTANT_SP + THINK_END;\n }\n } else if (role === \"assistant\") {\n if (msg.reasoning_content) {\n prompt += THINK_START + msg.reasoning_content + THINK_END;\n }\n if (msg.content) prompt += msg.content;\n const tcs = msg.tool_calls;\n if (Array.isArray(tcs) && tcs.length > 0) {\n prompt += renderToolCallsDsml(tcs);\n }\n prompt += EOS;\n }\n }\n\n return prompt;\n}\n\n/** Token-count the FULL conversation as the API would see it: wraps messages in V4 chat template, then encodes once. */\nexport function estimateConversationTokens(\n messages: Array<{\n role?: string;\n content?: string | null;\n tool_calls?: unknown;\n tool_call_id?: string;\n reasoning_content?: string | null;\n }>,\n drop_thinking = false,\n): number {\n if (messages.length === 0) return 0;\n return countTokensBounded(formatDeepSeekPrompt(messages, drop_thinking));\n}\n\n/** Total request tokens (messages + tool specs) as the API counts them. Tool specs rendered via V4 TOOLS_TEMPLATE and added to message token count. */\nexport function estimateRequestTokens(\n messages: Array<{\n role?: string;\n content?: string | null;\n tool_calls?: unknown;\n tool_call_id?: string;\n reasoning_content?: string | null;\n }>,\n toolSpecs?: ReadonlyArray<unknown> | null,\n drop_thinking = false,\n): number {\n let total = estimateConversationTokens(messages, drop_thinking);\n if (toolSpecs && toolSpecs.length > 0) {\n total += countTokensBounded(renderTools(toolSpecs));\n }\n return total;\n}\n\n/** Exposed for tests — resets the lazy-load singleton. */\nexport function _resetForTests(): void {\n cached = null;\n}\n"],"mappings":"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","names":["process","cached"]}
|
|
File without changes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
4
|
t
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CGDR2ELH.js";
|
|
6
6
|
|
|
7
7
|
// src/hooks.ts
|
|
8
8
|
import { spawn } from "child_process";
|
|
@@ -206,4 +206,4 @@ export {
|
|
|
206
206
|
formatHookOutcomeMessage,
|
|
207
207
|
runHooks
|
|
208
208
|
};
|
|
209
|
-
//# sourceMappingURL=chunk-
|
|
209
|
+
//# sourceMappingURL=chunk-7CIGMZT3.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
4
|
t
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CGDR2ELH.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/ui/mcp-lifecycle.ts
|
|
8
8
|
var STATE = {
|
|
@@ -10,7 +10,9 @@ var STATE = {
|
|
|
10
10
|
connected: { glyph: "\u2713", label: () => t("mcpLifecycle.connected") },
|
|
11
11
|
failed: { glyph: "\u2716", label: () => t("mcpLifecycle.failed") },
|
|
12
12
|
disabled: { glyph: "\u25CB", label: () => t("mcpLifecycle.disabled") },
|
|
13
|
-
reconnect: { glyph: "\u21BB", label: () => t("mcpLifecycle.reconnect") }
|
|
13
|
+
reconnect: { glyph: "\u21BB", label: () => t("mcpLifecycle.reconnect") },
|
|
14
|
+
"tools-ready": { glyph: "\u26A1", label: () => "tools ready" },
|
|
15
|
+
warn: { glyph: "\u26A0", label: () => "warn" }
|
|
14
16
|
};
|
|
15
17
|
var NAME_COL = 22;
|
|
16
18
|
var STATE_COL = 15;
|
|
@@ -26,6 +28,8 @@ function describeDetail(ev) {
|
|
|
26
28
|
if (ev.state === "failed") return ev.reason;
|
|
27
29
|
if (ev.state === "disabled") return t("mcpLifecycle.disabledDetail", { name: ev.name });
|
|
28
30
|
if (ev.state === "reconnect") return t("mcpLifecycle.reconnectDetail");
|
|
31
|
+
if (ev.state === "tools-ready") return `${ev.tools} tools \xB7 ${ev.ms}ms`;
|
|
32
|
+
if (ev.state === "warn") return ev.reason;
|
|
29
33
|
const parts = [`${ev.tools} tools`];
|
|
30
34
|
if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);
|
|
31
35
|
if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);
|
|
@@ -43,4 +47,4 @@ export {
|
|
|
43
47
|
formatMcpLifecycleEvent,
|
|
44
48
|
formatMcpSlowToast
|
|
45
49
|
};
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
50
|
+
//# sourceMappingURL=chunk-7UCMM425.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/ui/mcp-lifecycle.ts","../../src/cli/ui/mcp-toast.ts"],"sourcesContent":["/** Formats one-liner MCP lifecycle events per `docs/design/agent-tui-terminal.html` §37. */\n\nimport { t } from \"../../i18n/index.js\";\n\nexport type McpLifecycleEvent =\n | { state: \"handshake\"; name: string }\n | {\n state: \"connected\";\n name: string;\n tools: number;\n resources?: number;\n prompts?: number;\n ms: number;\n }\n | { state: \"failed\"; name: string; reason: string }\n | { state: \"disabled\"; name: string }\n | { state: \"reconnect\"; name: string }\n | { state: \"tools-ready\"; name: string; tools: number; ms: number }\n | { state: \"warn\"; name: string; reason: string };\n\nconst STATE: Record<McpLifecycleEvent[\"state\"], { glyph: string; label: () => string }> = {\n handshake: { glyph: \"↻\", label: () => t(\"mcpLifecycle.handshake\") },\n connected: { glyph: \"✓\", label: () => t(\"mcpLifecycle.connected\") },\n failed: { glyph: \"✖\", label: () => t(\"mcpLifecycle.failed\") },\n disabled: { glyph: \"○\", label: () => t(\"mcpLifecycle.disabled\") },\n reconnect: { glyph: \"↻\", label: () => t(\"mcpLifecycle.reconnect\") },\n \"tools-ready\": { glyph: \"⚡\", label: () => \"tools ready\" },\n warn: { glyph: \"⚠\", label: () => \"warn\" },\n};\n\nconst NAME_COL = 22;\nconst STATE_COL = 15;\n\nexport function formatMcpLifecycleEvent(ev: McpLifecycleEvent): string {\n const { glyph, label } = STATE[ev.state];\n const namePart = `MCP · ${ev.name}`;\n const namePad = \" \".repeat(Math.max(1, NAME_COL - namePart.length));\n const stateField = `${glyph} ${label()}`.padEnd(STATE_COL);\n return `⌘ ${namePart}${namePad}${stateField}${describeDetail(ev)}`;\n}\n\nfunction describeDetail(ev: McpLifecycleEvent): string {\n if (ev.state === \"handshake\") return t(\"mcpLifecycle.initDetail\");\n if (ev.state === \"failed\") return ev.reason;\n if (ev.state === \"disabled\") return t(\"mcpLifecycle.disabledDetail\", { name: ev.name });\n if (ev.state === \"reconnect\") return t(\"mcpLifecycle.reconnectDetail\");\n if (ev.state === \"tools-ready\") return `${ev.tools} tools · ${ev.ms}ms`;\n if (ev.state === \"warn\") return ev.reason;\n const parts: string[] = [`${ev.tools} tools`];\n if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);\n if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);\n parts.push(`${ev.ms}ms`);\n return parts.join(\" · \");\n}\n","/** One-line warn toast emitted when an MCP server's p95 crosses the slow threshold (design §32). */\n\nimport { t } from \"../../i18n/index.js\";\n\nexport interface McpSlowToast {\n name: string;\n p95Ms: number;\n sampleSize: number;\n}\n\nexport function formatMcpSlowToast(tst: McpSlowToast): string {\n const seconds = (tst.p95Ms / 1000).toFixed(1);\n return t(\"mcpHealth.slowToast\", { name: tst.name, seconds, sampleSize: tst.sampleSize });\n}\n"],"mappings":";;;;;;;AAoBA,IAAM,QAAoF;AAAA,EACxF,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,QAAQ,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,qBAAqB,EAAE;AAAA,EAC5D,UAAU,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,uBAAuB,EAAE;AAAA,EAChE,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,eAAe,EAAE,OAAO,UAAK,OAAO,MAAM,cAAc;AAAA,EACxD,MAAM,EAAE,OAAO,UAAK,OAAO,MAAM,OAAO;AAC1C;AAEA,IAAM,WAAW;AACjB,IAAM,YAAY;AAEX,SAAS,wBAAwB,IAA+B;AACrE,QAAM,EAAE,OAAO,MAAM,IAAI,MAAM,GAAG,KAAK;AACvC,QAAM,WAAW,YAAS,GAAG,IAAI;AACjC,QAAM,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,WAAW,SAAS,MAAM,CAAC;AAClE,QAAM,aAAa,GAAG,KAAK,IAAI,MAAM,CAAC,GAAG,OAAO,SAAS;AACzD,SAAO,UAAK,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,eAAe,EAAE,CAAC;AAClE;AAEA,SAAS,eAAe,IAA+B;AACrD,MAAI,GAAG,UAAU,YAAa,QAAO,EAAE,yBAAyB;AAChE,MAAI,GAAG,UAAU,SAAU,QAAO,GAAG;AACrC,MAAI,GAAG,UAAU,WAAY,QAAO,EAAE,+BAA+B,EAAE,MAAM,GAAG,KAAK,CAAC;AACtF,MAAI,GAAG,UAAU,YAAa,QAAO,EAAE,8BAA8B;AACrE,MAAI,GAAG,UAAU,cAAe,QAAO,GAAG,GAAG,KAAK,eAAY,GAAG,EAAE;AACnE,MAAI,GAAG,UAAU,OAAQ,QAAO,GAAG;AACnC,QAAM,QAAkB,CAAC,GAAG,GAAG,KAAK,QAAQ;AAC5C,MAAI,GAAG,aAAa,GAAG,YAAY,EAAG,OAAM,KAAK,GAAG,GAAG,SAAS,YAAY;AAC5E,MAAI,GAAG,WAAW,GAAG,UAAU,EAAG,OAAM,KAAK,GAAG,GAAG,OAAO,UAAU;AACpE,QAAM,KAAK,GAAG,GAAG,EAAE,IAAI;AACvB,SAAO,MAAM,KAAK,QAAK;AACzB;;;AC3CO,SAAS,mBAAmB,KAA2B;AAC5D,QAAM,WAAW,IAAI,QAAQ,KAAM,QAAQ,CAAC;AAC5C,SAAO,EAAE,uBAAuB,EAAE,MAAM,IAAI,MAAM,SAAS,YAAY,IAAI,WAAW,CAAC;AACzF;","names":[]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
4
|
require_react
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-X53B3JIX.js";
|
|
6
6
|
import {
|
|
7
7
|
CARD,
|
|
8
8
|
DEFAULT_THEME_NAME,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
TONE_ACTIVE,
|
|
14
14
|
resolveThemeName,
|
|
15
15
|
setActiveTheme
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-AVFXO2EZ.js";
|
|
17
17
|
import {
|
|
18
18
|
__toESM
|
|
19
19
|
} from "./chunk-TUK7OWJA.js";
|
|
@@ -157,4 +157,4 @@ export {
|
|
|
157
157
|
COLOR,
|
|
158
158
|
GLYPH
|
|
159
159
|
};
|
|
160
|
-
//# sourceMappingURL=chunk-
|
|
160
|
+
//# sourceMappingURL=chunk-AB2RED3C.js.map
|