avantgate 1.1.0 → 1.1.2
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 +45 -232
- package/dist/agent/index.d.mts +743 -0
- package/dist/agent/index.d.ts +743 -0
- package/dist/agent/index.js +1803 -0
- package/dist/agent/index.mjs +1700 -0
- package/dist/chunk-DVCF4CSV.mjs +56 -0
- package/dist/index.d.mts +89 -7
- package/dist/index.d.ts +89 -7
- package/dist/index.js +432 -51
- package/dist/index.mjs +424 -104
- package/package.json +19 -4
package/dist/index.js
CHANGED
|
@@ -20,64 +20,236 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
AvantGateBudgetExceededError: () => BudgetExceededError,
|
|
24
|
+
AvantGateConfigurationError: () => ConfigurationError,
|
|
23
25
|
AvantGateControlLayer: () => AvantGateControlLayer,
|
|
26
|
+
BudgetExceededError: () => BudgetExceededError,
|
|
27
|
+
CachedPricingAdapter: () => CachedPricingAdapter,
|
|
28
|
+
ConfigurationError: () => ConfigurationError,
|
|
24
29
|
DEFAULT_MODEL_PRICES: () => DEFAULT_MODEL_PRICES,
|
|
30
|
+
HttpProviderClient: () => HttpProviderClient,
|
|
31
|
+
PricingRegistry: () => PricingRegistry,
|
|
25
32
|
PromptBuilder: () => PromptBuilder,
|
|
26
33
|
PromptRegistry: () => PromptRegistry,
|
|
27
34
|
PromptTemplate: () => PromptTemplate,
|
|
35
|
+
SEED_MODEL_PRICES: () => SEED_MODEL_PRICES,
|
|
28
36
|
ZenLLMControlLayer: () => AvantGateControlLayer,
|
|
29
37
|
calculateCostUSD: () => calculateCostUSD,
|
|
30
38
|
createAvantGate: () => createAvantGate,
|
|
39
|
+
createHttpProviderClient: () => createHttpProviderClient,
|
|
31
40
|
createLLMControlLayer: () => createLLMControlLayer,
|
|
32
41
|
extractAndCleanJSON: () => extractAndCleanJSON,
|
|
42
|
+
resolveModelPrice: () => resolveModelPrice,
|
|
43
|
+
resolveModelPriceAsync: () => resolveModelPriceAsync,
|
|
33
44
|
sanitizePII: () => sanitizePII,
|
|
34
45
|
validateUserInput: () => validateUserInput,
|
|
35
46
|
validateWithZod: () => validateWithZod
|
|
36
47
|
});
|
|
37
48
|
module.exports = __toCommonJS(index_exports);
|
|
38
49
|
|
|
50
|
+
// src/types.ts
|
|
51
|
+
var ConfigurationError = class extends Error {
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = "ConfigurationError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var BudgetExceededError = class extends Error {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = "BudgetExceededError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
39
64
|
// src/pricing.ts
|
|
40
|
-
var
|
|
41
|
-
// DeepSeek
|
|
42
|
-
"deepseek-chat": {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
var SEED_MODEL_PRICES = {
|
|
66
|
+
// DeepSeek Direct
|
|
67
|
+
"deepseek-chat": { promptUSDPerMillion: 0.14, completionUSDPerMillion: 0.28, cacheHitUSDPerMillion: 0.014 },
|
|
68
|
+
"deepseek-reasoner": { promptUSDPerMillion: 0.55, completionUSDPerMillion: 2.19, cacheHitUSDPerMillion: 0.14 },
|
|
69
|
+
"deepseek/deepseek-chat": { promptUSDPerMillion: 0.14, completionUSDPerMillion: 0.28, cacheHitUSDPerMillion: 0.014 },
|
|
70
|
+
"deepseek/deepseek-reasoner": { promptUSDPerMillion: 0.55, completionUSDPerMillion: 2.19, cacheHitUSDPerMillion: 0.14 },
|
|
71
|
+
// Mistral AI Direct
|
|
72
|
+
"mistral-small-latest": { promptUSDPerMillion: 0.2, completionUSDPerMillion: 0.6 },
|
|
73
|
+
"mistral-large-latest": { promptUSDPerMillion: 2, completionUSDPerMillion: 6 },
|
|
74
|
+
"mistral/mistral-small-latest": { promptUSDPerMillion: 0.2, completionUSDPerMillion: 0.6 },
|
|
75
|
+
"mistral/mistral-large-latest": { promptUSDPerMillion: 2, completionUSDPerMillion: 6 },
|
|
76
|
+
// OpenAI Direct
|
|
77
|
+
"gpt-4o-mini": { promptUSDPerMillion: 0.15, completionUSDPerMillion: 0.6 },
|
|
78
|
+
"gpt-4o": { promptUSDPerMillion: 2.5, completionUSDPerMillion: 10 },
|
|
79
|
+
"openai/gpt-4o-mini": { promptUSDPerMillion: 0.15, completionUSDPerMillion: 0.6 },
|
|
80
|
+
"openai/gpt-4o": { promptUSDPerMillion: 2.5, completionUSDPerMillion: 10 },
|
|
81
|
+
// OpenRouter Direct
|
|
82
|
+
"openrouter/deepseek/deepseek-chat": { promptUSDPerMillion: 0.14, completionUSDPerMillion: 0.28 },
|
|
83
|
+
"openrouter/deepseek/deepseek-r1": { promptUSDPerMillion: 0.55, completionUSDPerMillion: 2.19 },
|
|
84
|
+
"openrouter/anthropic/claude-3.5-sonnet": { promptUSDPerMillion: 3, completionUSDPerMillion: 15 },
|
|
85
|
+
// Local Ollama (Toujours $0)
|
|
86
|
+
"ollama": { promptUSDPerMillion: 0, completionUSDPerMillion: 0 }
|
|
87
|
+
};
|
|
88
|
+
function normalizeKey(identifier) {
|
|
89
|
+
return identifier.trim().toLowerCase().replace(":", "/");
|
|
90
|
+
}
|
|
91
|
+
var CachedPricingAdapter = class {
|
|
92
|
+
cache = /* @__PURE__ */ new Map();
|
|
93
|
+
ttlMs;
|
|
94
|
+
delegate;
|
|
95
|
+
constructor(delegate, ttlMs = 5 * 60 * 1e3) {
|
|
96
|
+
this.delegate = delegate;
|
|
97
|
+
this.ttlMs = ttlMs;
|
|
98
|
+
}
|
|
99
|
+
async fetchPrice(model, provider) {
|
|
100
|
+
const key = provider ? normalizeKey(`${provider}/${model}`) : normalizeKey(model);
|
|
101
|
+
const cached = this.cache.get(key);
|
|
102
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
103
|
+
return cached.price;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const freshPrice = await this.delegate.fetchPrice(model, provider);
|
|
107
|
+
if (freshPrice) {
|
|
108
|
+
this.cache.set(key, { price: freshPrice, expiresAt: Date.now() + this.ttlMs });
|
|
109
|
+
return freshPrice;
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
if (cached) {
|
|
113
|
+
return cached.price;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return void 0;
|
|
117
|
+
}
|
|
118
|
+
peek(model, provider) {
|
|
119
|
+
const key = provider ? normalizeKey(`${provider}/${model}`) : normalizeKey(model);
|
|
120
|
+
return this.cache.get(key)?.price;
|
|
121
|
+
}
|
|
122
|
+
clearCache() {
|
|
123
|
+
this.cache.clear();
|
|
124
|
+
}
|
|
125
|
+
invalidate(model, provider) {
|
|
126
|
+
if (!model) {
|
|
127
|
+
this.clearCache();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const key = provider ? normalizeKey(`${provider}/${model}`) : normalizeKey(model);
|
|
131
|
+
this.cache.delete(key);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
var PricingRegistry = class {
|
|
135
|
+
static prices = /* @__PURE__ */ new Map();
|
|
136
|
+
static adapter;
|
|
137
|
+
static registerPrice(identifier, price) {
|
|
138
|
+
this.prices.set(normalizeKey(identifier), price);
|
|
139
|
+
}
|
|
140
|
+
static registerDistributorPrices(distributor, priceMap) {
|
|
141
|
+
for (const [model, price] of Object.entries(priceMap)) {
|
|
142
|
+
this.prices.set(normalizeKey(`${distributor}/${model}`), price);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
static registerPrices(prices) {
|
|
146
|
+
for (const [key, price] of Object.entries(prices)) {
|
|
147
|
+
this.prices.set(normalizeKey(key), price);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
static getPrice(model, provider) {
|
|
151
|
+
if (provider) {
|
|
152
|
+
const distributorKey = normalizeKey(`${provider}/${model}`);
|
|
153
|
+
const directDistributorPrice = this.prices.get(distributorKey);
|
|
154
|
+
if (directDistributorPrice) {
|
|
155
|
+
return directDistributorPrice;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return this.prices.get(normalizeKey(model));
|
|
159
|
+
}
|
|
160
|
+
static setAdapter(adapter) {
|
|
161
|
+
this.adapter = adapter;
|
|
162
|
+
}
|
|
163
|
+
static getAdapter() {
|
|
164
|
+
return this.adapter;
|
|
165
|
+
}
|
|
166
|
+
static clear() {
|
|
167
|
+
this.prices.clear();
|
|
168
|
+
this.adapter = void 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Réinitialise le registre en chargeant le catalogue d'exemple SEED_MODEL_PRICES.
|
|
172
|
+
*/
|
|
173
|
+
static loadSeedPrices() {
|
|
174
|
+
this.registerPrices(SEED_MODEL_PRICES);
|
|
175
|
+
}
|
|
176
|
+
static getAllPrices() {
|
|
177
|
+
const out = {};
|
|
178
|
+
for (const [k, v] of this.prices.entries()) {
|
|
179
|
+
out[k] = v;
|
|
180
|
+
}
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var DEFAULT_MODEL_PRICES = new Proxy({}, {
|
|
185
|
+
get(_target, prop) {
|
|
186
|
+
return PricingRegistry.getPrice(prop);
|
|
60
187
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
promptUSDPerMillion: 0.15,
|
|
64
|
-
completionUSDPerMillion: 0.6
|
|
188
|
+
has(_target, prop) {
|
|
189
|
+
return Boolean(PricingRegistry.getPrice(prop));
|
|
65
190
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
completionUSDPerMillion: 10
|
|
191
|
+
ownKeys() {
|
|
192
|
+
return Object.keys(PricingRegistry.getAllPrices());
|
|
69
193
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
194
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
195
|
+
const price = PricingRegistry.getPrice(prop);
|
|
196
|
+
if (price) {
|
|
197
|
+
return { value: price, enumerable: true, configurable: true, writable: false };
|
|
198
|
+
}
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
function resolveModelPrice(model, options) {
|
|
203
|
+
const opts = typeof options === "string" ? { provider: options } : options ?? {};
|
|
204
|
+
if (opts.providerPricing) {
|
|
205
|
+
return opts.providerPricing;
|
|
206
|
+
}
|
|
207
|
+
if (opts.customPricing) {
|
|
208
|
+
if (opts.provider) {
|
|
209
|
+
const customDistributorKey = normalizeKey(`${opts.provider}/${model}`);
|
|
210
|
+
if (opts.customPricing[customDistributorKey]) {
|
|
211
|
+
return opts.customPricing[customDistributorKey];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (opts.customPricing[normalizeKey(model)] ?? opts.customPricing[model]) {
|
|
215
|
+
return opts.customPricing[normalizeKey(model)] ?? opts.customPricing[model];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const activeAdapter = opts.adapter ?? PricingRegistry.getAdapter();
|
|
219
|
+
if (activeAdapter instanceof CachedPricingAdapter) {
|
|
220
|
+
const cached = activeAdapter.peek(model, opts.provider);
|
|
221
|
+
if (cached) {
|
|
222
|
+
return cached;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const registeredPrice = PricingRegistry.getPrice(model, opts.provider);
|
|
226
|
+
if (registeredPrice) {
|
|
227
|
+
return registeredPrice;
|
|
228
|
+
}
|
|
229
|
+
if (opts.provider === "ollama" || model.toLowerCase().includes("ollama")) {
|
|
230
|
+
return { promptUSDPerMillion: 0, completionUSDPerMillion: 0 };
|
|
231
|
+
}
|
|
232
|
+
return void 0;
|
|
233
|
+
}
|
|
234
|
+
async function resolveModelPriceAsync(model, options) {
|
|
235
|
+
const opts = typeof options === "string" ? { provider: options } : options ?? {};
|
|
236
|
+
const activeAdapter = opts.adapter ?? PricingRegistry.getAdapter();
|
|
237
|
+
if (activeAdapter) {
|
|
238
|
+
try {
|
|
239
|
+
const adapterPrice = await activeAdapter.fetchPrice(model, opts.provider);
|
|
240
|
+
if (adapterPrice) {
|
|
241
|
+
return adapterPrice;
|
|
242
|
+
}
|
|
243
|
+
} catch {
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return resolveModelPrice(model, options);
|
|
247
|
+
}
|
|
248
|
+
function calculateCostUSD(model, promptTokens, completionTokens, cacheHitTokens = 0, options) {
|
|
249
|
+
const pricing = resolveModelPrice(model, options);
|
|
250
|
+
if (!pricing) {
|
|
251
|
+
return 0;
|
|
74
252
|
}
|
|
75
|
-
};
|
|
76
|
-
function calculateCostUSD(model, promptTokens, completionTokens, cacheHitTokens = 0) {
|
|
77
|
-
const pricing = DEFAULT_MODEL_PRICES[model] ?? {
|
|
78
|
-
promptUSDPerMillion: 0.5,
|
|
79
|
-
completionUSDPerMillion: 1.5
|
|
80
|
-
};
|
|
81
253
|
const promptCost = promptTokens / 1e6 * pricing.promptUSDPerMillion;
|
|
82
254
|
const completionCost = completionTokens / 1e6 * pricing.completionUSDPerMillion;
|
|
83
255
|
const cacheDiscount = cacheHitTokens && pricing.cacheHitUSDPerMillion ? cacheHitTokens / 1e6 * (pricing.promptUSDPerMillion - pricing.cacheHitUSDPerMillion) : 0;
|
|
@@ -673,11 +845,144 @@ function validateWithZod(rawText, schema, options) {
|
|
|
673
845
|
return schema.parse(parsed);
|
|
674
846
|
}
|
|
675
847
|
|
|
848
|
+
// src/providers/http-client.ts
|
|
849
|
+
var DEFAULT_BASE_URLS = {
|
|
850
|
+
deepseek: "https://api.deepseek.com/v1",
|
|
851
|
+
mistral: "https://api.mistral.ai/v1",
|
|
852
|
+
openai: "https://api.openai.com/v1",
|
|
853
|
+
ollama: "http://localhost:11434/v1",
|
|
854
|
+
openrouter: "https://openrouter.ai/api/v1"
|
|
855
|
+
};
|
|
856
|
+
var HttpProviderClient = class {
|
|
857
|
+
name;
|
|
858
|
+
baseUrl;
|
|
859
|
+
apiKey;
|
|
860
|
+
providerType;
|
|
861
|
+
constructor(config) {
|
|
862
|
+
this.providerType = config.provider;
|
|
863
|
+
this.name = `${config.provider}-http`;
|
|
864
|
+
this.apiKey = config.apiKey;
|
|
865
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URLS[config.provider] || "https://api.openai.com/v1";
|
|
866
|
+
}
|
|
867
|
+
resolveEndpoint() {
|
|
868
|
+
const trimmed = this.baseUrl.replace(/\/+$/, "");
|
|
869
|
+
if (trimmed.endsWith("/chat/completions")) {
|
|
870
|
+
return trimmed;
|
|
871
|
+
}
|
|
872
|
+
return `${trimmed}/chat/completions`;
|
|
873
|
+
}
|
|
874
|
+
buildHeaders() {
|
|
875
|
+
const headers = {
|
|
876
|
+
"Content-Type": "application/json"
|
|
877
|
+
};
|
|
878
|
+
if (this.apiKey) {
|
|
879
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
880
|
+
}
|
|
881
|
+
if (this.providerType === "openrouter") {
|
|
882
|
+
headers["HTTP-Referer"] = "https://avantgate.dev";
|
|
883
|
+
headers["X-Title"] = "AvantGate";
|
|
884
|
+
}
|
|
885
|
+
return headers;
|
|
886
|
+
}
|
|
887
|
+
buildPayload(options, model) {
|
|
888
|
+
return {
|
|
889
|
+
model,
|
|
890
|
+
messages: options.messages.map((m) => ({
|
|
891
|
+
role: m.role,
|
|
892
|
+
content: m.content
|
|
893
|
+
})),
|
|
894
|
+
temperature: options.temperature ?? 0.2,
|
|
895
|
+
...options.responseFormat ? { response_format: options.responseFormat } : {}
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
extractUsage(usageData) {
|
|
899
|
+
if (!usageData) {
|
|
900
|
+
return void 0;
|
|
901
|
+
}
|
|
902
|
+
return {
|
|
903
|
+
promptTokens: usageData.prompt_tokens,
|
|
904
|
+
completionTokens: usageData.completion_tokens,
|
|
905
|
+
totalTokens: usageData.total_tokens,
|
|
906
|
+
promptCacheHitTokens: usageData.prompt_tokens_details?.cached_tokens
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
async complete(options) {
|
|
910
|
+
const endpoint = this.resolveEndpoint();
|
|
911
|
+
const model = options.model ?? "default";
|
|
912
|
+
const headers = this.buildHeaders();
|
|
913
|
+
const body = JSON.stringify(this.buildPayload(options, model));
|
|
914
|
+
const response = await fetch(endpoint, {
|
|
915
|
+
method: "POST",
|
|
916
|
+
headers,
|
|
917
|
+
body
|
|
918
|
+
});
|
|
919
|
+
if (!response.ok) {
|
|
920
|
+
const errorText = await response.text();
|
|
921
|
+
throw new Error(
|
|
922
|
+
`[AvantGate HTTP Provider ${this.providerType}] HTTP ${response.status} ${response.statusText}: ${errorText}`
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
const data = await response.json();
|
|
926
|
+
const text = data.choices?.[0]?.message?.content ?? "";
|
|
927
|
+
const usage = this.extractUsage(data.usage);
|
|
928
|
+
return { text, usage };
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
function createHttpProviderClient(config) {
|
|
932
|
+
return new HttpProviderClient(config);
|
|
933
|
+
}
|
|
934
|
+
|
|
676
935
|
// src/control-layer.ts
|
|
677
936
|
var AvantGateControlLayer = class {
|
|
678
937
|
config;
|
|
938
|
+
cachedPricingAdapter;
|
|
679
939
|
constructor(config) {
|
|
680
|
-
this.config =
|
|
940
|
+
this.config = {
|
|
941
|
+
...config,
|
|
942
|
+
primary: this.resolveProviderConfig(config.primary),
|
|
943
|
+
fallback: this.resolveProviderConfig(config.fallback),
|
|
944
|
+
emergencyFallback: this.resolveProviderConfig(config.emergencyFallback)
|
|
945
|
+
};
|
|
946
|
+
if (config.pricingAdapter) {
|
|
947
|
+
this.cachedPricingAdapter = new CachedPricingAdapter(
|
|
948
|
+
config.pricingAdapter,
|
|
949
|
+
config.pricingCacheTtlMs ?? 5 * 60 * 1e3
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
resolveProviderConfig(provider) {
|
|
954
|
+
if (!provider) return void 0;
|
|
955
|
+
if (provider.client) return provider;
|
|
956
|
+
if (provider.apiKey || provider.baseUrl || provider.provider === "ollama") {
|
|
957
|
+
return {
|
|
958
|
+
...provider,
|
|
959
|
+
client: createHttpProviderClient(provider)
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
return provider;
|
|
963
|
+
}
|
|
964
|
+
findProviderConfig(provider, model) {
|
|
965
|
+
const list = [this.config.primary, this.config.fallback, this.config.emergencyFallback].filter(
|
|
966
|
+
(p) => Boolean(p)
|
|
967
|
+
);
|
|
968
|
+
if (provider) {
|
|
969
|
+
const matchProvider = list.find((p) => p.provider === provider);
|
|
970
|
+
if (matchProvider) return matchProvider;
|
|
971
|
+
}
|
|
972
|
+
if (model) {
|
|
973
|
+
const matchModel = list.find((p) => p.model === model);
|
|
974
|
+
if (matchModel) return matchModel;
|
|
975
|
+
}
|
|
976
|
+
return this.config.primary;
|
|
977
|
+
}
|
|
978
|
+
calculateCost(model, promptTokens, completionTokens, cacheHitTokens = 0, provider) {
|
|
979
|
+
const providerCfg = this.findProviderConfig(provider, model);
|
|
980
|
+
return calculateCostUSD(model, promptTokens, completionTokens, cacheHitTokens, {
|
|
981
|
+
provider: provider ?? providerCfg?.provider,
|
|
982
|
+
providerPricing: providerCfg?.pricing,
|
|
983
|
+
customPricing: this.config.customPricing,
|
|
984
|
+
adapter: this.cachedPricingAdapter
|
|
985
|
+
});
|
|
681
986
|
}
|
|
682
987
|
applySecurityGuards(userQuery) {
|
|
683
988
|
const guard = validateUserInput(userQuery, {
|
|
@@ -692,6 +997,46 @@ var AvantGateControlLayer = class {
|
|
|
692
997
|
}
|
|
693
998
|
return userQuery;
|
|
694
999
|
}
|
|
1000
|
+
checkPreflightBudget(estimatedPromptTokens, targetModel, provider) {
|
|
1001
|
+
if (this.config.maxTokenBudget !== void 0 && estimatedPromptTokens > this.config.maxTokenBudget) {
|
|
1002
|
+
throw new BudgetExceededError(
|
|
1003
|
+
`[AvantGate Budget Guard] Pre-flight token budget exceeded: estimated prompt (${estimatedPromptTokens} tokens) exceeds maxTokenBudget (${this.config.maxTokenBudget}).`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
if (this.config.maxCostUSD !== void 0) {
|
|
1007
|
+
const isLocalFree = provider === "ollama" || targetModel.toLowerCase().includes("ollama");
|
|
1008
|
+
const providerCfg = this.findProviderConfig(provider, targetModel);
|
|
1009
|
+
const price = resolveModelPrice(targetModel, {
|
|
1010
|
+
provider: provider ?? providerCfg?.provider,
|
|
1011
|
+
providerPricing: providerCfg?.pricing,
|
|
1012
|
+
customPricing: this.config.customPricing,
|
|
1013
|
+
adapter: this.cachedPricingAdapter
|
|
1014
|
+
});
|
|
1015
|
+
if (!isLocalFree && !price) {
|
|
1016
|
+
throw new ConfigurationError(
|
|
1017
|
+
`[AvantGate Configuration Error] 'maxCostUSD' was set to $${this.config.maxCostUSD}, but no pricing was configured for model '${targetModel}'. Please define pricing in ProviderConfig, customPricing, or via PricingAdapter.`
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
const estimatedPromptCost = this.calculateCost(targetModel, estimatedPromptTokens, 0, 0, provider);
|
|
1021
|
+
if (estimatedPromptCost > this.config.maxCostUSD) {
|
|
1022
|
+
throw new BudgetExceededError(
|
|
1023
|
+
`[AvantGate Budget Guard] Pre-flight cost budget exceeded: estimated prompt cost ($${estimatedPromptCost.toFixed(6)}) exceeds maxCostUSD ($${this.config.maxCostUSD}).`
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
checkPostExecutionBudget(tokensTotal, costUSD) {
|
|
1029
|
+
if (this.config.maxTokenBudget !== void 0 && tokensTotal > this.config.maxTokenBudget) {
|
|
1030
|
+
throw new BudgetExceededError(
|
|
1031
|
+
`[AvantGate Budget Guard] Execution total tokens (${tokensTotal}) exceeded maxTokenBudget (${this.config.maxTokenBudget}).`
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
if (this.config.maxCostUSD !== void 0 && costUSD > this.config.maxCostUSD) {
|
|
1035
|
+
throw new BudgetExceededError(
|
|
1036
|
+
`[AvantGate Budget Guard] Execution cost ($${costUSD.toFixed(6)}) exceeded maxCostUSD ($${this.config.maxCostUSD}).`
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
695
1040
|
buildMessages(systemPrompt, query) {
|
|
696
1041
|
const messages = [];
|
|
697
1042
|
if (systemPrompt) {
|
|
@@ -704,7 +1049,12 @@ var AvantGateControlLayer = class {
|
|
|
704
1049
|
const promptTokens = rawUsage?.promptTokens ?? Math.ceil(query.length / 4);
|
|
705
1050
|
const completionTokens = rawUsage?.completionTokens ?? Math.ceil(text.length / 4);
|
|
706
1051
|
const totalTokens = rawUsage?.totalTokens ?? promptTokens + completionTokens;
|
|
707
|
-
return {
|
|
1052
|
+
return {
|
|
1053
|
+
promptTokens,
|
|
1054
|
+
completionTokens,
|
|
1055
|
+
totalTokens,
|
|
1056
|
+
promptCacheHitTokens: rawUsage?.promptCacheHitTokens
|
|
1057
|
+
};
|
|
708
1058
|
}
|
|
709
1059
|
getProviderChain() {
|
|
710
1060
|
return [
|
|
@@ -716,7 +1066,7 @@ var AvantGateControlLayer = class {
|
|
|
716
1066
|
executeSimulation(query, systemPrompt) {
|
|
717
1067
|
const promptTokens = Math.ceil(((systemPrompt?.length ?? 0) + query.length) / 4);
|
|
718
1068
|
const completionTokens = 50;
|
|
719
|
-
const cost =
|
|
1069
|
+
const cost = this.calculateCost(this.config.primary.model, promptTokens, completionTokens);
|
|
720
1070
|
return {
|
|
721
1071
|
text: `[AvantGate In-Process Engine] Response simulation for model: ${this.config.primary.model}`,
|
|
722
1072
|
tokens: {
|
|
@@ -772,10 +1122,11 @@ var AvantGateControlLayer = class {
|
|
|
772
1122
|
throw lastError;
|
|
773
1123
|
}
|
|
774
1124
|
assembleResult(output) {
|
|
775
|
-
const costUSD =
|
|
1125
|
+
const costUSD = this.calculateCost(
|
|
776
1126
|
output.modelUsed,
|
|
777
1127
|
output.usage.promptTokens,
|
|
778
|
-
output.usage.completionTokens
|
|
1128
|
+
output.usage.completionTokens,
|
|
1129
|
+
output.usage.promptCacheHitTokens ?? 0
|
|
779
1130
|
);
|
|
780
1131
|
return {
|
|
781
1132
|
text: output.responseText,
|
|
@@ -804,18 +1155,27 @@ var AvantGateControlLayer = class {
|
|
|
804
1155
|
});
|
|
805
1156
|
}
|
|
806
1157
|
/**
|
|
807
|
-
* Exécute une requête avec garde d'entrée, masquage PII, et calcul des coûts.
|
|
1158
|
+
* Exécute une requête avec garde d'entrée, masquage PII, garde pré-vol et calcul des coûts.
|
|
808
1159
|
*/
|
|
809
1160
|
async execute(options) {
|
|
810
1161
|
const sanitizedQuery = this.applySecurityGuards(options.userQuery);
|
|
811
1162
|
const messages = this.buildMessages(options.systemPrompt, sanitizedQuery);
|
|
1163
|
+
const promptLength = (options.systemPrompt?.length ?? 0) + sanitizedQuery.length;
|
|
1164
|
+
const estimatedPromptTokens = Math.ceil(promptLength / 4);
|
|
1165
|
+
this.checkPreflightBudget(estimatedPromptTokens, this.config.primary.model, this.config.primary.provider);
|
|
812
1166
|
if (!options.providerOverride && this.getProviderChain().length === 0) {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1167
|
+
if (this.config.mockSimulation) {
|
|
1168
|
+
const simResult = this.executeSimulation(sanitizedQuery, options.systemPrompt);
|
|
1169
|
+
await this.notifyAuditSink(simResult);
|
|
1170
|
+
return simResult;
|
|
1171
|
+
}
|
|
1172
|
+
throw new ConfigurationError(
|
|
1173
|
+
"[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
|
|
1174
|
+
);
|
|
816
1175
|
}
|
|
817
1176
|
const output = options.providerOverride ? await this.executeOverrideProvider(options.providerOverride, messages, sanitizedQuery, options.temperature) : await this.executeProviderPipeline(messages, sanitizedQuery, options.temperature);
|
|
818
1177
|
const result = this.assembleResult(output);
|
|
1178
|
+
this.checkPostExecutionBudget(result.tokens.total, result.costUSD);
|
|
819
1179
|
await this.notifyAuditSink(result);
|
|
820
1180
|
return result;
|
|
821
1181
|
}
|
|
@@ -858,6 +1218,9 @@ var AvantGateControlLayer = class {
|
|
|
858
1218
|
}
|
|
859
1219
|
return msg;
|
|
860
1220
|
});
|
|
1221
|
+
const promptLength = processedMessages.reduce((sum, msg) => sum + msg.content.length, 0);
|
|
1222
|
+
const estimatedPromptTokens = Math.ceil(promptLength / 4);
|
|
1223
|
+
this.checkPreflightBudget(estimatedPromptTokens, modelToUse);
|
|
861
1224
|
let lastError;
|
|
862
1225
|
let accumulatedPromptTokens = 0;
|
|
863
1226
|
let accumulatedCompletionTokens = 0;
|
|
@@ -880,10 +1243,16 @@ var AvantGateControlLayer = class {
|
|
|
880
1243
|
attemptCompletionTokens = usage.completionTokens;
|
|
881
1244
|
modelUsed = modelToUse;
|
|
882
1245
|
} else if (this.getProviderChain().length === 0) {
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1246
|
+
if (this.config.mockSimulation) {
|
|
1247
|
+
const sim = this.executeSimulation(JSON.stringify(processedMessages));
|
|
1248
|
+
responseText = sim.text;
|
|
1249
|
+
attemptPromptTokens = sim.tokens.prompt;
|
|
1250
|
+
attemptCompletionTokens = sim.tokens.completion;
|
|
1251
|
+
} else {
|
|
1252
|
+
throw new ConfigurationError(
|
|
1253
|
+
"[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
887
1256
|
} else {
|
|
888
1257
|
const output = await this.executeProviderPipeline(
|
|
889
1258
|
processedMessages,
|
|
@@ -907,7 +1276,8 @@ var AvantGateControlLayer = class {
|
|
|
907
1276
|
jurisdiction: this.config.features?.finance?.jurisdiction
|
|
908
1277
|
});
|
|
909
1278
|
const totalTokens = accumulatedPromptTokens + accumulatedCompletionTokens;
|
|
910
|
-
const costUSD =
|
|
1279
|
+
const costUSD = this.calculateCost(modelUsed, accumulatedPromptTokens, accumulatedCompletionTokens);
|
|
1280
|
+
this.checkPostExecutionBudget(totalTokens, costUSD);
|
|
911
1281
|
const result = {
|
|
912
1282
|
data: parsedData,
|
|
913
1283
|
rawText: responseText,
|
|
@@ -1261,16 +1631,27 @@ var PromptRegistry = class {
|
|
|
1261
1631
|
};
|
|
1262
1632
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1263
1633
|
0 && (module.exports = {
|
|
1634
|
+
AvantGateBudgetExceededError,
|
|
1635
|
+
AvantGateConfigurationError,
|
|
1264
1636
|
AvantGateControlLayer,
|
|
1637
|
+
BudgetExceededError,
|
|
1638
|
+
CachedPricingAdapter,
|
|
1639
|
+
ConfigurationError,
|
|
1265
1640
|
DEFAULT_MODEL_PRICES,
|
|
1641
|
+
HttpProviderClient,
|
|
1642
|
+
PricingRegistry,
|
|
1266
1643
|
PromptBuilder,
|
|
1267
1644
|
PromptRegistry,
|
|
1268
1645
|
PromptTemplate,
|
|
1646
|
+
SEED_MODEL_PRICES,
|
|
1269
1647
|
ZenLLMControlLayer,
|
|
1270
1648
|
calculateCostUSD,
|
|
1271
1649
|
createAvantGate,
|
|
1650
|
+
createHttpProviderClient,
|
|
1272
1651
|
createLLMControlLayer,
|
|
1273
1652
|
extractAndCleanJSON,
|
|
1653
|
+
resolveModelPrice,
|
|
1654
|
+
resolveModelPriceAsync,
|
|
1274
1655
|
sanitizePII,
|
|
1275
1656
|
validateUserInput,
|
|
1276
1657
|
validateWithZod
|