@absolutejs/ai 0.0.56 → 0.0.57

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.
@@ -1,6 +1,286 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
+ // src/ai/inputCapacity.ts
5
+ class AIInputError extends Error {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.code = code;
10
+ this.name = "AIInputError";
11
+ }
12
+ }
13
+ var positiveTokenLimit = (value) => {
14
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)
15
+ throw new AIInputError("capacity_unavailable", "The provider did not supply a valid model limit.");
16
+ return value;
17
+ };
18
+ var inputTokenCount = (value) => {
19
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
20
+ throw new AIInputError("capacity_unavailable", "The provider did not supply a valid token count.");
21
+ return value;
22
+ };
23
+ var inspectAIInput = async (provider, params) => {
24
+ params.signal?.throwIfAborted();
25
+ if (!provider.inputCapacity)
26
+ throw new AIInputError("capacity_unavailable", "This provider does not expose model capacity and token counting.");
27
+ const [limits, tokens] = await Promise.all([
28
+ provider.inputCapacity.getLimits(params),
29
+ provider.inputCapacity.countTokens(params)
30
+ ]);
31
+ const inputTokens = inputTokenCount(tokens);
32
+ const outputTokens = positiveTokenLimit(provider.inputCapacity.outputTokens?.(params) ?? params.maxTokens ?? limits.maxOutputTokens);
33
+ const maxInputTokens = positiveTokenLimit(limits.maxInputTokens);
34
+ const maxOutputTokens = positiveTokenLimit(limits.maxOutputTokens);
35
+ const availableInputTokens = Math.max(0, Math.min(maxInputTokens, limits.contextWindowTokens === undefined ? maxInputTokens : positiveTokenLimit(limits.contextWindowTokens) - outputTokens));
36
+ return {
37
+ limits,
38
+ inputTokens,
39
+ outputTokens,
40
+ availableInputTokens,
41
+ fits: outputTokens <= maxOutputTokens && inputTokens <= availableInputTokens
42
+ };
43
+ };
44
+ var cacheModelLimits = (load, ttlMs = 300000) => {
45
+ const cache = new Map;
46
+ return async (params) => {
47
+ const entry = cache.get(params.model);
48
+ if (entry && Date.now() - entry.at < ttlMs)
49
+ return entry.limits;
50
+ const limits = await load(params);
51
+ positiveTokenLimit(limits.maxInputTokens);
52
+ positiveTokenLimit(limits.maxOutputTokens);
53
+ if (cache.size >= 100)
54
+ cache.clear();
55
+ cache.set(params.model, { at: Date.now(), limits });
56
+ return limits;
57
+ };
58
+ };
59
+ var capacityJson = async (response) => {
60
+ if (!response.ok)
61
+ throw new AIInputError("capacity_unavailable", `Model capacity request failed (${response.status}).`);
62
+ const value = await response.json();
63
+ if (!value || typeof value !== "object" || Array.isArray(value))
64
+ throw new AIInputError("capacity_unavailable", "Model capacity response was invalid.");
65
+ return value;
66
+ };
67
+
68
+ // src/ai/providers/openaiCapacity.ts
69
+ var LIMITS = {
70
+ "gpt-4.1": {
71
+ maxInputTokens: 1047576,
72
+ contextWindowTokens: 1047576,
73
+ maxOutputTokens: 32768
74
+ },
75
+ "gpt-4.1-2025-04-14": {
76
+ maxInputTokens: 1047576,
77
+ contextWindowTokens: 1047576,
78
+ maxOutputTokens: 32768
79
+ },
80
+ "gpt-4.1-mini": {
81
+ maxInputTokens: 1047576,
82
+ contextWindowTokens: 1047576,
83
+ maxOutputTokens: 32768
84
+ },
85
+ "gpt-4.1-mini-2025-04-14": {
86
+ maxInputTokens: 1047576,
87
+ contextWindowTokens: 1047576,
88
+ maxOutputTokens: 32768
89
+ },
90
+ "gpt-4.1-nano": {
91
+ maxInputTokens: 1047576,
92
+ contextWindowTokens: 1047576,
93
+ maxOutputTokens: 32768
94
+ },
95
+ "gpt-4.1-nano-2025-04-14": {
96
+ maxInputTokens: 1047576,
97
+ contextWindowTokens: 1047576,
98
+ maxOutputTokens: 32768
99
+ },
100
+ "gpt-4o": {
101
+ maxInputTokens: 128000,
102
+ contextWindowTokens: 128000,
103
+ maxOutputTokens: 16384
104
+ },
105
+ "gpt-4o-mini": {
106
+ maxInputTokens: 128000,
107
+ contextWindowTokens: 128000,
108
+ maxOutputTokens: 16384
109
+ },
110
+ "gpt-4o-mini-2024-07-18": {
111
+ maxInputTokens: 128000,
112
+ contextWindowTokens: 128000,
113
+ maxOutputTokens: 16384
114
+ },
115
+ "gpt-5": {
116
+ maxInputTokens: 272000,
117
+ contextWindowTokens: 400000,
118
+ maxOutputTokens: 128000
119
+ },
120
+ "gpt-5-mini": {
121
+ maxInputTokens: 272000,
122
+ contextWindowTokens: 400000,
123
+ maxOutputTokens: 128000
124
+ },
125
+ "gpt-5-mini-2025-08-07": {
126
+ maxInputTokens: 272000,
127
+ contextWindowTokens: 400000,
128
+ maxOutputTokens: 128000
129
+ },
130
+ "gpt-5-nano": {
131
+ maxInputTokens: 272000,
132
+ contextWindowTokens: 400000,
133
+ maxOutputTokens: 128000
134
+ },
135
+ "gpt-5-nano-2025-08-07": {
136
+ maxInputTokens: 272000,
137
+ contextWindowTokens: 400000,
138
+ maxOutputTokens: 128000
139
+ },
140
+ "gpt-5.4-mini": {
141
+ maxInputTokens: 272000,
142
+ contextWindowTokens: 400000,
143
+ maxOutputTokens: 128000
144
+ },
145
+ "gpt-5.4-nano": {
146
+ maxInputTokens: 272000,
147
+ contextWindowTokens: 400000,
148
+ maxOutputTokens: 128000
149
+ },
150
+ "gpt-5.1": {
151
+ maxInputTokens: 400000,
152
+ contextWindowTokens: 400000,
153
+ maxOutputTokens: 128000
154
+ },
155
+ "gpt-5.1-2025-11-13": {
156
+ maxInputTokens: 400000,
157
+ contextWindowTokens: 400000,
158
+ maxOutputTokens: 128000
159
+ },
160
+ "gpt-5.2": {
161
+ maxInputTokens: 400000,
162
+ contextWindowTokens: 400000,
163
+ maxOutputTokens: 128000
164
+ },
165
+ "gpt-5.2-2025-12-11": {
166
+ maxInputTokens: 400000,
167
+ contextWindowTokens: 400000,
168
+ maxOutputTokens: 128000
169
+ },
170
+ "gpt-5.4": {
171
+ maxInputTokens: 1050000,
172
+ contextWindowTokens: 1050000,
173
+ maxOutputTokens: 128000
174
+ },
175
+ "gpt-5.4-2026-03-05": {
176
+ maxInputTokens: 1050000,
177
+ contextWindowTokens: 1050000,
178
+ maxOutputTokens: 128000
179
+ },
180
+ "gpt-5.5": {
181
+ maxInputTokens: 1050000,
182
+ contextWindowTokens: 1050000,
183
+ maxOutputTokens: 128000
184
+ },
185
+ "gpt-6-astra": {
186
+ maxInputTokens: 922000,
187
+ contextWindowTokens: 1050000,
188
+ maxOutputTokens: 128000
189
+ },
190
+ "gpt-5.6-sol": {
191
+ maxInputTokens: 922000,
192
+ contextWindowTokens: 1050000,
193
+ maxOutputTokens: 128000
194
+ },
195
+ "gpt-5.6-terra": {
196
+ maxInputTokens: 922000,
197
+ contextWindowTokens: 1050000,
198
+ maxOutputTokens: 128000
199
+ },
200
+ "gpt-5.6-luna": {
201
+ maxInputTokens: 922000,
202
+ contextWindowTokens: 1050000,
203
+ maxOutputTokens: 128000
204
+ },
205
+ o3: {
206
+ maxInputTokens: 200000,
207
+ contextWindowTokens: 200000,
208
+ maxOutputTokens: 1e5
209
+ },
210
+ "o3-2025-04-16": {
211
+ maxInputTokens: 200000,
212
+ contextWindowTokens: 200000,
213
+ maxOutputTokens: 1e5
214
+ },
215
+ "o4-mini": {
216
+ maxInputTokens: 200000,
217
+ contextWindowTokens: 200000,
218
+ maxOutputTokens: 1e5
219
+ },
220
+ "o4-mini-2025-04-16": {
221
+ maxInputTokens: 200000,
222
+ contextWindowTokens: 200000,
223
+ maxOutputTokens: 1e5
224
+ },
225
+ "gpt-5-chat-latest": {
226
+ maxInputTokens: 128000,
227
+ contextWindowTokens: 128000,
228
+ maxOutputTokens: 16384
229
+ },
230
+ "gpt-5.1-chat-latest": {
231
+ maxInputTokens: 128000,
232
+ contextWindowTokens: 128000,
233
+ maxOutputTokens: 16384
234
+ },
235
+ "gpt-5.2-chat-latest": {
236
+ maxInputTokens: 128000,
237
+ contextWindowTokens: 128000,
238
+ maxOutputTokens: 16384
239
+ }
240
+ };
241
+ var openaiInputCapacity = (config) => ({
242
+ outputTokens: (params) => {
243
+ const value = config.body(params).max_output_tokens;
244
+ return value === undefined ? undefined : positiveTokenLimit(value);
245
+ },
246
+ getLimits: async (params) => {
247
+ if (config.modelLimits)
248
+ return config.modelLimits(params);
249
+ if (new URL(config.baseUrl).origin !== "https://api.openai.com")
250
+ throw new AIInputError("capacity_unavailable", "This compatible endpoint must expose its own model capacity.");
251
+ const limits = LIMITS[params.model];
252
+ if (!limits)
253
+ throw new AIInputError("capacity_unavailable", `Model limits are unavailable for ${params.model}; no character limit has been substituted.`);
254
+ return { ...limits };
255
+ },
256
+ countTokens: async (params) => {
257
+ const headers = new Headers(await config.headers(params));
258
+ headers.set("Authorization", `Bearer ${await config.key()}`);
259
+ headers.set("Content-Type", "application/json");
260
+ const body = config.body(params);
261
+ const counted = {};
262
+ for (const key of [
263
+ "model",
264
+ "input",
265
+ "instructions",
266
+ "tools",
267
+ "tool_choice",
268
+ "reasoning",
269
+ "text",
270
+ "parallel_tool_calls"
271
+ ])
272
+ if (body[key] !== undefined)
273
+ counted[key] = body[key];
274
+ const response = await config.fetch(`${config.baseUrl}/v1/responses/input_tokens`, {
275
+ method: "POST",
276
+ headers,
277
+ body: JSON.stringify(counted),
278
+ signal: params.signal ? AbortSignal.any([params.signal, AbortSignal.timeout(15000)]) : AbortSignal.timeout(15000)
279
+ });
280
+ return inputTokenCount((await capacityJson(response)).input_tokens);
281
+ }
282
+ });
283
+
4
284
  // src/ai/errors/providerError.ts
