@antseed/cli 0.1.152 → 0.1.153
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/proxy/buyer-proxy.d.ts.map +1 -1
- package/dist/proxy/buyer-proxy.js +53 -9
- package/dist/proxy/buyer-proxy.js.map +1 -1
- package/dist/proxy/buyer-proxy.test.js +92 -0
- package/dist/proxy/buyer-proxy.test.js.map +1 -1
- package/dist/proxy/routing-parameters.test.js +12 -1
- package/dist/proxy/routing-parameters.test.js.map +1 -1
- package/dist/proxy/routing.d.ts +8 -0
- package/dist/proxy/routing.d.ts.map +1 -1
- package/dist/proxy/routing.js +42 -2
- package/dist/proxy/routing.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buyer-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/buyer-proxy.ts"],"names":[],"mappings":"AAKA,OAAO,EAYL,KAAK,WAAW,EAGhB,KAAK,QAAQ,EAEb,KAAK,uBAAuB,EAI5B,KAAK,sBAAsB,EAE3B,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"buyer-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/buyer-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { canonicalModelKey } from '@antseed/node/model-identity';
|
|
|
8
8
|
import { createStreamingAdapter, detectRequestServiceApiProtocol, transformRequest, transformResponse, } from './service-api-adapter.js';
|
|
9
9
|
import { DEBUG, log, extractRequestedService, summarizeRequestShape, summarizeErrorResponse, requestWantsStreaming, parsePeerPinnedService, rewritePeerPinnedServiceInBody, substituteRoutedModelAlias, overrideRoutedModelInBody, ROUTED_MODEL_ALIAS, SYSTEM_PROXY_SOURCE_HEADER, SYSTEM_ROUTED_MODEL_HEADER, normalizePeerId, } from './request-utils.js';
|
|
10
10
|
import { buildNetworkModels, effectiveModelReputationScore, normalizedModelReputationScore, parseModelTypeFilter, } from './network-models.js';
|
|
11
|
-
import { findUnannouncedRequestParameters, findAdvertisedServiceOffer, getExplicitProviderOverride, getExplicitPeerIdOverride, resolvePeerRoutePlan, selectCandidatePeersForRouting, } from './routing.js';
|
|
11
|
+
import { findMissingRequiredParameters, findUnannouncedRequestParameters, findAdvertisedServiceOffer, getExplicitProviderOverride, getExplicitPeerIdOverride, parseRequiredParametersHeader, REQUIRED_PARAMETERS_HEADER, resolvePeerRoutePlan, selectCandidatePeersForRouting, } from './routing.js';
|
|
12
12
|
import { computeResponseTelemetry, attachAntseedTelemetryHeaders, attachStreamingAntseedHeaders, } from './telemetry.js';
|
|
13
13
|
import { DEFAULT_BUYER_PEER_REFRESH_INTERVAL_MS } from '../config/defaults.js';
|
|
14
14
|
import { extractConversationIdentity, extractFirstUserSnippet, isCompletionRequestPath, isTitleGenerationRequest, parseRequestBodyObject, } from './conversation-identity.js';
|
|
@@ -1890,6 +1890,19 @@ export class BuyerProxy {
|
|
|
1890
1890
|
headers,
|
|
1891
1891
|
body: new Uint8Array(body),
|
|
1892
1892
|
};
|
|
1893
|
+
const requiredParameters = parseRequiredParametersHeader(serializedReq.headers[REQUIRED_PARAMETERS_HEADER]);
|
|
1894
|
+
if (requiredParameters === null) {
|
|
1895
|
+
res.writeHead(400, { 'content-type': 'application/json' });
|
|
1896
|
+
res.end(JSON.stringify({
|
|
1897
|
+
error: {
|
|
1898
|
+
type: 'invalid_request_error',
|
|
1899
|
+
code: 'invalid_required_parameters',
|
|
1900
|
+
message: `${REQUIRED_PARAMETERS_HEADER} must contain at most 16 comma-separated parameter names.`,
|
|
1901
|
+
param: REQUIRED_PARAMETERS_HEADER,
|
|
1902
|
+
},
|
|
1903
|
+
}));
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1893
1906
|
// Snapshot the session overrides before any await so a concurrent
|
|
1894
1907
|
// _reloadSessionOverrides() cannot change routing mid-request.
|
|
1895
1908
|
const effectivePinnedPeer = this._pinnedPeer;
|
|
@@ -2088,6 +2101,14 @@ export class BuyerProxy {
|
|
|
2088
2101
|
const offer = findAdvertisedServiceOffer(peer, plan.provider, plan.serviceId);
|
|
2089
2102
|
if (!offer)
|
|
2090
2103
|
return null;
|
|
2104
|
+
const missingRequired = plan.selection?.requiresTransform
|
|
2105
|
+
? requiredParameters
|
|
2106
|
+
: findMissingRequiredParameters(peer, plan.provider, plan.serviceId, requiredParameters);
|
|
2107
|
+
if (missingRequired.length > 0) {
|
|
2108
|
+
log(`Capability filter: peer ${peer.peerId.slice(0, 12)}... service="${plan.serviceId}" `
|
|
2109
|
+
+ `missing required parameter(s): ${missingRequired.join(', ')}`);
|
|
2110
|
+
return null;
|
|
2111
|
+
}
|
|
2091
2112
|
const requestForPolicy = withRoutedModel(serializedReq, plan.serviceId);
|
|
2092
2113
|
if (!peerAllowedByPolicy(policyRouter, requestForPolicy, peer))
|
|
2093
2114
|
return null;
|
|
@@ -2137,14 +2158,22 @@ export class BuyerProxy {
|
|
|
2137
2158
|
}
|
|
2138
2159
|
}
|
|
2139
2160
|
if (candidates.length === 0) {
|
|
2140
|
-
|
|
2161
|
+
const capabilityRequired = requiredParameters.length > 0;
|
|
2162
|
+
res.writeHead(capabilityRequired ? 422 : 502, { 'content-type': 'application/json' });
|
|
2141
2163
|
res.end(JSON.stringify({
|
|
2142
|
-
error:
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2164
|
+
error: capabilityRequired
|
|
2165
|
+
? {
|
|
2166
|
+
type: 'required_capability_unavailable',
|
|
2167
|
+
code: 'required_capability_unavailable',
|
|
2168
|
+
message: `No policy-allowed seller for model "${requestedService}" advertises required parameter(s): ${requiredParameters.join(', ')}.`,
|
|
2169
|
+
param: REQUIRED_PARAMETERS_HEADER,
|
|
2170
|
+
}
|
|
2171
|
+
: {
|
|
2172
|
+
type: 'model_not_found',
|
|
2173
|
+
code: 'model_not_found',
|
|
2174
|
+
message: `No policy-allowed peer currently serves model "${requestedService}".`,
|
|
2175
|
+
param: 'model',
|
|
2176
|
+
},
|
|
2148
2177
|
}));
|
|
2149
2178
|
return;
|
|
2150
2179
|
}
|
|
@@ -2304,6 +2333,21 @@ export class BuyerProxy {
|
|
|
2304
2333
|
const selectedPlan = routingPlans.get(selectedPeer.peerId)
|
|
2305
2334
|
?? resolvePeerRoutePlan(selectedPeer, requestProtocol, requestedService, explicitProvider, 'lenient');
|
|
2306
2335
|
const pinnedServiceId = selectedPlan?.serviceId ?? requestedService;
|
|
2336
|
+
const missingRequired = selectedPlan && !selectedPlan.selection?.requiresTransform
|
|
2337
|
+
? findMissingRequiredParameters(selectedPeer, selectedPlan.provider, pinnedServiceId, requiredParameters)
|
|
2338
|
+
: requiredParameters;
|
|
2339
|
+
if (missingRequired.length > 0) {
|
|
2340
|
+
res.writeHead(422, { 'content-type': 'application/json' });
|
|
2341
|
+
res.end(JSON.stringify({
|
|
2342
|
+
error: {
|
|
2343
|
+
type: 'required_capability_unavailable',
|
|
2344
|
+
code: 'required_capability_unavailable',
|
|
2345
|
+
message: `Pinned seller does not advertise required parameter(s) for model "${pinnedServiceId ?? requestedService ?? 'unknown'}": ${missingRequired.join(', ')}.`,
|
|
2346
|
+
param: REQUIRED_PARAMETERS_HEADER,
|
|
2347
|
+
},
|
|
2348
|
+
}));
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2307
2351
|
const pinnedRequest = pinnedServiceId ? withRoutedModel(serializedReq, pinnedServiceId) : serializedReq;
|
|
2308
2352
|
if (!peerAllowedByPolicy(policyRouter, pinnedRequest, selectedPeer)) {
|
|
2309
2353
|
log(`Pinned peer ${selectedPeer.peerId.slice(0, 12)}... filtered out by buyer routing policy`);
|
|
@@ -2418,7 +2462,7 @@ export class BuyerProxy {
|
|
|
2418
2462
|
+ `did not announce for this service: ${unannounced.join(', ')} — the upstream may ignore or reject them`);
|
|
2419
2463
|
}
|
|
2420
2464
|
}
|
|
2421
|
-
const { 'x-antseed-pin-peer': _pinPeer, 'x-antseed-prefer-peer': _preferPeer, 'x-vpr-session-id': _vprSession,
|
|
2465
|
+
const { 'x-antseed-pin-peer': _pinPeer, 'x-antseed-prefer-peer': _preferPeer, [REQUIRED_PARAMETERS_HEADER]: _requiredParameters, 'x-vpr-session-id': _vprSession,
|
|
2422
2466
|
// Legacy desktop builds (pre AntStation → VPR rename) still send this.
|
|
2423
2467
|
'x-antstation-session-id': _antstationSession, ...headersForPeer } = serializedReq.headers;
|
|
2424
2468
|
let requestForPeer = {
|