@kunal_dutt/token-lens 0.2.22 → 0.2.25
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/PRIVACY.md +2 -1
- package/README.md +12 -1
- package/check-agent.mjs +22 -22
- package/gateway.mjs +58 -58
- package/package.json +1 -1
- package/sdk.mjs +13 -12
- package/server.mjs +136 -57
- package/token-lens.mcpb +0 -0
- package/types/src/core/advice.d.ts +1 -1
- package/types/src/core/budget.d.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kunal_dutt/token-lens",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Count and cut the tokens your prompts, chats and agents use, adapted to the model and task. MCP server and self-hosted gateway. Collects no data.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
package/sdk.mjs
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
// src/sdk/index.ts
|
|
2
2
|
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
3
3
|
|
|
4
|
+
// src/core/budget.ts
|
|
5
|
+
var LONG_CHAT_TOKENS = 4e4;
|
|
6
|
+
function contextUsage(conversationTokens, promptTokens, profile, windowOverride) {
|
|
7
|
+
const window = windowOverride && windowOverride > 0 ? windowOverride : profile.contextWindow;
|
|
8
|
+
const ratio2 = (conversationTokens + promptTokens) / window;
|
|
9
|
+
const zone = ratio2 >= 0.95 ? "full" : ratio2 >= 0.8 ? "hot" : ratio2 >= 0.5 ? "warm" : "ok";
|
|
10
|
+
return { conversationTokens, promptTokens, window, ratio: ratio2, zone, longChat: conversationTokens >= LONG_CHAT_TOKENS };
|
|
11
|
+
}
|
|
12
|
+
var HANDOFF_CAVEAT = "Optional: the new chat only knows what the brief keeps, so later answers can differ. Check the brief before you rely on it.";
|
|
13
|
+
|
|
4
14
|
// src/core/advice.ts
|
|
5
15
|
var fmt = (n) => n.toLocaleString("en-US");
|
|
6
16
|
function advise(input) {
|
|
@@ -36,13 +46,13 @@ function advise(input) {
|
|
|
36
46
|
if (usage.zone === "hot" || usage.zone === "full") {
|
|
37
47
|
tips.push({
|
|
38
48
|
id: "handoff",
|
|
39
|
-
text: `This chat fills about ${Math.round(usage.ratio * 100)}% of ${profile.label}'s context. Older messages will be dropped or compacted soon. Hand off to a new chat
|
|
49
|
+
text: `This chat fills about ${Math.round(usage.ratio * 100)}% of ${profile.label}'s context. Older messages will be dropped or compacted soon. Hand off to a new chat. ${HANDOFF_CAVEAT}`,
|
|
40
50
|
saves: "input"
|
|
41
51
|
});
|
|
42
52
|
} else if (usage.longChat || usage.zone === "warm") {
|
|
43
53
|
tips.push({
|
|
44
54
|
id: "handoff",
|
|
45
|
-
text: `Every new message re-reads about ${fmt(usage.conversationTokens)} tokens of history. A handoff brief and a new chat cut that
|
|
55
|
+
text: `Every new message re-reads about ${fmt(usage.conversationTokens)} tokens of history. A handoff brief and a new chat cut that. ${HANDOFF_CAVEAT}`,
|
|
46
56
|
saves: "input"
|
|
47
57
|
});
|
|
48
58
|
}
|
|
@@ -51,21 +61,12 @@ function advise(input) {
|
|
|
51
61
|
if (lc && profile.pricing && reads >= lc.aboveTokens * 0.85)
|
|
52
62
|
tips.push({
|
|
53
63
|
id: "price-threshold",
|
|
54
|
-
text: reads > lc.aboveTokens ? `This message reads \u2248${fmt(reads)} tokens, past ${fmt(lc.aboveTokens)}, so ${profile.label} bills all of it at $${lc.inputPerMTok}/M instead of $${profile.pricing.inputPerMTok}/M. Continuing from a handoff brief in a new chat brings it back under
|
|
64
|
+
text: reads > lc.aboveTokens ? `This message reads \u2248${fmt(reads)} tokens, past ${fmt(lc.aboveTokens)}, so ${profile.label} bills all of it at $${lc.inputPerMTok}/M instead of $${profile.pricing.inputPerMTok}/M. Continuing from a handoff brief in a new chat brings it back under. ${HANDOFF_CAVEAT}` : `This chat is \u2248${fmt(reads)} tokens; past ${fmt(lc.aboveTokens)}, ${profile.label} bills every message at $${lc.inputPerMTok}/M instead of $${profile.pricing.inputPerMTok}/M. Hand off to a new chat before then. ${HANDOFF_CAVEAT}`,
|
|
55
65
|
saves: "input"
|
|
56
66
|
});
|
|
57
67
|
return tips;
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
// src/core/budget.ts
|
|
61
|
-
var LONG_CHAT_TOKENS = 4e4;
|
|
62
|
-
function contextUsage(conversationTokens, promptTokens, profile, windowOverride) {
|
|
63
|
-
const window = windowOverride && windowOverride > 0 ? windowOverride : profile.contextWindow;
|
|
64
|
-
const ratio2 = (conversationTokens + promptTokens) / window;
|
|
65
|
-
const zone = ratio2 >= 0.95 ? "full" : ratio2 >= 0.8 ? "hot" : ratio2 >= 0.5 ? "warm" : "ok";
|
|
66
|
-
return { conversationTokens, promptTokens, window, ratio: ratio2, zone, longChat: conversationTokens >= LONG_CHAT_TOKENS };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
70
|
// node_modules/gpt-tokenizer/esm/constants.js
|
|
70
71
|
var DEFAULT_MERGE_CACHE_SIZE = 1e5;
|
|
71
72
|
|