5
285
  var PROVIDER_STATUS_PAGES = {
6
286
  anthropic: "https://status.claude.com",
@@ -231,6 +511,7 @@ var withResilience = (provider, providerName = "unknown") => {
231
511
  }
232
512
  };
233
513
  return {
514
+ ...provider,
234
515
  stream: (params) => {
235
516
  const tripped = circuitOpen(providerName);
236
517
  if (tripped) {
@@ -247,6 +528,7 @@ var withResilience = (provider, providerName = "unknown") => {
247
528
  var instrumentAIProvider = (provider, providerName) => {
248
529
  const resilient = withResilience(provider, providerName);
249
530
  return {
531
+ ...provider,
250
532
  stream: (params) => {
251
533
  if (!params.onUsage && !params.onSpan) {
252
534
  return resilient.stream(params);
@@ -496,7 +778,7 @@ var buildTools = (tools, isImageModel) => {
496
778
  }
497
779
  return result.length > 0 ? result : undefined;
498
780
  };
499
- var buildRequestBody = (params, isImageModel, capabilityModel = params.model) => {
781
+ var buildResponsesRequestBody = (params, isImageModel, capabilityModel = params.model) => {
500
782
  const body = {
501
783
  input: buildInput(params.messages),
502
784
  model: params.model,
@@ -906,9 +1188,20 @@ var openaiResponses = (config2) => {
906
1188
  const resolveKey = async () => config2.tokenSource ? await Promise.resolve(config2.tokenSource()) : config2.apiKey;
907
1189
  const resolveHeaders = async (params) => typeof config2.headers === "function" ? await config2.headers(params) : config2.headers ?? {};
908
1190
  return instrumentAIProvider({
1191
+ inputCapacity: openaiInputCapacity({
1192
+ baseUrl,
1193
+ fetch: fetchImpl,
1194
+ key: resolveKey,
1195
+ headers: resolveHeaders,
1196
+ modelLimits: config2.modelLimits,
1197
+ body: (params) => {
1198
+ const built = buildResponsesRequestBody(params, imageModels.has(params.model), config2.modelForCapabilities?.(params.model) ?? params.model);
1199
+ return config2.transformRequestBody ? config2.transformRequestBody(built, params) : built;
1200
+ }
1201
+ }),
909
1202
  stream: (params) => {
910
1203
  const isImageModel = imageModels.has(params.model);
911
- const builtBody = buildRequestBody(params, isImageModel, config2.modelForCapabilities?.(params.model) ?? params.model);
1204
+ const builtBody = buildResponsesRequestBody(params, isImageModel, config2.modelForCapabilities?.(params.model) ?? params.model);
912
1205
  const body = config2.transformRequestBody ? config2.transformRequestBody(builtBody, params) : builtBody;
913
1206
  return async function* () {
914
1207
  const [apiKey, headers] = await Promise.all([
@@ -921,8 +1214,9 @@ var openaiResponses = (config2) => {
921
1214
  }, providerName);
922
1215
  };
923
1216
  export {
1217
+ buildResponsesRequestBody,
924
1218
  openaiResponses
925
1219
  };
926
1220
 
927
- //# debugId=6C012FE2A677780E64756E2164756E21
1221
+ //# debugId=CDF72AC7A40CBC7664756E2164756E21
928
1222
  //# sourceMappingURL=openaiResponses.js.map