@chainfuse/ai-tools 1.0.14 → 1.0.16
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/base.d.mts +1 -1
- package/dist/base.mjs +4 -1
- package/dist/providers/rawProviders.mjs +80 -27
- package/package.json +10 -10
package/dist/base.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ export declare class AiBase {
|
|
|
3
3
|
protected readonly chalk: import("chalk").ChalkInstance;
|
|
4
4
|
protected _config: AiConfig;
|
|
5
5
|
constructor(config: AiConfig);
|
|
6
|
-
get config(): Readonly<AiConfig>;
|
|
6
|
+
get config(): Readonly<Omit<AiConfig, 'backgroundContext'>> & Pick<AiConfig, 'backgroundContext'>;
|
|
7
7
|
protected get gatewayName(): "nocost" | "production-passive-bot" | "production-passive-human" | "production-active-bot" | "production-active-human" | "preview-passive-bot" | "preview-passive-human" | "preview-active-bot" | "preview-active-human";
|
|
8
8
|
protected get gatewayLog(): boolean;
|
|
9
9
|
}
|
package/dist/base.mjs
CHANGED
|
@@ -6,7 +6,10 @@ export class AiBase {
|
|
|
6
6
|
this._config = config;
|
|
7
7
|
}
|
|
8
8
|
get config() {
|
|
9
|
-
return
|
|
9
|
+
return {
|
|
10
|
+
...Object.freeze(this._config),
|
|
11
|
+
backgroundContext: this._config.backgroundContext,
|
|
12
|
+
};
|
|
10
13
|
}
|
|
11
14
|
get gatewayName() {
|
|
12
15
|
if (this.config.billing.noCost) {
|
|
@@ -23,22 +23,39 @@ export class AiRawProviders extends AiBase {
|
|
|
23
23
|
},
|
|
24
24
|
};
|
|
25
25
|
if (logId) {
|
|
26
|
-
const updateMetadata =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
const updateMetadata = (() => {
|
|
27
|
+
if ('gateway' in this.config.providers.workersAi && typeof this.config.providers.workersAi.gateway === 'function') {
|
|
28
|
+
return this.config.providers.workersAi
|
|
29
|
+
.gateway(this.gatewayName)
|
|
30
|
+
.patchLog(logId, {
|
|
31
|
+
metadata: {
|
|
32
|
+
...Object.entries(rawMetadata).reduce((acc, [key, value]) => {
|
|
33
|
+
acc[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
34
|
+
return acc;
|
|
35
|
+
}, {}),
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
.catch((error) => console.warn('Not updating gateway log', error));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return import('@chainfuse/helpers')
|
|
42
|
+
.then(({ NetHelpers }) => NetHelpers.cfApi(this.config.gateway.apiToken, { logging: { level: Number(logging) } }))
|
|
43
|
+
.then((cf) => cf.aiGateway.logs.edit(this.gatewayName, logId, {
|
|
44
|
+
account_id: this.config.gateway.accountId,
|
|
45
|
+
metadata: {
|
|
46
|
+
...Object.entries(rawMetadata).reduce((acc, [key, value]) => {
|
|
47
|
+
acc[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
48
|
+
return acc;
|
|
49
|
+
}, {}),
|
|
50
|
+
},
|
|
51
|
+
}).catch((error) => console.warn('Not updating gateway log', error)));
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
37
54
|
if (this.config.backgroundContext) {
|
|
38
55
|
this.config.backgroundContext.waitUntil(updateMetadata);
|
|
39
56
|
}
|
|
40
57
|
else {
|
|
41
|
-
await updateMetadata
|
|
58
|
+
await updateMetadata;
|
|
42
59
|
}
|
|
43
60
|
}
|
|
44
61
|
else {
|
|
@@ -99,31 +116,36 @@ export class AiRawProviders extends AiBase {
|
|
|
99
116
|
},
|
|
100
117
|
}));
|
|
101
118
|
}
|
|
102
|
-
azOpenai(args) {
|
|
103
|
-
|
|
119
|
+
async azOpenai(args) {
|
|
120
|
+
const metadataHeader = {
|
|
121
|
+
dataspaceId: (await BufferHelpers.uuidConvert(args.dataspaceId)).utf8,
|
|
122
|
+
...(args.groupBillingId && { groupBillingId: (await BufferHelpers.uuidConvert(args.groupBillingId)).utf8 }),
|
|
123
|
+
// Generate incomplete id because we don't have the body to hash yet. Fill it in in the `fetch()`
|
|
124
|
+
idempotencyId: args.idempotencyId ?? (await BufferHelpers.generateUuid7()).utf8.slice(0, 23),
|
|
125
|
+
executor: JSON.stringify(args.executor),
|
|
126
|
+
// @ts-expect-error server info gets added in afterwards
|
|
127
|
+
};
|
|
128
|
+
return import('@ai-sdk/azure').then(({ createAzure }) => createAzure({
|
|
104
129
|
apiKey: 'apikey-placeholder',
|
|
130
|
+
/**
|
|
131
|
+
* @link https://learn.microsoft.com/en-us/azure/ai-foundry/openai/api-version-lifecycle?view=foundry-classic
|
|
132
|
+
* @link https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#api-specs
|
|
133
|
+
* From the table, pick the `Latest GA release` for `Data plane - inference`
|
|
134
|
+
*/
|
|
135
|
+
apiVersion: '2025-04-01-preview',
|
|
105
136
|
useDeploymentBasedUrls: true,
|
|
106
137
|
baseURL: new URL(['v1', this.config.gateway.accountId, this.gatewayName, 'azure-openai', 'server-placeholder'].join('/'), 'https://gateway.ai.cloudflare.com').toString(),
|
|
107
138
|
headers: {
|
|
108
139
|
'cf-aig-authorization': `Bearer ${this.config.gateway.apiToken}`,
|
|
109
|
-
|
|
110
|
-
'cf-aig-metadata': JSON.stringify({
|
|
111
|
-
dataspaceId: (await BufferHelpers.uuidConvert(args.dataspaceId)).utf8,
|
|
112
|
-
...(args.groupBillingId && { groupBillingId: (await BufferHelpers.uuidConvert(args.groupBillingId)).utf8 }),
|
|
113
|
-
// Generate incomplete id because we don't have the body to hash yet. Fill it in in the `fetch()`
|
|
114
|
-
idempotencyId: args.idempotencyId ?? (await BufferHelpers.generateUuid7()).utf8.slice(0, 23),
|
|
115
|
-
executor: JSON.stringify(args.executor),
|
|
116
|
-
// @ts-expect-error server info gets added in afterwards
|
|
117
|
-
}),
|
|
140
|
+
'cf-aig-metadata': JSON.stringify(metadataHeader),
|
|
118
141
|
...(args.cache && { 'cf-aig-cache-ttl': (typeof args.cache === 'boolean' ? (args.cache ? this.cacheTtl : 0) : args.cache).toString() }),
|
|
119
142
|
...(args.skipCache && { 'cf-aig-skip-cache': 'true' }),
|
|
120
143
|
},
|
|
121
144
|
fetch: (input, rawInit) => Promise.all([import('../serverSelector.mjs'), import('@chainfuse/types/ai-tools/azure/catalog')])
|
|
122
145
|
.then(([{ ServerSelector }, { azureCatalog }]) => new ServerSelector(this.config).closestServers(azureCatalog))
|
|
123
|
-
.then(async (
|
|
146
|
+
.then(async (closestServers) => {
|
|
124
147
|
const startRoundTrip = performance.now();
|
|
125
148
|
const headers = new Headers(rawInit?.headers);
|
|
126
|
-
const metadataHeader = JSON.parse(headers.get('cf-aig-metadata'));
|
|
127
149
|
// Calculate the idempotencyId if it doesn't exist yet
|
|
128
150
|
if (metadataHeader.idempotencyId.split('-').length === 4) {
|
|
129
151
|
metadataHeader.idempotencyId = `${metadataHeader.idempotencyId}-${(await CryptoHelpers.getHash('SHA-256', await new Request(input, rawInit).arrayBuffer())).slice(0, 12)}`;
|
|
@@ -148,6 +170,14 @@ export class AiRawProviders extends AiBase {
|
|
|
148
170
|
catch (error) {
|
|
149
171
|
fallbackedQuery = rawInit?.body;
|
|
150
172
|
}
|
|
173
|
+
const modelName = fallbackedEndpointParts[1];
|
|
174
|
+
const filteredServers =
|
|
175
|
+
// Check language models
|
|
176
|
+
closestServers.filter((server) => server.languageModelAvailability.some((model) => model.name === modelName) ??
|
|
177
|
+
// Check image models
|
|
178
|
+
server.imageModelAvailability.some((model) => model.name === modelName) ??
|
|
179
|
+
// Check embedding models
|
|
180
|
+
server.textEmbeddingModelAvailability.some((model) => model.name === modelName));
|
|
151
181
|
// Build universal gateway request
|
|
152
182
|
const fallbackedBody = await Promise.all([import('haversine-distance'), import("../serverSelector.mjs")]).then(([{ default: haversine }, { ServerSelector }]) => Promise.all(filteredServers.map(async (server) => {
|
|
153
183
|
const fallbackedHeaders = {
|
|
@@ -167,7 +197,6 @@ export class AiRawProviders extends AiBase {
|
|
|
167
197
|
}),
|
|
168
198
|
}),
|
|
169
199
|
};
|
|
170
|
-
const modelName = fallbackedEndpointParts[0];
|
|
171
200
|
const languageModel = server.languageModelAvailability.find((model) => model.name === modelName);
|
|
172
201
|
if (languageModel && ('inputTokenCost' in languageModel || 'outputTokenCost' in languageModel)) {
|
|
173
202
|
fallbackedHeaders['cf-aig-custom-cost'] = {
|
|
@@ -190,7 +219,31 @@ export class AiRawProviders extends AiBase {
|
|
|
190
219
|
})));
|
|
191
220
|
if (args.logging ?? this.gatewayLog)
|
|
192
221
|
console.info(new Date().toISOString(), this.chalk.rgb(...Helpers.uniqueIdColor(metadataHeader.idempotencyId))(`[${metadataHeader.idempotencyId}]`), this.chalk.magenta(rawInit?.method), this.chalk.magenta(new URL(new Request(input).url).pathname));
|
|
193
|
-
return
|
|
222
|
+
return (() => {
|
|
223
|
+
if ('gateway' in this.config.providers.workersAi && typeof this.config.providers.workersAi.gateway === 'function') {
|
|
224
|
+
return this.config.providers.workersAi.gateway(this.gatewayName).run(fallbackedBody, {
|
|
225
|
+
extraHeaders: (() => {
|
|
226
|
+
// Prevent duplicates
|
|
227
|
+
headers.delete('cf-aig-authorization');
|
|
228
|
+
headers.delete('cf-aig-metadata');
|
|
229
|
+
headers.delete('cf-aig-cache-ttl');
|
|
230
|
+
headers.delete('cf-aig-skip-cache');
|
|
231
|
+
return headers;
|
|
232
|
+
})(),
|
|
233
|
+
gateway: {
|
|
234
|
+
id: this.gatewayName,
|
|
235
|
+
eventId: metadataHeader.idempotencyId,
|
|
236
|
+
metadata: metadataHeader,
|
|
237
|
+
...(args.cache && { cacheTtl: typeof args.cache === 'boolean' ? (args.cache ? this.cacheTtl : 0) : args.cache }),
|
|
238
|
+
...(args.skipCache && { skipCache: true }),
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
return fetch(new URL(['v1', this.config.gateway.accountId, this.gatewayName].join('/'), 'https://gateway.ai.cloudflare.com'), { ...rawInit, headers, body: JSON.stringify(fallbackedBody) });
|
|
244
|
+
}
|
|
245
|
+
})().then(async (_response) => {
|
|
246
|
+
const response = _response;
|
|
194
247
|
// Inject it to have it available for retries
|
|
195
248
|
const mutableHeaders = new Headers(response.headers);
|
|
196
249
|
// Carry down
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainfuse/ai-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "ChainFuse",
|
|
6
6
|
"homepage": "https://github.com/ChainFuse/packages/tree/main/packages/ai-tools#readme",
|
|
@@ -48,23 +48,23 @@
|
|
|
48
48
|
},
|
|
49
49
|
"prettier": "@demosjarco/prettier-config",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@ai-sdk/anthropic": "^2.0.
|
|
52
|
-
"@ai-sdk/azure": "^2.0.
|
|
53
|
-
"@ai-sdk/google": "^2.0.
|
|
51
|
+
"@ai-sdk/anthropic": "^2.0.49",
|
|
52
|
+
"@ai-sdk/azure": "^2.0.75",
|
|
53
|
+
"@ai-sdk/google": "^2.0.43",
|
|
54
54
|
"@ai-sdk/openai": "^2.0.71",
|
|
55
55
|
"@ai-sdk/openai-compatible": "^1.0.27",
|
|
56
56
|
"@ai-sdk/provider": "^2.0.0",
|
|
57
|
-
"@chainfuse/helpers": "^4.2.
|
|
58
|
-
"@chainfuse/types": "^4.1.
|
|
59
|
-
"ai": "^5.0.
|
|
57
|
+
"@chainfuse/helpers": "^4.2.6",
|
|
58
|
+
"@chainfuse/types": "^4.1.6",
|
|
59
|
+
"ai": "^5.0.102",
|
|
60
60
|
"chalk": "^5.6.2",
|
|
61
61
|
"haversine-distance": "^1.2.4",
|
|
62
62
|
"workers-ai-provider": "^2.0.0",
|
|
63
|
-
"zod": "^4.1.
|
|
63
|
+
"zod": "^4.1.13"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@cloudflare/workers-types": "^4.
|
|
66
|
+
"@cloudflare/workers-types": "^4.20251127.0",
|
|
67
67
|
"openai": "^6.9.1"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "a7ba85aa01dd1c54356ef54b1af743cd9f6a767e"
|
|
70
70
|
}
|