slash-tokens 1.5.6 → 1.5.7
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/dist/cli.js +2 -2
- package/dist/intercept.d.ts +1 -0
- package/dist/intercept.js +26 -7
- package/dist/models.d.ts +7 -0
- package/dist/models.js +16 -2
- package/dist/preflight.js +6 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -208,8 +208,8 @@ var MODELS = {
|
|
|
208
208
|
"claude-opus-4.7": { input: 5, output: 25, context: 1e6 },
|
|
209
209
|
"claude-sonnet": { input: 2, output: 10, context: 1e6 },
|
|
210
210
|
"claude-haiku": { input: 1, output: 5, context: 200000 },
|
|
211
|
-
"grok-4.20": { input: 1.25, output: 2.5, context: 1e6 },
|
|
212
|
-
"grok-4-1-fast": { input: 1.25, output: 2.5, context: 1e6 },
|
|
211
|
+
"grok-4.20": { input: 1.25, output: 2.5, context: 1e6, longContextThreshold: 200000, longContextInput: 2.5, longContextOutput: 5 },
|
|
212
|
+
"grok-4-1-fast": { input: 1.25, output: 2.5, context: 1e6, longContextThreshold: 200000, longContextInput: 2.5, longContextOutput: 5 },
|
|
213
213
|
"gemini-3.1-pro": { input: 2, output: 12, context: 1e6 },
|
|
214
214
|
"gemini-2.5-flash": { input: 0.3, output: 2.5, context: 1e6 },
|
|
215
215
|
"gpt-5.4": { input: 2.5, output: 15, context: 1e6 },
|
package/dist/intercept.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export interface InterceptEvent {
|
|
|
11
11
|
routed: boolean;
|
|
12
12
|
timestamp: string;
|
|
13
13
|
}
|
|
14
|
+
export declare function normalizeModel(raw: string): string;
|
|
14
15
|
export declare function onIntercept(handler: (event: InterceptEvent) => void): void;
|
|
15
16
|
export declare function patchFetch(): void;
|
package/dist/intercept.js
CHANGED
|
@@ -6,6 +6,7 @@ import { PROVIDER_MODELS } from './providers.js';
|
|
|
6
6
|
// (what to put back in the request body)
|
|
7
7
|
const MODEL_API_NAMES = {
|
|
8
8
|
'claude-opus': 'claude-opus-5',
|
|
9
|
+
'claude-opus-4.7': 'claude-opus-4-7',
|
|
9
10
|
'claude-sonnet': 'claude-sonnet-5',
|
|
10
11
|
'claude-haiku': 'claude-haiku-4-5-20251001',
|
|
11
12
|
'gpt-5.4': 'gpt-5.4',
|
|
@@ -43,10 +44,20 @@ const AI_ENDPOINTS = [
|
|
|
43
44
|
modelExtractor: (body) => body?.model || 'grok-4.20',
|
|
44
45
|
},
|
|
45
46
|
];
|
|
46
|
-
// Normalize model names to our pricing table keys
|
|
47
|
-
|
|
47
|
+
// Normalize model names to our pricing table keys.
|
|
48
|
+
// Kept in sync by hand with mcpaas-cf/src/slash-models.ts's normalizeModel
|
|
49
|
+
// (no shared import between the two repos) — fixed 2026-08-23: this copy
|
|
50
|
+
// was missing the opus-4.7 special case and several OpenAI legacy
|
|
51
|
+
// fallbacks the other copy already had, which silently mapped those
|
|
52
|
+
// intercepted calls to generic claude-opus / an unmapped raw string
|
|
53
|
+
// (getModel() returning undefined → $0 reported cost, see slash.ts's
|
|
54
|
+
// DEFAULT_UNKNOWN_MODEL_FACTOR comment for why "unrecognized" defaulting
|
|
55
|
+
// to a falsely-safe-looking value is the dangerous case).
|
|
56
|
+
export function normalizeModel(raw) {
|
|
48
57
|
const lower = raw.toLowerCase();
|
|
49
|
-
// Anthropic
|
|
58
|
+
// Anthropic — 4.7 before generic opus check, same order as slash-models.ts
|
|
59
|
+
if (lower.includes('opus') && (lower.includes('4-7') || lower.includes('4.7')))
|
|
60
|
+
return 'claude-opus-4.7';
|
|
50
61
|
if (lower.includes('opus'))
|
|
51
62
|
return 'claude-opus';
|
|
52
63
|
if (lower.includes('sonnet'))
|
|
@@ -63,20 +74,28 @@ function normalizeModel(raw) {
|
|
|
63
74
|
return 'gemini-3.1-pro';
|
|
64
75
|
if (lower.includes('gemini'))
|
|
65
76
|
return 'gemini-2.5-flash';
|
|
66
|
-
// OpenAI
|
|
77
|
+
// OpenAI — current (5.4 family)
|
|
67
78
|
if (lower.includes('5.4') && lower.includes('nano'))
|
|
68
79
|
return 'gpt-5.4-nano';
|
|
69
80
|
if (lower.includes('5.4') && lower.includes('mini'))
|
|
70
81
|
return 'gpt-5.4-mini';
|
|
71
82
|
if (lower.includes('5.4'))
|
|
72
83
|
return 'gpt-5.4';
|
|
73
|
-
//
|
|
84
|
+
// OpenAI — legacy model names → map to closest current equivalent
|
|
85
|
+
if (lower.includes('o1-mini') || lower.includes('o1_mini'))
|
|
86
|
+
return 'gpt-5.4-mini';
|
|
87
|
+
if (lower.includes('o1'))
|
|
88
|
+
return 'gpt-5.4';
|
|
74
89
|
if (lower.includes('4o-mini') || lower.includes('4o_mini'))
|
|
75
90
|
return 'gpt-5.4-mini';
|
|
76
91
|
if (lower.includes('4o') || lower.includes('4.1'))
|
|
77
92
|
return 'gpt-5.4';
|
|
78
|
-
if (lower.includes('
|
|
79
|
-
return '
|
|
93
|
+
if (lower.includes('gpt-4-turbo') || lower.includes('gpt-4-1'))
|
|
94
|
+
return 'gpt-5.4';
|
|
95
|
+
if (lower.includes('gpt-4'))
|
|
96
|
+
return 'gpt-5.4';
|
|
97
|
+
if (lower.includes('gpt-3.5') || lower.includes('gpt-35'))
|
|
98
|
+
return 'gpt-5.4-nano';
|
|
80
99
|
return raw;
|
|
81
100
|
}
|
|
82
101
|
// Extract message content from request body
|
package/dist/models.d.ts
CHANGED
|
@@ -2,7 +2,14 @@ export interface ModelInfo {
|
|
|
2
2
|
input: number;
|
|
3
3
|
output: number;
|
|
4
4
|
context: number;
|
|
5
|
+
longContextThreshold?: number;
|
|
6
|
+
longContextInput?: number;
|
|
7
|
+
longContextOutput?: number;
|
|
5
8
|
}
|
|
6
9
|
export declare const MODELS: Record<string, ModelInfo>;
|
|
7
10
|
export declare function getModel(name: string): ModelInfo | undefined;
|
|
11
|
+
export declare function effectiveRate(tokens: number, info: ModelInfo): {
|
|
12
|
+
input: number;
|
|
13
|
+
output: number;
|
|
14
|
+
};
|
|
8
15
|
export declare function listModels(): string[];
|
package/dist/models.js
CHANGED
|
@@ -21,8 +21,8 @@ export const MODELS = {
|
|
|
21
21
|
'claude-sonnet': { input: 2.00, output: 10.00, context: 1000000 },
|
|
22
22
|
'claude-haiku': { input: 1.00, output: 5.00, context: 200000 },
|
|
23
23
|
// xAI
|
|
24
|
-
'grok-4.20': { input: 1.25, output: 2.50, context: 1000000 },
|
|
25
|
-
'grok-4-1-fast': { input: 1.25, output: 2.50, context: 1000000 },
|
|
24
|
+
'grok-4.20': { input: 1.25, output: 2.50, context: 1000000, longContextThreshold: 200000, longContextInput: 2.50, longContextOutput: 5.00 },
|
|
25
|
+
'grok-4-1-fast': { input: 1.25, output: 2.50, context: 1000000, longContextThreshold: 200000, longContextInput: 2.50, longContextOutput: 5.00 },
|
|
26
26
|
// Google
|
|
27
27
|
'gemini-3.1-pro': { input: 2.00, output: 12.00, context: 1000000 },
|
|
28
28
|
'gemini-2.5-flash': { input: 0.30, output: 2.50, context: 1000000 },
|
|
@@ -34,6 +34,20 @@ export const MODELS = {
|
|
|
34
34
|
export function getModel(name) {
|
|
35
35
|
return MODELS[name] || MODELS[name.toLowerCase()];
|
|
36
36
|
}
|
|
37
|
+
// Resolve the actual billable rate for a given token count — applies the
|
|
38
|
+
// long-context tier above if the model has one and tokens cross it.
|
|
39
|
+
// preflight()/preflightRoute() should go through this, not read
|
|
40
|
+
// .input/.output directly, or a Grok call over 200K tokens gets silently
|
|
41
|
+
// under-costed at the base rate.
|
|
42
|
+
export function effectiveRate(tokens, info) {
|
|
43
|
+
if (info.longContextThreshold !== undefined && tokens > info.longContextThreshold) {
|
|
44
|
+
return {
|
|
45
|
+
input: info.longContextInput ?? info.input,
|
|
46
|
+
output: info.longContextOutput ?? info.output,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { input: info.input, output: info.output };
|
|
50
|
+
}
|
|
37
51
|
export function listModels() {
|
|
38
52
|
return Object.keys(MODELS);
|
|
39
53
|
}
|
package/dist/preflight.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { slash } from './slash.js';
|
|
2
|
-
import { getModel, MODELS } from './models.js';
|
|
2
|
+
import { getModel, MODELS, effectiveRate } from './models.js';
|
|
3
3
|
import { PROVIDER_MODELS, providerOf } from './providers.js';
|
|
4
4
|
import { shouldRoute, isModelAllowed } from './config.js';
|
|
5
5
|
/**
|
|
6
6
|
* Compute cost of a prompt of `tokens` tokens on the given ModelInfo.
|
|
7
7
|
* Uses input-token price only (output is not known at preflight time).
|
|
8
|
-
* Rounded to 6 decimals.
|
|
8
|
+
* Rounded to 6 decimals. Goes through effectiveRate() so a long-context
|
|
9
|
+
* model (currently only Grok, over 200K tokens) isn't silently costed at
|
|
10
|
+
* its base rate — fixed 2026-08-23.
|
|
9
11
|
*/
|
|
10
12
|
function computeCost(tokens, info) {
|
|
11
|
-
|
|
13
|
+
const rate = effectiveRate(tokens, info);
|
|
14
|
+
return Math.round(((tokens / 1000000) * rate.input) * 1000000) / 1000000;
|
|
12
15
|
}
|
|
13
16
|
function buildAlternative(model, originalCost, tokens, info) {
|
|
14
17
|
const altCost = computeCost(tokens, info);
|