tokenfirewall 1.0.1
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/LICENSE +21 -0
- package/README.md +312 -0
- package/dist/adapters/anthropic.d.ts +5 -0
- package/dist/adapters/anthropic.js +34 -0
- package/dist/adapters/gemini.d.ts +5 -0
- package/dist/adapters/gemini.js +42 -0
- package/dist/adapters/grok.d.ts +6 -0
- package/dist/adapters/grok.js +33 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.js +18 -0
- package/dist/adapters/kimi.d.ts +6 -0
- package/dist/adapters/kimi.js +33 -0
- package/dist/adapters/openai.d.ts +5 -0
- package/dist/adapters/openai.js +46 -0
- package/dist/core/budgetManager.d.ts +40 -0
- package/dist/core/budgetManager.js +116 -0
- package/dist/core/costEngine.d.ts +6 -0
- package/dist/core/costEngine.js +30 -0
- package/dist/core/pricingRegistry.d.ts +27 -0
- package/dist/core/pricingRegistry.js +75 -0
- package/dist/core/types.d.ts +66 -0
- package/dist/core/types.js +2 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +134 -0
- package/dist/interceptors/fetchInterceptor.d.ts +13 -0
- package/dist/interceptors/fetchInterceptor.js +73 -0
- package/dist/interceptors/sdkInterceptor.d.ts +9 -0
- package/dist/interceptors/sdkInterceptor.js +37 -0
- package/dist/introspection/contextRegistry.d.ts +30 -0
- package/dist/introspection/contextRegistry.js +81 -0
- package/dist/introspection/modelLister.d.ts +22 -0
- package/dist/introspection/modelLister.js +190 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +31 -0
- package/dist/registry.d.ts +18 -0
- package/dist/registry.js +38 -0
- package/package.json +46 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context window registry for LLM models
|
|
3
|
+
* Maintains static mapping of model -> context limits
|
|
4
|
+
*/
|
|
5
|
+
interface ContextLimit {
|
|
6
|
+
tokens: number;
|
|
7
|
+
}
|
|
8
|
+
declare class ContextRegistry {
|
|
9
|
+
private limits;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Initialize known context limits for supported models
|
|
13
|
+
*/
|
|
14
|
+
private initializeContextLimits;
|
|
15
|
+
/**
|
|
16
|
+
* Register context limit for a model
|
|
17
|
+
*/
|
|
18
|
+
register(provider: string, model: string, limit: ContextLimit): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get context limit for a model
|
|
21
|
+
* Returns undefined if not found (does not throw)
|
|
22
|
+
*/
|
|
23
|
+
getContextLimit(provider: string, model: string): number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Check if provider is supported
|
|
26
|
+
*/
|
|
27
|
+
isProviderSupported(provider: string): boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const contextRegistry: ContextRegistry;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Context window registry for LLM models
|
|
4
|
+
* Maintains static mapping of model -> context limits
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.contextRegistry = void 0;
|
|
8
|
+
class ContextRegistry {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.limits = new Map();
|
|
11
|
+
this.initializeContextLimits();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Initialize known context limits for supported models
|
|
15
|
+
*/
|
|
16
|
+
initializeContextLimits() {
|
|
17
|
+
// OpenAI context limits
|
|
18
|
+
this.register("openai", "gpt-4o", { tokens: 128000 });
|
|
19
|
+
this.register("openai", "gpt-4o-mini", { tokens: 128000 });
|
|
20
|
+
this.register("openai", "gpt-4-turbo", { tokens: 128000 });
|
|
21
|
+
this.register("openai", "gpt-4", { tokens: 8192 });
|
|
22
|
+
this.register("openai", "gpt-3.5-turbo", { tokens: 16385 });
|
|
23
|
+
this.register("openai", "gpt-3.5-turbo-16k", { tokens: 16385 });
|
|
24
|
+
// Anthropic context limits
|
|
25
|
+
this.register("anthropic", "claude-3-5-sonnet-20241022", { tokens: 200000 });
|
|
26
|
+
this.register("anthropic", "claude-3-5-haiku-20241022", { tokens: 200000 });
|
|
27
|
+
this.register("anthropic", "claude-3-opus-20240229", { tokens: 200000 });
|
|
28
|
+
this.register("anthropic", "claude-3-sonnet-20240229", { tokens: 200000 });
|
|
29
|
+
this.register("anthropic", "claude-3-haiku-20240307", { tokens: 200000 });
|
|
30
|
+
// Gemini context limits (updated with latest models)
|
|
31
|
+
this.register("gemini", "gemini-2.5-flash", { tokens: 1048576 });
|
|
32
|
+
this.register("gemini", "gemini-2.5-pro", { tokens: 2097152 });
|
|
33
|
+
this.register("gemini", "gemini-2.0-flash", { tokens: 1048576 });
|
|
34
|
+
this.register("gemini", "gemini-2.0-flash-exp", { tokens: 1048576 });
|
|
35
|
+
this.register("gemini", "gemini-1.5-pro", { tokens: 2097152 });
|
|
36
|
+
this.register("gemini", "gemini-1.5-flash", { tokens: 1048576 });
|
|
37
|
+
this.register("gemini", "gemini-1.0-pro", { tokens: 32768 });
|
|
38
|
+
// Grok context limits
|
|
39
|
+
this.register("grok", "grok-beta", { tokens: 131072 });
|
|
40
|
+
this.register("grok", "grok-vision-beta", { tokens: 131072 });
|
|
41
|
+
this.register("grok", "grok-2-1212", { tokens: 131072 });
|
|
42
|
+
this.register("grok", "grok-2-vision-1212", { tokens: 131072 });
|
|
43
|
+
// Llama models via Grok
|
|
44
|
+
this.register("grok", "llama-3.1-70b", { tokens: 131072 });
|
|
45
|
+
this.register("grok", "llama-3.1-8b", { tokens: 131072 });
|
|
46
|
+
this.register("grok", "llama-3.2-90b-vision", { tokens: 131072 });
|
|
47
|
+
this.register("grok", "llama-3.3-70b", { tokens: 131072 });
|
|
48
|
+
// Kimi context limits
|
|
49
|
+
this.register("kimi", "moonshot-v1-8k", { tokens: 8192 });
|
|
50
|
+
this.register("kimi", "moonshot-v1-32k", { tokens: 32768 });
|
|
51
|
+
this.register("kimi", "moonshot-v1-128k", { tokens: 131072 });
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Register context limit for a model
|
|
55
|
+
*/
|
|
56
|
+
register(provider, model, limit) {
|
|
57
|
+
if (!this.limits.has(provider)) {
|
|
58
|
+
this.limits.set(provider, new Map());
|
|
59
|
+
}
|
|
60
|
+
this.limits.get(provider).set(model, limit);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get context limit for a model
|
|
64
|
+
* Returns undefined if not found (does not throw)
|
|
65
|
+
*/
|
|
66
|
+
getContextLimit(provider, model) {
|
|
67
|
+
const providerLimits = this.limits.get(provider);
|
|
68
|
+
if (!providerLimits) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const limit = providerLimits.get(model);
|
|
72
|
+
return limit?.tokens;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if provider is supported
|
|
76
|
+
*/
|
|
77
|
+
isProviderSupported(provider) {
|
|
78
|
+
return this.limits.has(provider);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.contextRegistry = new ContextRegistry();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model information with context limits and budget usage
|
|
3
|
+
*/
|
|
4
|
+
export interface ModelInfo {
|
|
5
|
+
model: string;
|
|
6
|
+
contextLimit?: number;
|
|
7
|
+
budgetUsagePercentage?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Options for listing available models
|
|
11
|
+
*/
|
|
12
|
+
export interface ListModelsOptions {
|
|
13
|
+
provider: string;
|
|
14
|
+
apiKey: string;
|
|
15
|
+
baseURL?: string;
|
|
16
|
+
includeBudgetUsage?: boolean;
|
|
17
|
+
budgetManager?: any;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* List available models for a provider
|
|
21
|
+
*/
|
|
22
|
+
export declare function listAvailableModels(options: ListModelsOptions): Promise<ModelInfo[]>;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listAvailableModels = listAvailableModels;
|
|
4
|
+
const contextRegistry_1 = require("./contextRegistry");
|
|
5
|
+
/**
|
|
6
|
+
* List available models for a provider
|
|
7
|
+
*/
|
|
8
|
+
async function listAvailableModels(options) {
|
|
9
|
+
const { provider, apiKey, baseURL, includeBudgetUsage, budgetManager } = options;
|
|
10
|
+
const providerLower = provider.toLowerCase();
|
|
11
|
+
let models = [];
|
|
12
|
+
try {
|
|
13
|
+
switch (providerLower) {
|
|
14
|
+
case "openai":
|
|
15
|
+
models = await listOpenAIModels(apiKey, baseURL);
|
|
16
|
+
break;
|
|
17
|
+
case "anthropic":
|
|
18
|
+
models = await listAnthropicModels();
|
|
19
|
+
break;
|
|
20
|
+
case "gemini":
|
|
21
|
+
models = await listGeminiModels(apiKey, baseURL);
|
|
22
|
+
break;
|
|
23
|
+
case "grok":
|
|
24
|
+
models = await listGrokModels(apiKey, baseURL);
|
|
25
|
+
break;
|
|
26
|
+
case "kimi":
|
|
27
|
+
models = await listKimiModels(apiKey, baseURL);
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
console.warn(`TokenFirewall: Provider "${provider}" not supported for model listing`);
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.warn(`TokenFirewall: Failed to list models for ${provider}:`, error);
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return enrichModelsWithMetadata(providerLower, models, includeBudgetUsage, budgetManager);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Enrich model list with context limits and budget usage
|
|
42
|
+
*/
|
|
43
|
+
function enrichModelsWithMetadata(provider, models, includeBudgetUsage, budgetManager) {
|
|
44
|
+
let budgetPercentage;
|
|
45
|
+
if (includeBudgetUsage && budgetManager) {
|
|
46
|
+
const status = budgetManager.getStatus();
|
|
47
|
+
budgetPercentage = status ? status.percentageUsed : undefined;
|
|
48
|
+
}
|
|
49
|
+
return models.map((model) => {
|
|
50
|
+
const contextLimit = contextRegistry_1.contextRegistry.getContextLimit(provider, model);
|
|
51
|
+
const info = {
|
|
52
|
+
model,
|
|
53
|
+
};
|
|
54
|
+
if (contextLimit !== undefined) {
|
|
55
|
+
info.contextLimit = contextLimit;
|
|
56
|
+
}
|
|
57
|
+
if (budgetPercentage !== undefined) {
|
|
58
|
+
info.budgetUsagePercentage = budgetPercentage;
|
|
59
|
+
}
|
|
60
|
+
return info;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Remove the circular dependency function
|
|
64
|
+
// function getBudgetUsagePercentage(): number | undefined {
|
|
65
|
+
// try {
|
|
66
|
+
// const { getBudgetStatus } = require("../index");
|
|
67
|
+
// const status = getBudgetStatus();
|
|
68
|
+
// return status ? status.percentageUsed : undefined;
|
|
69
|
+
// } catch {
|
|
70
|
+
// return undefined;
|
|
71
|
+
// }
|
|
72
|
+
// }
|
|
73
|
+
/**
|
|
74
|
+
* Fetch with timeout
|
|
75
|
+
*/
|
|
76
|
+
async function fetchWithTimeout(url, options, timeoutMs = 10000) {
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(url, {
|
|
81
|
+
...options,
|
|
82
|
+
signal: controller.signal
|
|
83
|
+
});
|
|
84
|
+
clearTimeout(timeoutId);
|
|
85
|
+
return response;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
clearTimeout(timeoutId);
|
|
89
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
90
|
+
throw new Error('Request timeout');
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* List OpenAI models
|
|
97
|
+
*/
|
|
98
|
+
async function listOpenAIModels(apiKey, baseURL) {
|
|
99
|
+
const url = baseURL || "https://api.openai.com/v1/models";
|
|
100
|
+
const response = await fetchWithTimeout(url, {
|
|
101
|
+
method: "GET",
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: `Bearer ${apiKey}`,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
throw new Error(`OpenAI API error: ${response.status}`);
|
|
108
|
+
}
|
|
109
|
+
const data = (await response.json());
|
|
110
|
+
if (!data.data || !Array.isArray(data.data)) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
return data.data.map((model) => model.id);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* List Anthropic models
|
|
117
|
+
* Note: Anthropic does not provide a models endpoint
|
|
118
|
+
*/
|
|
119
|
+
async function listAnthropicModels() {
|
|
120
|
+
console.warn("TokenFirewall: Anthropic does not provide a model listing API");
|
|
121
|
+
return [
|
|
122
|
+
"claude-3-5-sonnet-20241022",
|
|
123
|
+
"claude-3-5-haiku-20241022",
|
|
124
|
+
"claude-3-opus-20240229",
|
|
125
|
+
"claude-3-sonnet-20240229",
|
|
126
|
+
"claude-3-haiku-20240307",
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* List Gemini models
|
|
131
|
+
*/
|
|
132
|
+
async function listGeminiModels(apiKey, baseURL) {
|
|
133
|
+
const url = baseURL || `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`;
|
|
134
|
+
const response = await fetchWithTimeout(url, {
|
|
135
|
+
method: "GET",
|
|
136
|
+
});
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
throw new Error(`Gemini API error: ${response.status}`);
|
|
139
|
+
}
|
|
140
|
+
const data = (await response.json());
|
|
141
|
+
if (!data.models || !Array.isArray(data.models)) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
return data.models
|
|
145
|
+
.filter((model) => model.name.includes("gemini"))
|
|
146
|
+
.map((model) => {
|
|
147
|
+
const parts = model.name.split("/");
|
|
148
|
+
return parts[parts.length - 1];
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* List Grok models
|
|
153
|
+
*/
|
|
154
|
+
async function listGrokModels(apiKey, baseURL) {
|
|
155
|
+
const url = baseURL || "https://api.x.ai/v1/models";
|
|
156
|
+
const response = await fetchWithTimeout(url, {
|
|
157
|
+
method: "GET",
|
|
158
|
+
headers: {
|
|
159
|
+
Authorization: `Bearer ${apiKey}`,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
throw new Error(`Grok API error: ${response.status}`);
|
|
164
|
+
}
|
|
165
|
+
const data = (await response.json());
|
|
166
|
+
if (!data.data || !Array.isArray(data.data)) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
return data.data.map((model) => model.id);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* List Kimi models
|
|
173
|
+
*/
|
|
174
|
+
async function listKimiModels(apiKey, baseURL) {
|
|
175
|
+
const url = baseURL || "https://api.moonshot.cn/v1/models";
|
|
176
|
+
const response = await fetchWithTimeout(url, {
|
|
177
|
+
method: "GET",
|
|
178
|
+
headers: {
|
|
179
|
+
Authorization: `Bearer ${apiKey}`,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
throw new Error(`Kimi API error: ${response.status}`);
|
|
184
|
+
}
|
|
185
|
+
const data = (await response.json());
|
|
186
|
+
if (!data.data || !Array.isArray(data.data)) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
return data.data.map((model) => model.id);
|
|
190
|
+
}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NormalizedUsage, CostBreakdown } from "./core/types";
|
|
2
|
+
/**
|
|
3
|
+
* Structured logger for LLM usage and costs
|
|
4
|
+
*/
|
|
5
|
+
export declare class Logger {
|
|
6
|
+
/**
|
|
7
|
+
* Log usage and cost information
|
|
8
|
+
*/
|
|
9
|
+
logUsage(usage: NormalizedUsage, cost: CostBreakdown): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const logger: Logger;
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = exports.Logger = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Structured logger for LLM usage and costs
|
|
6
|
+
*/
|
|
7
|
+
class Logger {
|
|
8
|
+
/**
|
|
9
|
+
* Log usage and cost information
|
|
10
|
+
*/
|
|
11
|
+
logUsage(usage, cost) {
|
|
12
|
+
const timestamp = new Date().toISOString();
|
|
13
|
+
console.log(JSON.stringify({
|
|
14
|
+
timestamp,
|
|
15
|
+
provider: usage.provider,
|
|
16
|
+
model: usage.model,
|
|
17
|
+
tokens: {
|
|
18
|
+
input: usage.inputTokens,
|
|
19
|
+
output: usage.outputTokens,
|
|
20
|
+
total: usage.totalTokens,
|
|
21
|
+
},
|
|
22
|
+
cost: {
|
|
23
|
+
input: cost.inputCost.toFixed(6),
|
|
24
|
+
output: cost.outputCost.toFixed(6),
|
|
25
|
+
total: cost.totalCost.toFixed(6),
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.Logger = Logger;
|
|
31
|
+
exports.logger = new Logger();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ProviderAdapter, NormalizedUsage } from "./core/types";
|
|
2
|
+
/**
|
|
3
|
+
* Adapter registry - manages provider detection and normalization
|
|
4
|
+
*/
|
|
5
|
+
declare class AdapterRegistry {
|
|
6
|
+
private adapters;
|
|
7
|
+
/**
|
|
8
|
+
* Register a custom adapter
|
|
9
|
+
*/
|
|
10
|
+
register(adapter: ProviderAdapter): void;
|
|
11
|
+
/**
|
|
12
|
+
* Detect and normalize a response using registered adapters
|
|
13
|
+
* @returns NormalizedUsage or null if no adapter matches
|
|
14
|
+
*/
|
|
15
|
+
process(response: unknown, request?: unknown): NormalizedUsage | null;
|
|
16
|
+
}
|
|
17
|
+
export declare const adapterRegistry: AdapterRegistry;
|
|
18
|
+
export {};
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.adapterRegistry = void 0;
|
|
4
|
+
const adapters_1 = require("./adapters");
|
|
5
|
+
/**
|
|
6
|
+
* Adapter registry - manages provider detection and normalization
|
|
7
|
+
*/
|
|
8
|
+
class AdapterRegistry {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.adapters = [...adapters_1.adapters];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register a custom adapter
|
|
14
|
+
*/
|
|
15
|
+
register(adapter) {
|
|
16
|
+
this.adapters.push(adapter);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Detect and normalize a response using registered adapters
|
|
20
|
+
* @returns NormalizedUsage or null if no adapter matches
|
|
21
|
+
*/
|
|
22
|
+
process(response, request) {
|
|
23
|
+
for (const adapter of this.adapters) {
|
|
24
|
+
try {
|
|
25
|
+
if (adapter.detect(response)) {
|
|
26
|
+
return adapter.normalize(response, request);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// If normalize throws, log warning and try next adapter
|
|
31
|
+
console.warn(`TokenFirewall: Adapter "${adapter.name}" failed to normalize response:`, error);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.adapterRegistry = new AdapterRegistry();
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tokenfirewall",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Scalable, adapter-driven LLM cost enforcement middleware for Node.js with model discovery and context intelligence",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"llm",
|
|
13
|
+
"cost",
|
|
14
|
+
"budget",
|
|
15
|
+
"openai",
|
|
16
|
+
"anthropic",
|
|
17
|
+
"gemini",
|
|
18
|
+
"grok",
|
|
19
|
+
"middleware",
|
|
20
|
+
"token-tracking",
|
|
21
|
+
"cost-control",
|
|
22
|
+
"model-discovery"
|
|
23
|
+
],
|
|
24
|
+
"author": "Ruthwik",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/Ruthwik000/tokenfirewall.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/Ruthwik000/tokenfirewall/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/Ruthwik000/tokenfirewall#readme",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=16.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|