ghc-proxy 0.6.2 → 0.7.0
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/README.md +13 -61
- package/dist/main.mjs +1154 -1416
- package/dist/main.mjs.map +1 -1
- package/package.json +9 -4
package/dist/main.mjs
CHANGED
|
@@ -5761,12 +5761,6 @@ const configFileSchema = object({
|
|
|
5761
5761
|
from: string(),
|
|
5762
5762
|
to: string()
|
|
5763
5763
|
})).optional(),
|
|
5764
|
-
contextUpgradeRules: array(object({
|
|
5765
|
-
from: string(),
|
|
5766
|
-
to: string()
|
|
5767
|
-
})).optional(),
|
|
5768
|
-
contextUpgrade: boolean().optional(),
|
|
5769
|
-
contextUpgradeTokenThreshold: number().int().positive().optional(),
|
|
5770
5764
|
upstreamQueueConcurrency: number().int().positive().optional(),
|
|
5771
5765
|
upstreamQueueMaxRetries: number().int().nonnegative().optional(),
|
|
5772
5766
|
upstreamQueueBaseDelaySeconds: number().int().nonnegative().optional(),
|
|
@@ -5855,12 +5849,6 @@ var ConfigStore = class {
|
|
|
5855
5849
|
getEmulatorTtlSeconds() {
|
|
5856
5850
|
return getCachedConfig().responsesOfficialEmulatorTtlSeconds ?? 14400;
|
|
5857
5851
|
}
|
|
5858
|
-
isContextUpgradeEnabled() {
|
|
5859
|
-
return getCachedConfig().contextUpgrade !== false;
|
|
5860
|
-
}
|
|
5861
|
-
getContextUpgradeThreshold() {
|
|
5862
|
-
return getCachedConfig().contextUpgradeTokenThreshold ?? 16e4;
|
|
5863
|
-
}
|
|
5864
5852
|
isCompactSmallModelEnabled() {
|
|
5865
5853
|
return getCachedConfig().compactUseSmallModel ?? false;
|
|
5866
5854
|
}
|
|
@@ -5886,33 +5874,221 @@ var ConfigStore = class {
|
|
|
5886
5874
|
getModelRewrites() {
|
|
5887
5875
|
return getCachedConfig().modelRewrites ?? [];
|
|
5888
5876
|
}
|
|
5889
|
-
getContextUpgradeRules() {
|
|
5890
|
-
return getCachedConfig().contextUpgradeRules ?? [];
|
|
5891
|
-
}
|
|
5892
5877
|
getModelFallback() {
|
|
5893
5878
|
return getCachedConfig().modelFallback;
|
|
5894
5879
|
}
|
|
5895
|
-
|
|
5896
|
-
|
|
5880
|
+
};
|
|
5881
|
+
const configStore = new ConfigStore();
|
|
5882
|
+
//#endregion
|
|
5883
|
+
//#region src/state/model-cache.ts
|
|
5884
|
+
const RESPONSES_ENDPOINT = "/responses";
|
|
5885
|
+
/**
|
|
5886
|
+
* Models whose upstream `/v1/messages` endpoint rejects the `output_config`
|
|
5887
|
+
* field with "Extra inputs are not permitted".
|
|
5888
|
+
*
|
|
5889
|
+
* Verified via `scripts/probes/messages/output-config.ts` (2026-03-14).
|
|
5890
|
+
* When new models appear, re-run the probe and update this list.
|
|
5891
|
+
*/
|
|
5892
|
+
const MODELS_REJECTING_OUTPUT_CONFIG = new Set([
|
|
5893
|
+
"claude-sonnet-4",
|
|
5894
|
+
"claude-sonnet-4.5",
|
|
5895
|
+
"claude-haiku-4.5"
|
|
5896
|
+
]);
|
|
5897
|
+
var ModelCache = class {
|
|
5898
|
+
models;
|
|
5899
|
+
vsCodeVersion;
|
|
5900
|
+
cacheModels(models) {
|
|
5901
|
+
this.models = models;
|
|
5902
|
+
}
|
|
5903
|
+
clearModels() {
|
|
5904
|
+
this.models = void 0;
|
|
5905
|
+
}
|
|
5906
|
+
getModels() {
|
|
5907
|
+
return this.models;
|
|
5897
5908
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
5909
|
+
setVSCodeVersion(version) {
|
|
5910
|
+
this.vsCodeVersion = version;
|
|
5900
5911
|
}
|
|
5901
|
-
|
|
5902
|
-
|
|
5912
|
+
clearVSCodeVersion() {
|
|
5913
|
+
this.vsCodeVersion = void 0;
|
|
5903
5914
|
}
|
|
5904
|
-
|
|
5905
|
-
return
|
|
5915
|
+
getVSCodeVersion() {
|
|
5916
|
+
return this.vsCodeVersion;
|
|
5917
|
+
}
|
|
5918
|
+
findById(modelId) {
|
|
5919
|
+
return this.models?.data.find((model) => model.id === modelId);
|
|
5920
|
+
}
|
|
5921
|
+
getModelIds() {
|
|
5922
|
+
return this.models?.data.map((model) => model.id) ?? [];
|
|
5923
|
+
}
|
|
5924
|
+
supportsEndpoint(model, endpoint) {
|
|
5925
|
+
return model?.supported_endpoints?.includes(endpoint) ?? false;
|
|
5926
|
+
}
|
|
5927
|
+
supportsToolCalls(model) {
|
|
5928
|
+
return model?.capabilities.supports.tool_calls ?? false;
|
|
5929
|
+
}
|
|
5930
|
+
supportsAdaptiveThinking(model) {
|
|
5931
|
+
return model?.capabilities.supports.adaptive_thinking ?? false;
|
|
5932
|
+
}
|
|
5933
|
+
supportsVision(model) {
|
|
5934
|
+
return model?.capabilities.supports.vision ?? false;
|
|
5935
|
+
}
|
|
5936
|
+
supportsOutputConfig(model) {
|
|
5937
|
+
if (!model) return true;
|
|
5938
|
+
return !MODELS_REJECTING_OUTPUT_CONFIG.has(model.id);
|
|
5906
5939
|
}
|
|
5907
5940
|
};
|
|
5908
|
-
const
|
|
5941
|
+
const modelCache = new ModelCache();
|
|
5909
5942
|
//#endregion
|
|
5910
|
-
//#region src/
|
|
5943
|
+
//#region src/translator/anthropic/translation-issue.ts
|
|
5944
|
+
var TranslationFailure = class extends Error {
|
|
5945
|
+
status;
|
|
5946
|
+
kind;
|
|
5947
|
+
constructor(message, options) {
|
|
5948
|
+
super(message);
|
|
5949
|
+
this.name = "TranslationFailure";
|
|
5950
|
+
this.status = options.status;
|
|
5951
|
+
this.kind = options.kind;
|
|
5952
|
+
}
|
|
5953
|
+
};
|
|
5954
|
+
//#endregion
|
|
5955
|
+
//#region src/lib/error.ts
|
|
5956
|
+
var HTTPError = class extends Error {
|
|
5957
|
+
status;
|
|
5958
|
+
body;
|
|
5959
|
+
constructor(status, body) {
|
|
5960
|
+
super(body.error.message);
|
|
5961
|
+
this.name = "HTTPError";
|
|
5962
|
+
this.status = status;
|
|
5963
|
+
this.body = body;
|
|
5964
|
+
}
|
|
5965
|
+
toResponse() {
|
|
5966
|
+
return Response.json(this.body, { status: this.status });
|
|
5967
|
+
}
|
|
5968
|
+
};
|
|
5969
|
+
function throwInvalidRequestError(message, param, code) {
|
|
5970
|
+
throw new HTTPError(400, { error: {
|
|
5971
|
+
message,
|
|
5972
|
+
type: "invalid_request_error",
|
|
5973
|
+
param,
|
|
5974
|
+
...code ? { code } : {}
|
|
5975
|
+
} });
|
|
5976
|
+
}
|
|
5977
|
+
function fromTranslationFailure(failure) {
|
|
5978
|
+
return new HTTPError(failure.status, { error: {
|
|
5979
|
+
message: failure.message,
|
|
5980
|
+
type: "translation_error"
|
|
5981
|
+
} });
|
|
5982
|
+
}
|
|
5983
|
+
function resolveModelOrThrow(modelId) {
|
|
5984
|
+
const model = modelCache.findById(modelId);
|
|
5985
|
+
if (!model) throwInvalidRequestError("The selected model could not be resolved.", "model");
|
|
5986
|
+
return model;
|
|
5987
|
+
}
|
|
5988
|
+
function withTranslationErrors(fn) {
|
|
5989
|
+
try {
|
|
5990
|
+
return fn();
|
|
5991
|
+
} catch (error) {
|
|
5992
|
+
if (error instanceof TranslationFailure) throw fromTranslationFailure(error);
|
|
5993
|
+
throw error;
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
function previewBody(text, maxLength = 500) {
|
|
5997
|
+
return text.length > maxLength ? `${text.slice(0, maxLength)}…` : text;
|
|
5998
|
+
}
|
|
5999
|
+
function isStructuredErrorPayload(value) {
|
|
6000
|
+
return typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null;
|
|
6001
|
+
}
|
|
6002
|
+
function upstreamErrorType(status) {
|
|
6003
|
+
return status === 429 ? "rate_limit_error" : "upstream_error";
|
|
6004
|
+
}
|
|
6005
|
+
function createFallbackUpstreamError(message, response, rawText) {
|
|
6006
|
+
return { error: {
|
|
6007
|
+
message: rawText.trim() || message,
|
|
6008
|
+
type: upstreamErrorType(response.status)
|
|
6009
|
+
} };
|
|
6010
|
+
}
|
|
6011
|
+
function getDiagnosticHeaders(response) {
|
|
6012
|
+
const headerNames = [
|
|
6013
|
+
"retry-after",
|
|
6014
|
+
"x-ratelimit-limit",
|
|
6015
|
+
"x-ratelimit-remaining",
|
|
6016
|
+
"x-ratelimit-reset",
|
|
6017
|
+
"x-github-request-id",
|
|
6018
|
+
"x-request-id"
|
|
6019
|
+
];
|
|
6020
|
+
const headers = {};
|
|
6021
|
+
for (const name of headerNames) {
|
|
6022
|
+
const value = response.headers.get(name);
|
|
6023
|
+
if (value) headers[name] = value;
|
|
6024
|
+
}
|
|
6025
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
6026
|
+
}
|
|
6027
|
+
async function throwUpstreamError(message, response) {
|
|
6028
|
+
let rawText = "";
|
|
6029
|
+
let body;
|
|
6030
|
+
try {
|
|
6031
|
+
rawText = await response.text();
|
|
6032
|
+
const json = JSON.parse(rawText);
|
|
6033
|
+
body = isStructuredErrorPayload(json) ? json : createFallbackUpstreamError(message, response, rawText);
|
|
6034
|
+
} catch {
|
|
6035
|
+
body = createFallbackUpstreamError(message, response, rawText);
|
|
6036
|
+
}
|
|
6037
|
+
consola.error("Upstream error:", {
|
|
6038
|
+
status: response.status,
|
|
6039
|
+
statusText: response.statusText,
|
|
6040
|
+
url: response.url,
|
|
6041
|
+
body,
|
|
6042
|
+
rawBody: rawText ? previewBody(rawText) : "<empty>",
|
|
6043
|
+
headers: getDiagnosticHeaders(response)
|
|
6044
|
+
});
|
|
6045
|
+
throw new HTTPError(response.status, body);
|
|
6046
|
+
}
|
|
6047
|
+
//#endregion
|
|
6048
|
+
//#region src/util/sleep.ts
|
|
6049
|
+
function sleep(ms) {
|
|
6050
|
+
return new Promise((resolve) => {
|
|
6051
|
+
setTimeout(resolve, ms);
|
|
6052
|
+
});
|
|
6053
|
+
}
|
|
6054
|
+
//#endregion
|
|
6055
|
+
//#region src/state/rate-limiter.ts
|
|
6056
|
+
var RateLimiter = class {
|
|
6057
|
+
nextAvailableAt = 0;
|
|
6058
|
+
reset() {
|
|
6059
|
+
this.nextAvailableAt = 0;
|
|
6060
|
+
}
|
|
6061
|
+
async acquire(intervalSeconds, waitMode) {
|
|
6062
|
+
if (intervalSeconds === void 0) return;
|
|
6063
|
+
const now = Date.now();
|
|
6064
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
6065
|
+
if (!this.nextAvailableAt || now >= this.nextAvailableAt) {
|
|
6066
|
+
this.nextAvailableAt = now + intervalMs;
|
|
6067
|
+
return;
|
|
6068
|
+
}
|
|
6069
|
+
const waitMs = this.nextAvailableAt - now;
|
|
6070
|
+
const waitTimeSeconds = Math.ceil(waitMs / 1e3);
|
|
6071
|
+
if (!waitMode) {
|
|
6072
|
+
consola.warn(`Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`);
|
|
6073
|
+
throw new HTTPError(429, { error: {
|
|
6074
|
+
message: "Rate limit exceeded",
|
|
6075
|
+
type: "rate_limit_error"
|
|
6076
|
+
} });
|
|
6077
|
+
}
|
|
6078
|
+
const claimedSlot = this.nextAvailableAt;
|
|
6079
|
+
this.nextAvailableAt = claimedSlot + intervalMs;
|
|
6080
|
+
consola.warn(`Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`);
|
|
6081
|
+
await sleep(waitMs);
|
|
6082
|
+
consola.info("Rate limit wait completed, proceeding with request");
|
|
6083
|
+
}
|
|
6084
|
+
};
|
|
6085
|
+
const rateLimiter = new RateLimiter();
|
|
6086
|
+
//#endregion
|
|
6087
|
+
//#region src/state/responses-emulator-state.ts
|
|
5911
6088
|
const DEFAULT_MAX_TOTAL_ENTRIES = 1e4;
|
|
5912
6089
|
const BACKGROUND_PRUNE_INTERVAL_MS = 6e4;
|
|
5913
6090
|
function cloneValue$1(value) {
|
|
5914
|
-
|
|
5915
|
-
return JSON.parse(JSON.stringify(value));
|
|
6091
|
+
return structuredClone(value);
|
|
5916
6092
|
}
|
|
5917
6093
|
function currentTime() {
|
|
5918
6094
|
return Date.now();
|
|
@@ -5958,7 +6134,6 @@ function createResponsesEmulatorState(opts) {
|
|
|
5958
6134
|
pruneIntervalId = void 0;
|
|
5959
6135
|
}
|
|
5960
6136
|
}
|
|
5961
|
-
startBackgroundPrune();
|
|
5962
6137
|
function totalEntries() {
|
|
5963
6138
|
let sum = 0;
|
|
5964
6139
|
for (const map of allMaps) sum += map.size;
|
|
@@ -5977,6 +6152,7 @@ function createResponsesEmulatorState(opts) {
|
|
|
5977
6152
|
return cloneValue$1(entry.value);
|
|
5978
6153
|
}
|
|
5979
6154
|
function writeMap(map, key, value, ttlSeconds, at = currentTime()) {
|
|
6155
|
+
startBackgroundPrune();
|
|
5980
6156
|
if (!map.has(key)) enforceCapOnWrite();
|
|
5981
6157
|
const cloned = cloneValue$1(value);
|
|
5982
6158
|
map.set(key, {
|
|
@@ -5989,6 +6165,7 @@ function createResponsesEmulatorState(opts) {
|
|
|
5989
6165
|
return map.delete(key);
|
|
5990
6166
|
}
|
|
5991
6167
|
function putDeletionFlag(map, id, ttlSeconds, at = currentTime()) {
|
|
6168
|
+
startBackgroundPrune();
|
|
5992
6169
|
if (!map.has(id)) enforceCapOnWrite();
|
|
5993
6170
|
const flag = {
|
|
5994
6171
|
deleted: true,
|
|
@@ -6136,9 +6313,6 @@ function createResponsesEmulatorState(opts) {
|
|
|
6136
6313
|
getConversationHead(conversationId) {
|
|
6137
6314
|
return readMap(conversationHeadRecords, conversationId);
|
|
6138
6315
|
},
|
|
6139
|
-
clearConversationHead(conversationId) {
|
|
6140
|
-
deleteMapEntry(conversationHeadRecords, conversationId);
|
|
6141
|
-
},
|
|
6142
6316
|
setInputItems(responseId, inputItems, options) {
|
|
6143
6317
|
removeDeletionFlag(inputItemDeletionFlags, responseId);
|
|
6144
6318
|
return writeMap(inputItemRecords, responseId, inputItems, options?.ttlSeconds);
|
|
@@ -6157,329 +6331,19 @@ function createResponsesEmulatorState(opts) {
|
|
|
6157
6331
|
deleted: true
|
|
6158
6332
|
};
|
|
6159
6333
|
},
|
|
6160
|
-
setDeletionFlag(kind, id, options) {
|
|
6161
|
-
return putDeletionFlag(deletionMap(kind), id, options?.ttlSeconds);
|
|
6162
|
-
},
|
|
6163
6334
|
getDeletionFlag(kind, id) {
|
|
6164
6335
|
return readDeletionFlag(deletionMap(kind), id);
|
|
6165
|
-
},
|
|
6166
|
-
clearDeletionFlag(kind, id) {
|
|
6167
|
-
removeDeletionFlag(deletionMap(kind), id);
|
|
6168
6336
|
}
|
|
6169
6337
|
};
|
|
6170
6338
|
}
|
|
6171
6339
|
const responsesEmulatorState = createResponsesEmulatorState();
|
|
6172
6340
|
//#endregion
|
|
6173
|
-
//#region src/state/model-cache.ts
|
|
6174
|
-
const RESPONSES_ENDPOINT = "/responses";
|
|
6175
|
-
/**
|
|
6176
|
-
* Models whose upstream `/v1/messages` endpoint rejects the `output_config`
|
|
6177
|
-
* field with "Extra inputs are not permitted".
|
|
6178
|
-
*
|
|
6179
|
-
* Verified via `scripts/probe-all-models-output-config.ts` (2026-03-14).
|
|
6180
|
-
* When new models appear, re-run the probe and update this list.
|
|
6181
|
-
*/
|
|
6182
|
-
const MODELS_REJECTING_OUTPUT_CONFIG = new Set([
|
|
6183
|
-
"claude-sonnet-4",
|
|
6184
|
-
"claude-sonnet-4.5",
|
|
6185
|
-
"claude-haiku-4.5"
|
|
6186
|
-
]);
|
|
6187
|
-
var ModelCache = class {
|
|
6188
|
-
models;
|
|
6189
|
-
vsCodeVersion;
|
|
6190
|
-
cacheModels(models) {
|
|
6191
|
-
this.models = models;
|
|
6192
|
-
}
|
|
6193
|
-
clearModels() {
|
|
6194
|
-
this.models = void 0;
|
|
6195
|
-
}
|
|
6196
|
-
getModels() {
|
|
6197
|
-
return this.models;
|
|
6198
|
-
}
|
|
6199
|
-
setVSCodeVersion(version) {
|
|
6200
|
-
this.vsCodeVersion = version;
|
|
6201
|
-
}
|
|
6202
|
-
clearVSCodeVersion() {
|
|
6203
|
-
this.vsCodeVersion = void 0;
|
|
6204
|
-
}
|
|
6205
|
-
getVSCodeVersion() {
|
|
6206
|
-
return this.vsCodeVersion;
|
|
6207
|
-
}
|
|
6208
|
-
findById(modelId) {
|
|
6209
|
-
return this.models?.data.find((model) => model.id === modelId);
|
|
6210
|
-
}
|
|
6211
|
-
getModelIds() {
|
|
6212
|
-
return this.models?.data.map((model) => model.id) ?? [];
|
|
6213
|
-
}
|
|
6214
|
-
supportsEndpoint(model, endpoint) {
|
|
6215
|
-
return model?.supported_endpoints?.includes(endpoint) ?? false;
|
|
6216
|
-
}
|
|
6217
|
-
supportsToolCalls(model) {
|
|
6218
|
-
return model?.capabilities.supports.tool_calls ?? false;
|
|
6219
|
-
}
|
|
6220
|
-
supportsAdaptiveThinking(model) {
|
|
6221
|
-
return model?.capabilities.supports.adaptive_thinking ?? false;
|
|
6222
|
-
}
|
|
6223
|
-
supportsVision(model) {
|
|
6224
|
-
return model?.capabilities.supports.vision ?? false;
|
|
6225
|
-
}
|
|
6226
|
-
supportsOutputConfig(model) {
|
|
6227
|
-
if (!model) return true;
|
|
6228
|
-
return !MODELS_REJECTING_OUTPUT_CONFIG.has(model.id);
|
|
6229
|
-
}
|
|
6230
|
-
getVisionLimits(model) {
|
|
6231
|
-
return model?.capabilities.limits.vision;
|
|
6232
|
-
}
|
|
6233
|
-
};
|
|
6234
|
-
const modelCache = new ModelCache();
|
|
6235
|
-
//#endregion
|
|
6236
|
-
//#region src/translator/anthropic/translation-issue.ts
|
|
6237
|
-
var TranslationFailure = class extends Error {
|
|
6238
|
-
status;
|
|
6239
|
-
kind;
|
|
6240
|
-
constructor(message, options) {
|
|
6241
|
-
super(message);
|
|
6242
|
-
this.name = "TranslationFailure";
|
|
6243
|
-
this.status = options.status;
|
|
6244
|
-
this.kind = options.kind;
|
|
6245
|
-
}
|
|
6246
|
-
};
|
|
6247
|
-
//#endregion
|
|
6248
|
-
//#region src/lib/error.ts
|
|
6249
|
-
var HTTPError = class extends Error {
|
|
6250
|
-
status;
|
|
6251
|
-
body;
|
|
6252
|
-
constructor(status, body) {
|
|
6253
|
-
super(body.error.message);
|
|
6254
|
-
this.name = "HTTPError";
|
|
6255
|
-
this.status = status;
|
|
6256
|
-
this.body = body;
|
|
6257
|
-
}
|
|
6258
|
-
toResponse() {
|
|
6259
|
-
return Response.json(this.body, { status: this.status });
|
|
6260
|
-
}
|
|
6261
|
-
};
|
|
6262
|
-
function throwInvalidRequestError(message, param, code) {
|
|
6263
|
-
throw new HTTPError(400, { error: {
|
|
6264
|
-
message,
|
|
6265
|
-
type: "invalid_request_error",
|
|
6266
|
-
param,
|
|
6267
|
-
...code ? { code } : {}
|
|
6268
|
-
} });
|
|
6269
|
-
}
|
|
6270
|
-
function fromTranslationFailure(failure) {
|
|
6271
|
-
return new HTTPError(failure.status, { error: {
|
|
6272
|
-
message: failure.message,
|
|
6273
|
-
type: "translation_error"
|
|
6274
|
-
} });
|
|
6275
|
-
}
|
|
6276
|
-
function resolveModelOrThrow(modelId) {
|
|
6277
|
-
const model = modelCache.findById(modelId);
|
|
6278
|
-
if (!model) throwInvalidRequestError("The selected model could not be resolved.", "model");
|
|
6279
|
-
return model;
|
|
6280
|
-
}
|
|
6281
|
-
function withTranslationErrors(fn) {
|
|
6282
|
-
try {
|
|
6283
|
-
return fn();
|
|
6284
|
-
} catch (error) {
|
|
6285
|
-
if (error instanceof TranslationFailure) throw fromTranslationFailure(error);
|
|
6286
|
-
throw error;
|
|
6287
|
-
}
|
|
6288
|
-
}
|
|
6289
|
-
function previewBody(text, maxLength = 500) {
|
|
6290
|
-
return text.length > maxLength ? `${text.slice(0, maxLength)}…` : text;
|
|
6291
|
-
}
|
|
6292
|
-
function isStructuredErrorPayload(value) {
|
|
6293
|
-
return typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null;
|
|
6294
|
-
}
|
|
6295
|
-
function upstreamErrorType(status) {
|
|
6296
|
-
return status === 429 ? "rate_limit_error" : "upstream_error";
|
|
6297
|
-
}
|
|
6298
|
-
function createFallbackUpstreamError(message, response, rawText) {
|
|
6299
|
-
return { error: {
|
|
6300
|
-
message: rawText.trim() || message,
|
|
6301
|
-
type: upstreamErrorType(response.status)
|
|
6302
|
-
} };
|
|
6303
|
-
}
|
|
6304
|
-
function getDiagnosticHeaders(response) {
|
|
6305
|
-
const headerNames = [
|
|
6306
|
-
"retry-after",
|
|
6307
|
-
"x-ratelimit-limit",
|
|
6308
|
-
"x-ratelimit-remaining",
|
|
6309
|
-
"x-ratelimit-reset",
|
|
6310
|
-
"x-github-request-id",
|
|
6311
|
-
"x-request-id"
|
|
6312
|
-
];
|
|
6313
|
-
const headers = {};
|
|
6314
|
-
for (const name of headerNames) {
|
|
6315
|
-
const value = response.headers.get(name);
|
|
6316
|
-
if (value) headers[name] = value;
|
|
6317
|
-
}
|
|
6318
|
-
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
6319
|
-
}
|
|
6320
|
-
async function throwUpstreamError(message, response) {
|
|
6321
|
-
let rawText = "";
|
|
6322
|
-
let body;
|
|
6323
|
-
try {
|
|
6324
|
-
rawText = await response.text();
|
|
6325
|
-
const json = JSON.parse(rawText);
|
|
6326
|
-
body = isStructuredErrorPayload(json) ? json : createFallbackUpstreamError(message, response, rawText);
|
|
6327
|
-
} catch {
|
|
6328
|
-
body = createFallbackUpstreamError(message, response, rawText);
|
|
6329
|
-
}
|
|
6330
|
-
consola.error("Upstream error:", {
|
|
6331
|
-
status: response.status,
|
|
6332
|
-
statusText: response.statusText,
|
|
6333
|
-
url: response.url,
|
|
6334
|
-
body,
|
|
6335
|
-
rawBody: rawText ? previewBody(rawText) : "<empty>",
|
|
6336
|
-
headers: getDiagnosticHeaders(response)
|
|
6337
|
-
});
|
|
6338
|
-
throw new HTTPError(response.status, body);
|
|
6339
|
-
}
|
|
6340
|
-
//#endregion
|
|
6341
|
-
//#region src/lib/sleep.ts
|
|
6342
|
-
function sleep(ms) {
|
|
6343
|
-
return new Promise((resolve) => {
|
|
6344
|
-
setTimeout(resolve, ms);
|
|
6345
|
-
});
|
|
6346
|
-
}
|
|
6347
|
-
//#endregion
|
|
6348
|
-
//#region src/state/rate-limiter.ts
|
|
6349
|
-
var RateLimiter = class {
|
|
6350
|
-
nextAvailableAt = 0;
|
|
6351
|
-
reset() {
|
|
6352
|
-
this.nextAvailableAt = 0;
|
|
6353
|
-
}
|
|
6354
|
-
async acquire(intervalSeconds, waitMode) {
|
|
6355
|
-
if (intervalSeconds === void 0) return;
|
|
6356
|
-
const now = Date.now();
|
|
6357
|
-
const intervalMs = intervalSeconds * 1e3;
|
|
6358
|
-
if (!this.nextAvailableAt || now >= this.nextAvailableAt) {
|
|
6359
|
-
this.nextAvailableAt = now + intervalMs;
|
|
6360
|
-
return;
|
|
6361
|
-
}
|
|
6362
|
-
const waitMs = this.nextAvailableAt - now;
|
|
6363
|
-
const waitTimeSeconds = Math.ceil(waitMs / 1e3);
|
|
6364
|
-
if (!waitMode) {
|
|
6365
|
-
consola.warn(`Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`);
|
|
6366
|
-
throw new HTTPError(429, { error: {
|
|
6367
|
-
message: "Rate limit exceeded",
|
|
6368
|
-
type: "rate_limit_error"
|
|
6369
|
-
} });
|
|
6370
|
-
}
|
|
6371
|
-
const claimedSlot = this.nextAvailableAt;
|
|
6372
|
-
this.nextAvailableAt = claimedSlot + intervalMs;
|
|
6373
|
-
consola.warn(`Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`);
|
|
6374
|
-
await sleep(waitMs);
|
|
6375
|
-
consola.info("Rate limit wait completed, proceeding with request");
|
|
6376
|
-
}
|
|
6377
|
-
};
|
|
6378
|
-
const rateLimiter = new RateLimiter();
|
|
6379
|
-
//#endregion
|
|
6380
6341
|
//#region src/state/runtime.ts
|
|
6381
6342
|
var RuntimeStore = class {
|
|
6382
6343
|
dumpFailedPayloads = false;
|
|
6383
6344
|
};
|
|
6384
6345
|
const runtimeStore = new RuntimeStore();
|
|
6385
6346
|
//#endregion
|
|
6386
|
-
//#region src/lib/api-config.ts
|
|
6387
|
-
function standardHeaders() {
|
|
6388
|
-
return {
|
|
6389
|
-
"content-type": "application/json",
|
|
6390
|
-
"accept": "application/json"
|
|
6391
|
-
};
|
|
6392
|
-
}
|
|
6393
|
-
const COPILOT_VERSION = "0.26.7";
|
|
6394
|
-
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
6395
|
-
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
6396
|
-
const API_VERSION = "2025-04-01";
|
|
6397
|
-
const TRAILING_SLASHES_RE$1 = /\/+$/;
|
|
6398
|
-
/** Headers shared by both Copilot and GitHub API requests (editor identity + versioning) */
|
|
6399
|
-
function editorHeaders(config) {
|
|
6400
|
-
return {
|
|
6401
|
-
"editor-version": `vscode/${config.vsCodeVersion ?? "unknown"}`,
|
|
6402
|
-
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
6403
|
-
"user-agent": USER_AGENT,
|
|
6404
|
-
"x-github-api-version": API_VERSION,
|
|
6405
|
-
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
6406
|
-
};
|
|
6407
|
-
}
|
|
6408
|
-
function copilotBaseUrl(config) {
|
|
6409
|
-
if (config.copilotApiBase) return config.copilotApiBase.replace(TRAILING_SLASHES_RE$1, "");
|
|
6410
|
-
return config.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${config.accountType}.githubcopilot.com`;
|
|
6411
|
-
}
|
|
6412
|
-
function copilotHeaders(auth, config, options = {}) {
|
|
6413
|
-
const requestContext = options.requestContext;
|
|
6414
|
-
const headers = {
|
|
6415
|
-
"Authorization": `Bearer ${auth.copilotToken}`,
|
|
6416
|
-
"content-type": standardHeaders()["content-type"],
|
|
6417
|
-
"copilot-integration-id": "vscode-chat",
|
|
6418
|
-
...editorHeaders(config),
|
|
6419
|
-
"openai-intent": "conversation-panel",
|
|
6420
|
-
"x-request-id": randomUUID()
|
|
6421
|
-
};
|
|
6422
|
-
if (options.vision) headers["copilot-vision-request"] = "true";
|
|
6423
|
-
if (options.initiator) headers["X-Initiator"] = options.initiator;
|
|
6424
|
-
if (requestContext?.interactionType) headers["X-Interaction-Type"] = requestContext.interactionType;
|
|
6425
|
-
if (requestContext?.agentTaskId) headers["X-Agent-Task-Id"] = requestContext.agentTaskId;
|
|
6426
|
-
if (requestContext?.parentAgentTaskId) headers["X-Parent-Agent-Id"] = requestContext.parentAgentTaskId;
|
|
6427
|
-
if (requestContext?.clientSessionId) headers["X-Client-Session-Id"] = requestContext.clientSessionId;
|
|
6428
|
-
if (requestContext?.interactionId) headers["X-Interaction-Id"] = requestContext.interactionId;
|
|
6429
|
-
if (requestContext?.clientMachineId) headers["X-Client-Machine-Id"] = requestContext.clientMachineId;
|
|
6430
|
-
return headers;
|
|
6431
|
-
}
|
|
6432
|
-
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
6433
|
-
function githubHeaders(auth, config) {
|
|
6434
|
-
return {
|
|
6435
|
-
...standardHeaders(),
|
|
6436
|
-
authorization: `token ${auth.githubToken}`,
|
|
6437
|
-
...editorHeaders(config)
|
|
6438
|
-
};
|
|
6439
|
-
}
|
|
6440
|
-
const GITHUB_BASE_URL = "https://github.com";
|
|
6441
|
-
const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
|
6442
|
-
const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
6443
|
-
//#endregion
|
|
6444
|
-
//#region src/lib/ghe-domain.ts
|
|
6445
|
-
const GHE_SUFFIX = ".ghe.com";
|
|
6446
|
-
/**
|
|
6447
|
-
* Normalize a GHE domain input to a lowercase bare domain.
|
|
6448
|
-
*
|
|
6449
|
-
* Accepted inputs: `company.ghe.com`, `https://company.ghe.com`,
|
|
6450
|
-
* `https://Company.GHE.com/`, etc.
|
|
6451
|
-
*
|
|
6452
|
-
* @returns Bare lowercase domain, e.g. `company.ghe.com`
|
|
6453
|
-
* @throws {Error} If the input is empty or does not end with `.ghe.com`
|
|
6454
|
-
*/
|
|
6455
|
-
function normalizeGheDomain(input) {
|
|
6456
|
-
const trimmed = input.trim();
|
|
6457
|
-
if (!trimmed) throw new Error("GHE domain must not be empty");
|
|
6458
|
-
let domain;
|
|
6459
|
-
try {
|
|
6460
|
-
domain = (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname.toLowerCase();
|
|
6461
|
-
} catch {
|
|
6462
|
-
throw new Error(`Invalid GHE domain: ${trimmed}`);
|
|
6463
|
-
}
|
|
6464
|
-
if (!domain.endsWith(GHE_SUFFIX) || domain === GHE_SUFFIX.slice(1)) throw new Error(`GHE domain must end with ${GHE_SUFFIX} (got "${domain}")`);
|
|
6465
|
-
return domain;
|
|
6466
|
-
}
|
|
6467
|
-
/**
|
|
6468
|
-
* Build GitHub base URL and API base URL for a given GHE domain,
|
|
6469
|
-
* or return the public GitHub defaults when no domain is provided.
|
|
6470
|
-
*/
|
|
6471
|
-
function buildGitHubUrls(gheDomain) {
|
|
6472
|
-
if (!gheDomain) return {
|
|
6473
|
-
baseUrl: GITHUB_BASE_URL,
|
|
6474
|
-
apiBaseUrl: GITHUB_API_BASE_URL
|
|
6475
|
-
};
|
|
6476
|
-
const domain = normalizeGheDomain(gheDomain);
|
|
6477
|
-
return {
|
|
6478
|
-
baseUrl: `https://${domain}`,
|
|
6479
|
-
apiBaseUrl: `https://api.${domain}`
|
|
6480
|
-
};
|
|
6481
|
-
}
|
|
6482
|
-
//#endregion
|
|
6483
6347
|
//#region node_modules/fetch-event-stream/esm/deps/jsr.io/@std/streams/0.221.0/text_line_stream.js
|
|
6484
6348
|
/**
|
|
6485
6349
|
* Transform a stream into a stream where each chunk is divided by a newline,
|
|
@@ -6602,6 +6466,64 @@ async function* events(res, signal) {
|
|
|
6602
6466
|
}
|
|
6603
6467
|
}
|
|
6604
6468
|
//#endregion
|
|
6469
|
+
//#region src/clients/api-config.ts
|
|
6470
|
+
function standardHeaders() {
|
|
6471
|
+
return {
|
|
6472
|
+
"content-type": "application/json",
|
|
6473
|
+
"accept": "application/json"
|
|
6474
|
+
};
|
|
6475
|
+
}
|
|
6476
|
+
const COPILOT_VERSION = "0.26.7";
|
|
6477
|
+
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
6478
|
+
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
6479
|
+
const API_VERSION = "2025-04-01";
|
|
6480
|
+
const TRAILING_SLASHES_RE$1 = /\/+$/;
|
|
6481
|
+
/** Headers shared by both Copilot and GitHub API requests (editor identity + versioning) */
|
|
6482
|
+
function editorHeaders(config) {
|
|
6483
|
+
return {
|
|
6484
|
+
"editor-version": `vscode/${config.vsCodeVersion ?? "unknown"}`,
|
|
6485
|
+
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
6486
|
+
"user-agent": USER_AGENT,
|
|
6487
|
+
"x-github-api-version": API_VERSION,
|
|
6488
|
+
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
6489
|
+
};
|
|
6490
|
+
}
|
|
6491
|
+
function copilotBaseUrl(config) {
|
|
6492
|
+
if (config.copilotApiBase) return config.copilotApiBase.replace(TRAILING_SLASHES_RE$1, "");
|
|
6493
|
+
return config.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${config.accountType}.githubcopilot.com`;
|
|
6494
|
+
}
|
|
6495
|
+
function copilotHeaders(auth, config, options = {}) {
|
|
6496
|
+
const requestContext = options.requestContext;
|
|
6497
|
+
const headers = {
|
|
6498
|
+
"Authorization": `Bearer ${auth.copilotToken}`,
|
|
6499
|
+
"content-type": standardHeaders()["content-type"],
|
|
6500
|
+
"copilot-integration-id": "vscode-chat",
|
|
6501
|
+
...editorHeaders(config),
|
|
6502
|
+
"openai-intent": "conversation-panel",
|
|
6503
|
+
"x-request-id": randomUUID()
|
|
6504
|
+
};
|
|
6505
|
+
if (options.vision) headers["copilot-vision-request"] = "true";
|
|
6506
|
+
if (options.initiator) headers["X-Initiator"] = options.initiator;
|
|
6507
|
+
if (requestContext?.interactionType) headers["X-Interaction-Type"] = requestContext.interactionType;
|
|
6508
|
+
if (requestContext?.agentTaskId) headers["X-Agent-Task-Id"] = requestContext.agentTaskId;
|
|
6509
|
+
if (requestContext?.parentAgentTaskId) headers["X-Parent-Agent-Id"] = requestContext.parentAgentTaskId;
|
|
6510
|
+
if (requestContext?.clientSessionId) headers["X-Client-Session-Id"] = requestContext.clientSessionId;
|
|
6511
|
+
if (requestContext?.interactionId) headers["X-Interaction-Id"] = requestContext.interactionId;
|
|
6512
|
+
if (requestContext?.clientMachineId) headers["X-Client-Machine-Id"] = requestContext.clientMachineId;
|
|
6513
|
+
return headers;
|
|
6514
|
+
}
|
|
6515
|
+
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
6516
|
+
function githubHeaders(auth, config) {
|
|
6517
|
+
return {
|
|
6518
|
+
...standardHeaders(),
|
|
6519
|
+
authorization: `token ${auth.githubToken}`,
|
|
6520
|
+
...editorHeaders(config)
|
|
6521
|
+
};
|
|
6522
|
+
}
|
|
6523
|
+
const GITHUB_BASE_URL = "https://github.com";
|
|
6524
|
+
const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
|
6525
|
+
const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
6526
|
+
//#endregion
|
|
6605
6527
|
//#region src/clients/copilot-client.ts
|
|
6606
6528
|
var CopilotClient = class {
|
|
6607
6529
|
auth;
|
|
@@ -6930,7 +6852,55 @@ async function getVSCodeVersion() {
|
|
|
6930
6852
|
return remoteVersion ?? localVersion ?? FALLBACK;
|
|
6931
6853
|
}
|
|
6932
6854
|
//#endregion
|
|
6933
|
-
//#region src/
|
|
6855
|
+
//#region src/clients/ghe-domain.ts
|
|
6856
|
+
const GHE_SUFFIX = ".ghe.com";
|
|
6857
|
+
/**
|
|
6858
|
+
* Normalize a GHE domain input to a lowercase bare domain.
|
|
6859
|
+
*
|
|
6860
|
+
* Accepted inputs: `company.ghe.com`, `https://company.ghe.com`,
|
|
6861
|
+
* `https://Company.GHE.com/`, etc.
|
|
6862
|
+
*
|
|
6863
|
+
* @returns Bare lowercase domain, e.g. `company.ghe.com`
|
|
6864
|
+
* @throws {Error} If the input is empty or does not end with `.ghe.com`
|
|
6865
|
+
*/
|
|
6866
|
+
function normalizeGheDomain(input) {
|
|
6867
|
+
const trimmed = input.trim();
|
|
6868
|
+
if (!trimmed) throw new Error("GHE domain must not be empty");
|
|
6869
|
+
let domain;
|
|
6870
|
+
try {
|
|
6871
|
+
domain = (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname.toLowerCase();
|
|
6872
|
+
} catch {
|
|
6873
|
+
throw new Error(`Invalid GHE domain: ${trimmed}`);
|
|
6874
|
+
}
|
|
6875
|
+
if (!domain.endsWith(GHE_SUFFIX) || domain === GHE_SUFFIX.slice(1)) throw new Error(`GHE domain must end with ${GHE_SUFFIX} (got "${domain}")`);
|
|
6876
|
+
return domain;
|
|
6877
|
+
}
|
|
6878
|
+
/**
|
|
6879
|
+
* Build GitHub base URL and API base URL for a given GHE domain,
|
|
6880
|
+
* or return the public GitHub defaults when no domain is provided.
|
|
6881
|
+
*/
|
|
6882
|
+
function buildGitHubUrls(gheDomain) {
|
|
6883
|
+
if (!gheDomain) return {
|
|
6884
|
+
baseUrl: GITHUB_BASE_URL,
|
|
6885
|
+
apiBaseUrl: GITHUB_API_BASE_URL
|
|
6886
|
+
};
|
|
6887
|
+
const domain = normalizeGheDomain(gheDomain);
|
|
6888
|
+
return {
|
|
6889
|
+
baseUrl: `https://${domain}`,
|
|
6890
|
+
apiBaseUrl: `https://api.${domain}`
|
|
6891
|
+
};
|
|
6892
|
+
}
|
|
6893
|
+
//#endregion
|
|
6894
|
+
//#region src/util/duration.ts
|
|
6895
|
+
/**
|
|
6896
|
+
* Formats a millisecond duration as a compact human-readable string:
|
|
6897
|
+
* `<n>ms` under one second, otherwise `<n>s` rounded to whole seconds.
|
|
6898
|
+
*/
|
|
6899
|
+
function formatDurationMs(ms) {
|
|
6900
|
+
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
6901
|
+
}
|
|
6902
|
+
//#endregion
|
|
6903
|
+
//#region src/clients/upstream-queue.ts
|
|
6934
6904
|
const DEFAULT_UPSTREAM_QUEUE_OPTIONS = {
|
|
6935
6905
|
concurrency: 10,
|
|
6936
6906
|
maxRetries: 5,
|
|
@@ -6987,7 +6957,7 @@ var UpstreamRequestQueue = class {
|
|
|
6987
6957
|
this.logger.warn([
|
|
6988
6958
|
"Upstream rate limited;",
|
|
6989
6959
|
`retrying ${formatRequestContext(context)}`,
|
|
6990
|
-
`in ${
|
|
6960
|
+
`in ${formatDurationMs(delayMs)}`,
|
|
6991
6961
|
`(attempt ${attempt + 1}/${this.options.maxRetries})`
|
|
6992
6962
|
].join(" "));
|
|
6993
6963
|
await abortableSleep(this.sleep, delayMs, signal);
|
|
@@ -7097,9 +7067,6 @@ function formatRequestContext(context) {
|
|
|
7097
7067
|
return `${context.method ?? "GET"} ${context.url}`;
|
|
7098
7068
|
}
|
|
7099
7069
|
}
|
|
7100
|
-
function formatDelay(delayMs) {
|
|
7101
|
-
return delayMs < 1e3 ? `${delayMs}ms` : `${Math.round(delayMs / 1e3)}s`;
|
|
7102
|
-
}
|
|
7103
7070
|
function abortableSleep(sleep, ms, signal) {
|
|
7104
7071
|
if (!signal) return sleep(ms);
|
|
7105
7072
|
signal.throwIfAborted();
|
|
@@ -7118,7 +7085,7 @@ function abortableSleep(sleep, ms, signal) {
|
|
|
7118
7085
|
});
|
|
7119
7086
|
}
|
|
7120
7087
|
//#endregion
|
|
7121
|
-
//#region src/
|
|
7088
|
+
//#region src/clients/factory.ts
|
|
7122
7089
|
const upstreamRequestQueue = createDefaultUpstreamRequestQueue();
|
|
7123
7090
|
function configureUpstreamRequestQueue(options) {
|
|
7124
7091
|
upstreamRequestQueue.updateOptions(options);
|
|
@@ -7363,11 +7330,6 @@ const checkUsage = defineCommand({
|
|
|
7363
7330
|
await setupGitHubToken();
|
|
7364
7331
|
try {
|
|
7365
7332
|
const usage = await new GitHubClient(authStore, getClientConfig()).getCopilotUsage();
|
|
7366
|
-
const premium = usage.quota_snapshots.premium_interactions;
|
|
7367
|
-
const premiumTotal = premium.entitlement;
|
|
7368
|
-
const premiumUsed = premiumTotal - premium.remaining;
|
|
7369
|
-
const premiumPercentUsed = premiumTotal > 0 ? premiumUsed / premiumTotal * 100 : 0;
|
|
7370
|
-
const premiumPercentRemaining = premium.percent_remaining;
|
|
7371
7333
|
function summarizeQuota(name, snap) {
|
|
7372
7334
|
if (!snap) return `${name}: N/A`;
|
|
7373
7335
|
const total = snap.entitlement;
|
|
@@ -7376,7 +7338,7 @@ const checkUsage = defineCommand({
|
|
|
7376
7338
|
const percentRemaining = snap.percent_remaining;
|
|
7377
7339
|
return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
|
|
7378
7340
|
}
|
|
7379
|
-
const premiumLine =
|
|
7341
|
+
const premiumLine = summarizeQuota("Premium", usage.quota_snapshots.premium_interactions);
|
|
7380
7342
|
const chatLine = summarizeQuota("Chat", usage.quota_snapshots.chat);
|
|
7381
7343
|
const completionsLine = summarizeQuota("Completions", usage.quota_snapshots.completions);
|
|
7382
7344
|
consola.box(`Copilot Usage (plan: ${usage.copilot_plan})\nQuota resets: ${usage.quota_reset_date}\n\nQuotas:\n ${premiumLine}\n ${chatLine}\n ${completionsLine}`);
|
|
@@ -7387,8 +7349,8 @@ const checkUsage = defineCommand({
|
|
|
7387
7349
|
}
|
|
7388
7350
|
});
|
|
7389
7351
|
//#endregion
|
|
7390
|
-
//#region src/
|
|
7391
|
-
const VERSION = "0.
|
|
7352
|
+
//#region src/util/version.ts
|
|
7353
|
+
const VERSION = "0.7.0";
|
|
7392
7354
|
//#endregion
|
|
7393
7355
|
//#region src/debug.ts
|
|
7394
7356
|
function getRuntimeInfo() {
|
|
@@ -7656,59 +7618,6 @@ async function getTokenCount(payload, model) {
|
|
|
7656
7618
|
async function estimateResponsesInputTokens(inputItems, model) {
|
|
7657
7619
|
return (await getEncoder(getTokenizerFromModel(model))).encode(JSON.stringify(inputItems)).length;
|
|
7658
7620
|
}
|
|
7659
|
-
/**
|
|
7660
|
-
* Fast character-based token estimate for Anthropic payloads.
|
|
7661
|
-
* Uses ~3.5 chars/token ratio (conservative for Claude's tokenizer).
|
|
7662
|
-
* Intentionally over-estimates to favor proactive routing.
|
|
7663
|
-
*/
|
|
7664
|
-
function estimateAnthropicInputTokens(payload) {
|
|
7665
|
-
let chars = 0;
|
|
7666
|
-
if (typeof payload.system === "string") chars += payload.system.length;
|
|
7667
|
-
else if (Array.isArray(payload.system)) for (const block of payload.system) chars += block.text?.length ?? 0;
|
|
7668
|
-
for (const msg of payload.messages) if (typeof msg.content === "string") chars += msg.content.length;
|
|
7669
|
-
else if (Array.isArray(msg.content)) chars += estimateContentBlockChars(msg.content);
|
|
7670
|
-
if (payload.tools?.length) chars += JSON.stringify(payload.tools).length;
|
|
7671
|
-
return Math.ceil(chars / 3.5);
|
|
7672
|
-
}
|
|
7673
|
-
function estimateContentBlockChars(blocks) {
|
|
7674
|
-
let chars = 0;
|
|
7675
|
-
for (const block of blocks) switch (block.type) {
|
|
7676
|
-
case "text":
|
|
7677
|
-
chars += block.text.length;
|
|
7678
|
-
break;
|
|
7679
|
-
case "thinking":
|
|
7680
|
-
chars += block.thinking.length;
|
|
7681
|
-
break;
|
|
7682
|
-
case "redacted_thinking":
|
|
7683
|
-
chars += block.data.length;
|
|
7684
|
-
break;
|
|
7685
|
-
case "tool_use":
|
|
7686
|
-
case "server_tool_use":
|
|
7687
|
-
case "mcp_tool_use":
|
|
7688
|
-
chars += JSON.stringify(block.input).length;
|
|
7689
|
-
break;
|
|
7690
|
-
case "tool_result":
|
|
7691
|
-
case "mcp_tool_result":
|
|
7692
|
-
chars += typeof block.content === "string" ? block.content.length : JSON.stringify(block.content ?? "").length;
|
|
7693
|
-
break;
|
|
7694
|
-
case "server_tool_result":
|
|
7695
|
-
case "web_search_tool_result":
|
|
7696
|
-
case "web_fetch_tool_result":
|
|
7697
|
-
case "code_execution_tool_result":
|
|
7698
|
-
case "bash_code_execution_tool_result":
|
|
7699
|
-
case "text_editor_code_execution_tool_result":
|
|
7700
|
-
case "tool_search_tool_result":
|
|
7701
|
-
chars += JSON.stringify(block.content ?? "").length;
|
|
7702
|
-
break;
|
|
7703
|
-
case "document":
|
|
7704
|
-
chars += JSON.stringify(block).length;
|
|
7705
|
-
break;
|
|
7706
|
-
case "image":
|
|
7707
|
-
chars += 1e3;
|
|
7708
|
-
break;
|
|
7709
|
-
}
|
|
7710
|
-
return chars;
|
|
7711
|
-
}
|
|
7712
7621
|
//#endregion
|
|
7713
7622
|
//#region src/selfcheck.ts
|
|
7714
7623
|
const PROBE_ENCODINGS = [
|
|
@@ -29208,7 +29117,7 @@ var require_eventsource = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
|
|
|
29208
29117
|
};
|
|
29209
29118
|
}));
|
|
29210
29119
|
//#endregion
|
|
29211
|
-
//#region src/
|
|
29120
|
+
//#region src/cli/proxy.ts
|
|
29212
29121
|
var import_undici = (/* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
29213
29122
|
const Client = require_client();
|
|
29214
29123
|
const Dispatcher = require_dispatcher();
|
|
@@ -29419,7 +29328,7 @@ function initProxyFromEnv() {
|
|
|
29419
29328
|
}
|
|
29420
29329
|
}
|
|
29421
29330
|
//#endregion
|
|
29422
|
-
//#region src/
|
|
29331
|
+
//#region src/cli/shell.ts
|
|
29423
29332
|
const EXE_EXTENSION_RE = /\.exe$/i;
|
|
29424
29333
|
function normalizeShellName(raw) {
|
|
29425
29334
|
if (!raw) return;
|
|
@@ -29508,7 +29417,7 @@ function generateEnvScript(envVars, commandToRun = "") {
|
|
|
29508
29417
|
//#endregion
|
|
29509
29418
|
//#region src/lib/model-resolver.ts
|
|
29510
29419
|
const DEFAULT_FALLBACKS = {
|
|
29511
|
-
claudeOpus: "claude-opus-4.
|
|
29420
|
+
claudeOpus: "claude-opus-4.8",
|
|
29512
29421
|
claudeSonnet: "claude-sonnet-4.6",
|
|
29513
29422
|
claudeHaiku: "claude-haiku-4.5"
|
|
29514
29423
|
};
|
|
@@ -29528,7 +29437,7 @@ function resolveModel(modelId, knownModelIds, config) {
|
|
|
29528
29437
|
return modelId;
|
|
29529
29438
|
}
|
|
29530
29439
|
//#endregion
|
|
29531
|
-
//#region src/
|
|
29440
|
+
//#region src/cli/startup-banner.ts
|
|
29532
29441
|
function printStartupBanner(serverUrl) {
|
|
29533
29442
|
const lines = [];
|
|
29534
29443
|
lines.push(`ghc-proxy v${VERSION}`);
|
|
@@ -47817,8 +47726,7 @@ function getRequestModelMapping(request) {
|
|
|
47817
47726
|
return requestModelMapping.get(request);
|
|
47818
47727
|
}
|
|
47819
47728
|
function formatElapsed(start) {
|
|
47820
|
-
|
|
47821
|
-
return delta < 1e3 ? `${delta}ms` : `${Math.round(delta / 1e3)}s`;
|
|
47729
|
+
return formatDurationMs(Date.now() - start);
|
|
47822
47730
|
}
|
|
47823
47731
|
function formatPath(rawUrl) {
|
|
47824
47732
|
try {
|
|
@@ -47849,8 +47757,8 @@ function getEffectiveModel(info) {
|
|
|
47849
47757
|
}
|
|
47850
47758
|
/**
|
|
47851
47759
|
* Mutate `modelMapping` in place by appending a transform step.
|
|
47852
|
-
*
|
|
47853
|
-
*
|
|
47760
|
+
* Strategy contexts hold a reference to the same `modelMapping`,
|
|
47761
|
+
* so steps are pushed directly rather than returning a new object.
|
|
47854
47762
|
*/
|
|
47855
47763
|
function appendModelStepInPlace(info, tag, newModel) {
|
|
47856
47764
|
const current = getEffectiveModel(info);
|
|
@@ -47893,6 +47801,16 @@ function logRequest(method, url, status, elapsed, modelInfo, requestId) {
|
|
|
47893
47801
|
//#endregion
|
|
47894
47802
|
//#region src/lib/sse-adapter.ts
|
|
47895
47803
|
/**
|
|
47804
|
+
* Serializes Anthropic stream events into SSE output items
|
|
47805
|
+
* (one `{ event, data }` per event, with `data` as the JSON-encoded event).
|
|
47806
|
+
*/
|
|
47807
|
+
function serializeAnthropicSSE(events) {
|
|
47808
|
+
return events.map((event) => ({
|
|
47809
|
+
event: event.type,
|
|
47810
|
+
data: JSON.stringify(event)
|
|
47811
|
+
}));
|
|
47812
|
+
}
|
|
47813
|
+
/**
|
|
47896
47814
|
* Bridges an AsyncGenerator<SSEOutput> to Elysia's SSE response format.
|
|
47897
47815
|
* Returns an async generator that yields sse() calls for each SSE output item.
|
|
47898
47816
|
*/
|
|
@@ -47906,7 +47824,7 @@ async function* sseAdapter(generator) {
|
|
|
47906
47824
|
//#endregion
|
|
47907
47825
|
//#region src/deliver/index.ts
|
|
47908
47826
|
function deliverResult(request, result, modelMapping) {
|
|
47909
|
-
|
|
47827
|
+
setRequestModelMapping(request, modelMapping);
|
|
47910
47828
|
if (result.kind === "json") return {
|
|
47911
47829
|
streaming: false,
|
|
47912
47830
|
data: result.data
|
|
@@ -47929,7 +47847,7 @@ function hasStreamingResponsesQuery(request) {
|
|
|
47929
47847
|
return new URL(request.url).searchParams.get("stream") === "true";
|
|
47930
47848
|
}
|
|
47931
47849
|
//#endregion
|
|
47932
|
-
//#region src/
|
|
47850
|
+
//#region src/guard/approval.ts
|
|
47933
47851
|
async function awaitApproval() {
|
|
47934
47852
|
if (!await consola.prompt(`Accept incoming request?`, { type: "confirm" })) throw new HTTPError(403, { error: {
|
|
47935
47853
|
message: "Request rejected",
|
|
@@ -47937,7 +47855,7 @@ async function awaitApproval() {
|
|
|
47937
47855
|
} });
|
|
47938
47856
|
}
|
|
47939
47857
|
//#endregion
|
|
47940
|
-
//#region src/guard/
|
|
47858
|
+
//#region src/guard/gate.ts
|
|
47941
47859
|
async function runGuard() {
|
|
47942
47860
|
await rateLimiter.acquire(authStore.rateLimitSeconds, authStore.rateLimitWait);
|
|
47943
47861
|
if (authStore.manualApprove) await awaitApproval();
|
|
@@ -47949,118 +47867,7 @@ const requestGuardPlugin = new Elysia({ name: "request-guard" }).macro({ guarded
|
|
|
47949
47867
|
await runGuard();
|
|
47950
47868
|
} }) });
|
|
47951
47869
|
//#endregion
|
|
47952
|
-
//#region src/
|
|
47953
|
-
/**
|
|
47954
|
-
* Unified model rewrite: user rules → built-in normalization → pass-through.
|
|
47955
|
-
* Call once at handler entry, before any model lookup or policy.
|
|
47956
|
-
*/
|
|
47957
|
-
function rewriteModel(modelId) {
|
|
47958
|
-
const userRules = configStore.getModelRewrites();
|
|
47959
|
-
if (userRules.length > 0) {
|
|
47960
|
-
for (const rule of userRules) if (matchesGlob(rule.from, modelId)) return {
|
|
47961
|
-
originalModel: modelId,
|
|
47962
|
-
model: normalizeToKnownModel(rule.to) ?? rule.to,
|
|
47963
|
-
reason: "CONFIG_REWRITE"
|
|
47964
|
-
};
|
|
47965
|
-
}
|
|
47966
|
-
const normalized = normalizeToKnownModel(modelId);
|
|
47967
|
-
if (normalized && normalized !== modelId) return {
|
|
47968
|
-
originalModel: modelId,
|
|
47969
|
-
model: normalized,
|
|
47970
|
-
reason: "AUTO_CORRECT"
|
|
47971
|
-
};
|
|
47972
|
-
return {
|
|
47973
|
-
originalModel: modelId,
|
|
47974
|
-
model: modelId
|
|
47975
|
-
};
|
|
47976
|
-
}
|
|
47977
|
-
/**
|
|
47978
|
-
* Apply model rewrite to a mutable model field and log if changed.
|
|
47979
|
-
* Returns the rewrite result for downstream use.
|
|
47980
|
-
*/
|
|
47981
|
-
function applyModelRewrite(payload) {
|
|
47982
|
-
const result = rewriteModel(payload.model);
|
|
47983
|
-
if (result.model !== result.originalModel) {
|
|
47984
|
-
consola.debug(`Model rewritten: ${result.originalModel} ~> ${result.model}`);
|
|
47985
|
-
payload.model = result.model;
|
|
47986
|
-
}
|
|
47987
|
-
return result;
|
|
47988
|
-
}
|
|
47989
|
-
const DOT_RE = /\./g;
|
|
47990
|
-
/**
|
|
47991
|
-
* Resolve a model ID against Copilot's cached model list using
|
|
47992
|
-
* dash/dot equivalence. Returns the canonical ID if found.
|
|
47993
|
-
*/
|
|
47994
|
-
function normalizeToKnownModel(modelId) {
|
|
47995
|
-
const models = modelCache.getModels()?.data;
|
|
47996
|
-
if (!models) return void 0;
|
|
47997
|
-
if (models.some((m) => m.id === modelId)) return modelId;
|
|
47998
|
-
const normalized = modelId.replace(DOT_RE, "-");
|
|
47999
|
-
for (const model of models) if (model.id.replace(DOT_RE, "-") === normalized) return model.id;
|
|
48000
|
-
}
|
|
48001
|
-
const GLOB_SPECIAL_RE = /[.+^${}()|[\]\\]/g;
|
|
48002
|
-
const GLOB_STAR_RE = /\*/g;
|
|
48003
|
-
function matchesGlob(pattern, value) {
|
|
48004
|
-
if (!pattern.includes("*")) return pattern === value;
|
|
48005
|
-
return new RegExp(`^${pattern.replace(GLOB_SPECIAL_RE, "\\$&").replace(GLOB_STAR_RE, ".*")}$`).test(value);
|
|
48006
|
-
}
|
|
48007
|
-
/**
|
|
48008
|
-
* Quick check: does this model have any configured context-upgrade rules?
|
|
48009
|
-
* Use to skip expensive token estimation for ineligible models.
|
|
48010
|
-
*/
|
|
48011
|
-
function hasContextUpgradeRule(model) {
|
|
48012
|
-
return configStore.getContextUpgradeRules().some((rule) => matchesGlob(rule.from, model));
|
|
48013
|
-
}
|
|
48014
|
-
/** Find the first configured upgrade rule for a model. */
|
|
48015
|
-
function findUpgradeRule(model) {
|
|
48016
|
-
for (const rule of configStore.getContextUpgradeRules()) if (matchesGlob(rule.from, model)) return {
|
|
48017
|
-
from: rule.from,
|
|
48018
|
-
to: normalizeToKnownModel(rule.to) ?? rule.to
|
|
48019
|
-
};
|
|
48020
|
-
}
|
|
48021
|
-
/**
|
|
48022
|
-
* Proactive: resolve the upgrade target model for a given model + token count.
|
|
48023
|
-
* Returns the target model ID, or undefined if no upgrade applies.
|
|
48024
|
-
*/
|
|
48025
|
-
function resolveContextUpgrade(model, estimatedTokens) {
|
|
48026
|
-
const rule = findUpgradeRule(model);
|
|
48027
|
-
if (rule && estimatedTokens > configStore.getContextUpgradeThreshold()) return rule.to;
|
|
48028
|
-
}
|
|
48029
|
-
/**
|
|
48030
|
-
* Reactive: get the upgrade target for a model on context-length error.
|
|
48031
|
-
* Returns the target model ID, or undefined if no fallback applies.
|
|
48032
|
-
*/
|
|
48033
|
-
function getContextUpgradeTarget(model) {
|
|
48034
|
-
return findUpgradeRule(model)?.to;
|
|
48035
|
-
}
|
|
48036
|
-
/** Context-length error detection with pattern matching */
|
|
48037
|
-
const CONTEXT_ERROR_PATTERNS = [
|
|
48038
|
-
/context.length/i,
|
|
48039
|
-
/too.long/i,
|
|
48040
|
-
/token.*(limit|maximum|exceed)/i,
|
|
48041
|
-
/(limit|maximum|exceed).*token/i
|
|
48042
|
-
];
|
|
48043
|
-
function isContextLengthError(error) {
|
|
48044
|
-
if (!(error instanceof HTTPError) || error.status !== 400) return false;
|
|
48045
|
-
const message = error.body?.error?.message;
|
|
48046
|
-
return message ? CONTEXT_ERROR_PATTERNS.some((pattern) => pattern.test(message)) : false;
|
|
48047
|
-
}
|
|
48048
|
-
//#endregion
|
|
48049
|
-
//#region src/dispatch/error-recovery.ts
|
|
48050
|
-
async function executeWithContextRetry(executeFn, modelInfo) {
|
|
48051
|
-
try {
|
|
48052
|
-
return await executeFn(modelInfo.model);
|
|
48053
|
-
} catch (error) {
|
|
48054
|
-
if (!isContextLengthError(error)) throw error;
|
|
48055
|
-
if (!configStore.isContextUpgradeEnabled()) throw error;
|
|
48056
|
-
const upgradeTarget = getContextUpgradeTarget(modelInfo.model);
|
|
48057
|
-
if (!upgradeTarget) throw error;
|
|
48058
|
-
consola.info(`Context length error → retrying with ${upgradeTarget}`);
|
|
48059
|
-
return await executeFn(upgradeTarget);
|
|
48060
|
-
}
|
|
48061
|
-
}
|
|
48062
|
-
//#endregion
|
|
48063
|
-
//#region src/lib/assert-never.ts
|
|
47870
|
+
//#region src/util/assert-never.ts
|
|
48064
47871
|
/**
|
|
48065
47872
|
* Compile-time exhaustiveness check for switch/if-else chains on
|
|
48066
47873
|
* discriminated unions. At runtime, throws with a descriptive message.
|
|
@@ -48111,54 +47918,20 @@ function selectCapiProfile(model) {
|
|
|
48111
47918
|
return inferModelFamily(model) === "claude" ? claudeProfile : baseProfile;
|
|
48112
47919
|
}
|
|
48113
47920
|
//#endregion
|
|
48114
|
-
//#region src/core/capi/
|
|
48115
|
-
|
|
48116
|
-
|
|
48117
|
-
|
|
47921
|
+
//#region src/core/capi/headers.ts
|
|
47922
|
+
/**
|
|
47923
|
+
* Leaf helper for reading optional request headers. Lives in its own module so
|
|
47924
|
+
* both request-context.ts and subagent-marker.ts can depend on it without
|
|
47925
|
+
* importing each other (which would form a cycle).
|
|
47926
|
+
*/
|
|
48118
47927
|
function readHeader(headers, name) {
|
|
48119
47928
|
return headers.get(name) ?? void 0;
|
|
48120
47929
|
}
|
|
48121
|
-
|
|
48122
|
-
|
|
48123
|
-
|
|
48124
|
-
|
|
48125
|
-
|
|
48126
|
-
interactionType: readHeader(headers, "x-interaction-type"),
|
|
48127
|
-
agentTaskId: readHeader(headers, "x-agent-task-id"),
|
|
48128
|
-
parentAgentTaskId: readHeader(headers, "x-parent-agent-id"),
|
|
48129
|
-
clientSessionId: readHeader(headers, "x-client-session-id") ?? readHeader(headers, "x-session-id"),
|
|
48130
|
-
interactionId: readHeader(headers, "x-interaction-id"),
|
|
48131
|
-
clientMachineId: readHeader(headers, "x-client-machine-id")
|
|
48132
|
-
};
|
|
48133
|
-
}
|
|
48134
|
-
function resolveInitiator(defaultInitiator, requestContext) {
|
|
48135
|
-
switch (requestContext?.interactionType) {
|
|
48136
|
-
case "conversation-agent":
|
|
48137
|
-
case "conversation-subagent":
|
|
48138
|
-
case "conversation-background": return "agent";
|
|
48139
|
-
case "conversation-user": return "user";
|
|
48140
|
-
default: return defaultInitiator;
|
|
48141
|
-
}
|
|
48142
|
-
}
|
|
48143
|
-
function buildCapiRequestContext(initiator, overrides = {}) {
|
|
48144
|
-
return {
|
|
48145
|
-
interactionType: overrides.interactionType ?? (initiator === "agent" ? "conversation-agent" : "conversation-user"),
|
|
48146
|
-
agentTaskId: overrides.agentTaskId,
|
|
48147
|
-
parentAgentTaskId: overrides.parentAgentTaskId,
|
|
48148
|
-
clientSessionId: overrides.clientSessionId,
|
|
48149
|
-
interactionId: overrides.interactionId ?? randomUUID(),
|
|
48150
|
-
clientMachineId: overrides.clientMachineId
|
|
48151
|
-
};
|
|
48152
|
-
}
|
|
48153
|
-
function normalizeAnthropicRequestContext(payload, headers) {
|
|
48154
|
-
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromAnthropicPayload(payload));
|
|
48155
|
-
}
|
|
48156
|
-
function normalizeChatRequestContext(payload, headers) {
|
|
48157
|
-
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromChatPayload(payload));
|
|
48158
|
-
}
|
|
48159
|
-
function normalizeResponsesRequestContext(payload, headers) {
|
|
48160
|
-
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromResponsesPayload(payload));
|
|
48161
|
-
}
|
|
47930
|
+
//#endregion
|
|
47931
|
+
//#region src/core/capi/subagent-marker.ts
|
|
47932
|
+
const SUBAGENT_MARKER_PREFIX = "__SUBAGENT_MARKER__";
|
|
47933
|
+
const SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
47934
|
+
const SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
48162
47935
|
function withSubagentMarker(baseContext, headers, marker) {
|
|
48163
47936
|
if (!marker) return baseContext;
|
|
48164
47937
|
const rootSessionId = readHeader(headers, "x-session-id") ?? baseContext.clientSessionId;
|
|
@@ -48433,6 +48206,49 @@ function findJsonObjectEnd(text, start) {
|
|
|
48433
48206
|
return -1;
|
|
48434
48207
|
}
|
|
48435
48208
|
//#endregion
|
|
48209
|
+
//#region src/core/capi/request-context.ts
|
|
48210
|
+
function inferInitiator(turns) {
|
|
48211
|
+
return turns.some((turn) => turn.role === "assistant" || turn.role === "tool") ? "agent" : "user";
|
|
48212
|
+
}
|
|
48213
|
+
function readCapiRequestContext(headers) {
|
|
48214
|
+
return {
|
|
48215
|
+
interactionType: readHeader(headers, "x-interaction-type"),
|
|
48216
|
+
agentTaskId: readHeader(headers, "x-agent-task-id"),
|
|
48217
|
+
parentAgentTaskId: readHeader(headers, "x-parent-agent-id"),
|
|
48218
|
+
clientSessionId: readHeader(headers, "x-client-session-id") ?? readHeader(headers, "x-session-id"),
|
|
48219
|
+
interactionId: readHeader(headers, "x-interaction-id"),
|
|
48220
|
+
clientMachineId: readHeader(headers, "x-client-machine-id")
|
|
48221
|
+
};
|
|
48222
|
+
}
|
|
48223
|
+
function resolveInitiator(defaultInitiator, requestContext) {
|
|
48224
|
+
switch (requestContext?.interactionType) {
|
|
48225
|
+
case "conversation-agent":
|
|
48226
|
+
case "conversation-subagent":
|
|
48227
|
+
case "conversation-background": return "agent";
|
|
48228
|
+
case "conversation-user": return "user";
|
|
48229
|
+
default: return defaultInitiator;
|
|
48230
|
+
}
|
|
48231
|
+
}
|
|
48232
|
+
function buildCapiRequestContext(initiator, overrides = {}) {
|
|
48233
|
+
return {
|
|
48234
|
+
interactionType: overrides.interactionType ?? (initiator === "agent" ? "conversation-agent" : "conversation-user"),
|
|
48235
|
+
agentTaskId: overrides.agentTaskId,
|
|
48236
|
+
parentAgentTaskId: overrides.parentAgentTaskId,
|
|
48237
|
+
clientSessionId: overrides.clientSessionId,
|
|
48238
|
+
interactionId: overrides.interactionId ?? randomUUID(),
|
|
48239
|
+
clientMachineId: overrides.clientMachineId
|
|
48240
|
+
};
|
|
48241
|
+
}
|
|
48242
|
+
function normalizeAnthropicRequestContext(payload, headers) {
|
|
48243
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromAnthropicPayload(payload));
|
|
48244
|
+
}
|
|
48245
|
+
function normalizeChatRequestContext(payload, headers) {
|
|
48246
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromChatPayload(payload));
|
|
48247
|
+
}
|
|
48248
|
+
function normalizeResponsesRequestContext(payload, headers) {
|
|
48249
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromResponsesPayload(payload));
|
|
48250
|
+
}
|
|
48251
|
+
//#endregion
|
|
48436
48252
|
//#region src/core/capi/plan-builder.ts
|
|
48437
48253
|
const EPHEMERAL_CACHE_CONTROL = { type: "ephemeral" };
|
|
48438
48254
|
function asContentPart(block) {
|
|
@@ -48636,7 +48452,7 @@ function buildCapiExecutionPlan(request, options = {}) {
|
|
|
48636
48452
|
};
|
|
48637
48453
|
}
|
|
48638
48454
|
//#endregion
|
|
48639
|
-
//#region src/
|
|
48455
|
+
//#region src/ingest/validation/shared.ts
|
|
48640
48456
|
const jsonObjectSchema = object({}).catchall(unknown());
|
|
48641
48457
|
const finiteNumberSchema = number().finite();
|
|
48642
48458
|
const nonNegativeIntegerSchema = number().int().nonnegative();
|
|
@@ -48733,7 +48549,7 @@ function parsePayload(schema, context, payload) {
|
|
|
48733
48549
|
return result.data;
|
|
48734
48550
|
}
|
|
48735
48551
|
//#endregion
|
|
48736
|
-
//#region src/
|
|
48552
|
+
//#region src/ingest/validation/anthropic-messages.ts
|
|
48737
48553
|
const anthropicTextBlockSchema = object({
|
|
48738
48554
|
type: literal("text"),
|
|
48739
48555
|
text: string()
|
|
@@ -48923,7 +48739,7 @@ function parseAnthropicCountTokensPayload(payload) {
|
|
|
48923
48739
|
return parsePayload(anthropicCountTokensPayloadSchema, "anthropic.messages.count_tokens", payload);
|
|
48924
48740
|
}
|
|
48925
48741
|
//#endregion
|
|
48926
|
-
//#region src/
|
|
48742
|
+
//#region src/ingest/validation/embeddings.ts
|
|
48927
48743
|
const embeddingRequestSchema = object({
|
|
48928
48744
|
input: union([string(), array(string())]),
|
|
48929
48745
|
model: string().min(1),
|
|
@@ -48943,7 +48759,7 @@ const REASONING_EFFORT_VALUES = [
|
|
|
48943
48759
|
"high"
|
|
48944
48760
|
];
|
|
48945
48761
|
//#endregion
|
|
48946
|
-
//#region src/
|
|
48762
|
+
//#region src/ingest/validation/openai-chat.ts
|
|
48947
48763
|
const openAIPenaltySchema = finiteNumberSchema.min(-2).max(2);
|
|
48948
48764
|
const openAILogitBiasKeySchema = string().regex(/^\d+$/);
|
|
48949
48765
|
const openAILogitBiasValueSchema = finiteNumberSchema.min(-100).max(100);
|
|
@@ -49052,53 +48868,77 @@ const openAIChatPayloadSchema = object({
|
|
|
49052
48868
|
function parseOpenAIChatPayload(payload) {
|
|
49053
48869
|
return parsePayload(openAIChatPayloadSchema, "openai.chat", payload);
|
|
49054
48870
|
}
|
|
48871
|
+
//#endregion
|
|
48872
|
+
//#region src/ingest/validation/responses.ts
|
|
48873
|
+
const responsesInputTextSchema = object({
|
|
48874
|
+
type: _enum(["input_text", "output_text"]),
|
|
48875
|
+
text: string()
|
|
48876
|
+
}).loose();
|
|
48877
|
+
const responsesInputImageSchema = object({
|
|
48878
|
+
type: literal("input_image"),
|
|
48879
|
+
image_url: string().nullable().optional(),
|
|
48880
|
+
file_id: string().nullable().optional(),
|
|
48881
|
+
detail: _enum([
|
|
48882
|
+
"low",
|
|
48883
|
+
"high",
|
|
48884
|
+
"auto",
|
|
48885
|
+
"original"
|
|
48886
|
+
]).optional()
|
|
48887
|
+
}).loose().superRefine((item, ctx) => {
|
|
48888
|
+
if (!item.image_url && !item.file_id) ctx.addIssue({
|
|
48889
|
+
code: "custom",
|
|
48890
|
+
message: "input_image requires image_url or file_id"
|
|
48891
|
+
});
|
|
48892
|
+
});
|
|
48893
|
+
const responsesFunctionCallOutputImageSchema = object({
|
|
48894
|
+
type: literal("input_image"),
|
|
48895
|
+
image_url: string().nullable().optional(),
|
|
48896
|
+
file_id: string().nullable().optional(),
|
|
48897
|
+
detail: _enum([
|
|
48898
|
+
"low",
|
|
48899
|
+
"high",
|
|
48900
|
+
"auto",
|
|
48901
|
+
"original"
|
|
48902
|
+
]).optional()
|
|
48903
|
+
}).loose();
|
|
48904
|
+
const responsesInputFileSchema = object({
|
|
48905
|
+
type: literal("input_file"),
|
|
48906
|
+
file_id: string().nullable().optional(),
|
|
48907
|
+
file_url: string().nullable().optional(),
|
|
48908
|
+
file_data: string().nullable().optional(),
|
|
48909
|
+
filename: string().nullable().optional()
|
|
48910
|
+
}).loose().superRefine((item, ctx) => {
|
|
48911
|
+
if (!item.file_id && !item.file_url && !item.file_data) ctx.addIssue({
|
|
48912
|
+
code: "custom",
|
|
48913
|
+
message: "input_file requires file_id, file_url, or file_data"
|
|
48914
|
+
});
|
|
48915
|
+
if (item.file_data && !item.filename) ctx.addIssue({
|
|
48916
|
+
code: "custom",
|
|
48917
|
+
message: "input_file with file_data requires filename"
|
|
48918
|
+
});
|
|
48919
|
+
});
|
|
48920
|
+
const responsesUnknownContentSchema = object({ type: string().min(1) }).catchall(unknown()).superRefine((item, ctx) => {
|
|
48921
|
+
if ([
|
|
48922
|
+
"input_text",
|
|
48923
|
+
"output_text",
|
|
48924
|
+
"input_image",
|
|
48925
|
+
"input_file"
|
|
48926
|
+
].includes(item.type)) ctx.addIssue({
|
|
48927
|
+
code: "custom",
|
|
48928
|
+
message: `content item type ${item.type} must match the explicit schema`
|
|
48929
|
+
});
|
|
48930
|
+
});
|
|
49055
48931
|
const responsesInputContentSchema = union([
|
|
49056
|
-
|
|
49057
|
-
|
|
49058
|
-
|
|
49059
|
-
|
|
49060
|
-
|
|
49061
|
-
|
|
49062
|
-
|
|
49063
|
-
|
|
49064
|
-
|
|
49065
|
-
|
|
49066
|
-
"high",
|
|
49067
|
-
"auto"
|
|
49068
|
-
]).optional()
|
|
49069
|
-
}).loose().superRefine((item, ctx) => {
|
|
49070
|
-
if (!item.image_url && !item.file_id) ctx.addIssue({
|
|
49071
|
-
code: "custom",
|
|
49072
|
-
message: "input_image requires image_url or file_id"
|
|
49073
|
-
});
|
|
49074
|
-
}),
|
|
49075
|
-
object({
|
|
49076
|
-
type: literal("input_file"),
|
|
49077
|
-
file_id: string().nullable().optional(),
|
|
49078
|
-
file_url: string().nullable().optional(),
|
|
49079
|
-
file_data: string().nullable().optional(),
|
|
49080
|
-
filename: string().nullable().optional()
|
|
49081
|
-
}).loose().superRefine((item, ctx) => {
|
|
49082
|
-
if (!item.file_id && !item.file_url && !item.file_data) ctx.addIssue({
|
|
49083
|
-
code: "custom",
|
|
49084
|
-
message: "input_file requires file_id, file_url, or file_data"
|
|
49085
|
-
});
|
|
49086
|
-
if (item.file_data && !item.filename) ctx.addIssue({
|
|
49087
|
-
code: "custom",
|
|
49088
|
-
message: "input_file with file_data requires filename"
|
|
49089
|
-
});
|
|
49090
|
-
}),
|
|
49091
|
-
object({ type: string().min(1) }).catchall(unknown()).superRefine((item, ctx) => {
|
|
49092
|
-
if ([
|
|
49093
|
-
"input_text",
|
|
49094
|
-
"output_text",
|
|
49095
|
-
"input_image",
|
|
49096
|
-
"input_file"
|
|
49097
|
-
].includes(item.type)) ctx.addIssue({
|
|
49098
|
-
code: "custom",
|
|
49099
|
-
message: `content item type ${item.type} must match the explicit schema`
|
|
49100
|
-
});
|
|
49101
|
-
})
|
|
48932
|
+
responsesInputTextSchema,
|
|
48933
|
+
responsesInputImageSchema,
|
|
48934
|
+
responsesInputFileSchema,
|
|
48935
|
+
responsesUnknownContentSchema
|
|
48936
|
+
]);
|
|
48937
|
+
const responsesFunctionCallOutputContentSchema = union([
|
|
48938
|
+
responsesInputTextSchema,
|
|
48939
|
+
responsesFunctionCallOutputImageSchema,
|
|
48940
|
+
responsesInputFileSchema,
|
|
48941
|
+
responsesUnknownContentSchema
|
|
49102
48942
|
]);
|
|
49103
48943
|
const responsesMessageSchema = object({
|
|
49104
48944
|
type: literal("message").optional(),
|
|
@@ -49126,7 +48966,7 @@ const responsesFunctionCallSchema = object({
|
|
|
49126
48966
|
const responsesFunctionCallOutputSchema = object({
|
|
49127
48967
|
type: literal("function_call_output"),
|
|
49128
48968
|
call_id: string().min(1),
|
|
49129
|
-
output: union([string(), array(
|
|
48969
|
+
output: union([string(), array(responsesFunctionCallOutputContentSchema)]),
|
|
49130
48970
|
status: _enum([
|
|
49131
48971
|
"in_progress",
|
|
49132
48972
|
"completed",
|
|
@@ -49464,16 +49304,16 @@ function createUpstreamSignalFromConfig(clientSignal) {
|
|
|
49464
49304
|
//#endregion
|
|
49465
49305
|
//#region src/pipeline/runner.ts
|
|
49466
49306
|
async function runPipeline(params, config) {
|
|
49467
|
-
const
|
|
49468
|
-
|
|
49469
|
-
|
|
49307
|
+
const ingested = protocolRegistry.ingest(config.protocol, params.body, params.headers);
|
|
49308
|
+
const meta = ingested.meta;
|
|
49309
|
+
const payload = config.afterIngest ? config.afterIngest({
|
|
49310
|
+
payload: ingested.payload,
|
|
49470
49311
|
meta,
|
|
49471
49312
|
headers: params.headers
|
|
49472
|
-
});
|
|
49313
|
+
}) : ingested.payload;
|
|
49473
49314
|
const transformResult = config.transformChain.apply({
|
|
49474
49315
|
model: payload.model,
|
|
49475
49316
|
payload,
|
|
49476
|
-
headers: params.headers,
|
|
49477
49317
|
meta: { betaHeaders: meta.betaHeaders }
|
|
49478
49318
|
});
|
|
49479
49319
|
payload.model = transformResult.model;
|
|
@@ -49495,7 +49335,7 @@ async function runPipeline(params, config) {
|
|
|
49495
49335
|
});
|
|
49496
49336
|
const upstreamSignal = createUpstreamSignalFromConfig(params.signal);
|
|
49497
49337
|
const copilotClient = createCopilotClient();
|
|
49498
|
-
const
|
|
49338
|
+
const ctx = config.buildStrategyContext({
|
|
49499
49339
|
payload,
|
|
49500
49340
|
meta,
|
|
49501
49341
|
headers: params.headers,
|
|
@@ -49504,93 +49344,12 @@ async function runPipeline(params, config) {
|
|
|
49504
49344
|
upstreamSignal,
|
|
49505
49345
|
modelMapping
|
|
49506
49346
|
});
|
|
49507
|
-
if (config.contextRetry) return {
|
|
49508
|
-
result: await executeWithContextRetry(async (model) => {
|
|
49509
|
-
const isRetry = model !== payload.model;
|
|
49510
|
-
const currentMapping = isRetry ? {
|
|
49511
|
-
originalModel: modelMapping.originalModel,
|
|
49512
|
-
steps: [...modelMapping.steps]
|
|
49513
|
-
} : modelMapping;
|
|
49514
|
-
const effectivePayload = isRetry ? {
|
|
49515
|
-
...payload,
|
|
49516
|
-
model
|
|
49517
|
-
} : payload;
|
|
49518
|
-
const currentModel = isRetry ? modelCache.findById(model) ?? selectedModel : selectedModel;
|
|
49519
|
-
const ctx = config.buildStrategyContext({
|
|
49520
|
-
payload: effectivePayload,
|
|
49521
|
-
meta,
|
|
49522
|
-
headers: params.headers,
|
|
49523
|
-
selectedModel: currentModel,
|
|
49524
|
-
copilotClient,
|
|
49525
|
-
upstreamSignal: isRetry ? createUpstreamSignalFromConfig(params.signal) : upstreamSignal,
|
|
49526
|
-
modelMapping: currentMapping
|
|
49527
|
-
});
|
|
49528
|
-
const entryResult = await config.strategyRegistry.select(currentModel, ctx).execute(ctx);
|
|
49529
|
-
if (isRetry) modelMapping.steps = currentMapping.steps;
|
|
49530
|
-
return entryResult;
|
|
49531
|
-
}, {
|
|
49532
|
-
model: payload.model,
|
|
49533
|
-
trace: modelMapping.steps.map((s) => ({
|
|
49534
|
-
tag: s.tag,
|
|
49535
|
-
from: s.from,
|
|
49536
|
-
to: s.to
|
|
49537
|
-
}))
|
|
49538
|
-
}),
|
|
49539
|
-
modelMapping
|
|
49540
|
-
};
|
|
49541
|
-
const ctx = buildCtx();
|
|
49542
49347
|
return {
|
|
49543
49348
|
result: await config.strategyRegistry.select(selectedModel, ctx).execute(ctx),
|
|
49544
49349
|
modelMapping
|
|
49545
49350
|
};
|
|
49546
49351
|
}
|
|
49547
49352
|
//#endregion
|
|
49548
|
-
//#region src/transform/constants.ts
|
|
49549
|
-
const CONTEXT_BETA_RE = /^context-\d+[km]-/;
|
|
49550
|
-
//#endregion
|
|
49551
|
-
//#region src/transform/beta-headers.ts
|
|
49552
|
-
const COPILOT_UNSUPPORTED_BETA_RE = /^mid-conversation-system-\d{4}-\d{2}-\d{2}$/;
|
|
49553
|
-
function processAnthropicBetaHeader(rawHeader, model) {
|
|
49554
|
-
if (!rawHeader) return {
|
|
49555
|
-
header: void 0,
|
|
49556
|
-
upgradeTarget: void 0
|
|
49557
|
-
};
|
|
49558
|
-
const values = rawHeader.split(",").map((v) => v.trim()).filter(Boolean);
|
|
49559
|
-
let upgradeTarget;
|
|
49560
|
-
const filtered = [];
|
|
49561
|
-
for (const value of values) {
|
|
49562
|
-
if (CONTEXT_BETA_RE.test(value)) {
|
|
49563
|
-
if (!upgradeTarget && configStore.isContextUpgradeEnabled()) {
|
|
49564
|
-
const target = getContextUpgradeTarget(model);
|
|
49565
|
-
if (target) upgradeTarget = target;
|
|
49566
|
-
}
|
|
49567
|
-
continue;
|
|
49568
|
-
}
|
|
49569
|
-
if (COPILOT_UNSUPPORTED_BETA_RE.test(value)) continue;
|
|
49570
|
-
filtered.push(value);
|
|
49571
|
-
}
|
|
49572
|
-
return {
|
|
49573
|
-
header: filtered.length > 0 ? filtered.join(",") : void 0,
|
|
49574
|
-
upgradeTarget
|
|
49575
|
-
};
|
|
49576
|
-
}
|
|
49577
|
-
const betaHeaderStep = {
|
|
49578
|
-
tag: "BETA_UPGRADE",
|
|
49579
|
-
apply({ model, headers, resolvedModel }) {
|
|
49580
|
-
if (!headers) return null;
|
|
49581
|
-
const result = processAnthropicBetaHeader(headers.get("anthropic-beta"), model);
|
|
49582
|
-
if (!result.upgradeTarget) return null;
|
|
49583
|
-
return {
|
|
49584
|
-
model: result.upgradeTarget,
|
|
49585
|
-
tag: "BETA_UPGRADE",
|
|
49586
|
-
resolvedModel: modelCache.findById(result.upgradeTarget) ?? resolvedModel ?? modelCache.findById(model),
|
|
49587
|
-
mutatePayload(payload) {
|
|
49588
|
-
if (payload && typeof payload === "object" && "model" in payload) payload.model = result.upgradeTarget;
|
|
49589
|
-
}
|
|
49590
|
-
};
|
|
49591
|
-
}
|
|
49592
|
-
};
|
|
49593
|
-
//#endregion
|
|
49594
49353
|
//#region src/transform/chain.ts
|
|
49595
49354
|
function composeModelTransforms(...steps) {
|
|
49596
49355
|
return { apply(input) {
|
|
@@ -49626,18 +49385,10 @@ function composeModelTransforms(...steps) {
|
|
|
49626
49385
|
} };
|
|
49627
49386
|
}
|
|
49628
49387
|
//#endregion
|
|
49629
|
-
//#region src/
|
|
49630
|
-
|
|
49631
|
-
return model?.capabilities.supports.tool_calls ?? false;
|
|
49632
|
-
}
|
|
49633
|
-
function modelSupportsAdaptiveThinking(model) {
|
|
49634
|
-
return model?.capabilities.supports.adaptive_thinking ?? false;
|
|
49635
|
-
}
|
|
49636
|
-
function modelSupportsVision(model) {
|
|
49637
|
-
return model?.capabilities.supports.vision ?? false;
|
|
49638
|
-
}
|
|
49388
|
+
//#region src/transform/constants.ts
|
|
49389
|
+
const CONTEXT_BETA_RE = /^context-\d+[km]-/;
|
|
49639
49390
|
//#endregion
|
|
49640
|
-
//#region src/
|
|
49391
|
+
//#region src/transform/request-model-policy.ts
|
|
49641
49392
|
const COMPACT_SYSTEM_PROMPT_START = "You are a helpful AI assistant tasked with summarizing conversations";
|
|
49642
49393
|
function applyMessagesModelPolicy(payload, options) {
|
|
49643
49394
|
const originalModel = payload.model;
|
|
@@ -49645,17 +49396,6 @@ function applyMessagesModelPolicy(payload, options) {
|
|
|
49645
49396
|
originalModel,
|
|
49646
49397
|
routedModel: originalModel
|
|
49647
49398
|
};
|
|
49648
|
-
if (configStore.isContextUpgradeEnabled() && hasContextUpgradeRule(payload.model)) {
|
|
49649
|
-
const contextUpgradeTarget = resolveContextUpgrade(payload.model, estimateAnthropicInputTokens(payload));
|
|
49650
|
-
if (contextUpgradeTarget) {
|
|
49651
|
-
payload.model = contextUpgradeTarget;
|
|
49652
|
-
return {
|
|
49653
|
-
originalModel,
|
|
49654
|
-
routedModel: contextUpgradeTarget,
|
|
49655
|
-
reason: "context-upgrade"
|
|
49656
|
-
};
|
|
49657
|
-
}
|
|
49658
|
-
}
|
|
49659
49399
|
const smallModel = configStore.getSmallModel();
|
|
49660
49400
|
if (!smallModel || !configStore.isCompactSmallModelEnabled() || !isCompactRequest(payload)) return {
|
|
49661
49401
|
originalModel,
|
|
@@ -49684,9 +49424,9 @@ function canRouteToSmallModel(payload, originalModel, smallModel) {
|
|
|
49684
49424
|
const originalEndpoints = new Set(originalModel.supported_endpoints ?? []);
|
|
49685
49425
|
const smallEndpoints = new Set(smallModel.supported_endpoints ?? []);
|
|
49686
49426
|
for (const endpoint of originalEndpoints) if (!smallEndpoints.has(endpoint)) return false;
|
|
49687
|
-
if (payload.tools?.length && !
|
|
49688
|
-
if (payload.thinking && !
|
|
49689
|
-
if (hasVisionInput$1(payload) && !
|
|
49427
|
+
if (payload.tools?.length && !(smallModel.capabilities.supports.tool_calls ?? false)) return false;
|
|
49428
|
+
if (payload.thinking && !(smallModel.capabilities.supports.adaptive_thinking ?? false)) return false;
|
|
49429
|
+
if (hasVisionInput$1(payload) && !(smallModel.capabilities.supports.vision ?? false)) return false;
|
|
49690
49430
|
return true;
|
|
49691
49431
|
}
|
|
49692
49432
|
function hasVisionInput$1(payload) {
|
|
@@ -49700,17 +49440,72 @@ function containsVisionContent$1(content) {
|
|
|
49700
49440
|
//#region src/transform/policy.ts
|
|
49701
49441
|
const modelPolicyStep = {
|
|
49702
49442
|
tag: "POLICY",
|
|
49703
|
-
apply({
|
|
49443
|
+
apply({ payload, meta }) {
|
|
49704
49444
|
const routing = applyMessagesModelPolicy(payload, { betaUpgraded: meta?.betaHeaders?.some((b) => CONTEXT_BETA_RE.test(b)) ?? false });
|
|
49705
49445
|
if (!routing.reason) return null;
|
|
49706
49446
|
return {
|
|
49707
49447
|
model: routing.routedModel,
|
|
49708
|
-
tag:
|
|
49709
|
-
resolvedModel: routing.reason === "context-upgrade" ? modelCache.findById(routing.routedModel) ?? resolvedModel ?? modelCache.findById(model) : void 0
|
|
49448
|
+
tag: "COMPACT"
|
|
49710
49449
|
};
|
|
49711
49450
|
}
|
|
49712
49451
|
};
|
|
49713
49452
|
//#endregion
|
|
49453
|
+
//#region src/transform/model-rewrite.ts
|
|
49454
|
+
/**
|
|
49455
|
+
* Unified model rewrite: user rules → built-in normalization → pass-through.
|
|
49456
|
+
* Call once at handler entry, before any model lookup or policy.
|
|
49457
|
+
*/
|
|
49458
|
+
function rewriteModel(modelId) {
|
|
49459
|
+
const userRules = configStore.getModelRewrites();
|
|
49460
|
+
if (userRules.length > 0) {
|
|
49461
|
+
for (const rule of userRules) if (matchesGlob(rule.from, modelId)) return {
|
|
49462
|
+
originalModel: modelId,
|
|
49463
|
+
model: normalizeToKnownModel(rule.to) ?? rule.to,
|
|
49464
|
+
reason: "CONFIG_REWRITE"
|
|
49465
|
+
};
|
|
49466
|
+
}
|
|
49467
|
+
const normalized = normalizeToKnownModel(modelId);
|
|
49468
|
+
if (normalized && normalized !== modelId) return {
|
|
49469
|
+
originalModel: modelId,
|
|
49470
|
+
model: normalized,
|
|
49471
|
+
reason: "AUTO_CORRECT"
|
|
49472
|
+
};
|
|
49473
|
+
return {
|
|
49474
|
+
originalModel: modelId,
|
|
49475
|
+
model: modelId
|
|
49476
|
+
};
|
|
49477
|
+
}
|
|
49478
|
+
/**
|
|
49479
|
+
* Apply model rewrite to a mutable model field and log if changed.
|
|
49480
|
+
* Returns the rewrite result for downstream use.
|
|
49481
|
+
*/
|
|
49482
|
+
function applyModelRewrite(payload) {
|
|
49483
|
+
const result = rewriteModel(payload.model);
|
|
49484
|
+
if (result.model !== result.originalModel) {
|
|
49485
|
+
consola.debug(`Model rewritten: ${result.originalModel} ~> ${result.model}`);
|
|
49486
|
+
payload.model = result.model;
|
|
49487
|
+
}
|
|
49488
|
+
return result;
|
|
49489
|
+
}
|
|
49490
|
+
const DOT_RE = /\./g;
|
|
49491
|
+
/**
|
|
49492
|
+
* Resolve a model ID against Copilot's cached model list using
|
|
49493
|
+
* dash/dot equivalence. Returns the canonical ID if found.
|
|
49494
|
+
*/
|
|
49495
|
+
function normalizeToKnownModel(modelId) {
|
|
49496
|
+
const models = modelCache.getModels()?.data;
|
|
49497
|
+
if (!models) return void 0;
|
|
49498
|
+
if (models.some((m) => m.id === modelId)) return modelId;
|
|
49499
|
+
const normalized = modelId.replace(DOT_RE, "-");
|
|
49500
|
+
for (const model of models) if (model.id.replace(DOT_RE, "-") === normalized) return model.id;
|
|
49501
|
+
}
|
|
49502
|
+
const GLOB_SPECIAL_RE = /[.+^${}()|[\]\\]/g;
|
|
49503
|
+
const GLOB_STAR_RE = /\*/g;
|
|
49504
|
+
function matchesGlob(pattern, value) {
|
|
49505
|
+
if (!pattern.includes("*")) return pattern === value;
|
|
49506
|
+
return new RegExp(`^${pattern.replace(GLOB_SPECIAL_RE, "\\$&").replace(GLOB_STAR_RE, ".*")}$`).test(value);
|
|
49507
|
+
}
|
|
49508
|
+
//#endregion
|
|
49714
49509
|
//#region src/transform/rewrite.ts
|
|
49715
49510
|
const rewriteStep = {
|
|
49716
49511
|
tag: "rewrite",
|
|
@@ -49735,6 +49530,20 @@ const rewriteStep = {
|
|
|
49735
49530
|
}
|
|
49736
49531
|
};
|
|
49737
49532
|
//#endregion
|
|
49533
|
+
//#region src/transform/beta-headers.ts
|
|
49534
|
+
const COPILOT_UNSUPPORTED_BETA_RE = /^mid-conversation-system-\d{4}-\d{2}-\d{2}$/;
|
|
49535
|
+
function processAnthropicBetaHeader(rawHeader) {
|
|
49536
|
+
if (!rawHeader) return void 0;
|
|
49537
|
+
const values = rawHeader.split(",").map((v) => v.trim()).filter(Boolean);
|
|
49538
|
+
const filtered = [];
|
|
49539
|
+
for (const value of values) {
|
|
49540
|
+
if (CONTEXT_BETA_RE.test(value)) continue;
|
|
49541
|
+
if (COPILOT_UNSUPPORTED_BETA_RE.test(value)) continue;
|
|
49542
|
+
filtered.push(value);
|
|
49543
|
+
}
|
|
49544
|
+
return filtered.length > 0 ? filtered.join(",") : void 0;
|
|
49545
|
+
}
|
|
49546
|
+
//#endregion
|
|
49738
49547
|
//#region src/translator/responses/signature-codec.ts
|
|
49739
49548
|
const COMPACTION_PREFIX = "cm1#";
|
|
49740
49549
|
const SEPARATOR = "@";
|
|
@@ -49797,8 +49606,8 @@ const OUTPUT_CONFIG_EFFORT_RANK = new Map([
|
|
|
49797
49606
|
"low",
|
|
49798
49607
|
"medium",
|
|
49799
49608
|
"high",
|
|
49800
|
-
"
|
|
49801
|
-
"
|
|
49609
|
+
"xhigh",
|
|
49610
|
+
"max"
|
|
49802
49611
|
].map((effort, index) => [effort, index]));
|
|
49803
49612
|
function isOutputConfigEffort(value) {
|
|
49804
49613
|
return OUTPUT_CONFIG_EFFORT_RANK.has(value);
|
|
@@ -49841,7 +49650,7 @@ function sanitizeCacheControl(payload) {
|
|
|
49841
49650
|
}
|
|
49842
49651
|
//#endregion
|
|
49843
49652
|
//#region src/transform/index.ts
|
|
49844
|
-
const messagesModelChain = composeModelTransforms(rewriteStep,
|
|
49653
|
+
const messagesModelChain = composeModelTransforms(rewriteStep, modelPolicyStep);
|
|
49845
49654
|
const chatCompletionsModelChain = composeModelTransforms(rewriteStep);
|
|
49846
49655
|
const responsesModelChain = composeModelTransforms(rewriteStep);
|
|
49847
49656
|
//#endregion
|
|
@@ -49881,9 +49690,6 @@ function normalizeSystemBlocks(system) {
|
|
|
49881
49690
|
blocks: system.map((block) => textBlock(block.text))
|
|
49882
49691
|
}];
|
|
49883
49692
|
}
|
|
49884
|
-
function normalizeToolResultContent(block) {
|
|
49885
|
-
return normalizeToolResultContentValue(block.content);
|
|
49886
|
-
}
|
|
49887
49693
|
function normalizeToolResultContentValue(content) {
|
|
49888
49694
|
if (typeof content === "string") return [textBlock(content)];
|
|
49889
49695
|
return content.map((contentBlock) => {
|
|
@@ -49895,9 +49701,6 @@ function normalizeToolResultContentValue(content) {
|
|
|
49895
49701
|
}
|
|
49896
49702
|
});
|
|
49897
49703
|
}
|
|
49898
|
-
function normalizeMcpToolResultContent(block) {
|
|
49899
|
-
return normalizeToolResultContentValue(block.content);
|
|
49900
|
-
}
|
|
49901
49704
|
function normalizeServerToolResultContent(block) {
|
|
49902
49705
|
return [textBlock(typeof block.content === "string" ? block.content : JSON.stringify(block.content) ?? "")];
|
|
49903
49706
|
}
|
|
@@ -49937,13 +49740,13 @@ function normalizeMessage(message) {
|
|
|
49937
49740
|
case "tool_result": return {
|
|
49938
49741
|
kind: "tool_result",
|
|
49939
49742
|
toolUseId: block.tool_use_id,
|
|
49940
|
-
content:
|
|
49743
|
+
content: normalizeToolResultContentValue(block.content),
|
|
49941
49744
|
isError: block.is_error
|
|
49942
49745
|
};
|
|
49943
49746
|
case "mcp_tool_result": return {
|
|
49944
49747
|
kind: "tool_result",
|
|
49945
49748
|
toolUseId: block.tool_use_id,
|
|
49946
|
-
content:
|
|
49749
|
+
content: normalizeToolResultContentValue(block.content),
|
|
49947
49750
|
isError: block.is_error
|
|
49948
49751
|
};
|
|
49949
49752
|
case "server_tool_result":
|
|
@@ -50169,10 +49972,6 @@ var AnthropicStreamTranslator = class {
|
|
|
50169
49972
|
for (const delta of deltas) switch (delta.kind) {
|
|
50170
49973
|
case "message_start": break;
|
|
50171
49974
|
case "thinking_delta":
|
|
50172
|
-
this.state.lastMetadata = {
|
|
50173
|
-
...this.state.lastMetadata,
|
|
50174
|
-
...delta.metadata
|
|
50175
|
-
};
|
|
50176
49975
|
this.textWriter.close(events);
|
|
50177
49976
|
this.thinkingWriter.append(events, delta.text);
|
|
50178
49977
|
break;
|
|
@@ -50193,10 +49992,6 @@ var AnthropicStreamTranslator = class {
|
|
|
50193
49992
|
});
|
|
50194
49993
|
break;
|
|
50195
49994
|
case "message_stop":
|
|
50196
|
-
this.state.lastMetadata = {
|
|
50197
|
-
...this.state.lastMetadata,
|
|
50198
|
-
...delta.metadata
|
|
50199
|
-
};
|
|
50200
49995
|
this.state.pendingStopReason = delta.stopReason;
|
|
50201
49996
|
this.closeAllBlocks(events);
|
|
50202
49997
|
break;
|
|
@@ -50273,13 +50068,7 @@ var AnthropicStreamTranslator = class {
|
|
|
50273
50068
|
});
|
|
50274
50069
|
if (choice.delta.reasoning_text) deltas.push({
|
|
50275
50070
|
kind: "thinking_delta",
|
|
50276
|
-
text: choice.delta.reasoning_text
|
|
50277
|
-
metadata: {
|
|
50278
|
-
reasoningOpaque: choice.delta.reasoning_opaque,
|
|
50279
|
-
encryptedContent: choice.delta.encrypted_content,
|
|
50280
|
-
phase: choice.delta.phase,
|
|
50281
|
-
copilotAnnotations: choice.delta.copilot_annotations
|
|
50282
|
-
}
|
|
50071
|
+
text: choice.delta.reasoning_text
|
|
50283
50072
|
});
|
|
50284
50073
|
if (choice.delta.content) deltas.push({
|
|
50285
50074
|
kind: "text_delta",
|
|
@@ -50295,13 +50084,7 @@ var AnthropicStreamTranslator = class {
|
|
|
50295
50084
|
if (choice.finish_reason) deltas.push({
|
|
50296
50085
|
kind: "message_stop",
|
|
50297
50086
|
stopReason: choice.finish_reason,
|
|
50298
|
-
usage: chunk.usage
|
|
50299
|
-
metadata: {
|
|
50300
|
-
reasoningOpaque: choice.delta.reasoning_opaque,
|
|
50301
|
-
encryptedContent: choice.delta.encrypted_content,
|
|
50302
|
-
phase: choice.delta.phase,
|
|
50303
|
-
copilotAnnotations: choice.delta.copilot_annotations
|
|
50304
|
-
}
|
|
50087
|
+
usage: chunk.usage
|
|
50305
50088
|
});
|
|
50306
50089
|
return deltas;
|
|
50307
50090
|
}
|
|
@@ -50417,13 +50200,7 @@ function normalizeAssistantTurn(message) {
|
|
|
50417
50200
|
}] : [],
|
|
50418
50201
|
...contentBlocks,
|
|
50419
50202
|
...toolBlocks
|
|
50420
|
-
]
|
|
50421
|
-
meta: {
|
|
50422
|
-
reasoningOpaque: message.reasoning_opaque,
|
|
50423
|
-
encryptedContent: message.encrypted_content,
|
|
50424
|
-
phase: message.phase,
|
|
50425
|
-
copilotAnnotations: message.copilot_annotations
|
|
50426
|
-
}
|
|
50203
|
+
]
|
|
50427
50204
|
};
|
|
50428
50205
|
}
|
|
50429
50206
|
function normalizeOpenAIResponse(response, context) {
|
|
@@ -50597,7 +50374,7 @@ var AnthropicMessagesAdapter = class {
|
|
|
50597
50374
|
constructor(options = {}) {
|
|
50598
50375
|
this.options = {
|
|
50599
50376
|
modelResolver: options.modelResolver ?? ((model) => model),
|
|
50600
|
-
getModelCapabilities: options.getModelCapabilities ?? ((model) => ({ supportsThinkingBudget: model
|
|
50377
|
+
getModelCapabilities: options.getModelCapabilities ?? ((model) => ({ supportsThinkingBudget: inferModelFamily(model) === "claude" })),
|
|
50601
50378
|
policy: options.policy ?? defaultTranslationPolicy
|
|
50602
50379
|
};
|
|
50603
50380
|
}
|
|
@@ -50633,21 +50410,6 @@ var AnthropicMessagesAdapter = class {
|
|
|
50633
50410
|
}
|
|
50634
50411
|
};
|
|
50635
50412
|
//#endregion
|
|
50636
|
-
//#region src/adapters/copilot-transport.ts
|
|
50637
|
-
var CopilotTransport = class {
|
|
50638
|
-
client;
|
|
50639
|
-
constructor(client) {
|
|
50640
|
-
this.client = client;
|
|
50641
|
-
}
|
|
50642
|
-
execute(plan, options) {
|
|
50643
|
-
return this.client.createChatCompletions(plan.payload, {
|
|
50644
|
-
signal: options?.signal,
|
|
50645
|
-
initiator: plan.initiator,
|
|
50646
|
-
requestContext: plan.requestContext
|
|
50647
|
-
});
|
|
50648
|
-
}
|
|
50649
|
-
};
|
|
50650
|
-
//#endregion
|
|
50651
50413
|
//#region src/adapters/openai-chat-adapter.ts
|
|
50652
50414
|
function toConversationBlocks(content) {
|
|
50653
50415
|
if (content === null) return [];
|
|
@@ -50796,280 +50558,6 @@ var OpenAIChatAdapter = class {
|
|
|
50796
50558
|
}
|
|
50797
50559
|
};
|
|
50798
50560
|
//#endregion
|
|
50799
|
-
//#region src/routes/responses/emulator.ts
|
|
50800
|
-
function cloneValue(value) {
|
|
50801
|
-
if (typeof globalThis.structuredClone === "function") return globalThis.structuredClone(value);
|
|
50802
|
-
return JSON.parse(JSON.stringify(value));
|
|
50803
|
-
}
|
|
50804
|
-
function rejectUnsupportedBackground(payload) {
|
|
50805
|
-
if (payload.background) throwInvalidRequestError("background mode is not supported by the responses official emulator.", "background", "unsupported_background_mode");
|
|
50806
|
-
}
|
|
50807
|
-
function prepareEmulatorRequest(payload) {
|
|
50808
|
-
rejectUnsupportedBackground(payload);
|
|
50809
|
-
const normalizedCurrentInput = normalizeResponsesInput(payload.input);
|
|
50810
|
-
const { continuationSourceResponseId, conversation: resolvedConversation, previousResponse } = resolveContinuation(payload);
|
|
50811
|
-
const conversation = resolvedConversation ?? createConversationRef();
|
|
50812
|
-
const effectiveInputItems = [...continuationSourceResponseId ? buildContinuationHistory(continuationSourceResponseId) : [], ...normalizedCurrentInput];
|
|
50813
|
-
const shouldStore = payload.store ?? true;
|
|
50814
|
-
return {
|
|
50815
|
-
upstreamPayload: {
|
|
50816
|
-
...payload,
|
|
50817
|
-
background: void 0,
|
|
50818
|
-
conversation: void 0,
|
|
50819
|
-
previous_response_id: void 0,
|
|
50820
|
-
store: void 0,
|
|
50821
|
-
input: effectiveInputItems
|
|
50822
|
-
},
|
|
50823
|
-
effectiveInputItems,
|
|
50824
|
-
previousResponseId: previousResponse?.id,
|
|
50825
|
-
conversation,
|
|
50826
|
-
shouldStore
|
|
50827
|
-
};
|
|
50828
|
-
}
|
|
50829
|
-
function decorateStoredResponse(upstreamResponse, requestPayload, prepared) {
|
|
50830
|
-
return {
|
|
50831
|
-
...cloneValue(upstreamResponse),
|
|
50832
|
-
previous_response_id: prepared.previousResponseId ?? null,
|
|
50833
|
-
conversation: prepared.conversation,
|
|
50834
|
-
truncation: requestPayload.truncation ?? null,
|
|
50835
|
-
store: prepared.shouldStore,
|
|
50836
|
-
user: normalizeNullableString(requestPayload.user),
|
|
50837
|
-
service_tier: normalizeServiceTier(requestPayload.service_tier)
|
|
50838
|
-
};
|
|
50839
|
-
}
|
|
50840
|
-
function persistEmulatorResponse(response, effectiveInputItems) {
|
|
50841
|
-
responsesEmulatorState.setResponse(response);
|
|
50842
|
-
if (response.conversation) {
|
|
50843
|
-
responsesEmulatorState.setConversation(response.conversation);
|
|
50844
|
-
responsesEmulatorState.setConversationHead(getConversationId(response.conversation), response.id);
|
|
50845
|
-
}
|
|
50846
|
-
responsesEmulatorState.setInputItems(response.id, effectiveInputItems);
|
|
50847
|
-
}
|
|
50848
|
-
function getStoredResponseOrThrow(responseId) {
|
|
50849
|
-
const response = responsesEmulatorState.getResponse(responseId);
|
|
50850
|
-
if (!response) throw new HTTPError(404, { error: {
|
|
50851
|
-
message: `No response found with id '${responseId}'.`,
|
|
50852
|
-
type: "invalid_request_error"
|
|
50853
|
-
} });
|
|
50854
|
-
return response;
|
|
50855
|
-
}
|
|
50856
|
-
function listStoredInputItemsOrThrow(responseId, params) {
|
|
50857
|
-
const items = responsesEmulatorState.getInputItems(responseId);
|
|
50858
|
-
if (!items) throw new HTTPError(404, { error: {
|
|
50859
|
-
message: `No response input items found for id '${responseId}'.`,
|
|
50860
|
-
type: "invalid_request_error"
|
|
50861
|
-
} });
|
|
50862
|
-
let orderedItems = cloneValue(items);
|
|
50863
|
-
if (params?.order === "desc") orderedItems.reverse();
|
|
50864
|
-
if (params?.after) {
|
|
50865
|
-
const afterIndex = orderedItems.findIndex((item) => getInputItemId(item) === params.after);
|
|
50866
|
-
if (afterIndex >= 0) orderedItems = orderedItems.slice(afterIndex + 1);
|
|
50867
|
-
}
|
|
50868
|
-
const limitedItems = orderedItems.slice(0, params?.limit ?? orderedItems.length);
|
|
50869
|
-
return {
|
|
50870
|
-
object: "list",
|
|
50871
|
-
data: limitedItems,
|
|
50872
|
-
first_id: getInputItemId(limitedItems[0]) ?? null,
|
|
50873
|
-
last_id: getInputItemId(limitedItems.at(-1)) ?? null,
|
|
50874
|
-
has_more: limitedItems.length < orderedItems.length
|
|
50875
|
-
};
|
|
50876
|
-
}
|
|
50877
|
-
function deleteStoredResponseOrThrow(responseId) {
|
|
50878
|
-
getStoredResponseOrThrow(responseId);
|
|
50879
|
-
return responsesEmulatorState.deleteResponse(responseId);
|
|
50880
|
-
}
|
|
50881
|
-
async function estimateEmulatorInputTokens(payload, selectedModel) {
|
|
50882
|
-
return {
|
|
50883
|
-
object: "response.input_tokens",
|
|
50884
|
-
input_tokens: await estimateResponsesInputTokens(resolveEffectiveInputForInputTokens(payload), selectedModel)
|
|
50885
|
-
};
|
|
50886
|
-
}
|
|
50887
|
-
function resolveEffectiveInputForInputTokens(payload) {
|
|
50888
|
-
const normalizedInput = normalizeResponsesInput(payload.input);
|
|
50889
|
-
const background = payload.background === null || typeof payload.background === "boolean" ? payload.background : void 0;
|
|
50890
|
-
const conversation = isConversationReference(payload.conversation) ? payload.conversation : void 0;
|
|
50891
|
-
const previousResponseId = typeof payload.previous_response_id === "string" ? payload.previous_response_id : void 0;
|
|
50892
|
-
rejectUnsupportedBackground({ background });
|
|
50893
|
-
const { continuationSourceResponseId } = resolveContinuation({
|
|
50894
|
-
conversation,
|
|
50895
|
-
previous_response_id: previousResponseId
|
|
50896
|
-
});
|
|
50897
|
-
if (continuationSourceResponseId) return [...buildContinuationHistory(continuationSourceResponseId), ...normalizedInput];
|
|
50898
|
-
return normalizedInput;
|
|
50899
|
-
}
|
|
50900
|
-
function resolveContinuation(payload) {
|
|
50901
|
-
const previousResponse = resolvePreviousResponse(payload.previous_response_id);
|
|
50902
|
-
const conversation = resolveConversation(payload.conversation, previousResponse);
|
|
50903
|
-
return {
|
|
50904
|
-
previousResponse,
|
|
50905
|
-
conversation,
|
|
50906
|
-
continuationSourceResponseId: resolveContinuationSourceResponseId(previousResponse, conversation)
|
|
50907
|
-
};
|
|
50908
|
-
}
|
|
50909
|
-
function resolvePreviousResponse(previousResponseId) {
|
|
50910
|
-
if (typeof previousResponseId !== "string" || previousResponseId.length === 0) return;
|
|
50911
|
-
const previousResponse = responsesEmulatorState.getResponse(previousResponseId);
|
|
50912
|
-
if (!previousResponse) throwInvalidRequestError("The selected previous_response_id could not be resolved.", "previous_response_id");
|
|
50913
|
-
return previousResponse;
|
|
50914
|
-
}
|
|
50915
|
-
function resolveConversation(conversation, previousResponse) {
|
|
50916
|
-
if (isConversationReference(conversation)) {
|
|
50917
|
-
const conversationId = getConversationId(conversation);
|
|
50918
|
-
const existingConversation = responsesEmulatorState.getConversation(conversationId);
|
|
50919
|
-
if (!existingConversation) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
50920
|
-
if (previousResponse?.conversation && getConversationId(previousResponse.conversation) !== conversationId) throwInvalidRequestError("The selected previous_response_id does not belong to the selected conversation.", "previous_response_id");
|
|
50921
|
-
return existingConversation;
|
|
50922
|
-
}
|
|
50923
|
-
return previousResponse?.conversation ?? void 0;
|
|
50924
|
-
}
|
|
50925
|
-
function resolveContinuationSourceResponseId(previousResponse, conversation) {
|
|
50926
|
-
if (previousResponse) return previousResponse.id;
|
|
50927
|
-
if (!conversation) return;
|
|
50928
|
-
const head = responsesEmulatorState.getConversationHead(getConversationId(conversation));
|
|
50929
|
-
if (!head) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
50930
|
-
return head;
|
|
50931
|
-
}
|
|
50932
|
-
function buildContinuationHistory(responseId) {
|
|
50933
|
-
const previousResponse = getStoredResponseOrThrow(responseId);
|
|
50934
|
-
const previousInput = responsesEmulatorState.getInputItems(responseId);
|
|
50935
|
-
if (!previousInput) throwInvalidRequestError("The selected previous_response_id is missing stored input items.", "previous_response_id");
|
|
50936
|
-
return [...cloneValue(previousInput), ...convertOutputItemsToInputItems(previousResponse.output)];
|
|
50937
|
-
}
|
|
50938
|
-
function normalizeResponsesInput(input) {
|
|
50939
|
-
if (!input) return [];
|
|
50940
|
-
if (typeof input === "string") return [{
|
|
50941
|
-
type: "message",
|
|
50942
|
-
role: "user",
|
|
50943
|
-
content: input
|
|
50944
|
-
}];
|
|
50945
|
-
if (Array.isArray(input)) return cloneValue(input);
|
|
50946
|
-
return [];
|
|
50947
|
-
}
|
|
50948
|
-
function convertOutputItemsToInputItems(output) {
|
|
50949
|
-
const items = [];
|
|
50950
|
-
for (const item of output) switch (item.type) {
|
|
50951
|
-
case "message":
|
|
50952
|
-
items.push(convertMessageOutputToInput(item));
|
|
50953
|
-
break;
|
|
50954
|
-
case "function_call":
|
|
50955
|
-
items.push(convertFunctionCallOutputToInput(item));
|
|
50956
|
-
break;
|
|
50957
|
-
case "reasoning": {
|
|
50958
|
-
const reasoningInput = convertReasoningOutputToInput(item);
|
|
50959
|
-
if (reasoningInput) items.push(reasoningInput);
|
|
50960
|
-
break;
|
|
50961
|
-
}
|
|
50962
|
-
case "compaction":
|
|
50963
|
-
items.push(convertCompactionOutputToInput(item));
|
|
50964
|
-
break;
|
|
50965
|
-
}
|
|
50966
|
-
return items;
|
|
50967
|
-
}
|
|
50968
|
-
function convertMessageOutputToInput(item) {
|
|
50969
|
-
return {
|
|
50970
|
-
type: "message",
|
|
50971
|
-
role: item.role,
|
|
50972
|
-
status: item.status,
|
|
50973
|
-
content: item.content?.map((content) => {
|
|
50974
|
-
if (content.type === "output_text" && typeof content.text === "string") return {
|
|
50975
|
-
type: "output_text",
|
|
50976
|
-
text: content.text
|
|
50977
|
-
};
|
|
50978
|
-
return cloneValue(content);
|
|
50979
|
-
}) ?? []
|
|
50980
|
-
};
|
|
50981
|
-
}
|
|
50982
|
-
function convertFunctionCallOutputToInput(item) {
|
|
50983
|
-
return {
|
|
50984
|
-
type: "function_call",
|
|
50985
|
-
call_id: item.call_id,
|
|
50986
|
-
name: item.name,
|
|
50987
|
-
arguments: item.arguments,
|
|
50988
|
-
status: item.status
|
|
50989
|
-
};
|
|
50990
|
-
}
|
|
50991
|
-
function convertReasoningOutputToInput(item) {
|
|
50992
|
-
if (!item.encrypted_content) return;
|
|
50993
|
-
return {
|
|
50994
|
-
id: item.id,
|
|
50995
|
-
type: "reasoning",
|
|
50996
|
-
summary: (item.summary ?? []).filter((summary) => typeof summary.text === "string").map((summary) => ({
|
|
50997
|
-
type: "summary_text",
|
|
50998
|
-
text: summary.text
|
|
50999
|
-
})),
|
|
51000
|
-
encrypted_content: item.encrypted_content
|
|
51001
|
-
};
|
|
51002
|
-
}
|
|
51003
|
-
function convertCompactionOutputToInput(item) {
|
|
51004
|
-
return {
|
|
51005
|
-
id: item.id,
|
|
51006
|
-
type: "compaction",
|
|
51007
|
-
encrypted_content: item.encrypted_content
|
|
51008
|
-
};
|
|
51009
|
-
}
|
|
51010
|
-
function normalizeNullableString(value) {
|
|
51011
|
-
return typeof value === "string" ? value : null;
|
|
51012
|
-
}
|
|
51013
|
-
function normalizeServiceTier(value) {
|
|
51014
|
-
if (value === "auto" || value === "default" || value === "flex" || value === "scale" || value === "priority") return value;
|
|
51015
|
-
return null;
|
|
51016
|
-
}
|
|
51017
|
-
function createConversationRef() {
|
|
51018
|
-
return { id: `conv_${randomUUID().replaceAll("-", "")}` };
|
|
51019
|
-
}
|
|
51020
|
-
function isConversationReference(value) {
|
|
51021
|
-
if (typeof value === "string") return value.length > 0;
|
|
51022
|
-
return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && value.id.length > 0;
|
|
51023
|
-
}
|
|
51024
|
-
function getConversationId(conversation) {
|
|
51025
|
-
return typeof conversation === "string" ? conversation : conversation.id;
|
|
51026
|
-
}
|
|
51027
|
-
function getInputItemId(item) {
|
|
51028
|
-
if (!item || typeof item !== "object") return;
|
|
51029
|
-
if ("id" in item && typeof item.id === "string") return item.id;
|
|
51030
|
-
if ("call_id" in item && typeof item.call_id === "string") return item.call_id;
|
|
51031
|
-
}
|
|
51032
|
-
//#endregion
|
|
51033
|
-
//#region src/dispatch/resource-dispatcher.ts
|
|
51034
|
-
var EmulatorResourceDispatcher = class {
|
|
51035
|
-
retrieve(responseId) {
|
|
51036
|
-
return Promise.resolve(getStoredResponseOrThrow(responseId));
|
|
51037
|
-
}
|
|
51038
|
-
listInputItems(responseId, params) {
|
|
51039
|
-
return Promise.resolve(listStoredInputItemsOrThrow(responseId, params));
|
|
51040
|
-
}
|
|
51041
|
-
async createInputTokens(payload) {
|
|
51042
|
-
return estimateEmulatorInputTokens(payload, resolveModelOrThrow(payload.model ?? ""));
|
|
51043
|
-
}
|
|
51044
|
-
delete(responseId) {
|
|
51045
|
-
return Promise.resolve(deleteStoredResponseOrThrow(responseId));
|
|
51046
|
-
}
|
|
51047
|
-
};
|
|
51048
|
-
var UpstreamResourceDispatcher = class {
|
|
51049
|
-
client;
|
|
51050
|
-
constructor(client) {
|
|
51051
|
-
this.client = client;
|
|
51052
|
-
}
|
|
51053
|
-
retrieve(responseId, params, options) {
|
|
51054
|
-
return this.client.getResponse(responseId, {
|
|
51055
|
-
params,
|
|
51056
|
-
...options
|
|
51057
|
-
});
|
|
51058
|
-
}
|
|
51059
|
-
listInputItems(responseId, params, options) {
|
|
51060
|
-
return this.client.getResponseInputItems(responseId, params, options);
|
|
51061
|
-
}
|
|
51062
|
-
createInputTokens(payload, options) {
|
|
51063
|
-
return this.client.createResponseInputTokens(payload, options);
|
|
51064
|
-
}
|
|
51065
|
-
delete(responseId, options) {
|
|
51066
|
-
return this.client.deleteResponse(responseId, options);
|
|
51067
|
-
}
|
|
51068
|
-
};
|
|
51069
|
-
function createResourceDispatcher() {
|
|
51070
|
-
return configStore.isEmulatorEnabled() ? new EmulatorResourceDispatcher() : new UpstreamResourceDispatcher(createCopilotClient());
|
|
51071
|
-
}
|
|
51072
|
-
//#endregion
|
|
51073
50561
|
//#region src/dispatch/strategy-registry.ts
|
|
51074
50562
|
var StrategyRegistry = class {
|
|
51075
50563
|
entries = [];
|
|
@@ -51141,19 +50629,21 @@ function normalizeOutputs(value) {
|
|
|
51141
50629
|
*/
|
|
51142
50630
|
function passthroughSSEChunk(chunk, data) {
|
|
51143
50631
|
return {
|
|
51144
|
-
...chunk.comment ? { comment: chunk.comment } : {},
|
|
51145
50632
|
...chunk.event ? { event: chunk.event } : {},
|
|
51146
50633
|
...chunk.id !== void 0 ? { id: String(chunk.id) } : {},
|
|
51147
|
-
...chunk.retry !== void 0 ? { retry: chunk.retry } : {},
|
|
51148
50634
|
data
|
|
51149
50635
|
};
|
|
51150
50636
|
}
|
|
51151
50637
|
//#endregion
|
|
51152
50638
|
//#region src/routes/chat-completions/strategy.ts
|
|
51153
|
-
function createChatCompletionsStrategy(
|
|
50639
|
+
function createChatCompletionsStrategy(client, adapter, plan, signal) {
|
|
51154
50640
|
return {
|
|
51155
50641
|
execute() {
|
|
51156
|
-
return
|
|
50642
|
+
return client.createChatCompletions(plan.payload, {
|
|
50643
|
+
signal,
|
|
50644
|
+
initiator: plan.initiator,
|
|
50645
|
+
requestContext: plan.requestContext
|
|
50646
|
+
});
|
|
51157
50647
|
},
|
|
51158
50648
|
isStream(result) {
|
|
51159
50649
|
return !isNonStreamingResponse(result);
|
|
@@ -51180,9 +50670,8 @@ const chatCompletionsEntry$1 = {
|
|
|
51180
50670
|
const adapter = new OpenAIChatAdapter();
|
|
51181
50671
|
const plan = adapter.toCapiPlan(ctx.payload, { requestContext: ctx.requestContext });
|
|
51182
50672
|
appendModelStepInPlace(ctx.modelMapping, "MODEL_RESOLVE", plan.resolvedModel);
|
|
51183
|
-
const transport = new CopilotTransport(ctx.copilotClient);
|
|
51184
50673
|
consola.debug("Streaming response");
|
|
51185
|
-
return await runStrategy(createChatCompletionsStrategy(
|
|
50674
|
+
return await runStrategy(createChatCompletionsStrategy(ctx.copilotClient, adapter, plan, ctx.upstreamSignal.signal), ctx.upstreamSignal);
|
|
51186
50675
|
}
|
|
51187
50676
|
};
|
|
51188
50677
|
const chatCompletionsStrategyRegistry = new StrategyRegistry();
|
|
@@ -51200,6 +50689,7 @@ async function handleCompletionCore({ body, signal, headers }) {
|
|
|
51200
50689
|
strategyRegistry: chatCompletionsStrategyRegistry,
|
|
51201
50690
|
afterIngest({ payload }) {
|
|
51202
50691
|
consola.debug("Request payload:", JSON.stringify(payload).slice(-400));
|
|
50692
|
+
return payload;
|
|
51203
50693
|
},
|
|
51204
50694
|
async afterTransform({ payload, selectedModel }) {
|
|
51205
50695
|
try {
|
|
@@ -51275,7 +50765,7 @@ function createAnthropicAdapter() {
|
|
|
51275
50765
|
const fallbackConfig = getModelFallbackConfig();
|
|
51276
50766
|
return new AnthropicMessagesAdapter({
|
|
51277
50767
|
modelResolver: (model) => resolveModel(model, knownModelIds, fallbackConfig),
|
|
51278
|
-
getModelCapabilities: (model) => ({ supportsThinkingBudget: model
|
|
50768
|
+
getModelCapabilities: (model) => ({ supportsThinkingBudget: inferModelFamily(model) === "claude" })
|
|
51279
50769
|
});
|
|
51280
50770
|
}
|
|
51281
50771
|
//#endregion
|
|
@@ -51314,7 +50804,68 @@ async function handleCountTokensCore({ body, headers }) {
|
|
|
51314
50804
|
return { input_tokens: finalTokenCount };
|
|
51315
50805
|
}
|
|
51316
50806
|
//#endregion
|
|
51317
|
-
//#region src/
|
|
50807
|
+
//#region src/transform/context-management.ts
|
|
50808
|
+
/** Default token threshold when model limits are unknown. */
|
|
50809
|
+
const DEFAULT_COMPACT_THRESHOLD = 5e4;
|
|
50810
|
+
/** Fraction of max prompt tokens to use as compact threshold. */
|
|
50811
|
+
const COMPACT_THRESHOLD_RATIO = .9;
|
|
50812
|
+
function getResponsesRequestOptions(payload) {
|
|
50813
|
+
return {
|
|
50814
|
+
vision: hasVisionInput(payload),
|
|
50815
|
+
initiator: hasAgentInitiator(payload) ? "agent" : "user"
|
|
50816
|
+
};
|
|
50817
|
+
}
|
|
50818
|
+
function hasAgentInitiator(payload) {
|
|
50819
|
+
const lastItem = getPayloadItems(payload).at(-1);
|
|
50820
|
+
if (!lastItem) return false;
|
|
50821
|
+
if (!("role" in lastItem) || !lastItem.role) return true;
|
|
50822
|
+
return String(lastItem.role).toLowerCase() === "assistant";
|
|
50823
|
+
}
|
|
50824
|
+
function hasVisionInput(payload) {
|
|
50825
|
+
return getPayloadItems(payload).some((item) => containsVisionContent(item));
|
|
50826
|
+
}
|
|
50827
|
+
function resolveResponsesCompactThreshold(maxPromptTokens) {
|
|
50828
|
+
if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * COMPACT_THRESHOLD_RATIO);
|
|
50829
|
+
return DEFAULT_COMPACT_THRESHOLD;
|
|
50830
|
+
}
|
|
50831
|
+
function createCompactionContextManagement(compactThreshold) {
|
|
50832
|
+
return [{
|
|
50833
|
+
type: "compaction",
|
|
50834
|
+
compact_threshold: compactThreshold
|
|
50835
|
+
}];
|
|
50836
|
+
}
|
|
50837
|
+
function applyContextManagement(payload, maxPromptTokens) {
|
|
50838
|
+
if (payload.context_management !== void 0) return;
|
|
50839
|
+
if (!configStore.isContextManagementModel(payload.model)) return;
|
|
50840
|
+
payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
|
|
50841
|
+
}
|
|
50842
|
+
function compactInputByLatestCompaction(payload) {
|
|
50843
|
+
if (!configStore.isAutoCompactResponsesInputEnabled()) return;
|
|
50844
|
+
if (!Array.isArray(payload.input) || payload.input.length === 0) return;
|
|
50845
|
+
const latestCompactionMessageIndex = getLatestCompactionMessageIndex(payload.input);
|
|
50846
|
+
if (latestCompactionMessageIndex === void 0) return;
|
|
50847
|
+
payload.input = payload.input.slice(latestCompactionMessageIndex);
|
|
50848
|
+
}
|
|
50849
|
+
function getLatestCompactionMessageIndex(input) {
|
|
50850
|
+
for (let index = input.length - 1; index >= 0; index--) if (isCompactionInputItem(input[index])) return index;
|
|
50851
|
+
}
|
|
50852
|
+
function isCompactionInputItem(value) {
|
|
50853
|
+
return "type" in value && value.type === "compaction";
|
|
50854
|
+
}
|
|
50855
|
+
function getPayloadItems(payload) {
|
|
50856
|
+
return Array.isArray(payload.input) ? payload.input : [];
|
|
50857
|
+
}
|
|
50858
|
+
function containsVisionContent(value) {
|
|
50859
|
+
if (!value) return false;
|
|
50860
|
+
if (Array.isArray(value)) return value.some((entry) => containsVisionContent(entry));
|
|
50861
|
+
if (typeof value !== "object") return false;
|
|
50862
|
+
const record = value;
|
|
50863
|
+
if (record.type === "input_image") return true;
|
|
50864
|
+
if (Array.isArray(record.content)) return record.content.some((entry) => containsVisionContent(entry));
|
|
50865
|
+
return false;
|
|
50866
|
+
}
|
|
50867
|
+
//#endregion
|
|
50868
|
+
//#region src/translator/responses/function-schema.ts
|
|
51318
50869
|
function isRecord$2(value) {
|
|
51319
50870
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
51320
50871
|
}
|
|
@@ -51356,147 +50907,9 @@ function normalizeFunctionParametersSchemaForCopilot(schema) {
|
|
|
51356
50907
|
return normalizeSchemaNode(schema);
|
|
51357
50908
|
}
|
|
51358
50909
|
//#endregion
|
|
51359
|
-
//#region src/translator/responses/
|
|
50910
|
+
//#region src/translator/responses/response-items.ts
|
|
51360
50911
|
const MESSAGE_TYPE = "message";
|
|
51361
|
-
const USER_ID_ACCOUNT_RE = /user_([^_]+)_account/;
|
|
51362
|
-
const USER_ID_SESSION_RE = /_session_(.+)$/;
|
|
51363
50912
|
const THINKING_TEXT = "Thinking...";
|
|
51364
|
-
function translateAnthropicToResponsesPayload(payload, options) {
|
|
51365
|
-
assertResponsesCompatibleRequest(payload);
|
|
51366
|
-
const input = [];
|
|
51367
|
-
for (const message of payload.messages) input.push(...translateMessage(message));
|
|
51368
|
-
const { safetyIdentifier, promptCacheKey } = parseUserId(payload.metadata?.user_id);
|
|
51369
|
-
const reasoning = resolveResponsesReasoningConfig(payload, options);
|
|
51370
|
-
const text = resolveResponsesTextConfig(payload);
|
|
51371
|
-
return {
|
|
51372
|
-
model: payload.model,
|
|
51373
|
-
input,
|
|
51374
|
-
instructions: translateSystemPrompt(payload.system),
|
|
51375
|
-
temperature: payload.temperature ?? null,
|
|
51376
|
-
top_p: payload.top_p ?? null,
|
|
51377
|
-
max_output_tokens: payload.max_tokens,
|
|
51378
|
-
tools: convertAnthropicTools(payload.tools),
|
|
51379
|
-
tool_choice: convertAnthropicToolChoice(payload.tool_choice),
|
|
51380
|
-
metadata: payload.metadata ? { ...payload.metadata } : null,
|
|
51381
|
-
safety_identifier: safetyIdentifier,
|
|
51382
|
-
prompt_cache_key: promptCacheKey,
|
|
51383
|
-
stream: payload.stream ?? null,
|
|
51384
|
-
store: false,
|
|
51385
|
-
parallel_tool_calls: true,
|
|
51386
|
-
...text ? { text } : {},
|
|
51387
|
-
...reasoning ? {
|
|
51388
|
-
reasoning,
|
|
51389
|
-
include: ["reasoning.encrypted_content"]
|
|
51390
|
-
} : {}
|
|
51391
|
-
};
|
|
51392
|
-
}
|
|
51393
|
-
function decodeCompactionCarrierSignature(signature) {
|
|
51394
|
-
return SignatureCodec.decodeCompaction(signature);
|
|
51395
|
-
}
|
|
51396
|
-
function translateMessage(message) {
|
|
51397
|
-
switch (message.role) {
|
|
51398
|
-
case "user": return translateUserMessage(message);
|
|
51399
|
-
case "assistant": return translateAssistantMessage(message);
|
|
51400
|
-
case "system": return translateSystemMessage(message);
|
|
51401
|
-
}
|
|
51402
|
-
}
|
|
51403
|
-
function translateSystemMessage(message) {
|
|
51404
|
-
if (typeof message.content === "string") return [createMessage("system", message.content)];
|
|
51405
|
-
if (!Array.isArray(message.content)) return [];
|
|
51406
|
-
return [createMessage("system", message.content.map((block) => createTextContent(block.text)))];
|
|
51407
|
-
}
|
|
51408
|
-
function translateUserMessage(message) {
|
|
51409
|
-
if (typeof message.content === "string") return [createMessage("user", message.content)];
|
|
51410
|
-
if (!Array.isArray(message.content)) return [];
|
|
51411
|
-
const items = [];
|
|
51412
|
-
const pendingContent = [];
|
|
51413
|
-
for (const block of message.content) {
|
|
51414
|
-
if (block.type === "tool_result" || block.type === "mcp_tool_result") {
|
|
51415
|
-
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51416
|
-
items.push(createFunctionCallOutput(block));
|
|
51417
|
-
continue;
|
|
51418
|
-
}
|
|
51419
|
-
if (isServerToolResultBlock(block)) {
|
|
51420
|
-
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51421
|
-
items.push(createServerFunctionCallOutput(block));
|
|
51422
|
-
continue;
|
|
51423
|
-
}
|
|
51424
|
-
const converted = translateUserContentBlock(block);
|
|
51425
|
-
if (converted) pendingContent.push(converted);
|
|
51426
|
-
}
|
|
51427
|
-
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51428
|
-
return items;
|
|
51429
|
-
}
|
|
51430
|
-
function translateAssistantMessage(message) {
|
|
51431
|
-
const assistantPhase = resolveAssistantPhase(message.content);
|
|
51432
|
-
if (typeof message.content === "string") return [createMessage("assistant", message.content, assistantPhase)];
|
|
51433
|
-
if (!Array.isArray(message.content)) return [];
|
|
51434
|
-
const items = [];
|
|
51435
|
-
const pendingContent = [];
|
|
51436
|
-
for (const block of message.content) {
|
|
51437
|
-
if (block.type === "tool_use" || block.type === "server_tool_use" || block.type === "mcp_tool_use") {
|
|
51438
|
-
flushPendingContent(pendingContent, items, {
|
|
51439
|
-
role: "assistant",
|
|
51440
|
-
phase: assistantPhase
|
|
51441
|
-
});
|
|
51442
|
-
items.push(createFunctionToolCall(block));
|
|
51443
|
-
continue;
|
|
51444
|
-
}
|
|
51445
|
-
if (block.type === "redacted_thinking") {
|
|
51446
|
-
flushPendingContent(pendingContent, items, {
|
|
51447
|
-
role: "assistant",
|
|
51448
|
-
phase: assistantPhase
|
|
51449
|
-
});
|
|
51450
|
-
items.push(createRedactedReasoningContent(block));
|
|
51451
|
-
continue;
|
|
51452
|
-
}
|
|
51453
|
-
if (block.type === "mcp_tool_result") {
|
|
51454
|
-
flushPendingContent(pendingContent, items, {
|
|
51455
|
-
role: "assistant",
|
|
51456
|
-
phase: assistantPhase
|
|
51457
|
-
});
|
|
51458
|
-
items.push(createFunctionCallOutput(block));
|
|
51459
|
-
continue;
|
|
51460
|
-
}
|
|
51461
|
-
if (isServerToolResultBlock(block)) {
|
|
51462
|
-
flushPendingContent(pendingContent, items, {
|
|
51463
|
-
role: "assistant",
|
|
51464
|
-
phase: assistantPhase
|
|
51465
|
-
});
|
|
51466
|
-
items.push(createServerFunctionCallOutput(block));
|
|
51467
|
-
continue;
|
|
51468
|
-
}
|
|
51469
|
-
if (block.type === "thinking" && block.signature) {
|
|
51470
|
-
const compaction = createCompactionContent(block);
|
|
51471
|
-
if (compaction) {
|
|
51472
|
-
flushPendingContent(pendingContent, items, {
|
|
51473
|
-
role: "assistant",
|
|
51474
|
-
phase: assistantPhase
|
|
51475
|
-
});
|
|
51476
|
-
items.push(compaction);
|
|
51477
|
-
continue;
|
|
51478
|
-
}
|
|
51479
|
-
if (SignatureCodec.isReasoningSignature(block.signature)) {
|
|
51480
|
-
const { id } = SignatureCodec.decodeReasoning(block.signature);
|
|
51481
|
-
if (id) {
|
|
51482
|
-
flushPendingContent(pendingContent, items, {
|
|
51483
|
-
role: "assistant",
|
|
51484
|
-
phase: assistantPhase
|
|
51485
|
-
});
|
|
51486
|
-
items.push(createReasoningContent(block));
|
|
51487
|
-
continue;
|
|
51488
|
-
}
|
|
51489
|
-
}
|
|
51490
|
-
}
|
|
51491
|
-
const converted = translateAssistantContentBlock(block);
|
|
51492
|
-
if (converted) pendingContent.push(converted);
|
|
51493
|
-
}
|
|
51494
|
-
flushPendingContent(pendingContent, items, {
|
|
51495
|
-
role: "assistant",
|
|
51496
|
-
phase: assistantPhase
|
|
51497
|
-
});
|
|
51498
|
-
return items;
|
|
51499
|
-
}
|
|
51500
50913
|
function translateUserContentBlock(block) {
|
|
51501
50914
|
switch (block.type) {
|
|
51502
50915
|
case "text": return createTextContent(block.text);
|
|
@@ -51595,7 +51008,7 @@ function createRedactedReasoningContent(block) {
|
|
|
51595
51008
|
};
|
|
51596
51009
|
}
|
|
51597
51010
|
function createCompactionContent(block) {
|
|
51598
|
-
const compaction =
|
|
51011
|
+
const compaction = SignatureCodec.decodeCompaction(block.signature ?? "");
|
|
51599
51012
|
if (!compaction) return;
|
|
51600
51013
|
return {
|
|
51601
51014
|
id: compaction.id,
|
|
@@ -51631,6 +51044,160 @@ function createServerFunctionCallOutput(block) {
|
|
|
51631
51044
|
function isServerToolResultBlock(block) {
|
|
51632
51045
|
return block.type === "server_tool_result" || block.type === "web_search_tool_result" || block.type === "web_fetch_tool_result" || block.type === "code_execution_tool_result" || block.type === "bash_code_execution_tool_result" || block.type === "text_editor_code_execution_tool_result" || block.type === "tool_search_tool_result";
|
|
51633
51046
|
}
|
|
51047
|
+
function convertToolResultContent(content) {
|
|
51048
|
+
if (typeof content === "string") return content;
|
|
51049
|
+
const result = [];
|
|
51050
|
+
for (const block of content) switch (block.type) {
|
|
51051
|
+
case "text":
|
|
51052
|
+
result.push(createTextContent(block.text));
|
|
51053
|
+
break;
|
|
51054
|
+
case "image":
|
|
51055
|
+
result.push(createImageContent(block));
|
|
51056
|
+
break;
|
|
51057
|
+
case "search_result":
|
|
51058
|
+
result.push(createTextContent(formatSearchResultBlock(block)));
|
|
51059
|
+
break;
|
|
51060
|
+
default: break;
|
|
51061
|
+
}
|
|
51062
|
+
return result;
|
|
51063
|
+
}
|
|
51064
|
+
//#endregion
|
|
51065
|
+
//#region src/translator/responses/anthropic-to-responses.ts
|
|
51066
|
+
const USER_ID_ACCOUNT_RE = /user_([^_]+)_account/;
|
|
51067
|
+
const USER_ID_SESSION_RE = /_session_(.+)$/;
|
|
51068
|
+
function translateAnthropicToResponsesPayload(payload, options) {
|
|
51069
|
+
assertResponsesCompatibleRequest(payload);
|
|
51070
|
+
const input = [];
|
|
51071
|
+
for (const message of payload.messages) input.push(...translateMessage(message));
|
|
51072
|
+
const { safetyIdentifier, promptCacheKey } = parseUserId(payload.metadata?.user_id);
|
|
51073
|
+
const reasoning = resolveResponsesReasoningConfig(payload, options);
|
|
51074
|
+
const text = resolveResponsesTextConfig(payload);
|
|
51075
|
+
return {
|
|
51076
|
+
model: payload.model,
|
|
51077
|
+
input,
|
|
51078
|
+
instructions: translateSystemPrompt(payload.system),
|
|
51079
|
+
temperature: payload.temperature ?? null,
|
|
51080
|
+
top_p: payload.top_p ?? null,
|
|
51081
|
+
max_output_tokens: payload.max_tokens,
|
|
51082
|
+
tools: convertAnthropicTools(payload.tools),
|
|
51083
|
+
tool_choice: convertAnthropicToolChoice(payload.tool_choice),
|
|
51084
|
+
metadata: payload.metadata ? { ...payload.metadata } : null,
|
|
51085
|
+
safety_identifier: safetyIdentifier,
|
|
51086
|
+
prompt_cache_key: promptCacheKey,
|
|
51087
|
+
stream: payload.stream ?? null,
|
|
51088
|
+
store: false,
|
|
51089
|
+
parallel_tool_calls: true,
|
|
51090
|
+
...text ? { text } : {},
|
|
51091
|
+
...reasoning ? {
|
|
51092
|
+
reasoning,
|
|
51093
|
+
include: ["reasoning.encrypted_content"]
|
|
51094
|
+
} : {}
|
|
51095
|
+
};
|
|
51096
|
+
}
|
|
51097
|
+
function translateMessage(message) {
|
|
51098
|
+
switch (message.role) {
|
|
51099
|
+
case "user": return translateUserMessage(message);
|
|
51100
|
+
case "assistant": return translateAssistantMessage(message);
|
|
51101
|
+
case "system": return translateSystemMessage(message);
|
|
51102
|
+
}
|
|
51103
|
+
}
|
|
51104
|
+
function translateSystemMessage(message) {
|
|
51105
|
+
if (typeof message.content === "string") return [createMessage("system", message.content)];
|
|
51106
|
+
if (!Array.isArray(message.content)) return [];
|
|
51107
|
+
return [createMessage("system", message.content.map((block) => createTextContent(block.text)))];
|
|
51108
|
+
}
|
|
51109
|
+
function translateUserMessage(message) {
|
|
51110
|
+
if (typeof message.content === "string") return [createMessage("user", message.content)];
|
|
51111
|
+
if (!Array.isArray(message.content)) return [];
|
|
51112
|
+
const items = [];
|
|
51113
|
+
const pendingContent = [];
|
|
51114
|
+
for (const block of message.content) {
|
|
51115
|
+
if (block.type === "tool_result" || block.type === "mcp_tool_result") {
|
|
51116
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51117
|
+
items.push(createFunctionCallOutput(block));
|
|
51118
|
+
continue;
|
|
51119
|
+
}
|
|
51120
|
+
if (isServerToolResultBlock(block)) {
|
|
51121
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51122
|
+
items.push(createServerFunctionCallOutput(block));
|
|
51123
|
+
continue;
|
|
51124
|
+
}
|
|
51125
|
+
const converted = translateUserContentBlock(block);
|
|
51126
|
+
if (converted) pendingContent.push(converted);
|
|
51127
|
+
}
|
|
51128
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51129
|
+
return items;
|
|
51130
|
+
}
|
|
51131
|
+
function translateAssistantMessage(message) {
|
|
51132
|
+
const assistantPhase = resolveAssistantPhase(message.content);
|
|
51133
|
+
if (typeof message.content === "string") return [createMessage("assistant", message.content, assistantPhase)];
|
|
51134
|
+
if (!Array.isArray(message.content)) return [];
|
|
51135
|
+
const items = [];
|
|
51136
|
+
const pendingContent = [];
|
|
51137
|
+
for (const block of message.content) {
|
|
51138
|
+
if (block.type === "tool_use" || block.type === "server_tool_use" || block.type === "mcp_tool_use") {
|
|
51139
|
+
flushPendingContent(pendingContent, items, {
|
|
51140
|
+
role: "assistant",
|
|
51141
|
+
phase: assistantPhase
|
|
51142
|
+
});
|
|
51143
|
+
items.push(createFunctionToolCall(block));
|
|
51144
|
+
continue;
|
|
51145
|
+
}
|
|
51146
|
+
if (block.type === "redacted_thinking") {
|
|
51147
|
+
flushPendingContent(pendingContent, items, {
|
|
51148
|
+
role: "assistant",
|
|
51149
|
+
phase: assistantPhase
|
|
51150
|
+
});
|
|
51151
|
+
items.push(createRedactedReasoningContent(block));
|
|
51152
|
+
continue;
|
|
51153
|
+
}
|
|
51154
|
+
if (block.type === "mcp_tool_result") {
|
|
51155
|
+
flushPendingContent(pendingContent, items, {
|
|
51156
|
+
role: "assistant",
|
|
51157
|
+
phase: assistantPhase
|
|
51158
|
+
});
|
|
51159
|
+
items.push(createFunctionCallOutput(block));
|
|
51160
|
+
continue;
|
|
51161
|
+
}
|
|
51162
|
+
if (isServerToolResultBlock(block)) {
|
|
51163
|
+
flushPendingContent(pendingContent, items, {
|
|
51164
|
+
role: "assistant",
|
|
51165
|
+
phase: assistantPhase
|
|
51166
|
+
});
|
|
51167
|
+
items.push(createServerFunctionCallOutput(block));
|
|
51168
|
+
continue;
|
|
51169
|
+
}
|
|
51170
|
+
if (block.type === "thinking" && block.signature) {
|
|
51171
|
+
const compaction = createCompactionContent(block);
|
|
51172
|
+
if (compaction) {
|
|
51173
|
+
flushPendingContent(pendingContent, items, {
|
|
51174
|
+
role: "assistant",
|
|
51175
|
+
phase: assistantPhase
|
|
51176
|
+
});
|
|
51177
|
+
items.push(compaction);
|
|
51178
|
+
continue;
|
|
51179
|
+
}
|
|
51180
|
+
if (SignatureCodec.isReasoningSignature(block.signature)) {
|
|
51181
|
+
const { id } = SignatureCodec.decodeReasoning(block.signature);
|
|
51182
|
+
if (id) {
|
|
51183
|
+
flushPendingContent(pendingContent, items, {
|
|
51184
|
+
role: "assistant",
|
|
51185
|
+
phase: assistantPhase
|
|
51186
|
+
});
|
|
51187
|
+
items.push(createReasoningContent(block));
|
|
51188
|
+
continue;
|
|
51189
|
+
}
|
|
51190
|
+
}
|
|
51191
|
+
}
|
|
51192
|
+
const converted = translateAssistantContentBlock(block);
|
|
51193
|
+
if (converted) pendingContent.push(converted);
|
|
51194
|
+
}
|
|
51195
|
+
flushPendingContent(pendingContent, items, {
|
|
51196
|
+
role: "assistant",
|
|
51197
|
+
phase: assistantPhase
|
|
51198
|
+
});
|
|
51199
|
+
return items;
|
|
51200
|
+
}
|
|
51634
51201
|
function translateSystemPrompt(system) {
|
|
51635
51202
|
if (!system) return null;
|
|
51636
51203
|
if (typeof system === "string") return system;
|
|
@@ -51716,92 +51283,18 @@ function parseUserId(userId) {
|
|
|
51716
51283
|
promptCacheKey: sessionMatch ? sessionMatch[1] : null
|
|
51717
51284
|
};
|
|
51718
51285
|
}
|
|
51719
|
-
function convertToolResultContent(content) {
|
|
51720
|
-
if (typeof content === "string") return content;
|
|
51721
|
-
const result = [];
|
|
51722
|
-
for (const block of content) switch (block.type) {
|
|
51723
|
-
case "text":
|
|
51724
|
-
result.push(createTextContent(block.text));
|
|
51725
|
-
break;
|
|
51726
|
-
case "image":
|
|
51727
|
-
result.push(createImageContent(block));
|
|
51728
|
-
break;
|
|
51729
|
-
case "search_result":
|
|
51730
|
-
result.push(createTextContent(formatSearchResultBlock(block)));
|
|
51731
|
-
break;
|
|
51732
|
-
default: break;
|
|
51733
|
-
}
|
|
51734
|
-
return result;
|
|
51735
|
-
}
|
|
51736
|
-
//#endregion
|
|
51737
|
-
//#region src/routes/responses/context-management.ts
|
|
51738
|
-
/** Default token threshold when model limits are unknown. */
|
|
51739
|
-
const DEFAULT_COMPACT_THRESHOLD = 5e4;
|
|
51740
|
-
/** Fraction of max prompt tokens to use as compact threshold. */
|
|
51741
|
-
const COMPACT_THRESHOLD_RATIO = .9;
|
|
51742
|
-
function getResponsesRequestOptions(payload) {
|
|
51743
|
-
return {
|
|
51744
|
-
vision: hasVisionInput(payload),
|
|
51745
|
-
initiator: hasAgentInitiator(payload) ? "agent" : "user"
|
|
51746
|
-
};
|
|
51747
|
-
}
|
|
51748
|
-
function hasAgentInitiator(payload) {
|
|
51749
|
-
const lastItem = getPayloadItems(payload).at(-1);
|
|
51750
|
-
if (!lastItem) return false;
|
|
51751
|
-
if (!("role" in lastItem) || !lastItem.role) return true;
|
|
51752
|
-
return String(lastItem.role).toLowerCase() === "assistant";
|
|
51753
|
-
}
|
|
51754
|
-
function hasVisionInput(payload) {
|
|
51755
|
-
return getPayloadItems(payload).some((item) => containsVisionContent(item));
|
|
51756
|
-
}
|
|
51757
|
-
function resolveResponsesCompactThreshold(maxPromptTokens) {
|
|
51758
|
-
if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * COMPACT_THRESHOLD_RATIO);
|
|
51759
|
-
return DEFAULT_COMPACT_THRESHOLD;
|
|
51760
|
-
}
|
|
51761
|
-
function createCompactionContextManagement(compactThreshold) {
|
|
51762
|
-
return [{
|
|
51763
|
-
type: "compaction",
|
|
51764
|
-
compact_threshold: compactThreshold
|
|
51765
|
-
}];
|
|
51766
|
-
}
|
|
51767
|
-
function applyContextManagement(payload, maxPromptTokens) {
|
|
51768
|
-
if (payload.context_management !== void 0) return;
|
|
51769
|
-
if (!configStore.isContextManagementModel(payload.model)) return;
|
|
51770
|
-
payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
|
|
51771
|
-
}
|
|
51772
|
-
function compactInputByLatestCompaction(payload) {
|
|
51773
|
-
if (!configStore.isAutoCompactResponsesInputEnabled()) return;
|
|
51774
|
-
if (!Array.isArray(payload.input) || payload.input.length === 0) return;
|
|
51775
|
-
const latestCompactionMessageIndex = getLatestCompactionMessageIndex(payload.input);
|
|
51776
|
-
if (latestCompactionMessageIndex === void 0) return;
|
|
51777
|
-
payload.input = payload.input.slice(latestCompactionMessageIndex);
|
|
51778
|
-
}
|
|
51779
|
-
function getLatestCompactionMessageIndex(input) {
|
|
51780
|
-
for (let index = input.length - 1; index >= 0; index--) if (isCompactionInputItem(input[index])) return index;
|
|
51781
|
-
}
|
|
51782
|
-
function isCompactionInputItem(value) {
|
|
51783
|
-
return "type" in value && value.type === "compaction";
|
|
51784
|
-
}
|
|
51785
|
-
function getPayloadItems(payload) {
|
|
51786
|
-
return Array.isArray(payload.input) ? payload.input : [];
|
|
51787
|
-
}
|
|
51788
|
-
function containsVisionContent(value) {
|
|
51789
|
-
if (!value) return false;
|
|
51790
|
-
if (Array.isArray(value)) return value.some((entry) => containsVisionContent(entry));
|
|
51791
|
-
if (typeof value !== "object") return false;
|
|
51792
|
-
const record = value;
|
|
51793
|
-
if (record.type === "input_image") return true;
|
|
51794
|
-
if (Array.isArray(record.content)) return record.content.some((entry) => containsVisionContent(entry));
|
|
51795
|
-
return false;
|
|
51796
|
-
}
|
|
51797
51286
|
//#endregion
|
|
51798
51287
|
//#region src/routes/messages/strategies/chat-completions.ts
|
|
51799
|
-
function createMessagesViaChatCompletionsStrategy(
|
|
51288
|
+
function createMessagesViaChatCompletionsStrategy(client, adapter, plan, signal) {
|
|
51800
51289
|
let streamTranslator;
|
|
51801
51290
|
let done = false;
|
|
51802
51291
|
return {
|
|
51803
51292
|
execute() {
|
|
51804
|
-
return
|
|
51293
|
+
return client.createChatCompletions(plan.payload, {
|
|
51294
|
+
signal,
|
|
51295
|
+
initiator: plan.initiator,
|
|
51296
|
+
requestContext: plan.requestContext
|
|
51297
|
+
});
|
|
51805
51298
|
},
|
|
51806
51299
|
isStream(result) {
|
|
51807
51300
|
return !isNonStreamingResponse(result);
|
|
@@ -51818,24 +51311,15 @@ function createMessagesViaChatCompletionsStrategy(transport, adapter, plan, sign
|
|
|
51818
51311
|
if (chunk.data === "[DONE]") {
|
|
51819
51312
|
const finalEvents = streamTranslator.onDone();
|
|
51820
51313
|
done = true;
|
|
51821
|
-
return finalEvents
|
|
51822
|
-
event: event.type,
|
|
51823
|
-
data: JSON.stringify(event)
|
|
51824
|
-
}));
|
|
51314
|
+
return serializeAnthropicSSE(finalEvents);
|
|
51825
51315
|
}
|
|
51826
51316
|
if (!chunk.data) return null;
|
|
51827
51317
|
const parsed = JSON.parse(chunk.data);
|
|
51828
|
-
return streamTranslator.onChunk(parsed)
|
|
51829
|
-
event: event.type,
|
|
51830
|
-
data: JSON.stringify(event)
|
|
51831
|
-
}));
|
|
51318
|
+
return serializeAnthropicSSE(streamTranslator.onChunk(parsed));
|
|
51832
51319
|
},
|
|
51833
51320
|
onStreamDone() {
|
|
51834
51321
|
if (!streamTranslator) return null;
|
|
51835
|
-
return streamTranslator.onDone()
|
|
51836
|
-
event: event.type,
|
|
51837
|
-
data: JSON.stringify(event)
|
|
51838
|
-
}));
|
|
51322
|
+
return serializeAnthropicSSE(streamTranslator.onDone());
|
|
51839
51323
|
},
|
|
51840
51324
|
shouldBreakStream() {
|
|
51841
51325
|
return done;
|
|
@@ -51843,15 +51327,12 @@ function createMessagesViaChatCompletionsStrategy(transport, adapter, plan, sign
|
|
|
51843
51327
|
onStreamError(error) {
|
|
51844
51328
|
consola.error("Error streaming Anthropic response:", error);
|
|
51845
51329
|
if (!streamTranslator) streamTranslator = adapter.createStreamSerializer();
|
|
51846
|
-
return streamTranslator.onError(error)
|
|
51847
|
-
event: event.type,
|
|
51848
|
-
data: JSON.stringify(event)
|
|
51849
|
-
}));
|
|
51330
|
+
return serializeAnthropicSSE(streamTranslator.onError(error));
|
|
51850
51331
|
}
|
|
51851
51332
|
};
|
|
51852
51333
|
}
|
|
51853
51334
|
//#endregion
|
|
51854
|
-
//#region src/
|
|
51335
|
+
//#region src/util/async-iterable.ts
|
|
51855
51336
|
function isAsyncIterable(value) {
|
|
51856
51337
|
return Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
51857
51338
|
}
|
|
@@ -51924,6 +51405,30 @@ function createNativeMessagesStrategy(copilotClient, payload, anthropicBetaHeade
|
|
|
51924
51405
|
}
|
|
51925
51406
|
};
|
|
51926
51407
|
}
|
|
51408
|
+
var FunctionCallArgumentsValidationError = class extends Error {
|
|
51409
|
+
constructor(message) {
|
|
51410
|
+
super(message);
|
|
51411
|
+
this.name = "FunctionCallArgumentsValidationError";
|
|
51412
|
+
}
|
|
51413
|
+
};
|
|
51414
|
+
function updateWhitespaceRunState(previousCount, chunk) {
|
|
51415
|
+
let count = previousCount;
|
|
51416
|
+
for (const char of chunk) {
|
|
51417
|
+
if (char === " " || char === "\r" || char === "\n" || char === " ") {
|
|
51418
|
+
count += 1;
|
|
51419
|
+
if (count > 20) return {
|
|
51420
|
+
nextCount: count,
|
|
51421
|
+
exceeded: true
|
|
51422
|
+
};
|
|
51423
|
+
continue;
|
|
51424
|
+
}
|
|
51425
|
+
count = 0;
|
|
51426
|
+
}
|
|
51427
|
+
return {
|
|
51428
|
+
nextCount: count,
|
|
51429
|
+
exceeded: false
|
|
51430
|
+
};
|
|
51431
|
+
}
|
|
51927
51432
|
//#endregion
|
|
51928
51433
|
//#region src/translator/responses/responses-to-anthropic.ts
|
|
51929
51434
|
function translateResponsesToAnthropic(response) {
|
|
@@ -51996,12 +51501,9 @@ function combineMessageTextContent(content) {
|
|
|
51996
51501
|
function extractReasoningText(item) {
|
|
51997
51502
|
if (!item.summary || item.summary.length === 0) return THINKING_TEXT;
|
|
51998
51503
|
const segments = [];
|
|
51999
|
-
|
|
51504
|
+
for (const block of item.summary) if (typeof block.text === "string") segments.push(block.text);
|
|
52000
51505
|
return segments.join("").trim();
|
|
52001
51506
|
}
|
|
52002
|
-
function collectReasoningSegments(blocks, segments) {
|
|
52003
|
-
for (const block of blocks) if (typeof block.text === "string") segments.push(block.text);
|
|
52004
|
-
}
|
|
52005
51507
|
function createToolUseContentBlock(call) {
|
|
52006
51508
|
if (!call.name || !call.call_id) return null;
|
|
52007
51509
|
return {
|
|
@@ -52061,31 +51563,6 @@ function isResponseOutputRefusal(block) {
|
|
|
52061
51563
|
}
|
|
52062
51564
|
//#endregion
|
|
52063
51565
|
//#region src/translator/responses/responses-stream-translator.ts
|
|
52064
|
-
const MAX_CONSECUTIVE_FUNCTION_CALL_WHITESPACE = 20;
|
|
52065
|
-
var FunctionCallArgumentsValidationError = class extends Error {
|
|
52066
|
-
constructor(message) {
|
|
52067
|
-
super(message);
|
|
52068
|
-
this.name = "FunctionCallArgumentsValidationError";
|
|
52069
|
-
}
|
|
52070
|
-
};
|
|
52071
|
-
function updateWhitespaceRunState(previousCount, chunk) {
|
|
52072
|
-
let count = previousCount;
|
|
52073
|
-
for (const char of chunk) {
|
|
52074
|
-
if (char === " " || char === "\r" || char === "\n" || char === " ") {
|
|
52075
|
-
count += 1;
|
|
52076
|
-
if (count > MAX_CONSECUTIVE_FUNCTION_CALL_WHITESPACE) return {
|
|
52077
|
-
nextCount: count,
|
|
52078
|
-
exceeded: true
|
|
52079
|
-
};
|
|
52080
|
-
continue;
|
|
52081
|
-
}
|
|
52082
|
-
count = 0;
|
|
52083
|
-
}
|
|
52084
|
-
return {
|
|
52085
|
-
nextCount: count,
|
|
52086
|
-
exceeded: false
|
|
52087
|
-
};
|
|
52088
|
-
}
|
|
52089
51566
|
var ResponsesStreamTranslator = class {
|
|
52090
51567
|
state = {
|
|
52091
51568
|
messageStartSent: false,
|
|
@@ -52345,6 +51822,7 @@ var ResponsesStreamTranslator = class {
|
|
|
52345
51822
|
return events;
|
|
52346
51823
|
}
|
|
52347
51824
|
handleResponseCompleted(rawEvent) {
|
|
51825
|
+
if (this.state.messageCompleted) return [];
|
|
52348
51826
|
const events = [];
|
|
52349
51827
|
this.closeAllOpenBlocks(events);
|
|
52350
51828
|
const anthropic = translateResponsesToAnthropic(rawEvent.response);
|
|
@@ -52505,27 +51983,18 @@ function createMessagesViaResponsesStrategy(copilotClient, responsesPayload, opt
|
|
|
52505
51983
|
data: "{\"type\":\"ping\"}"
|
|
52506
51984
|
};
|
|
52507
51985
|
if (!chunk.data) return null;
|
|
52508
|
-
return translator.onEvent(JSON.parse(chunk.data))
|
|
52509
|
-
event: event.type,
|
|
52510
|
-
data: JSON.stringify(event)
|
|
52511
|
-
}));
|
|
51986
|
+
return serializeAnthropicSSE(translator.onEvent(JSON.parse(chunk.data)));
|
|
52512
51987
|
},
|
|
52513
51988
|
shouldBreakStream() {
|
|
52514
51989
|
return translator.isCompleted;
|
|
52515
51990
|
},
|
|
52516
51991
|
onStreamDone() {
|
|
52517
51992
|
if (translator.isCompleted) return null;
|
|
52518
|
-
return translator.onDone()
|
|
52519
|
-
event: event.type,
|
|
52520
|
-
data: JSON.stringify(event)
|
|
52521
|
-
}));
|
|
51993
|
+
return serializeAnthropicSSE(translator.onDone());
|
|
52522
51994
|
},
|
|
52523
51995
|
onStreamError(error) {
|
|
52524
51996
|
consola.error("Error streaming Anthropic response via Responses API:", error);
|
|
52525
|
-
return translator.onError(error)
|
|
52526
|
-
event: event.type,
|
|
52527
|
-
data: JSON.stringify(event)
|
|
52528
|
-
}));
|
|
51997
|
+
return serializeAnthropicSSE(translator.onError(error));
|
|
52529
51998
|
}
|
|
52530
51999
|
};
|
|
52531
52000
|
}
|
|
@@ -52570,7 +52039,7 @@ const chatCompletionsEntry = {
|
|
|
52570
52039
|
appendModelStepInPlace(ctx.modelMapping, "MODEL_RESOLVE", plan.resolvedModel);
|
|
52571
52040
|
consola.debug("Claude Code requested model:", ctx.anthropicPayload.model, "-> Copilot model:", plan.resolvedModel);
|
|
52572
52041
|
if (consola.level >= 4) consola.debug("Planned Copilot request payload:", JSON.stringify(plan.payload));
|
|
52573
|
-
return await runStrategy(createMessagesViaChatCompletionsStrategy(
|
|
52042
|
+
return await runStrategy(createMessagesViaChatCompletionsStrategy(ctx.copilotClient, adapter, plan, ctx.upstreamSignal.signal), ctx.upstreamSignal);
|
|
52574
52043
|
}
|
|
52575
52044
|
};
|
|
52576
52045
|
const defaultStrategyRegistry = new StrategyRegistry();
|
|
@@ -52589,10 +52058,10 @@ async function handleMessagesCore({ body, signal, headers }) {
|
|
|
52589
52058
|
protocol: "anthropic-messages",
|
|
52590
52059
|
transformChain: messagesModelChain,
|
|
52591
52060
|
strategyRegistry: defaultStrategyRegistry,
|
|
52592
|
-
contextRetry: true,
|
|
52593
52061
|
afterIngest({ payload, headers: reqHeaders }) {
|
|
52594
52062
|
if (consola.level >= 4) consola.debug("Anthropic request payload:", JSON.stringify(payload));
|
|
52595
|
-
anthropicBetaHeader = processAnthropicBetaHeader(reqHeaders.get("anthropic-beta")
|
|
52063
|
+
anthropicBetaHeader = processAnthropicBetaHeader(reqHeaders.get("anthropic-beta"));
|
|
52064
|
+
return payload;
|
|
52596
52065
|
},
|
|
52597
52066
|
buildStrategyContext({ payload, meta, headers: reqHeaders, selectedModel, copilotClient, upstreamSignal, modelMapping }) {
|
|
52598
52067
|
return {
|
|
@@ -52657,13 +52126,243 @@ function createModelRoutes() {
|
|
|
52657
52126
|
});
|
|
52658
52127
|
}
|
|
52659
52128
|
//#endregion
|
|
52129
|
+
//#region src/routes/responses/emulator.ts
|
|
52130
|
+
function cloneValue(value) {
|
|
52131
|
+
return structuredClone(value);
|
|
52132
|
+
}
|
|
52133
|
+
function rejectUnsupportedBackground(payload) {
|
|
52134
|
+
if (payload.background) throwInvalidRequestError("background mode is not supported by the responses official emulator.", "background", "unsupported_background_mode");
|
|
52135
|
+
}
|
|
52136
|
+
function prepareEmulatorRequest(payload) {
|
|
52137
|
+
rejectUnsupportedBackground(payload);
|
|
52138
|
+
const normalizedCurrentInput = normalizeResponsesInput(payload.input);
|
|
52139
|
+
const { continuationSourceResponseId, conversation: resolvedConversation, previousResponse } = resolveContinuation(payload);
|
|
52140
|
+
const conversation = resolvedConversation ?? createConversationRef();
|
|
52141
|
+
const effectiveInputItems = [...continuationSourceResponseId ? buildContinuationHistory(continuationSourceResponseId) : [], ...normalizedCurrentInput];
|
|
52142
|
+
const shouldStore = payload.store ?? true;
|
|
52143
|
+
return {
|
|
52144
|
+
upstreamPayload: {
|
|
52145
|
+
...payload,
|
|
52146
|
+
background: void 0,
|
|
52147
|
+
conversation: void 0,
|
|
52148
|
+
previous_response_id: void 0,
|
|
52149
|
+
store: void 0,
|
|
52150
|
+
input: effectiveInputItems
|
|
52151
|
+
},
|
|
52152
|
+
effectiveInputItems,
|
|
52153
|
+
previousResponseId: previousResponse?.id,
|
|
52154
|
+
conversation,
|
|
52155
|
+
shouldStore
|
|
52156
|
+
};
|
|
52157
|
+
}
|
|
52158
|
+
function decorateStoredResponse(upstreamResponse, requestPayload, prepared) {
|
|
52159
|
+
return {
|
|
52160
|
+
...cloneValue(upstreamResponse),
|
|
52161
|
+
previous_response_id: prepared.previousResponseId ?? null,
|
|
52162
|
+
conversation: prepared.conversation,
|
|
52163
|
+
truncation: requestPayload.truncation ?? null,
|
|
52164
|
+
store: prepared.shouldStore,
|
|
52165
|
+
user: normalizeNullableString(requestPayload.user),
|
|
52166
|
+
service_tier: normalizeServiceTier(requestPayload.service_tier)
|
|
52167
|
+
};
|
|
52168
|
+
}
|
|
52169
|
+
function persistEmulatorResponse(response, effectiveInputItems) {
|
|
52170
|
+
responsesEmulatorState.setResponse(response);
|
|
52171
|
+
if (response.conversation) {
|
|
52172
|
+
responsesEmulatorState.setConversation(response.conversation);
|
|
52173
|
+
responsesEmulatorState.setConversationHead(getConversationId(response.conversation), response.id);
|
|
52174
|
+
}
|
|
52175
|
+
responsesEmulatorState.setInputItems(response.id, effectiveInputItems);
|
|
52176
|
+
}
|
|
52177
|
+
function getStoredResponseOrThrow(responseId) {
|
|
52178
|
+
const response = responsesEmulatorState.getResponse(responseId);
|
|
52179
|
+
if (!response) throw new HTTPError(404, { error: {
|
|
52180
|
+
message: `No response found with id '${responseId}'.`,
|
|
52181
|
+
type: "invalid_request_error"
|
|
52182
|
+
} });
|
|
52183
|
+
return response;
|
|
52184
|
+
}
|
|
52185
|
+
function listStoredInputItemsOrThrow(responseId, params) {
|
|
52186
|
+
const items = responsesEmulatorState.getInputItems(responseId);
|
|
52187
|
+
if (!items) throw new HTTPError(404, { error: {
|
|
52188
|
+
message: `No response input items found for id '${responseId}'.`,
|
|
52189
|
+
type: "invalid_request_error"
|
|
52190
|
+
} });
|
|
52191
|
+
let orderedItems = cloneValue(items);
|
|
52192
|
+
if (params?.order === "desc") orderedItems.reverse();
|
|
52193
|
+
if (params?.after) {
|
|
52194
|
+
const afterIndex = orderedItems.findIndex((item) => getInputItemId(item) === params.after);
|
|
52195
|
+
if (afterIndex >= 0) orderedItems = orderedItems.slice(afterIndex + 1);
|
|
52196
|
+
}
|
|
52197
|
+
const limitedItems = orderedItems.slice(0, params?.limit ?? orderedItems.length);
|
|
52198
|
+
return {
|
|
52199
|
+
object: "list",
|
|
52200
|
+
data: limitedItems,
|
|
52201
|
+
first_id: getInputItemId(limitedItems[0]) ?? null,
|
|
52202
|
+
last_id: getInputItemId(limitedItems.at(-1)) ?? null,
|
|
52203
|
+
has_more: limitedItems.length < orderedItems.length
|
|
52204
|
+
};
|
|
52205
|
+
}
|
|
52206
|
+
function deleteStoredResponseOrThrow(responseId) {
|
|
52207
|
+
getStoredResponseOrThrow(responseId);
|
|
52208
|
+
return responsesEmulatorState.deleteResponse(responseId);
|
|
52209
|
+
}
|
|
52210
|
+
async function estimateEmulatorInputTokens(payload, selectedModel) {
|
|
52211
|
+
return {
|
|
52212
|
+
object: "response.input_tokens",
|
|
52213
|
+
input_tokens: await estimateResponsesInputTokens(resolveEffectiveInputForInputTokens(payload), selectedModel)
|
|
52214
|
+
};
|
|
52215
|
+
}
|
|
52216
|
+
function resolveEffectiveInputForInputTokens(payload) {
|
|
52217
|
+
const normalizedInput = normalizeResponsesInput(payload.input);
|
|
52218
|
+
const background = payload.background === null || typeof payload.background === "boolean" ? payload.background : void 0;
|
|
52219
|
+
const conversation = isConversationReference(payload.conversation) ? payload.conversation : void 0;
|
|
52220
|
+
const previousResponseId = typeof payload.previous_response_id === "string" ? payload.previous_response_id : void 0;
|
|
52221
|
+
rejectUnsupportedBackground({ background });
|
|
52222
|
+
const { continuationSourceResponseId } = resolveContinuation({
|
|
52223
|
+
conversation,
|
|
52224
|
+
previous_response_id: previousResponseId
|
|
52225
|
+
});
|
|
52226
|
+
if (continuationSourceResponseId) return [...buildContinuationHistory(continuationSourceResponseId), ...normalizedInput];
|
|
52227
|
+
return normalizedInput;
|
|
52228
|
+
}
|
|
52229
|
+
function resolveContinuation(payload) {
|
|
52230
|
+
const previousResponse = resolvePreviousResponse(payload.previous_response_id);
|
|
52231
|
+
const conversation = resolveConversation(payload.conversation, previousResponse);
|
|
52232
|
+
return {
|
|
52233
|
+
previousResponse,
|
|
52234
|
+
conversation,
|
|
52235
|
+
continuationSourceResponseId: resolveContinuationSourceResponseId(previousResponse, conversation)
|
|
52236
|
+
};
|
|
52237
|
+
}
|
|
52238
|
+
function resolvePreviousResponse(previousResponseId) {
|
|
52239
|
+
if (typeof previousResponseId !== "string" || previousResponseId.length === 0) return;
|
|
52240
|
+
const previousResponse = responsesEmulatorState.getResponse(previousResponseId);
|
|
52241
|
+
if (!previousResponse) throwInvalidRequestError("The selected previous_response_id could not be resolved.", "previous_response_id");
|
|
52242
|
+
return previousResponse;
|
|
52243
|
+
}
|
|
52244
|
+
function resolveConversation(conversation, previousResponse) {
|
|
52245
|
+
if (isConversationReference(conversation)) {
|
|
52246
|
+
const conversationId = getConversationId(conversation);
|
|
52247
|
+
const existingConversation = responsesEmulatorState.getConversation(conversationId);
|
|
52248
|
+
if (!existingConversation) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
52249
|
+
if (previousResponse?.conversation && getConversationId(previousResponse.conversation) !== conversationId) throwInvalidRequestError("The selected previous_response_id does not belong to the selected conversation.", "previous_response_id");
|
|
52250
|
+
return existingConversation;
|
|
52251
|
+
}
|
|
52252
|
+
return previousResponse?.conversation ?? void 0;
|
|
52253
|
+
}
|
|
52254
|
+
function resolveContinuationSourceResponseId(previousResponse, conversation) {
|
|
52255
|
+
if (previousResponse) return previousResponse.id;
|
|
52256
|
+
if (!conversation) return;
|
|
52257
|
+
const head = responsesEmulatorState.getConversationHead(getConversationId(conversation));
|
|
52258
|
+
if (!head) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
52259
|
+
return head;
|
|
52260
|
+
}
|
|
52261
|
+
function buildContinuationHistory(responseId) {
|
|
52262
|
+
const previousResponse = getStoredResponseOrThrow(responseId);
|
|
52263
|
+
const previousInput = responsesEmulatorState.getInputItems(responseId);
|
|
52264
|
+
if (!previousInput) throwInvalidRequestError("The selected previous_response_id is missing stored input items.", "previous_response_id");
|
|
52265
|
+
return [...cloneValue(previousInput), ...convertOutputItemsToInputItems(previousResponse.output)];
|
|
52266
|
+
}
|
|
52267
|
+
function normalizeResponsesInput(input) {
|
|
52268
|
+
if (!input) return [];
|
|
52269
|
+
if (typeof input === "string") return [{
|
|
52270
|
+
type: "message",
|
|
52271
|
+
role: "user",
|
|
52272
|
+
content: input
|
|
52273
|
+
}];
|
|
52274
|
+
if (Array.isArray(input)) return cloneValue(input);
|
|
52275
|
+
return [];
|
|
52276
|
+
}
|
|
52277
|
+
function convertOutputItemsToInputItems(output) {
|
|
52278
|
+
const items = [];
|
|
52279
|
+
for (const item of output) switch (item.type) {
|
|
52280
|
+
case "message":
|
|
52281
|
+
items.push(convertMessageOutputToInput(item));
|
|
52282
|
+
break;
|
|
52283
|
+
case "function_call":
|
|
52284
|
+
items.push(convertFunctionCallOutputToInput(item));
|
|
52285
|
+
break;
|
|
52286
|
+
case "reasoning": {
|
|
52287
|
+
const reasoningInput = convertReasoningOutputToInput(item);
|
|
52288
|
+
if (reasoningInput) items.push(reasoningInput);
|
|
52289
|
+
break;
|
|
52290
|
+
}
|
|
52291
|
+
case "compaction":
|
|
52292
|
+
items.push(convertCompactionOutputToInput(item));
|
|
52293
|
+
break;
|
|
52294
|
+
}
|
|
52295
|
+
return items;
|
|
52296
|
+
}
|
|
52297
|
+
function convertMessageOutputToInput(item) {
|
|
52298
|
+
return {
|
|
52299
|
+
type: "message",
|
|
52300
|
+
role: item.role,
|
|
52301
|
+
status: item.status,
|
|
52302
|
+
content: item.content?.map((content) => {
|
|
52303
|
+
if (content.type === "output_text" && typeof content.text === "string") return {
|
|
52304
|
+
type: "output_text",
|
|
52305
|
+
text: content.text
|
|
52306
|
+
};
|
|
52307
|
+
return cloneValue(content);
|
|
52308
|
+
}) ?? []
|
|
52309
|
+
};
|
|
52310
|
+
}
|
|
52311
|
+
function convertFunctionCallOutputToInput(item) {
|
|
52312
|
+
return {
|
|
52313
|
+
type: "function_call",
|
|
52314
|
+
call_id: item.call_id,
|
|
52315
|
+
name: item.name,
|
|
52316
|
+
arguments: item.arguments,
|
|
52317
|
+
status: item.status
|
|
52318
|
+
};
|
|
52319
|
+
}
|
|
52320
|
+
function convertReasoningOutputToInput(item) {
|
|
52321
|
+
if (!item.encrypted_content) return;
|
|
52322
|
+
return {
|
|
52323
|
+
id: item.id,
|
|
52324
|
+
type: "reasoning",
|
|
52325
|
+
summary: (item.summary ?? []).filter((summary) => typeof summary.text === "string").map((summary) => ({
|
|
52326
|
+
type: "summary_text",
|
|
52327
|
+
text: summary.text
|
|
52328
|
+
})),
|
|
52329
|
+
encrypted_content: item.encrypted_content
|
|
52330
|
+
};
|
|
52331
|
+
}
|
|
52332
|
+
function convertCompactionOutputToInput(item) {
|
|
52333
|
+
return {
|
|
52334
|
+
id: item.id,
|
|
52335
|
+
type: "compaction",
|
|
52336
|
+
encrypted_content: item.encrypted_content
|
|
52337
|
+
};
|
|
52338
|
+
}
|
|
52339
|
+
function normalizeNullableString(value) {
|
|
52340
|
+
return typeof value === "string" ? value : null;
|
|
52341
|
+
}
|
|
52342
|
+
function normalizeServiceTier(value) {
|
|
52343
|
+
if (value === "auto" || value === "default" || value === "flex" || value === "scale" || value === "priority") return value;
|
|
52344
|
+
return null;
|
|
52345
|
+
}
|
|
52346
|
+
function createConversationRef() {
|
|
52347
|
+
return { id: `conv_${randomUUID().replaceAll("-", "")}` };
|
|
52348
|
+
}
|
|
52349
|
+
function isConversationReference(value) {
|
|
52350
|
+
if (typeof value === "string") return value.length > 0;
|
|
52351
|
+
return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && value.id.length > 0;
|
|
52352
|
+
}
|
|
52353
|
+
function getConversationId(conversation) {
|
|
52354
|
+
return typeof conversation === "string" ? conversation : conversation.id;
|
|
52355
|
+
}
|
|
52356
|
+
function getInputItemId(item) {
|
|
52357
|
+
if (!item || typeof item !== "object") return;
|
|
52358
|
+
if ("id" in item && typeof item.id === "string") return item.id;
|
|
52359
|
+
if ("call_id" in item && typeof item.call_id === "string") return item.call_id;
|
|
52360
|
+
}
|
|
52361
|
+
//#endregion
|
|
52660
52362
|
//#region src/routes/responses/strategy.ts
|
|
52661
52363
|
function isRecord(value) {
|
|
52662
52364
|
return typeof value === "object" && value !== null;
|
|
52663
52365
|
}
|
|
52664
|
-
function createStreamIdTracker() {
|
|
52665
|
-
return { itemIdsByOutputIndex: /* @__PURE__ */ new Map() };
|
|
52666
|
-
}
|
|
52667
52366
|
function fixStreamIds(rawData, eventName, state) {
|
|
52668
52367
|
if (!rawData) return rawData;
|
|
52669
52368
|
let parsed;
|
|
@@ -52693,7 +52392,7 @@ function fixStreamIds(rawData, eventName, state) {
|
|
|
52693
52392
|
return JSON.stringify(parsed);
|
|
52694
52393
|
}
|
|
52695
52394
|
function createResponsesPassthroughStrategy(copilotClient, payload, options) {
|
|
52696
|
-
const tracker =
|
|
52395
|
+
const tracker = { itemIdsByOutputIndex: /* @__PURE__ */ new Map() };
|
|
52697
52396
|
return {
|
|
52698
52397
|
async execute() {
|
|
52699
52398
|
try {
|
|
@@ -52707,7 +52406,10 @@ function createResponsesPassthroughStrategy(copilotClient, payload, options) {
|
|
|
52707
52406
|
return Boolean(payload.stream) && isAsyncIterable(result);
|
|
52708
52407
|
},
|
|
52709
52408
|
translateResult(result) {
|
|
52710
|
-
|
|
52409
|
+
const response = result;
|
|
52410
|
+
const mapped = options.mapResponse ? options.mapResponse(response) : response;
|
|
52411
|
+
if (options.mapResponse) options.onTerminalResponse?.(mapped);
|
|
52412
|
+
return mapped;
|
|
52711
52413
|
},
|
|
52712
52414
|
translateStreamChunk(chunk) {
|
|
52713
52415
|
const fixedData = fixStreamIds(chunk.data ?? "", chunk.event, tracker);
|
|
@@ -52786,59 +52488,55 @@ responsesStrategyRegistry.register(responsesPassthroughEntry);
|
|
|
52786
52488
|
//#region src/routes/responses/handler.ts
|
|
52787
52489
|
const HTTP_URL_RE = /^https?:\/\//i;
|
|
52788
52490
|
/**
|
|
52789
|
-
* Core handler for responses endpoint.
|
|
52491
|
+
* Core handler for responses endpoint. Orchestrates the standard pipeline
|
|
52492
|
+
* (ingest → transform → dispatch) via runPipeline, with the responses-specific
|
|
52493
|
+
* emulator request prep, tool/input policies, and context management applied
|
|
52494
|
+
* through the afterIngest / afterTransform lifecycle hooks.
|
|
52790
52495
|
*/
|
|
52791
52496
|
async function handleResponsesCore({ body, signal, headers }) {
|
|
52792
|
-
const
|
|
52793
|
-
|
|
52794
|
-
|
|
52795
|
-
|
|
52796
|
-
|
|
52797
|
-
|
|
52798
|
-
payload: effectivePayload,
|
|
52497
|
+
const emulatorMode = configStore.isEmulatorEnabled();
|
|
52498
|
+
let originalPayload;
|
|
52499
|
+
let emulatorPrepared;
|
|
52500
|
+
return await runPipeline({
|
|
52501
|
+
body,
|
|
52502
|
+
signal,
|
|
52799
52503
|
headers
|
|
52800
|
-
}
|
|
52801
|
-
|
|
52802
|
-
|
|
52803
|
-
|
|
52804
|
-
|
|
52805
|
-
|
|
52806
|
-
|
|
52807
|
-
|
|
52808
|
-
|
|
52809
|
-
|
|
52810
|
-
|
|
52811
|
-
|
|
52812
|
-
|
|
52813
|
-
|
|
52814
|
-
|
|
52815
|
-
|
|
52816
|
-
|
|
52817
|
-
|
|
52818
|
-
|
|
52819
|
-
|
|
52820
|
-
|
|
52821
|
-
|
|
52822
|
-
|
|
52823
|
-
|
|
52824
|
-
|
|
52825
|
-
|
|
52826
|
-
|
|
52827
|
-
|
|
52828
|
-
|
|
52829
|
-
|
|
52830
|
-
|
|
52831
|
-
|
|
52832
|
-
|
|
52833
|
-
|
|
52834
|
-
originalModel: transformResult.trace.length > 0 ? transformResult.trace[0].from : effectivePayload.model,
|
|
52835
|
-
steps: transformResult.trace.map((r) => ({
|
|
52836
|
-
tag: r.tag,
|
|
52837
|
-
from: r.from,
|
|
52838
|
-
to: r.to
|
|
52839
|
-
}))
|
|
52504
|
+
}, {
|
|
52505
|
+
protocol: "responses",
|
|
52506
|
+
transformChain: responsesModelChain,
|
|
52507
|
+
strategyRegistry: responsesStrategyRegistry,
|
|
52508
|
+
afterIngest({ payload }) {
|
|
52509
|
+
originalPayload = payload;
|
|
52510
|
+
emulatorPrepared = emulatorMode ? prepareEmulatorRequest(payload) : void 0;
|
|
52511
|
+
return emulatorPrepared?.upstreamPayload ?? payload;
|
|
52512
|
+
},
|
|
52513
|
+
afterTransform({ payload, selectedModel }) {
|
|
52514
|
+
applyResponsesToolTransforms(payload);
|
|
52515
|
+
applyResponsesInputPolicies(payload);
|
|
52516
|
+
compactInputByLatestCompaction(payload);
|
|
52517
|
+
if (!selectedModel) throwInvalidRequestError("The selected model could not be resolved.", "model");
|
|
52518
|
+
if (!modelCache.supportsEndpoint(selectedModel, "/responses")) throwInvalidRequestError("The selected model does not support the responses endpoint.", "model");
|
|
52519
|
+
applyContextManagement(payload, selectedModel.capabilities.limits.max_prompt_tokens);
|
|
52520
|
+
},
|
|
52521
|
+
buildStrategyContext({ payload, meta, copilotClient, upstreamSignal }) {
|
|
52522
|
+
const { vision, initiator } = getResponsesRequestOptions(payload);
|
|
52523
|
+
const prepared = emulatorPrepared;
|
|
52524
|
+
const requestPayload = originalPayload ?? payload;
|
|
52525
|
+
return {
|
|
52526
|
+
copilotClient,
|
|
52527
|
+
payload,
|
|
52528
|
+
upstreamSignal,
|
|
52529
|
+
requestContext: meta.requestContext ?? {},
|
|
52530
|
+
vision,
|
|
52531
|
+
initiator,
|
|
52532
|
+
decorateResponse: prepared ? (response) => decorateStoredResponse(response, requestPayload, prepared) : void 0,
|
|
52533
|
+
onTerminalResponse: prepared ? (terminalResponse) => {
|
|
52534
|
+
if (!prepared.shouldStore) return;
|
|
52535
|
+
persistEmulatorResponse(terminalResponse, prepared.effectiveInputItems);
|
|
52536
|
+
} : void 0
|
|
52537
|
+
};
|
|
52840
52538
|
}
|
|
52841
|
-
};
|
|
52539
|
+
});
|
|
52842
52540
|
}
|
|
52843
52541
|
function applyResponsesToolTransforms(payload) {
|
|
52844
52542
|
applyFunctionApplyPatch(payload);
|
|
@@ -52944,6 +52642,46 @@ function containsRemoteImageUrl(value) {
|
|
|
52944
52642
|
return Object.values(record).some((entry) => containsRemoteImageUrl(entry));
|
|
52945
52643
|
}
|
|
52946
52644
|
//#endregion
|
|
52645
|
+
//#region src/routes/responses/resource-dispatcher.ts
|
|
52646
|
+
var EmulatorResourceDispatcher = class {
|
|
52647
|
+
retrieve(responseId) {
|
|
52648
|
+
return Promise.resolve(getStoredResponseOrThrow(responseId));
|
|
52649
|
+
}
|
|
52650
|
+
listInputItems(responseId, params) {
|
|
52651
|
+
return Promise.resolve(listStoredInputItemsOrThrow(responseId, params));
|
|
52652
|
+
}
|
|
52653
|
+
async createInputTokens(payload) {
|
|
52654
|
+
return estimateEmulatorInputTokens(payload, resolveModelOrThrow(payload.model ?? ""));
|
|
52655
|
+
}
|
|
52656
|
+
delete(responseId) {
|
|
52657
|
+
return Promise.resolve(deleteStoredResponseOrThrow(responseId));
|
|
52658
|
+
}
|
|
52659
|
+
};
|
|
52660
|
+
var UpstreamResourceDispatcher = class {
|
|
52661
|
+
client;
|
|
52662
|
+
constructor(client) {
|
|
52663
|
+
this.client = client;
|
|
52664
|
+
}
|
|
52665
|
+
retrieve(responseId, params, options) {
|
|
52666
|
+
return this.client.getResponse(responseId, {
|
|
52667
|
+
params,
|
|
52668
|
+
...options
|
|
52669
|
+
});
|
|
52670
|
+
}
|
|
52671
|
+
listInputItems(responseId, params, options) {
|
|
52672
|
+
return this.client.getResponseInputItems(responseId, params, options);
|
|
52673
|
+
}
|
|
52674
|
+
createInputTokens(payload, options) {
|
|
52675
|
+
return this.client.createResponseInputTokens(payload, options);
|
|
52676
|
+
}
|
|
52677
|
+
delete(responseId, options) {
|
|
52678
|
+
return this.client.deleteResponse(responseId, options);
|
|
52679
|
+
}
|
|
52680
|
+
};
|
|
52681
|
+
function createResourceDispatcher() {
|
|
52682
|
+
return configStore.isEmulatorEnabled() ? new EmulatorResourceDispatcher() : new UpstreamResourceDispatcher(createCopilotClient());
|
|
52683
|
+
}
|
|
52684
|
+
//#endregion
|
|
52947
52685
|
//#region src/routes/responses/resource-handler.ts
|
|
52948
52686
|
async function handleRetrieveResponseCore({ params, url, headers, signal }) {
|
|
52949
52687
|
const responseId = requireResponseId(params.responseId);
|
|
@@ -53312,7 +53050,7 @@ const start = defineCommand({
|
|
|
53312
53050
|
},
|
|
53313
53051
|
"upstream-queue-retries": {
|
|
53314
53052
|
type: "string",
|
|
53315
|
-
description: "Maximum retries for upstream 429 responses (default:
|
|
53053
|
+
description: "Maximum retries for upstream 429 responses (default: 5)"
|
|
53316
53054
|
},
|
|
53317
53055
|
"upstream-queue-base-delay": {
|
|
53318
53056
|
type: "string",
|