@jiayunxie/aerial 0.1.7 → 0.1.8
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/package.json +1 -1
- package/src/copilot.js +56 -12
package/package.json
CHANGED
package/src/copilot.js
CHANGED
|
@@ -174,18 +174,52 @@ function withDefaultAnthropicCache(payload) {
|
|
|
174
174
|
return next;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
function
|
|
177
|
+
function canonicalClaudeOpus47Family(model) {
|
|
178
|
+
return /^claude-opus-4[.-]7(?:-|$)/.test(model) ? "claude-opus-4.7" : undefined;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function modelHasMessagesRoute(model) {
|
|
182
|
+
const endpoints = Array.isArray(model?.supported_endpoints) ? model.supported_endpoints : [];
|
|
183
|
+
const routes = Array.isArray(model?.aerial?.routes) ? model.aerial.routes : [];
|
|
184
|
+
return endpoints.includes("/v1/messages") || routes.includes("messages");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function supportedReasoningEfforts(model) {
|
|
188
|
+
const supports = model?.capabilities?.supports;
|
|
189
|
+
const values = supports?.reasoning_effort ?? supports?.reasoning_efforts;
|
|
190
|
+
if (Array.isArray(values)) return values.map(String);
|
|
191
|
+
if (typeof values === "string") return [values];
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function modelSupportsAdaptiveThinking(model) {
|
|
196
|
+
const supports = model?.capabilities?.supports;
|
|
197
|
+
return supports?.adaptive_thinking === true || supports?.thinking?.adaptive === true;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function findAnthropicEffortModel(modelId, effort, models) {
|
|
201
|
+
if (!Array.isArray(models)) return undefined;
|
|
202
|
+
const family = canonicalClaudeOpus47Family(modelId);
|
|
203
|
+
if (!family) return undefined;
|
|
204
|
+
const candidates = models.filter((model) => {
|
|
205
|
+
const id = typeof model?.id === "string" ? model.id : "";
|
|
206
|
+
return canonicalClaudeOpus47Family(id) === family &&
|
|
207
|
+
modelHasMessagesRoute(model) &&
|
|
208
|
+
modelSupportsAdaptiveThinking(model) &&
|
|
209
|
+
supportedReasoningEfforts(model).includes(effort);
|
|
210
|
+
});
|
|
211
|
+
return candidates.find((model) => model.id === modelId) || candidates[0];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function withSupportedAnthropicEffort(payload, models) {
|
|
178
215
|
const effort = payload?.output_config?.effort;
|
|
179
216
|
if (effort === undefined) return payload;
|
|
180
217
|
const model = typeof payload?.model === "string" ? payload.model : "";
|
|
181
|
-
if (
|
|
218
|
+
if (!canonicalClaudeOpus47Family(model)) return payload;
|
|
182
219
|
const nextEffort = effort === "max" ? "xhigh" : effort;
|
|
183
220
|
if (!["low", "medium", "high", "xhigh"].includes(nextEffort)) return payload;
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const nextModel = legacyEffortModel || (baseModel && nextEffort !== "medium")
|
|
187
|
-
? "claude-opus-4.7-1m-internal"
|
|
188
|
-
: model;
|
|
221
|
+
const routed = findAnthropicEffortModel(model, nextEffort, models);
|
|
222
|
+
const nextModel = routed?.id || model;
|
|
189
223
|
if (model === nextModel && effort === nextEffort) return payload;
|
|
190
224
|
logEvent("anthropic_effort_route", { model, effort, routedModel: nextModel, routedEffort: nextEffort });
|
|
191
225
|
return { ...payload, model: nextModel, output_config: { ...payload.output_config, effort: nextEffort } };
|
|
@@ -221,8 +255,18 @@ function withSupportedAnthropicThinking(payload) {
|
|
|
221
255
|
};
|
|
222
256
|
}
|
|
223
257
|
|
|
224
|
-
function
|
|
225
|
-
|
|
258
|
+
function shouldLoadAnthropicCatalog(payload) {
|
|
259
|
+
const effort = payload?.output_config?.effort;
|
|
260
|
+
const model = typeof payload?.model === "string" ? payload.model : "";
|
|
261
|
+
return effort !== undefined && Boolean(canonicalClaudeOpus47Family(model));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function withAnthropicDefaults(payload) {
|
|
265
|
+
const next = withSupportedAnthropicThinking(withDefaultAnthropicCache(payload));
|
|
266
|
+
const models = shouldLoadAnthropicCatalog(next)
|
|
267
|
+
? await fetchModelsCatalog().catch(() => undefined)
|
|
268
|
+
: undefined;
|
|
269
|
+
return withSupportedAnthropicEffort(next, models);
|
|
226
270
|
}
|
|
227
271
|
|
|
228
272
|
function parseJsonBody(body, contentType) {
|
|
@@ -407,7 +451,7 @@ function wrapResponseWithCacheObserver(upstream, route, requestCache) {
|
|
|
407
451
|
|
|
408
452
|
async function requestWithJsonBody(request, transform) {
|
|
409
453
|
const payload = await request.json();
|
|
410
|
-
const nextPayload = transform(payload);
|
|
454
|
+
const nextPayload = await transform(payload);
|
|
411
455
|
return new Request(request.url, {
|
|
412
456
|
method: request.method,
|
|
413
457
|
headers: request.headers,
|
|
@@ -435,7 +479,7 @@ async function proxyFetch(path, request, { extraHeaders = {}, bodyOverride } = {
|
|
|
435
479
|
return wrapResponseWithCacheObserver(upstream, path, requestCache);
|
|
436
480
|
}
|
|
437
481
|
|
|
438
|
-
async function
|
|
482
|
+
async function fetchModelsCatalog() {
|
|
439
483
|
const token = await getCopilotToken();
|
|
440
484
|
const response = await fetch(`${COPILOT_API_ORIGIN}/models`, { method: "GET", headers: upstreamHeaders(token) });
|
|
441
485
|
if (!response.ok) return undefined;
|
|
@@ -461,7 +505,7 @@ export async function proxyResponses(request) {
|
|
|
461
505
|
// per-request /models lookup to avoid an extra upstream call and let the
|
|
462
506
|
// shared HTTP path handle cache_request logging via proxyFetch.
|
|
463
507
|
if (payload?.stream && isResponsesWebSocketOptIn()) {
|
|
464
|
-
const models = await
|
|
508
|
+
const models = await fetchModelsCatalog().catch(() => undefined);
|
|
465
509
|
const model = models ? responseModelFromCatalog(payload.model, models) : undefined;
|
|
466
510
|
if (shouldUseResponsesWebSocket(payload, model)) {
|
|
467
511
|
const requestCache = cacheRequestFields(payload);
|