@antseed/provider-core 0.1.0 → 0.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/LICENSE +674 -0
- package/dist/base-provider.d.ts +4 -1
- package/dist/base-provider.d.ts.map +1 -1
- package/dist/base-provider.js +97 -8
- package/dist/base-provider.js.map +1 -1
- package/dist/http-relay.d.ts +4 -0
- package/dist/http-relay.d.ts.map +1 -1
- package/dist/http-relay.js +53 -21
- package/dist/http-relay.js.map +1 -1
- package/package.json +12 -9
- package/src/auth-swap.ts +0 -89
- package/src/base-provider.ts +0 -84
- package/src/http-relay.test.ts +0 -269
- package/src/http-relay.ts +0 -187
- package/src/index.ts +0 -5
- package/src/token-providers.test.ts +0 -196
- package/src/token-providers.ts +0 -211
- package/tsconfig.json +0 -9
package/dist/base-provider.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Provider, SerializedHttpRequest, SerializedHttpResponse } from '@antseed/node';
|
|
1
|
+
import type { Provider, ProviderStreamCallbacks, SerializedHttpRequest, SerializedHttpResponse } from '@antseed/node';
|
|
2
2
|
import { type RelayConfig } from './http-relay.js';
|
|
3
3
|
export interface BaseProviderConfig {
|
|
4
4
|
name: string;
|
|
@@ -20,8 +20,11 @@ export declare class BaseProvider implements Provider {
|
|
|
20
20
|
private readonly _pending;
|
|
21
21
|
constructor(config: BaseProviderConfig);
|
|
22
22
|
private _resolvePending;
|
|
23
|
+
private _handlePendingChunk;
|
|
24
|
+
private _stripStreamingHeader;
|
|
23
25
|
init(): Promise<void>;
|
|
24
26
|
handleRequest(req: SerializedHttpRequest): Promise<SerializedHttpResponse>;
|
|
27
|
+
handleRequestStream(req: SerializedHttpRequest, callbacks: ProviderStreamCallbacks): Promise<SerializedHttpResponse>;
|
|
25
28
|
getCapacity(): {
|
|
26
29
|
current: number;
|
|
27
30
|
max: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC7B,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;gBAEvD,MAAM,EAAE,kBAAkB;IAgBtC,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,qBAAqB;IAavB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,aAAa,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA2B1E,mBAAmB,CACvB,GAAG,EAAE,qBAAqB,EAC1B,SAAS,EAAE,uBAAuB,GACjC,OAAO,CAAC,sBAAsB,CAAC;IA4BlC,WAAW,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;CAMhD"}
|
package/dist/base-provider.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ANTSEED_STREAMING_RESPONSE_HEADER } from '@antseed/node';
|
|
1
2
|
import { HttpRelay } from './http-relay.js';
|
|
2
3
|
/**
|
|
3
4
|
* Convenience base class that wires HttpRelay to the Provider interface.
|
|
@@ -20,17 +21,56 @@ export class BaseProvider {
|
|
|
20
21
|
onResponse: (response) => {
|
|
21
22
|
this._resolvePending(response.requestId, response);
|
|
22
23
|
},
|
|
23
|
-
onResponseChunk: (
|
|
24
|
-
|
|
24
|
+
onResponseChunk: (chunk) => {
|
|
25
|
+
this._handlePendingChunk(chunk);
|
|
25
26
|
},
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
29
|
_resolvePending(requestId, response) {
|
|
29
30
|
const entry = this._pending.get(requestId);
|
|
30
|
-
if (entry)
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (!entry)
|
|
32
|
+
return;
|
|
33
|
+
const isStreamingStart = response.headers[ANTSEED_STREAMING_RESPONSE_HEADER] === '1';
|
|
34
|
+
if (isStreamingStart) {
|
|
35
|
+
entry.responseStart = response;
|
|
36
|
+
entry.streamCallbacks?.onResponseStart(response);
|
|
37
|
+
return;
|
|
33
38
|
}
|
|
39
|
+
this._pending.delete(requestId);
|
|
40
|
+
entry.resolve(this._stripStreamingHeader(response));
|
|
41
|
+
}
|
|
42
|
+
_handlePendingChunk(chunk) {
|
|
43
|
+
const entry = this._pending.get(chunk.requestId);
|
|
44
|
+
if (!entry)
|
|
45
|
+
return;
|
|
46
|
+
entry.streamCallbacks?.onResponseChunk(chunk);
|
|
47
|
+
if (chunk.data.length > 0) {
|
|
48
|
+
entry.streamChunks.push(chunk.data);
|
|
49
|
+
}
|
|
50
|
+
if (!chunk.done) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!entry.responseStart) {
|
|
54
|
+
this._pending.delete(chunk.requestId);
|
|
55
|
+
entry.reject(new Error(`Stream ${chunk.requestId} ended before response start`));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this._pending.delete(chunk.requestId);
|
|
59
|
+
entry.resolve(this._stripStreamingHeader({
|
|
60
|
+
...entry.responseStart,
|
|
61
|
+
body: concatChunks(entry.streamChunks),
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
_stripStreamingHeader(response) {
|
|
65
|
+
if (response.headers[ANTSEED_STREAMING_RESPONSE_HEADER] !== '1') {
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
const headers = { ...response.headers };
|
|
69
|
+
delete headers[ANTSEED_STREAMING_RESPONSE_HEADER];
|
|
70
|
+
return {
|
|
71
|
+
...response,
|
|
72
|
+
headers,
|
|
73
|
+
};
|
|
34
74
|
}
|
|
35
75
|
async init() {
|
|
36
76
|
if (this._relay['_config'].tokenProvider) {
|
|
@@ -41,14 +81,49 @@ export class BaseProvider {
|
|
|
41
81
|
this._activeCount++;
|
|
42
82
|
try {
|
|
43
83
|
const responsePromise = new Promise((resolve, reject) => {
|
|
44
|
-
this._pending.set(req.requestId, {
|
|
84
|
+
this._pending.set(req.requestId, {
|
|
85
|
+
resolve,
|
|
86
|
+
reject,
|
|
87
|
+
responseStart: null,
|
|
88
|
+
streamChunks: [],
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
await this._relay.handleRequest(req);
|
|
92
|
+
return await responsePromise;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const entry = this._pending.get(req.requestId);
|
|
96
|
+
if (entry) {
|
|
97
|
+
this._pending.delete(req.requestId);
|
|
98
|
+
entry.reject(err instanceof Error ? err : new Error(String(err)));
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
this._activeCount--;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async handleRequestStream(req, callbacks) {
|
|
107
|
+
this._activeCount++;
|
|
108
|
+
try {
|
|
109
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
110
|
+
this._pending.set(req.requestId, {
|
|
111
|
+
resolve,
|
|
112
|
+
reject,
|
|
113
|
+
responseStart: null,
|
|
114
|
+
streamChunks: [],
|
|
115
|
+
streamCallbacks: callbacks,
|
|
116
|
+
});
|
|
45
117
|
});
|
|
46
|
-
// Fire the relay (it calls onResponse when done)
|
|
47
118
|
await this._relay.handleRequest(req);
|
|
48
119
|
return await responsePromise;
|
|
49
120
|
}
|
|
50
121
|
catch (err) {
|
|
51
|
-
this._pending.
|
|
122
|
+
const entry = this._pending.get(req.requestId);
|
|
123
|
+
if (entry) {
|
|
124
|
+
this._pending.delete(req.requestId);
|
|
125
|
+
entry.reject(err instanceof Error ? err : new Error(String(err)));
|
|
126
|
+
}
|
|
52
127
|
throw err;
|
|
53
128
|
}
|
|
54
129
|
finally {
|
|
@@ -62,4 +137,18 @@ export class BaseProvider {
|
|
|
62
137
|
};
|
|
63
138
|
}
|
|
64
139
|
}
|
|
140
|
+
function concatChunks(chunks) {
|
|
141
|
+
if (chunks.length === 0)
|
|
142
|
+
return new Uint8Array(0);
|
|
143
|
+
if (chunks.length === 1)
|
|
144
|
+
return chunks[0];
|
|
145
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
146
|
+
const output = new Uint8Array(totalLength);
|
|
147
|
+
let offset = 0;
|
|
148
|
+
for (const chunk of chunks) {
|
|
149
|
+
output.set(chunk, offset);
|
|
150
|
+
offset += chunk.length;
|
|
151
|
+
}
|
|
152
|
+
return output;
|
|
153
|
+
}
|
|
65
154
|
//# sourceMappingURL=base-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-provider.js","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base-provider.js","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/http-relay.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface RelayConfig {
|
|
|
9
9
|
maxConcurrency: number;
|
|
10
10
|
allowedModels: string[];
|
|
11
11
|
timeoutMs?: number;
|
|
12
|
+
/** Lowercase header-name prefixes to strip before forwarding upstream. */
|
|
13
|
+
stripHeaderPrefixes?: string[];
|
|
14
|
+
/** Fields to deep-merge into the JSON request body before forwarding upstream. */
|
|
15
|
+
injectJsonFields?: Record<string, unknown>;
|
|
12
16
|
}
|
|
13
17
|
export interface RelayCallbacks {
|
|
14
18
|
onResponse: (response: SerializedHttpResponse) => void;
|
package/dist/http-relay.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-relay.d.ts","sourceRoot":"","sources":["../src/http-relay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"http-relay.d.ts","sourceRoot":"","sources":["../src/http-relay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAehH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACvD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAChE;AAcD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;IAC5C,OAAO,CAAC,YAAY,CAAK;gBAEb,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc;IAK1D,cAAc,IAAI,MAAM;IAIxB,OAAO,CAAC,UAAU;IASZ,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAqJnE"}
|
package/dist/http-relay.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ANTSEED_STREAMING_RESPONSE_HEADER } from '@antseed/node';
|
|
1
2
|
import { swapAuthHeader, validateRequestModel } from './auth-swap.js';
|
|
2
3
|
/** Hop-by-hop headers that must not be forwarded. */
|
|
3
4
|
const HOP_BY_HOP_HEADERS = new Set([
|
|
@@ -8,6 +9,18 @@ const HOP_BY_HOP_HEADERS = new Set([
|
|
|
8
9
|
const INTERNAL_HEADERS = new Set([
|
|
9
10
|
'x-antseed-provider',
|
|
10
11
|
]);
|
|
12
|
+
function deepMerge(target, source) {
|
|
13
|
+
const out = { ...target };
|
|
14
|
+
for (const [key, val] of Object.entries(source)) {
|
|
15
|
+
if (val && typeof val === 'object' && !Array.isArray(val) && typeof out[key] === 'object' && out[key] !== null && !Array.isArray(out[key])) {
|
|
16
|
+
out[key] = deepMerge(out[key], val);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
out[key] = val;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
11
24
|
export class HttpRelay {
|
|
12
25
|
_config;
|
|
13
26
|
_callbacks;
|
|
@@ -56,18 +69,34 @@ export class HttpRelay {
|
|
|
56
69
|
effectiveConfig = { ...effectiveConfig, authHeaderValue: headerValue };
|
|
57
70
|
}
|
|
58
71
|
// Swap auth headers
|
|
59
|
-
|
|
72
|
+
let swappedRequest = swapAuthHeader(request, effectiveConfig);
|
|
73
|
+
// Inject extra JSON fields into the request body if configured
|
|
74
|
+
if (this._config.injectJsonFields && swappedRequest.method !== 'GET' && swappedRequest.method !== 'HEAD') {
|
|
75
|
+
try {
|
|
76
|
+
const decoded = JSON.parse(new TextDecoder().decode(swappedRequest.body));
|
|
77
|
+
const merged = deepMerge(decoded, this._config.injectJsonFields);
|
|
78
|
+
swappedRequest = { ...swappedRequest, body: new TextEncoder().encode(JSON.stringify(merged)) };
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Not JSON — leave body unchanged
|
|
82
|
+
}
|
|
83
|
+
}
|
|
60
84
|
// Build upstream URL
|
|
61
85
|
const base = this._config.baseUrl.replace(/\/+$/, '');
|
|
62
86
|
const path = request.path.startsWith('/') ? request.path : `/${request.path}`;
|
|
63
87
|
const url = `${base}${path}`;
|
|
64
|
-
// Build fetch headers, stripping hop-by-hop
|
|
88
|
+
// Build fetch headers, stripping hop-by-hop and provider-specific prefixes
|
|
89
|
+
const stripPrefixes = this._config.stripHeaderPrefixes ?? [];
|
|
65
90
|
const fetchHeaders = {};
|
|
66
91
|
for (const [key, value] of Object.entries(swappedRequest.headers)) {
|
|
67
92
|
const lower = key.toLowerCase();
|
|
68
|
-
if (
|
|
69
|
-
|
|
93
|
+
if (HOP_BY_HOP_HEADERS.has(lower) || INTERNAL_HEADERS.has(lower) || lower === 'host' || lower === 'content-length' || lower === 'accept-encoding') {
|
|
94
|
+
continue;
|
|
70
95
|
}
|
|
96
|
+
if (stripPrefixes.length > 0 && stripPrefixes.some((p) => lower.startsWith(p))) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
fetchHeaders[key] = value;
|
|
71
100
|
}
|
|
72
101
|
const timeoutMs = this._config.timeoutMs ?? 120_000;
|
|
73
102
|
const controller = new AbortController();
|
|
@@ -99,34 +128,37 @@ export class HttpRelay {
|
|
|
99
128
|
}
|
|
100
129
|
});
|
|
101
130
|
if (isSSE && fetchResponse.body) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
131
|
+
responseHeaders[ANTSEED_STREAMING_RESPONSE_HEADER] = '1';
|
|
132
|
+
this._callbacks.onResponse({
|
|
133
|
+
requestId: request.requestId,
|
|
134
|
+
statusCode: fetchResponse.status,
|
|
135
|
+
headers: responseHeaders,
|
|
136
|
+
body: new Uint8Array(0),
|
|
137
|
+
});
|
|
105
138
|
const reader = fetchResponse.body.getReader();
|
|
106
|
-
const chunks = [];
|
|
107
139
|
try {
|
|
108
140
|
while (true) {
|
|
109
141
|
const { done, value } = await reader.read();
|
|
110
142
|
if (done)
|
|
111
143
|
break;
|
|
112
|
-
|
|
144
|
+
this._callbacks.onResponseChunk?.({
|
|
145
|
+
requestId: request.requestId,
|
|
146
|
+
data: value,
|
|
147
|
+
done: false,
|
|
148
|
+
});
|
|
113
149
|
}
|
|
114
150
|
}
|
|
115
151
|
catch (err) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
for (const c of chunks) {
|
|
122
|
-
body.set(c, offset);
|
|
123
|
-
offset += c.length;
|
|
152
|
+
this._callbacks.onResponseChunk?.({
|
|
153
|
+
requestId: request.requestId,
|
|
154
|
+
data: new TextEncoder().encode(`event: error\ndata: ${err instanceof Error ? err.message : 'stream error'}\n\n`),
|
|
155
|
+
done: false,
|
|
156
|
+
});
|
|
124
157
|
}
|
|
125
|
-
this._callbacks.
|
|
158
|
+
this._callbacks.onResponseChunk?.({
|
|
126
159
|
requestId: request.requestId,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
body,
|
|
160
|
+
data: new Uint8Array(0),
|
|
161
|
+
done: true,
|
|
130
162
|
});
|
|
131
163
|
}
|
|
132
164
|
else {
|
package/dist/http-relay.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-relay.js","sourceRoot":"","sources":["../src/http-relay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,qDAAqD;AACrD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,qBAAqB;IACvE,IAAI,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS;CACjD,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,oBAAoB;CACrB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"http-relay.js","sourceRoot":"","sources":["../src/http-relay.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antseed/provider-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Shared provider infrastructure for Antseed plugins",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
6
9
|
"main": "dist/index.js",
|
|
7
10
|
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"prebuild": "rm -rf dist",
|
|
10
|
-
"build": "tsc",
|
|
11
|
-
"test": "vitest run",
|
|
12
|
-
"typecheck": "tsc --noEmit"
|
|
13
|
-
},
|
|
14
11
|
"peerDependencies": {
|
|
15
12
|
"@antseed/node": ">=0.1.0"
|
|
16
13
|
},
|
|
17
14
|
"devDependencies": {
|
|
18
15
|
"typescript": "^5.5.0",
|
|
19
16
|
"vitest": "^2.0.0",
|
|
20
|
-
"@antseed/node": "
|
|
17
|
+
"@antseed/node": "0.1.2"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"prebuild": "rm -rf dist",
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"typecheck": "tsc --noEmit"
|
|
21
24
|
}
|
|
22
|
-
}
|
|
25
|
+
}
|
package/src/auth-swap.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { SerializedHttpRequest } from '@antseed/node';
|
|
2
|
-
|
|
3
|
-
/** Set of all known auth header names (lowercase). */
|
|
4
|
-
export const KNOWN_AUTH_HEADERS: Set<string> = new Set([
|
|
5
|
-
'authorization', 'x-api-key', 'x-goog-api-key',
|
|
6
|
-
]);
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Strips all known auth headers and injects the seller's auth.
|
|
10
|
-
* Returns a NEW object (no mutation of the original).
|
|
11
|
-
*/
|
|
12
|
-
export function swapAuthHeader(
|
|
13
|
-
request: SerializedHttpRequest,
|
|
14
|
-
config: { authHeaderName: string; authHeaderValue: string; extraHeaders?: Record<string, string> }
|
|
15
|
-
): SerializedHttpRequest {
|
|
16
|
-
const newHeaders: Record<string, string> = {};
|
|
17
|
-
|
|
18
|
-
for (const [key, value] of Object.entries(request.headers)) {
|
|
19
|
-
if (!KNOWN_AUTH_HEADERS.has(key.toLowerCase())) {
|
|
20
|
-
newHeaders[key] = value;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
newHeaders[config.authHeaderName] = config.authHeaderValue;
|
|
25
|
-
|
|
26
|
-
// Inject any extra headers (e.g. anthropic-beta for OAuth).
|
|
27
|
-
// For anthropic-beta, merge with existing values (comma-separated)
|
|
28
|
-
// so the buyer's beta flags (e.g. context-management) are preserved.
|
|
29
|
-
if (config.extraHeaders) {
|
|
30
|
-
for (const [key, value] of Object.entries(config.extraHeaders)) {
|
|
31
|
-
const lower = key.toLowerCase();
|
|
32
|
-
if (lower === 'anthropic-beta' && newHeaders[key]) {
|
|
33
|
-
// Merge: deduplicate comma-separated beta flags
|
|
34
|
-
const existing = new Set(newHeaders[key]!.split(',').map((s) => s.trim()));
|
|
35
|
-
for (const flag of value.split(',').map((s) => s.trim())) {
|
|
36
|
-
existing.add(flag);
|
|
37
|
-
}
|
|
38
|
-
newHeaders[key] = [...existing].join(',');
|
|
39
|
-
} else {
|
|
40
|
-
newHeaders[key] = value;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
requestId: request.requestId,
|
|
47
|
-
method: request.method,
|
|
48
|
-
path: request.path,
|
|
49
|
-
headers: newHeaders,
|
|
50
|
-
body: request.body,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Validate request against allowed models.
|
|
56
|
-
* Parses JSON body and enforces strict top-level `"model"` allow-list.
|
|
57
|
-
* Returns null if ok, error string if rejected.
|
|
58
|
-
*/
|
|
59
|
-
export function validateRequestModel(
|
|
60
|
-
request: SerializedHttpRequest,
|
|
61
|
-
allowedModels: string[]
|
|
62
|
-
): string | null {
|
|
63
|
-
// If allowedModels is empty, allow everything
|
|
64
|
-
if (allowedModels.length === 0) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let payload: unknown;
|
|
69
|
-
try {
|
|
70
|
-
payload = JSON.parse(new TextDecoder().decode(request.body)) as unknown;
|
|
71
|
-
} catch {
|
|
72
|
-
return "Invalid JSON request body";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
76
|
-
return 'Request body must be a JSON object containing a "model" field';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const model = (payload as Record<string, unknown>)["model"];
|
|
80
|
-
if (typeof model !== "string" || model.trim() === "") {
|
|
81
|
-
return 'Request is missing a valid "model" field';
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!allowedModels.includes(model)) {
|
|
85
|
-
return `Model "${model}" is not in the allowed list`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return null;
|
|
89
|
-
}
|
package/src/base-provider.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import type { Provider, SerializedHttpRequest, SerializedHttpResponse, SerializedHttpResponseChunk } from '@antseed/node';
|
|
2
|
-
import { HttpRelay, type RelayConfig } from './http-relay.js';
|
|
3
|
-
|
|
4
|
-
export interface BaseProviderConfig {
|
|
5
|
-
name: string;
|
|
6
|
-
models: string[];
|
|
7
|
-
pricing: Provider['pricing'];
|
|
8
|
-
relay: RelayConfig;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Convenience base class that wires HttpRelay to the Provider interface.
|
|
13
|
-
* Pattern adapted from provider-anthropic's AnthropicProvider.
|
|
14
|
-
*/
|
|
15
|
-
export class BaseProvider implements Provider {
|
|
16
|
-
readonly name: string;
|
|
17
|
-
readonly models: string[];
|
|
18
|
-
readonly pricing: Provider['pricing'];
|
|
19
|
-
readonly maxConcurrency: number;
|
|
20
|
-
|
|
21
|
-
private readonly _relay: HttpRelay;
|
|
22
|
-
private _activeCount = 0;
|
|
23
|
-
|
|
24
|
-
private readonly _pending = new Map<
|
|
25
|
-
string,
|
|
26
|
-
{ resolve: (res: SerializedHttpResponse) => void; reject: (err: Error) => void }
|
|
27
|
-
>();
|
|
28
|
-
|
|
29
|
-
constructor(config: BaseProviderConfig) {
|
|
30
|
-
this.name = config.name;
|
|
31
|
-
this.models = config.models;
|
|
32
|
-
this.pricing = config.pricing;
|
|
33
|
-
this.maxConcurrency = config.relay.maxConcurrency;
|
|
34
|
-
|
|
35
|
-
this._relay = new HttpRelay(config.relay, {
|
|
36
|
-
onResponse: (response: SerializedHttpResponse) => {
|
|
37
|
-
this._resolvePending(response.requestId, response);
|
|
38
|
-
},
|
|
39
|
-
onResponseChunk: (_chunk: SerializedHttpResponseChunk) => {
|
|
40
|
-
// Chunks are accumulated by HttpRelay into a complete response
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private _resolvePending(requestId: string, response: SerializedHttpResponse): void {
|
|
46
|
-
const entry = this._pending.get(requestId);
|
|
47
|
-
if (entry) {
|
|
48
|
-
this._pending.delete(requestId);
|
|
49
|
-
entry.resolve(response);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async init(): Promise<void> {
|
|
54
|
-
if (this._relay['_config'].tokenProvider) {
|
|
55
|
-
await this._relay['_config'].tokenProvider.getToken();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async handleRequest(req: SerializedHttpRequest): Promise<SerializedHttpResponse> {
|
|
60
|
-
this._activeCount++;
|
|
61
|
-
try {
|
|
62
|
-
const responsePromise = new Promise<SerializedHttpResponse>((resolve, reject) => {
|
|
63
|
-
this._pending.set(req.requestId, { resolve, reject });
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Fire the relay (it calls onResponse when done)
|
|
67
|
-
await this._relay.handleRequest(req);
|
|
68
|
-
|
|
69
|
-
return await responsePromise;
|
|
70
|
-
} catch (err) {
|
|
71
|
-
this._pending.delete(req.requestId);
|
|
72
|
-
throw err;
|
|
73
|
-
} finally {
|
|
74
|
-
this._activeCount--;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
getCapacity(): { current: number; max: number } {
|
|
79
|
-
return {
|
|
80
|
-
current: this._activeCount,
|
|
81
|
-
max: this.maxConcurrency,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|