ghc-proxy 0.6.2 → 0.7.1
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 +38 -61
- package/dist/main.mjs +1225 -1416
- package/dist/main.mjs.map +1 -1
- package/package.json +9 -4
package/dist/main.mjs
CHANGED
|
@@ -5754,6 +5754,11 @@ const configFileSchema = object({
|
|
|
5754
5754
|
responsesApiAutoCompactInput: boolean().optional(),
|
|
5755
5755
|
responsesApiAutoContextManagement: boolean().optional(),
|
|
5756
5756
|
responsesApiContextManagementModels: array(string()).optional(),
|
|
5757
|
+
responsesApiParameterFilters: array(object({
|
|
5758
|
+
models: array(string()).min(1),
|
|
5759
|
+
params: array(string()).min(1)
|
|
5760
|
+
})).optional(),
|
|
5761
|
+
responsesApiParameterFiltersReplaceDefault: boolean().optional(),
|
|
5757
5762
|
responsesOfficialEmulator: boolean().optional(),
|
|
5758
5763
|
responsesOfficialEmulatorTtlSeconds: number().int().positive().optional(),
|
|
5759
5764
|
modelReasoningEfforts: record(string(), reasoningEffortSchema).optional(),
|
|
@@ -5761,12 +5766,6 @@ const configFileSchema = object({
|
|
|
5761
5766
|
from: string(),
|
|
5762
5767
|
to: string()
|
|
5763
5768
|
})).optional(),
|
|
5764
|
-
contextUpgradeRules: array(object({
|
|
5765
|
-
from: string(),
|
|
5766
|
-
to: string()
|
|
5767
|
-
})).optional(),
|
|
5768
|
-
contextUpgrade: boolean().optional(),
|
|
5769
|
-
contextUpgradeTokenThreshold: number().int().positive().optional(),
|
|
5770
5769
|
upstreamQueueConcurrency: number().int().positive().optional(),
|
|
5771
5770
|
upstreamQueueMaxRetries: number().int().nonnegative().optional(),
|
|
5772
5771
|
upstreamQueueBaseDelaySeconds: number().int().nonnegative().optional(),
|
|
@@ -5855,12 +5854,6 @@ var ConfigStore = class {
|
|
|
5855
5854
|
getEmulatorTtlSeconds() {
|
|
5856
5855
|
return getCachedConfig().responsesOfficialEmulatorTtlSeconds ?? 14400;
|
|
5857
5856
|
}
|
|
5858
|
-
isContextUpgradeEnabled() {
|
|
5859
|
-
return getCachedConfig().contextUpgrade !== false;
|
|
5860
|
-
}
|
|
5861
|
-
getContextUpgradeThreshold() {
|
|
5862
|
-
return getCachedConfig().contextUpgradeTokenThreshold ?? 16e4;
|
|
5863
|
-
}
|
|
5864
5857
|
isCompactSmallModelEnabled() {
|
|
5865
5858
|
return getCachedConfig().compactUseSmallModel ?? false;
|
|
5866
5859
|
}
|
|
@@ -5883,36 +5876,233 @@ var ConfigStore = class {
|
|
|
5883
5876
|
getReasoningEffort(model) {
|
|
5884
5877
|
return getCachedConfig().modelReasoningEfforts?.[model] ?? "high";
|
|
5885
5878
|
}
|
|
5879
|
+
getResponsesParameterFilters() {
|
|
5880
|
+
return getCachedConfig().responsesApiParameterFilters ?? [];
|
|
5881
|
+
}
|
|
5882
|
+
shouldReplaceDefaultParameterFilters() {
|
|
5883
|
+
return getCachedConfig().responsesApiParameterFiltersReplaceDefault ?? false;
|
|
5884
|
+
}
|
|
5886
5885
|
getModelRewrites() {
|
|
5887
5886
|
return getCachedConfig().modelRewrites ?? [];
|
|
5888
5887
|
}
|
|
5889
|
-
getContextUpgradeRules() {
|
|
5890
|
-
return getCachedConfig().contextUpgradeRules ?? [];
|
|
5891
|
-
}
|
|
5892
5888
|
getModelFallback() {
|
|
5893
5889
|
return getCachedConfig().modelFallback;
|
|
5894
5890
|
}
|
|
5895
|
-
|
|
5896
|
-
|
|
5891
|
+
};
|
|
5892
|
+
const configStore = new ConfigStore();
|
|
5893
|
+
//#endregion
|
|
5894
|
+
//#region src/state/model-cache.ts
|
|
5895
|
+
const RESPONSES_ENDPOINT = "/responses";
|
|
5896
|
+
/**
|
|
5897
|
+
* Models whose upstream `/v1/messages` endpoint rejects the `output_config`
|
|
5898
|
+
* field with "Extra inputs are not permitted".
|
|
5899
|
+
*
|
|
5900
|
+
* Verified via `scripts/probes/messages/output-config.ts` (2026-03-14).
|
|
5901
|
+
* When new models appear, re-run the probe and update this list.
|
|
5902
|
+
*/
|
|
5903
|
+
const MODELS_REJECTING_OUTPUT_CONFIG = new Set([
|
|
5904
|
+
"claude-sonnet-4",
|
|
5905
|
+
"claude-sonnet-4.5",
|
|
5906
|
+
"claude-haiku-4.5"
|
|
5907
|
+
]);
|
|
5908
|
+
var ModelCache = class {
|
|
5909
|
+
models;
|
|
5910
|
+
vsCodeVersion;
|
|
5911
|
+
cacheModels(models) {
|
|
5912
|
+
this.models = models;
|
|
5913
|
+
}
|
|
5914
|
+
clearModels() {
|
|
5915
|
+
this.models = void 0;
|
|
5897
5916
|
}
|
|
5898
|
-
|
|
5899
|
-
return
|
|
5917
|
+
getModels() {
|
|
5918
|
+
return this.models;
|
|
5900
5919
|
}
|
|
5901
|
-
|
|
5902
|
-
|
|
5920
|
+
setVSCodeVersion(version) {
|
|
5921
|
+
this.vsCodeVersion = version;
|
|
5903
5922
|
}
|
|
5904
|
-
|
|
5905
|
-
|
|
5923
|
+
clearVSCodeVersion() {
|
|
5924
|
+
this.vsCodeVersion = void 0;
|
|
5925
|
+
}
|
|
5926
|
+
getVSCodeVersion() {
|
|
5927
|
+
return this.vsCodeVersion;
|
|
5928
|
+
}
|
|
5929
|
+
findById(modelId) {
|
|
5930
|
+
return this.models?.data.find((model) => model.id === modelId);
|
|
5931
|
+
}
|
|
5932
|
+
getModelIds() {
|
|
5933
|
+
return this.models?.data.map((model) => model.id) ?? [];
|
|
5934
|
+
}
|
|
5935
|
+
supportsEndpoint(model, endpoint) {
|
|
5936
|
+
return model?.supported_endpoints?.includes(endpoint) ?? false;
|
|
5937
|
+
}
|
|
5938
|
+
supportsToolCalls(model) {
|
|
5939
|
+
return model?.capabilities.supports.tool_calls ?? false;
|
|
5940
|
+
}
|
|
5941
|
+
supportsAdaptiveThinking(model) {
|
|
5942
|
+
return model?.capabilities.supports.adaptive_thinking ?? false;
|
|
5943
|
+
}
|
|
5944
|
+
supportsVision(model) {
|
|
5945
|
+
return model?.capabilities.supports.vision ?? false;
|
|
5946
|
+
}
|
|
5947
|
+
supportsReasoningEffort(model) {
|
|
5948
|
+
return (model?.capabilities.supports.reasoning_effort?.length ?? 0) > 0;
|
|
5949
|
+
}
|
|
5950
|
+
supportsOutputConfig(model) {
|
|
5951
|
+
if (!model) return true;
|
|
5952
|
+
return !MODELS_REJECTING_OUTPUT_CONFIG.has(model.id);
|
|
5953
|
+
}
|
|
5954
|
+
};
|
|
5955
|
+
const modelCache = new ModelCache();
|
|
5956
|
+
//#endregion
|
|
5957
|
+
//#region src/translator/anthropic/translation-issue.ts
|
|
5958
|
+
var TranslationFailure = class extends Error {
|
|
5959
|
+
status;
|
|
5960
|
+
kind;
|
|
5961
|
+
constructor(message, options) {
|
|
5962
|
+
super(message);
|
|
5963
|
+
this.name = "TranslationFailure";
|
|
5964
|
+
this.status = options.status;
|
|
5965
|
+
this.kind = options.kind;
|
|
5906
5966
|
}
|
|
5907
5967
|
};
|
|
5908
|
-
const configStore = new ConfigStore();
|
|
5909
5968
|
//#endregion
|
|
5910
|
-
//#region src/lib/
|
|
5969
|
+
//#region src/lib/error.ts
|
|
5970
|
+
var HTTPError = class extends Error {
|
|
5971
|
+
status;
|
|
5972
|
+
body;
|
|
5973
|
+
constructor(status, body) {
|
|
5974
|
+
super(body.error.message);
|
|
5975
|
+
this.name = "HTTPError";
|
|
5976
|
+
this.status = status;
|
|
5977
|
+
this.body = body;
|
|
5978
|
+
}
|
|
5979
|
+
toResponse() {
|
|
5980
|
+
return Response.json(this.body, { status: this.status });
|
|
5981
|
+
}
|
|
5982
|
+
};
|
|
5983
|
+
function throwInvalidRequestError(message, param, code) {
|
|
5984
|
+
throw new HTTPError(400, { error: {
|
|
5985
|
+
message,
|
|
5986
|
+
type: "invalid_request_error",
|
|
5987
|
+
param,
|
|
5988
|
+
...code ? { code } : {}
|
|
5989
|
+
} });
|
|
5990
|
+
}
|
|
5991
|
+
function fromTranslationFailure(failure) {
|
|
5992
|
+
return new HTTPError(failure.status, { error: {
|
|
5993
|
+
message: failure.message,
|
|
5994
|
+
type: "translation_error"
|
|
5995
|
+
} });
|
|
5996
|
+
}
|
|
5997
|
+
function resolveModelOrThrow(modelId) {
|
|
5998
|
+
const model = modelCache.findById(modelId);
|
|
5999
|
+
if (!model) throwInvalidRequestError("The selected model could not be resolved.", "model");
|
|
6000
|
+
return model;
|
|
6001
|
+
}
|
|
6002
|
+
function withTranslationErrors(fn) {
|
|
6003
|
+
try {
|
|
6004
|
+
return fn();
|
|
6005
|
+
} catch (error) {
|
|
6006
|
+
if (error instanceof TranslationFailure) throw fromTranslationFailure(error);
|
|
6007
|
+
throw error;
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
6010
|
+
function previewBody(text, maxLength = 500) {
|
|
6011
|
+
return text.length > maxLength ? `${text.slice(0, maxLength)}…` : text;
|
|
6012
|
+
}
|
|
6013
|
+
function isStructuredErrorPayload(value) {
|
|
6014
|
+
return typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null;
|
|
6015
|
+
}
|
|
6016
|
+
function upstreamErrorType(status) {
|
|
6017
|
+
return status === 429 ? "rate_limit_error" : "upstream_error";
|
|
6018
|
+
}
|
|
6019
|
+
function createFallbackUpstreamError(message, response, rawText) {
|
|
6020
|
+
return { error: {
|
|
6021
|
+
message: rawText.trim() || message,
|
|
6022
|
+
type: upstreamErrorType(response.status)
|
|
6023
|
+
} };
|
|
6024
|
+
}
|
|
6025
|
+
function getDiagnosticHeaders(response) {
|
|
6026
|
+
const headerNames = [
|
|
6027
|
+
"retry-after",
|
|
6028
|
+
"x-ratelimit-limit",
|
|
6029
|
+
"x-ratelimit-remaining",
|
|
6030
|
+
"x-ratelimit-reset",
|
|
6031
|
+
"x-github-request-id",
|
|
6032
|
+
"x-request-id"
|
|
6033
|
+
];
|
|
6034
|
+
const headers = {};
|
|
6035
|
+
for (const name of headerNames) {
|
|
6036
|
+
const value = response.headers.get(name);
|
|
6037
|
+
if (value) headers[name] = value;
|
|
6038
|
+
}
|
|
6039
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
6040
|
+
}
|
|
6041
|
+
async function throwUpstreamError(message, response) {
|
|
6042
|
+
let rawText = "";
|
|
6043
|
+
let body;
|
|
6044
|
+
try {
|
|
6045
|
+
rawText = await response.text();
|
|
6046
|
+
const json = JSON.parse(rawText);
|
|
6047
|
+
body = isStructuredErrorPayload(json) ? json : createFallbackUpstreamError(message, response, rawText);
|
|
6048
|
+
} catch {
|
|
6049
|
+
body = createFallbackUpstreamError(message, response, rawText);
|
|
6050
|
+
}
|
|
6051
|
+
consola.error("Upstream error:", {
|
|
6052
|
+
status: response.status,
|
|
6053
|
+
statusText: response.statusText,
|
|
6054
|
+
url: response.url,
|
|
6055
|
+
body,
|
|
6056
|
+
rawBody: rawText ? previewBody(rawText) : "<empty>",
|
|
6057
|
+
headers: getDiagnosticHeaders(response)
|
|
6058
|
+
});
|
|
6059
|
+
throw new HTTPError(response.status, body);
|
|
6060
|
+
}
|
|
6061
|
+
//#endregion
|
|
6062
|
+
//#region src/util/sleep.ts
|
|
6063
|
+
function sleep(ms) {
|
|
6064
|
+
return new Promise((resolve) => {
|
|
6065
|
+
setTimeout(resolve, ms);
|
|
6066
|
+
});
|
|
6067
|
+
}
|
|
6068
|
+
//#endregion
|
|
6069
|
+
//#region src/state/rate-limiter.ts
|
|
6070
|
+
var RateLimiter = class {
|
|
6071
|
+
nextAvailableAt = 0;
|
|
6072
|
+
reset() {
|
|
6073
|
+
this.nextAvailableAt = 0;
|
|
6074
|
+
}
|
|
6075
|
+
async acquire(intervalSeconds, waitMode) {
|
|
6076
|
+
if (intervalSeconds === void 0) return;
|
|
6077
|
+
const now = Date.now();
|
|
6078
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
6079
|
+
if (!this.nextAvailableAt || now >= this.nextAvailableAt) {
|
|
6080
|
+
this.nextAvailableAt = now + intervalMs;
|
|
6081
|
+
return;
|
|
6082
|
+
}
|
|
6083
|
+
const waitMs = this.nextAvailableAt - now;
|
|
6084
|
+
const waitTimeSeconds = Math.ceil(waitMs / 1e3);
|
|
6085
|
+
if (!waitMode) {
|
|
6086
|
+
consola.warn(`Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`);
|
|
6087
|
+
throw new HTTPError(429, { error: {
|
|
6088
|
+
message: "Rate limit exceeded",
|
|
6089
|
+
type: "rate_limit_error"
|
|
6090
|
+
} });
|
|
6091
|
+
}
|
|
6092
|
+
const claimedSlot = this.nextAvailableAt;
|
|
6093
|
+
this.nextAvailableAt = claimedSlot + intervalMs;
|
|
6094
|
+
consola.warn(`Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`);
|
|
6095
|
+
await sleep(waitMs);
|
|
6096
|
+
consola.info("Rate limit wait completed, proceeding with request");
|
|
6097
|
+
}
|
|
6098
|
+
};
|
|
6099
|
+
const rateLimiter = new RateLimiter();
|
|
6100
|
+
//#endregion
|
|
6101
|
+
//#region src/state/responses-emulator-state.ts
|
|
5911
6102
|
const DEFAULT_MAX_TOTAL_ENTRIES = 1e4;
|
|
5912
6103
|
const BACKGROUND_PRUNE_INTERVAL_MS = 6e4;
|
|
5913
6104
|
function cloneValue$1(value) {
|
|
5914
|
-
|
|
5915
|
-
return JSON.parse(JSON.stringify(value));
|
|
6105
|
+
return structuredClone(value);
|
|
5916
6106
|
}
|
|
5917
6107
|
function currentTime() {
|
|
5918
6108
|
return Date.now();
|
|
@@ -5958,7 +6148,6 @@ function createResponsesEmulatorState(opts) {
|
|
|
5958
6148
|
pruneIntervalId = void 0;
|
|
5959
6149
|
}
|
|
5960
6150
|
}
|
|
5961
|
-
startBackgroundPrune();
|
|
5962
6151
|
function totalEntries() {
|
|
5963
6152
|
let sum = 0;
|
|
5964
6153
|
for (const map of allMaps) sum += map.size;
|
|
@@ -5977,6 +6166,7 @@ function createResponsesEmulatorState(opts) {
|
|
|
5977
6166
|
return cloneValue$1(entry.value);
|
|
5978
6167
|
}
|
|
5979
6168
|
function writeMap(map, key, value, ttlSeconds, at = currentTime()) {
|
|
6169
|
+
startBackgroundPrune();
|
|
5980
6170
|
if (!map.has(key)) enforceCapOnWrite();
|
|
5981
6171
|
const cloned = cloneValue$1(value);
|
|
5982
6172
|
map.set(key, {
|
|
@@ -5989,6 +6179,7 @@ function createResponsesEmulatorState(opts) {
|
|
|
5989
6179
|
return map.delete(key);
|
|
5990
6180
|
}
|
|
5991
6181
|
function putDeletionFlag(map, id, ttlSeconds, at = currentTime()) {
|
|
6182
|
+
startBackgroundPrune();
|
|
5992
6183
|
if (!map.has(id)) enforceCapOnWrite();
|
|
5993
6184
|
const flag = {
|
|
5994
6185
|
deleted: true,
|
|
@@ -6136,9 +6327,6 @@ function createResponsesEmulatorState(opts) {
|
|
|
6136
6327
|
getConversationHead(conversationId) {
|
|
6137
6328
|
return readMap(conversationHeadRecords, conversationId);
|
|
6138
6329
|
},
|
|
6139
|
-
clearConversationHead(conversationId) {
|
|
6140
|
-
deleteMapEntry(conversationHeadRecords, conversationId);
|
|
6141
|
-
},
|
|
6142
6330
|
setInputItems(responseId, inputItems, options) {
|
|
6143
6331
|
removeDeletionFlag(inputItemDeletionFlags, responseId);
|
|
6144
6332
|
return writeMap(inputItemRecords, responseId, inputItems, options?.ttlSeconds);
|
|
@@ -6157,329 +6345,19 @@ function createResponsesEmulatorState(opts) {
|
|
|
6157
6345
|
deleted: true
|
|
6158
6346
|
};
|
|
6159
6347
|
},
|
|
6160
|
-
setDeletionFlag(kind, id, options) {
|
|
6161
|
-
return putDeletionFlag(deletionMap(kind), id, options?.ttlSeconds);
|
|
6162
|
-
},
|
|
6163
6348
|
getDeletionFlag(kind, id) {
|
|
6164
6349
|
return readDeletionFlag(deletionMap(kind), id);
|
|
6165
|
-
},
|
|
6166
|
-
clearDeletionFlag(kind, id) {
|
|
6167
|
-
removeDeletionFlag(deletionMap(kind), id);
|
|
6168
6350
|
}
|
|
6169
6351
|
};
|
|
6170
6352
|
}
|
|
6171
6353
|
const responsesEmulatorState = createResponsesEmulatorState();
|
|
6172
6354
|
//#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
6355
|
//#region src/state/runtime.ts
|
|
6381
6356
|
var RuntimeStore = class {
|
|
6382
6357
|
dumpFailedPayloads = false;
|
|
6383
6358
|
};
|
|
6384
6359
|
const runtimeStore = new RuntimeStore();
|
|
6385
6360
|
//#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
6361
|
//#region node_modules/fetch-event-stream/esm/deps/jsr.io/@std/streams/0.221.0/text_line_stream.js
|
|
6484
6362
|
/**
|
|
6485
6363
|
* Transform a stream into a stream where each chunk is divided by a newline,
|
|
@@ -6602,6 +6480,64 @@ async function* events(res, signal) {
|
|
|
6602
6480
|
}
|
|
6603
6481
|
}
|
|
6604
6482
|
//#endregion
|
|
6483
|
+
//#region src/clients/api-config.ts
|
|
6484
|
+
function standardHeaders() {
|
|
6485
|
+
return {
|
|
6486
|
+
"content-type": "application/json",
|
|
6487
|
+
"accept": "application/json"
|
|
6488
|
+
};
|
|
6489
|
+
}
|
|
6490
|
+
const COPILOT_VERSION = "0.26.7";
|
|
6491
|
+
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
6492
|
+
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
6493
|
+
const API_VERSION = "2025-04-01";
|
|
6494
|
+
const TRAILING_SLASHES_RE$1 = /\/+$/;
|
|
6495
|
+
/** Headers shared by both Copilot and GitHub API requests (editor identity + versioning) */
|
|
6496
|
+
function editorHeaders(config) {
|
|
6497
|
+
return {
|
|
6498
|
+
"editor-version": `vscode/${config.vsCodeVersion ?? "unknown"}`,
|
|
6499
|
+
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
6500
|
+
"user-agent": USER_AGENT,
|
|
6501
|
+
"x-github-api-version": API_VERSION,
|
|
6502
|
+
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
6503
|
+
};
|
|
6504
|
+
}
|
|
6505
|
+
function copilotBaseUrl(config) {
|
|
6506
|
+
if (config.copilotApiBase) return config.copilotApiBase.replace(TRAILING_SLASHES_RE$1, "");
|
|
6507
|
+
return config.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${config.accountType}.githubcopilot.com`;
|
|
6508
|
+
}
|
|
6509
|
+
function copilotHeaders(auth, config, options = {}) {
|
|
6510
|
+
const requestContext = options.requestContext;
|
|
6511
|
+
const headers = {
|
|
6512
|
+
"Authorization": `Bearer ${auth.copilotToken}`,
|
|
6513
|
+
"content-type": standardHeaders()["content-type"],
|
|
6514
|
+
"copilot-integration-id": "vscode-chat",
|
|
6515
|
+
...editorHeaders(config),
|
|
6516
|
+
"openai-intent": "conversation-panel",
|
|
6517
|
+
"x-request-id": randomUUID()
|
|
6518
|
+
};
|
|
6519
|
+
if (options.vision) headers["copilot-vision-request"] = "true";
|
|
6520
|
+
if (options.initiator) headers["X-Initiator"] = options.initiator;
|
|
6521
|
+
if (requestContext?.interactionType) headers["X-Interaction-Type"] = requestContext.interactionType;
|
|
6522
|
+
if (requestContext?.agentTaskId) headers["X-Agent-Task-Id"] = requestContext.agentTaskId;
|
|
6523
|
+
if (requestContext?.parentAgentTaskId) headers["X-Parent-Agent-Id"] = requestContext.parentAgentTaskId;
|
|
6524
|
+
if (requestContext?.clientSessionId) headers["X-Client-Session-Id"] = requestContext.clientSessionId;
|
|
6525
|
+
if (requestContext?.interactionId) headers["X-Interaction-Id"] = requestContext.interactionId;
|
|
6526
|
+
if (requestContext?.clientMachineId) headers["X-Client-Machine-Id"] = requestContext.clientMachineId;
|
|
6527
|
+
return headers;
|
|
6528
|
+
}
|
|
6529
|
+
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
6530
|
+
function githubHeaders(auth, config) {
|
|
6531
|
+
return {
|
|
6532
|
+
...standardHeaders(),
|
|
6533
|
+
authorization: `token ${auth.githubToken}`,
|
|
6534
|
+
...editorHeaders(config)
|
|
6535
|
+
};
|
|
6536
|
+
}
|
|
6537
|
+
const GITHUB_BASE_URL = "https://github.com";
|
|
6538
|
+
const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
|
6539
|
+
const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
6540
|
+
//#endregion
|
|
6605
6541
|
//#region src/clients/copilot-client.ts
|
|
6606
6542
|
var CopilotClient = class {
|
|
6607
6543
|
auth;
|
|
@@ -6930,7 +6866,55 @@ async function getVSCodeVersion() {
|
|
|
6930
6866
|
return remoteVersion ?? localVersion ?? FALLBACK;
|
|
6931
6867
|
}
|
|
6932
6868
|
//#endregion
|
|
6933
|
-
//#region src/
|
|
6869
|
+
//#region src/clients/ghe-domain.ts
|
|
6870
|
+
const GHE_SUFFIX = ".ghe.com";
|
|
6871
|
+
/**
|
|
6872
|
+
* Normalize a GHE domain input to a lowercase bare domain.
|
|
6873
|
+
*
|
|
6874
|
+
* Accepted inputs: `company.ghe.com`, `https://company.ghe.com`,
|
|
6875
|
+
* `https://Company.GHE.com/`, etc.
|
|
6876
|
+
*
|
|
6877
|
+
* @returns Bare lowercase domain, e.g. `company.ghe.com`
|
|
6878
|
+
* @throws {Error} If the input is empty or does not end with `.ghe.com`
|
|
6879
|
+
*/
|
|
6880
|
+
function normalizeGheDomain(input) {
|
|
6881
|
+
const trimmed = input.trim();
|
|
6882
|
+
if (!trimmed) throw new Error("GHE domain must not be empty");
|
|
6883
|
+
let domain;
|
|
6884
|
+
try {
|
|
6885
|
+
domain = (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname.toLowerCase();
|
|
6886
|
+
} catch {
|
|
6887
|
+
throw new Error(`Invalid GHE domain: ${trimmed}`);
|
|
6888
|
+
}
|
|
6889
|
+
if (!domain.endsWith(GHE_SUFFIX) || domain === GHE_SUFFIX.slice(1)) throw new Error(`GHE domain must end with ${GHE_SUFFIX} (got "${domain}")`);
|
|
6890
|
+
return domain;
|
|
6891
|
+
}
|
|
6892
|
+
/**
|
|
6893
|
+
* Build GitHub base URL and API base URL for a given GHE domain,
|
|
6894
|
+
* or return the public GitHub defaults when no domain is provided.
|
|
6895
|
+
*/
|
|
6896
|
+
function buildGitHubUrls(gheDomain) {
|
|
6897
|
+
if (!gheDomain) return {
|
|
6898
|
+
baseUrl: GITHUB_BASE_URL,
|
|
6899
|
+
apiBaseUrl: GITHUB_API_BASE_URL
|
|
6900
|
+
};
|
|
6901
|
+
const domain = normalizeGheDomain(gheDomain);
|
|
6902
|
+
return {
|
|
6903
|
+
baseUrl: `https://${domain}`,
|
|
6904
|
+
apiBaseUrl: `https://api.${domain}`
|
|
6905
|
+
};
|
|
6906
|
+
}
|
|
6907
|
+
//#endregion
|
|
6908
|
+
//#region src/util/duration.ts
|
|
6909
|
+
/**
|
|
6910
|
+
* Formats a millisecond duration as a compact human-readable string:
|
|
6911
|
+
* `<n>ms` under one second, otherwise `<n>s` rounded to whole seconds.
|
|
6912
|
+
*/
|
|
6913
|
+
function formatDurationMs(ms) {
|
|
6914
|
+
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
6915
|
+
}
|
|
6916
|
+
//#endregion
|
|
6917
|
+
//#region src/clients/upstream-queue.ts
|
|
6934
6918
|
const DEFAULT_UPSTREAM_QUEUE_OPTIONS = {
|
|
6935
6919
|
concurrency: 10,
|
|
6936
6920
|
maxRetries: 5,
|
|
@@ -6987,7 +6971,7 @@ var UpstreamRequestQueue = class {
|
|
|
6987
6971
|
this.logger.warn([
|
|
6988
6972
|
"Upstream rate limited;",
|
|
6989
6973
|
`retrying ${formatRequestContext(context)}`,
|
|
6990
|
-
`in ${
|
|
6974
|
+
`in ${formatDurationMs(delayMs)}`,
|
|
6991
6975
|
`(attempt ${attempt + 1}/${this.options.maxRetries})`
|
|
6992
6976
|
].join(" "));
|
|
6993
6977
|
await abortableSleep(this.sleep, delayMs, signal);
|
|
@@ -7097,9 +7081,6 @@ function formatRequestContext(context) {
|
|
|
7097
7081
|
return `${context.method ?? "GET"} ${context.url}`;
|
|
7098
7082
|
}
|
|
7099
7083
|
}
|
|
7100
|
-
function formatDelay(delayMs) {
|
|
7101
|
-
return delayMs < 1e3 ? `${delayMs}ms` : `${Math.round(delayMs / 1e3)}s`;
|
|
7102
|
-
}
|
|
7103
7084
|
function abortableSleep(sleep, ms, signal) {
|
|
7104
7085
|
if (!signal) return sleep(ms);
|
|
7105
7086
|
signal.throwIfAborted();
|
|
@@ -7118,7 +7099,7 @@ function abortableSleep(sleep, ms, signal) {
|
|
|
7118
7099
|
});
|
|
7119
7100
|
}
|
|
7120
7101
|
//#endregion
|
|
7121
|
-
//#region src/
|
|
7102
|
+
//#region src/clients/factory.ts
|
|
7122
7103
|
const upstreamRequestQueue = createDefaultUpstreamRequestQueue();
|
|
7123
7104
|
function configureUpstreamRequestQueue(options) {
|
|
7124
7105
|
upstreamRequestQueue.updateOptions(options);
|
|
@@ -7363,11 +7344,6 @@ const checkUsage = defineCommand({
|
|
|
7363
7344
|
await setupGitHubToken();
|
|
7364
7345
|
try {
|
|
7365
7346
|
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
7347
|
function summarizeQuota(name, snap) {
|
|
7372
7348
|
if (!snap) return `${name}: N/A`;
|
|
7373
7349
|
const total = snap.entitlement;
|
|
@@ -7376,7 +7352,7 @@ const checkUsage = defineCommand({
|
|
|
7376
7352
|
const percentRemaining = snap.percent_remaining;
|
|
7377
7353
|
return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
|
|
7378
7354
|
}
|
|
7379
|
-
const premiumLine =
|
|
7355
|
+
const premiumLine = summarizeQuota("Premium", usage.quota_snapshots.premium_interactions);
|
|
7380
7356
|
const chatLine = summarizeQuota("Chat", usage.quota_snapshots.chat);
|
|
7381
7357
|
const completionsLine = summarizeQuota("Completions", usage.quota_snapshots.completions);
|
|
7382
7358
|
consola.box(`Copilot Usage (plan: ${usage.copilot_plan})\nQuota resets: ${usage.quota_reset_date}\n\nQuotas:\n ${premiumLine}\n ${chatLine}\n ${completionsLine}`);
|
|
@@ -7387,8 +7363,8 @@ const checkUsage = defineCommand({
|
|
|
7387
7363
|
}
|
|
7388
7364
|
});
|
|
7389
7365
|
//#endregion
|
|
7390
|
-
//#region src/
|
|
7391
|
-
const VERSION = "0.
|
|
7366
|
+
//#region src/util/version.ts
|
|
7367
|
+
const VERSION = "0.7.1";
|
|
7392
7368
|
//#endregion
|
|
7393
7369
|
//#region src/debug.ts
|
|
7394
7370
|
function getRuntimeInfo() {
|
|
@@ -7656,59 +7632,6 @@ async function getTokenCount(payload, model) {
|
|
|
7656
7632
|
async function estimateResponsesInputTokens(inputItems, model) {
|
|
7657
7633
|
return (await getEncoder(getTokenizerFromModel(model))).encode(JSON.stringify(inputItems)).length;
|
|
7658
7634
|
}
|
|
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
7635
|
//#endregion
|
|
7713
7636
|
//#region src/selfcheck.ts
|
|
7714
7637
|
const PROBE_ENCODINGS = [
|
|
@@ -29208,7 +29131,7 @@ var require_eventsource = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
|
|
|
29208
29131
|
};
|
|
29209
29132
|
}));
|
|
29210
29133
|
//#endregion
|
|
29211
|
-
//#region src/
|
|
29134
|
+
//#region src/cli/proxy.ts
|
|
29212
29135
|
var import_undici = (/* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
29213
29136
|
const Client = require_client();
|
|
29214
29137
|
const Dispatcher = require_dispatcher();
|
|
@@ -29419,7 +29342,7 @@ function initProxyFromEnv() {
|
|
|
29419
29342
|
}
|
|
29420
29343
|
}
|
|
29421
29344
|
//#endregion
|
|
29422
|
-
//#region src/
|
|
29345
|
+
//#region src/cli/shell.ts
|
|
29423
29346
|
const EXE_EXTENSION_RE = /\.exe$/i;
|
|
29424
29347
|
function normalizeShellName(raw) {
|
|
29425
29348
|
if (!raw) return;
|
|
@@ -29508,7 +29431,7 @@ function generateEnvScript(envVars, commandToRun = "") {
|
|
|
29508
29431
|
//#endregion
|
|
29509
29432
|
//#region src/lib/model-resolver.ts
|
|
29510
29433
|
const DEFAULT_FALLBACKS = {
|
|
29511
|
-
claudeOpus: "claude-opus-4.
|
|
29434
|
+
claudeOpus: "claude-opus-4.8",
|
|
29512
29435
|
claudeSonnet: "claude-sonnet-4.6",
|
|
29513
29436
|
claudeHaiku: "claude-haiku-4.5"
|
|
29514
29437
|
};
|
|
@@ -29528,7 +29451,7 @@ function resolveModel(modelId, knownModelIds, config) {
|
|
|
29528
29451
|
return modelId;
|
|
29529
29452
|
}
|
|
29530
29453
|
//#endregion
|
|
29531
|
-
//#region src/
|
|
29454
|
+
//#region src/cli/startup-banner.ts
|
|
29532
29455
|
function printStartupBanner(serverUrl) {
|
|
29533
29456
|
const lines = [];
|
|
29534
29457
|
lines.push(`ghc-proxy v${VERSION}`);
|
|
@@ -47817,8 +47740,7 @@ function getRequestModelMapping(request) {
|
|
|
47817
47740
|
return requestModelMapping.get(request);
|
|
47818
47741
|
}
|
|
47819
47742
|
function formatElapsed(start) {
|
|
47820
|
-
|
|
47821
|
-
return delta < 1e3 ? `${delta}ms` : `${Math.round(delta / 1e3)}s`;
|
|
47743
|
+
return formatDurationMs(Date.now() - start);
|
|
47822
47744
|
}
|
|
47823
47745
|
function formatPath(rawUrl) {
|
|
47824
47746
|
try {
|
|
@@ -47849,8 +47771,8 @@ function getEffectiveModel(info) {
|
|
|
47849
47771
|
}
|
|
47850
47772
|
/**
|
|
47851
47773
|
* Mutate `modelMapping` in place by appending a transform step.
|
|
47852
|
-
*
|
|
47853
|
-
*
|
|
47774
|
+
* Strategy contexts hold a reference to the same `modelMapping`,
|
|
47775
|
+
* so steps are pushed directly rather than returning a new object.
|
|
47854
47776
|
*/
|
|
47855
47777
|
function appendModelStepInPlace(info, tag, newModel) {
|
|
47856
47778
|
const current = getEffectiveModel(info);
|
|
@@ -47893,6 +47815,16 @@ function logRequest(method, url, status, elapsed, modelInfo, requestId) {
|
|
|
47893
47815
|
//#endregion
|
|
47894
47816
|
//#region src/lib/sse-adapter.ts
|
|
47895
47817
|
/**
|
|
47818
|
+
* Serializes Anthropic stream events into SSE output items
|
|
47819
|
+
* (one `{ event, data }` per event, with `data` as the JSON-encoded event).
|
|
47820
|
+
*/
|
|
47821
|
+
function serializeAnthropicSSE(events) {
|
|
47822
|
+
return events.map((event) => ({
|
|
47823
|
+
event: event.type,
|
|
47824
|
+
data: JSON.stringify(event)
|
|
47825
|
+
}));
|
|
47826
|
+
}
|
|
47827
|
+
/**
|
|
47896
47828
|
* Bridges an AsyncGenerator<SSEOutput> to Elysia's SSE response format.
|
|
47897
47829
|
* Returns an async generator that yields sse() calls for each SSE output item.
|
|
47898
47830
|
*/
|
|
@@ -47906,7 +47838,7 @@ async function* sseAdapter(generator) {
|
|
|
47906
47838
|
//#endregion
|
|
47907
47839
|
//#region src/deliver/index.ts
|
|
47908
47840
|
function deliverResult(request, result, modelMapping) {
|
|
47909
|
-
|
|
47841
|
+
setRequestModelMapping(request, modelMapping);
|
|
47910
47842
|
if (result.kind === "json") return {
|
|
47911
47843
|
streaming: false,
|
|
47912
47844
|
data: result.data
|
|
@@ -47929,7 +47861,7 @@ function hasStreamingResponsesQuery(request) {
|
|
|
47929
47861
|
return new URL(request.url).searchParams.get("stream") === "true";
|
|
47930
47862
|
}
|
|
47931
47863
|
//#endregion
|
|
47932
|
-
//#region src/
|
|
47864
|
+
//#region src/guard/approval.ts
|
|
47933
47865
|
async function awaitApproval() {
|
|
47934
47866
|
if (!await consola.prompt(`Accept incoming request?`, { type: "confirm" })) throw new HTTPError(403, { error: {
|
|
47935
47867
|
message: "Request rejected",
|
|
@@ -47937,7 +47869,7 @@ async function awaitApproval() {
|
|
|
47937
47869
|
} });
|
|
47938
47870
|
}
|
|
47939
47871
|
//#endregion
|
|
47940
|
-
//#region src/guard/
|
|
47872
|
+
//#region src/guard/gate.ts
|
|
47941
47873
|
async function runGuard() {
|
|
47942
47874
|
await rateLimiter.acquire(authStore.rateLimitSeconds, authStore.rateLimitWait);
|
|
47943
47875
|
if (authStore.manualApprove) await awaitApproval();
|
|
@@ -47949,118 +47881,7 @@ const requestGuardPlugin = new Elysia({ name: "request-guard" }).macro({ guarded
|
|
|
47949
47881
|
await runGuard();
|
|
47950
47882
|
} }) });
|
|
47951
47883
|
//#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
|
|
47884
|
+
//#region src/util/assert-never.ts
|
|
48064
47885
|
/**
|
|
48065
47886
|
* Compile-time exhaustiveness check for switch/if-else chains on
|
|
48066
47887
|
* discriminated unions. At runtime, throws with a descriptive message.
|
|
@@ -48111,54 +47932,20 @@ function selectCapiProfile(model) {
|
|
|
48111
47932
|
return inferModelFamily(model) === "claude" ? claudeProfile : baseProfile;
|
|
48112
47933
|
}
|
|
48113
47934
|
//#endregion
|
|
48114
|
-
//#region src/core/capi/
|
|
48115
|
-
|
|
48116
|
-
|
|
48117
|
-
|
|
47935
|
+
//#region src/core/capi/headers.ts
|
|
47936
|
+
/**
|
|
47937
|
+
* Leaf helper for reading optional request headers. Lives in its own module so
|
|
47938
|
+
* both request-context.ts and subagent-marker.ts can depend on it without
|
|
47939
|
+
* importing each other (which would form a cycle).
|
|
47940
|
+
*/
|
|
48118
47941
|
function readHeader(headers, name) {
|
|
48119
47942
|
return headers.get(name) ?? void 0;
|
|
48120
47943
|
}
|
|
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
|
-
}
|
|
47944
|
+
//#endregion
|
|
47945
|
+
//#region src/core/capi/subagent-marker.ts
|
|
47946
|
+
const SUBAGENT_MARKER_PREFIX = "__SUBAGENT_MARKER__";
|
|
47947
|
+
const SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
47948
|
+
const SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
48162
47949
|
function withSubagentMarker(baseContext, headers, marker) {
|
|
48163
47950
|
if (!marker) return baseContext;
|
|
48164
47951
|
const rootSessionId = readHeader(headers, "x-session-id") ?? baseContext.clientSessionId;
|
|
@@ -48433,6 +48220,49 @@ function findJsonObjectEnd(text, start) {
|
|
|
48433
48220
|
return -1;
|
|
48434
48221
|
}
|
|
48435
48222
|
//#endregion
|
|
48223
|
+
//#region src/core/capi/request-context.ts
|
|
48224
|
+
function inferInitiator(turns) {
|
|
48225
|
+
return turns.some((turn) => turn.role === "assistant" || turn.role === "tool") ? "agent" : "user";
|
|
48226
|
+
}
|
|
48227
|
+
function readCapiRequestContext(headers) {
|
|
48228
|
+
return {
|
|
48229
|
+
interactionType: readHeader(headers, "x-interaction-type"),
|
|
48230
|
+
agentTaskId: readHeader(headers, "x-agent-task-id"),
|
|
48231
|
+
parentAgentTaskId: readHeader(headers, "x-parent-agent-id"),
|
|
48232
|
+
clientSessionId: readHeader(headers, "x-client-session-id") ?? readHeader(headers, "x-session-id"),
|
|
48233
|
+
interactionId: readHeader(headers, "x-interaction-id"),
|
|
48234
|
+
clientMachineId: readHeader(headers, "x-client-machine-id")
|
|
48235
|
+
};
|
|
48236
|
+
}
|
|
48237
|
+
function resolveInitiator(defaultInitiator, requestContext) {
|
|
48238
|
+
switch (requestContext?.interactionType) {
|
|
48239
|
+
case "conversation-agent":
|
|
48240
|
+
case "conversation-subagent":
|
|
48241
|
+
case "conversation-background": return "agent";
|
|
48242
|
+
case "conversation-user": return "user";
|
|
48243
|
+
default: return defaultInitiator;
|
|
48244
|
+
}
|
|
48245
|
+
}
|
|
48246
|
+
function buildCapiRequestContext(initiator, overrides = {}) {
|
|
48247
|
+
return {
|
|
48248
|
+
interactionType: overrides.interactionType ?? (initiator === "agent" ? "conversation-agent" : "conversation-user"),
|
|
48249
|
+
agentTaskId: overrides.agentTaskId,
|
|
48250
|
+
parentAgentTaskId: overrides.parentAgentTaskId,
|
|
48251
|
+
clientSessionId: overrides.clientSessionId,
|
|
48252
|
+
interactionId: overrides.interactionId ?? randomUUID(),
|
|
48253
|
+
clientMachineId: overrides.clientMachineId
|
|
48254
|
+
};
|
|
48255
|
+
}
|
|
48256
|
+
function normalizeAnthropicRequestContext(payload, headers) {
|
|
48257
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromAnthropicPayload(payload));
|
|
48258
|
+
}
|
|
48259
|
+
function normalizeChatRequestContext(payload, headers) {
|
|
48260
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromChatPayload(payload));
|
|
48261
|
+
}
|
|
48262
|
+
function normalizeResponsesRequestContext(payload, headers) {
|
|
48263
|
+
return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromResponsesPayload(payload));
|
|
48264
|
+
}
|
|
48265
|
+
//#endregion
|
|
48436
48266
|
//#region src/core/capi/plan-builder.ts
|
|
48437
48267
|
const EPHEMERAL_CACHE_CONTROL = { type: "ephemeral" };
|
|
48438
48268
|
function asContentPart(block) {
|
|
@@ -48636,7 +48466,7 @@ function buildCapiExecutionPlan(request, options = {}) {
|
|
|
48636
48466
|
};
|
|
48637
48467
|
}
|
|
48638
48468
|
//#endregion
|
|
48639
|
-
//#region src/
|
|
48469
|
+
//#region src/ingest/validation/shared.ts
|
|
48640
48470
|
const jsonObjectSchema = object({}).catchall(unknown());
|
|
48641
48471
|
const finiteNumberSchema = number().finite();
|
|
48642
48472
|
const nonNegativeIntegerSchema = number().int().nonnegative();
|
|
@@ -48733,7 +48563,7 @@ function parsePayload(schema, context, payload) {
|
|
|
48733
48563
|
return result.data;
|
|
48734
48564
|
}
|
|
48735
48565
|
//#endregion
|
|
48736
|
-
//#region src/
|
|
48566
|
+
//#region src/ingest/validation/anthropic-messages.ts
|
|
48737
48567
|
const anthropicTextBlockSchema = object({
|
|
48738
48568
|
type: literal("text"),
|
|
48739
48569
|
text: string()
|
|
@@ -48923,7 +48753,7 @@ function parseAnthropicCountTokensPayload(payload) {
|
|
|
48923
48753
|
return parsePayload(anthropicCountTokensPayloadSchema, "anthropic.messages.count_tokens", payload);
|
|
48924
48754
|
}
|
|
48925
48755
|
//#endregion
|
|
48926
|
-
//#region src/
|
|
48756
|
+
//#region src/ingest/validation/embeddings.ts
|
|
48927
48757
|
const embeddingRequestSchema = object({
|
|
48928
48758
|
input: union([string(), array(string())]),
|
|
48929
48759
|
model: string().min(1),
|
|
@@ -48943,7 +48773,7 @@ const REASONING_EFFORT_VALUES = [
|
|
|
48943
48773
|
"high"
|
|
48944
48774
|
];
|
|
48945
48775
|
//#endregion
|
|
48946
|
-
//#region src/
|
|
48776
|
+
//#region src/ingest/validation/openai-chat.ts
|
|
48947
48777
|
const openAIPenaltySchema = finiteNumberSchema.min(-2).max(2);
|
|
48948
48778
|
const openAILogitBiasKeySchema = string().regex(/^\d+$/);
|
|
48949
48779
|
const openAILogitBiasValueSchema = finiteNumberSchema.min(-100).max(100);
|
|
@@ -49052,53 +48882,77 @@ const openAIChatPayloadSchema = object({
|
|
|
49052
48882
|
function parseOpenAIChatPayload(payload) {
|
|
49053
48883
|
return parsePayload(openAIChatPayloadSchema, "openai.chat", payload);
|
|
49054
48884
|
}
|
|
48885
|
+
//#endregion
|
|
48886
|
+
//#region src/ingest/validation/responses.ts
|
|
48887
|
+
const responsesInputTextSchema = object({
|
|
48888
|
+
type: _enum(["input_text", "output_text"]),
|
|
48889
|
+
text: string()
|
|
48890
|
+
}).loose();
|
|
48891
|
+
const responsesInputImageSchema = object({
|
|
48892
|
+
type: literal("input_image"),
|
|
48893
|
+
image_url: string().nullable().optional(),
|
|
48894
|
+
file_id: string().nullable().optional(),
|
|
48895
|
+
detail: _enum([
|
|
48896
|
+
"low",
|
|
48897
|
+
"high",
|
|
48898
|
+
"auto",
|
|
48899
|
+
"original"
|
|
48900
|
+
]).optional()
|
|
48901
|
+
}).loose().superRefine((item, ctx) => {
|
|
48902
|
+
if (!item.image_url && !item.file_id) ctx.addIssue({
|
|
48903
|
+
code: "custom",
|
|
48904
|
+
message: "input_image requires image_url or file_id"
|
|
48905
|
+
});
|
|
48906
|
+
});
|
|
48907
|
+
const responsesFunctionCallOutputImageSchema = object({
|
|
48908
|
+
type: literal("input_image"),
|
|
48909
|
+
image_url: string().nullable().optional(),
|
|
48910
|
+
file_id: string().nullable().optional(),
|
|
48911
|
+
detail: _enum([
|
|
48912
|
+
"low",
|
|
48913
|
+
"high",
|
|
48914
|
+
"auto",
|
|
48915
|
+
"original"
|
|
48916
|
+
]).optional()
|
|
48917
|
+
}).loose();
|
|
48918
|
+
const responsesInputFileSchema = object({
|
|
48919
|
+
type: literal("input_file"),
|
|
48920
|
+
file_id: string().nullable().optional(),
|
|
48921
|
+
file_url: string().nullable().optional(),
|
|
48922
|
+
file_data: string().nullable().optional(),
|
|
48923
|
+
filename: string().nullable().optional()
|
|
48924
|
+
}).loose().superRefine((item, ctx) => {
|
|
48925
|
+
if (!item.file_id && !item.file_url && !item.file_data) ctx.addIssue({
|
|
48926
|
+
code: "custom",
|
|
48927
|
+
message: "input_file requires file_id, file_url, or file_data"
|
|
48928
|
+
});
|
|
48929
|
+
if (item.file_data && !item.filename) ctx.addIssue({
|
|
48930
|
+
code: "custom",
|
|
48931
|
+
message: "input_file with file_data requires filename"
|
|
48932
|
+
});
|
|
48933
|
+
});
|
|
48934
|
+
const responsesUnknownContentSchema = object({ type: string().min(1) }).catchall(unknown()).superRefine((item, ctx) => {
|
|
48935
|
+
if ([
|
|
48936
|
+
"input_text",
|
|
48937
|
+
"output_text",
|
|
48938
|
+
"input_image",
|
|
48939
|
+
"input_file"
|
|
48940
|
+
].includes(item.type)) ctx.addIssue({
|
|
48941
|
+
code: "custom",
|
|
48942
|
+
message: `content item type ${item.type} must match the explicit schema`
|
|
48943
|
+
});
|
|
48944
|
+
});
|
|
49055
48945
|
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
|
-
})
|
|
48946
|
+
responsesInputTextSchema,
|
|
48947
|
+
responsesInputImageSchema,
|
|
48948
|
+
responsesInputFileSchema,
|
|
48949
|
+
responsesUnknownContentSchema
|
|
48950
|
+
]);
|
|
48951
|
+
const responsesFunctionCallOutputContentSchema = union([
|
|
48952
|
+
responsesInputTextSchema,
|
|
48953
|
+
responsesFunctionCallOutputImageSchema,
|
|
48954
|
+
responsesInputFileSchema,
|
|
48955
|
+
responsesUnknownContentSchema
|
|
49102
48956
|
]);
|
|
49103
48957
|
const responsesMessageSchema = object({
|
|
49104
48958
|
type: literal("message").optional(),
|
|
@@ -49126,7 +48980,7 @@ const responsesFunctionCallSchema = object({
|
|
|
49126
48980
|
const responsesFunctionCallOutputSchema = object({
|
|
49127
48981
|
type: literal("function_call_output"),
|
|
49128
48982
|
call_id: string().min(1),
|
|
49129
|
-
output: union([string(), array(
|
|
48983
|
+
output: union([string(), array(responsesFunctionCallOutputContentSchema)]),
|
|
49130
48984
|
status: _enum([
|
|
49131
48985
|
"in_progress",
|
|
49132
48986
|
"completed",
|
|
@@ -49464,16 +49318,16 @@ function createUpstreamSignalFromConfig(clientSignal) {
|
|
|
49464
49318
|
//#endregion
|
|
49465
49319
|
//#region src/pipeline/runner.ts
|
|
49466
49320
|
async function runPipeline(params, config) {
|
|
49467
|
-
const
|
|
49468
|
-
|
|
49469
|
-
|
|
49321
|
+
const ingested = protocolRegistry.ingest(config.protocol, params.body, params.headers);
|
|
49322
|
+
const meta = ingested.meta;
|
|
49323
|
+
const payload = config.afterIngest ? config.afterIngest({
|
|
49324
|
+
payload: ingested.payload,
|
|
49470
49325
|
meta,
|
|
49471
49326
|
headers: params.headers
|
|
49472
|
-
});
|
|
49327
|
+
}) : ingested.payload;
|
|
49473
49328
|
const transformResult = config.transformChain.apply({
|
|
49474
49329
|
model: payload.model,
|
|
49475
49330
|
payload,
|
|
49476
|
-
headers: params.headers,
|
|
49477
49331
|
meta: { betaHeaders: meta.betaHeaders }
|
|
49478
49332
|
});
|
|
49479
49333
|
payload.model = transformResult.model;
|
|
@@ -49495,7 +49349,7 @@ async function runPipeline(params, config) {
|
|
|
49495
49349
|
});
|
|
49496
49350
|
const upstreamSignal = createUpstreamSignalFromConfig(params.signal);
|
|
49497
49351
|
const copilotClient = createCopilotClient();
|
|
49498
|
-
const
|
|
49352
|
+
const ctx = config.buildStrategyContext({
|
|
49499
49353
|
payload,
|
|
49500
49354
|
meta,
|
|
49501
49355
|
headers: params.headers,
|
|
@@ -49504,93 +49358,12 @@ async function runPipeline(params, config) {
|
|
|
49504
49358
|
upstreamSignal,
|
|
49505
49359
|
modelMapping
|
|
49506
49360
|
});
|
|
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
49361
|
return {
|
|
49543
49362
|
result: await config.strategyRegistry.select(selectedModel, ctx).execute(ctx),
|
|
49544
49363
|
modelMapping
|
|
49545
49364
|
};
|
|
49546
49365
|
}
|
|
49547
49366
|
//#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
49367
|
//#region src/transform/chain.ts
|
|
49595
49368
|
function composeModelTransforms(...steps) {
|
|
49596
49369
|
return { apply(input) {
|
|
@@ -49626,18 +49399,10 @@ function composeModelTransforms(...steps) {
|
|
|
49626
49399
|
} };
|
|
49627
49400
|
}
|
|
49628
49401
|
//#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
|
-
}
|
|
49402
|
+
//#region src/transform/constants.ts
|
|
49403
|
+
const CONTEXT_BETA_RE = /^context-\d+[km]-/;
|
|
49639
49404
|
//#endregion
|
|
49640
|
-
//#region src/
|
|
49405
|
+
//#region src/transform/request-model-policy.ts
|
|
49641
49406
|
const COMPACT_SYSTEM_PROMPT_START = "You are a helpful AI assistant tasked with summarizing conversations";
|
|
49642
49407
|
function applyMessagesModelPolicy(payload, options) {
|
|
49643
49408
|
const originalModel = payload.model;
|
|
@@ -49645,17 +49410,6 @@ function applyMessagesModelPolicy(payload, options) {
|
|
|
49645
49410
|
originalModel,
|
|
49646
49411
|
routedModel: originalModel
|
|
49647
49412
|
};
|
|
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
49413
|
const smallModel = configStore.getSmallModel();
|
|
49660
49414
|
if (!smallModel || !configStore.isCompactSmallModelEnabled() || !isCompactRequest(payload)) return {
|
|
49661
49415
|
originalModel,
|
|
@@ -49684,9 +49438,9 @@ function canRouteToSmallModel(payload, originalModel, smallModel) {
|
|
|
49684
49438
|
const originalEndpoints = new Set(originalModel.supported_endpoints ?? []);
|
|
49685
49439
|
const smallEndpoints = new Set(smallModel.supported_endpoints ?? []);
|
|
49686
49440
|
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) && !
|
|
49441
|
+
if (payload.tools?.length && !(smallModel.capabilities.supports.tool_calls ?? false)) return false;
|
|
49442
|
+
if (payload.thinking && !(smallModel.capabilities.supports.adaptive_thinking ?? false)) return false;
|
|
49443
|
+
if (hasVisionInput$1(payload) && !(smallModel.capabilities.supports.vision ?? false)) return false;
|
|
49690
49444
|
return true;
|
|
49691
49445
|
}
|
|
49692
49446
|
function hasVisionInput$1(payload) {
|
|
@@ -49700,17 +49454,72 @@ function containsVisionContent$1(content) {
|
|
|
49700
49454
|
//#region src/transform/policy.ts
|
|
49701
49455
|
const modelPolicyStep = {
|
|
49702
49456
|
tag: "POLICY",
|
|
49703
|
-
apply({
|
|
49457
|
+
apply({ payload, meta }) {
|
|
49704
49458
|
const routing = applyMessagesModelPolicy(payload, { betaUpgraded: meta?.betaHeaders?.some((b) => CONTEXT_BETA_RE.test(b)) ?? false });
|
|
49705
49459
|
if (!routing.reason) return null;
|
|
49706
49460
|
return {
|
|
49707
49461
|
model: routing.routedModel,
|
|
49708
|
-
tag:
|
|
49709
|
-
resolvedModel: routing.reason === "context-upgrade" ? modelCache.findById(routing.routedModel) ?? resolvedModel ?? modelCache.findById(model) : void 0
|
|
49462
|
+
tag: "COMPACT"
|
|
49710
49463
|
};
|
|
49711
49464
|
}
|
|
49712
49465
|
};
|
|
49713
49466
|
//#endregion
|
|
49467
|
+
//#region src/transform/model-rewrite.ts
|
|
49468
|
+
/**
|
|
49469
|
+
* Unified model rewrite: user rules → built-in normalization → pass-through.
|
|
49470
|
+
* Call once at handler entry, before any model lookup or policy.
|
|
49471
|
+
*/
|
|
49472
|
+
function rewriteModel(modelId) {
|
|
49473
|
+
const userRules = configStore.getModelRewrites();
|
|
49474
|
+
if (userRules.length > 0) {
|
|
49475
|
+
for (const rule of userRules) if (matchesGlob(rule.from, modelId)) return {
|
|
49476
|
+
originalModel: modelId,
|
|
49477
|
+
model: normalizeToKnownModel(rule.to) ?? rule.to,
|
|
49478
|
+
reason: "CONFIG_REWRITE"
|
|
49479
|
+
};
|
|
49480
|
+
}
|
|
49481
|
+
const normalized = normalizeToKnownModel(modelId);
|
|
49482
|
+
if (normalized && normalized !== modelId) return {
|
|
49483
|
+
originalModel: modelId,
|
|
49484
|
+
model: normalized,
|
|
49485
|
+
reason: "AUTO_CORRECT"
|
|
49486
|
+
};
|
|
49487
|
+
return {
|
|
49488
|
+
originalModel: modelId,
|
|
49489
|
+
model: modelId
|
|
49490
|
+
};
|
|
49491
|
+
}
|
|
49492
|
+
/**
|
|
49493
|
+
* Apply model rewrite to a mutable model field and log if changed.
|
|
49494
|
+
* Returns the rewrite result for downstream use.
|
|
49495
|
+
*/
|
|
49496
|
+
function applyModelRewrite(payload) {
|
|
49497
|
+
const result = rewriteModel(payload.model);
|
|
49498
|
+
if (result.model !== result.originalModel) {
|
|
49499
|
+
consola.debug(`Model rewritten: ${result.originalModel} ~> ${result.model}`);
|
|
49500
|
+
payload.model = result.model;
|
|
49501
|
+
}
|
|
49502
|
+
return result;
|
|
49503
|
+
}
|
|
49504
|
+
const DOT_RE = /\./g;
|
|
49505
|
+
/**
|
|
49506
|
+
* Resolve a model ID against Copilot's cached model list using
|
|
49507
|
+
* dash/dot equivalence. Returns the canonical ID if found.
|
|
49508
|
+
*/
|
|
49509
|
+
function normalizeToKnownModel(modelId) {
|
|
49510
|
+
const models = modelCache.getModels()?.data;
|
|
49511
|
+
if (!models) return void 0;
|
|
49512
|
+
if (models.some((m) => m.id === modelId)) return modelId;
|
|
49513
|
+
const normalized = modelId.replace(DOT_RE, "-");
|
|
49514
|
+
for (const model of models) if (model.id.replace(DOT_RE, "-") === normalized) return model.id;
|
|
49515
|
+
}
|
|
49516
|
+
const GLOB_SPECIAL_RE = /[.+^${}()|[\]\\]/g;
|
|
49517
|
+
const GLOB_STAR_RE = /\*/g;
|
|
49518
|
+
function matchesGlob(pattern, value) {
|
|
49519
|
+
if (!pattern.includes("*")) return pattern === value;
|
|
49520
|
+
return new RegExp(`^${pattern.replace(GLOB_SPECIAL_RE, "\\$&").replace(GLOB_STAR_RE, ".*")}$`).test(value);
|
|
49521
|
+
}
|
|
49522
|
+
//#endregion
|
|
49714
49523
|
//#region src/transform/rewrite.ts
|
|
49715
49524
|
const rewriteStep = {
|
|
49716
49525
|
tag: "rewrite",
|
|
@@ -49735,6 +49544,20 @@ const rewriteStep = {
|
|
|
49735
49544
|
}
|
|
49736
49545
|
};
|
|
49737
49546
|
//#endregion
|
|
49547
|
+
//#region src/transform/beta-headers.ts
|
|
49548
|
+
const COPILOT_UNSUPPORTED_BETA_RE = /^mid-conversation-system-\d{4}-\d{2}-\d{2}$/;
|
|
49549
|
+
function processAnthropicBetaHeader(rawHeader) {
|
|
49550
|
+
if (!rawHeader) return void 0;
|
|
49551
|
+
const values = rawHeader.split(",").map((v) => v.trim()).filter(Boolean);
|
|
49552
|
+
const filtered = [];
|
|
49553
|
+
for (const value of values) {
|
|
49554
|
+
if (CONTEXT_BETA_RE.test(value)) continue;
|
|
49555
|
+
if (COPILOT_UNSUPPORTED_BETA_RE.test(value)) continue;
|
|
49556
|
+
filtered.push(value);
|
|
49557
|
+
}
|
|
49558
|
+
return filtered.length > 0 ? filtered.join(",") : void 0;
|
|
49559
|
+
}
|
|
49560
|
+
//#endregion
|
|
49738
49561
|
//#region src/translator/responses/signature-codec.ts
|
|
49739
49562
|
const COMPACTION_PREFIX = "cm1#";
|
|
49740
49563
|
const SEPARATOR = "@";
|
|
@@ -49797,8 +49620,8 @@ const OUTPUT_CONFIG_EFFORT_RANK = new Map([
|
|
|
49797
49620
|
"low",
|
|
49798
49621
|
"medium",
|
|
49799
49622
|
"high",
|
|
49800
|
-
"
|
|
49801
|
-
"
|
|
49623
|
+
"xhigh",
|
|
49624
|
+
"max"
|
|
49802
49625
|
].map((effort, index) => [effort, index]));
|
|
49803
49626
|
function isOutputConfigEffort(value) {
|
|
49804
49627
|
return OUTPUT_CONFIG_EFFORT_RANK.has(value);
|
|
@@ -49841,7 +49664,7 @@ function sanitizeCacheControl(payload) {
|
|
|
49841
49664
|
}
|
|
49842
49665
|
//#endregion
|
|
49843
49666
|
//#region src/transform/index.ts
|
|
49844
|
-
const messagesModelChain = composeModelTransforms(rewriteStep,
|
|
49667
|
+
const messagesModelChain = composeModelTransforms(rewriteStep, modelPolicyStep);
|
|
49845
49668
|
const chatCompletionsModelChain = composeModelTransforms(rewriteStep);
|
|
49846
49669
|
const responsesModelChain = composeModelTransforms(rewriteStep);
|
|
49847
49670
|
//#endregion
|
|
@@ -49881,9 +49704,6 @@ function normalizeSystemBlocks(system) {
|
|
|
49881
49704
|
blocks: system.map((block) => textBlock(block.text))
|
|
49882
49705
|
}];
|
|
49883
49706
|
}
|
|
49884
|
-
function normalizeToolResultContent(block) {
|
|
49885
|
-
return normalizeToolResultContentValue(block.content);
|
|
49886
|
-
}
|
|
49887
49707
|
function normalizeToolResultContentValue(content) {
|
|
49888
49708
|
if (typeof content === "string") return [textBlock(content)];
|
|
49889
49709
|
return content.map((contentBlock) => {
|
|
@@ -49895,9 +49715,6 @@ function normalizeToolResultContentValue(content) {
|
|
|
49895
49715
|
}
|
|
49896
49716
|
});
|
|
49897
49717
|
}
|
|
49898
|
-
function normalizeMcpToolResultContent(block) {
|
|
49899
|
-
return normalizeToolResultContentValue(block.content);
|
|
49900
|
-
}
|
|
49901
49718
|
function normalizeServerToolResultContent(block) {
|
|
49902
49719
|
return [textBlock(typeof block.content === "string" ? block.content : JSON.stringify(block.content) ?? "")];
|
|
49903
49720
|
}
|
|
@@ -49937,13 +49754,13 @@ function normalizeMessage(message) {
|
|
|
49937
49754
|
case "tool_result": return {
|
|
49938
49755
|
kind: "tool_result",
|
|
49939
49756
|
toolUseId: block.tool_use_id,
|
|
49940
|
-
content:
|
|
49757
|
+
content: normalizeToolResultContentValue(block.content),
|
|
49941
49758
|
isError: block.is_error
|
|
49942
49759
|
};
|
|
49943
49760
|
case "mcp_tool_result": return {
|
|
49944
49761
|
kind: "tool_result",
|
|
49945
49762
|
toolUseId: block.tool_use_id,
|
|
49946
|
-
content:
|
|
49763
|
+
content: normalizeToolResultContentValue(block.content),
|
|
49947
49764
|
isError: block.is_error
|
|
49948
49765
|
};
|
|
49949
49766
|
case "server_tool_result":
|
|
@@ -50169,10 +49986,6 @@ var AnthropicStreamTranslator = class {
|
|
|
50169
49986
|
for (const delta of deltas) switch (delta.kind) {
|
|
50170
49987
|
case "message_start": break;
|
|
50171
49988
|
case "thinking_delta":
|
|
50172
|
-
this.state.lastMetadata = {
|
|
50173
|
-
...this.state.lastMetadata,
|
|
50174
|
-
...delta.metadata
|
|
50175
|
-
};
|
|
50176
49989
|
this.textWriter.close(events);
|
|
50177
49990
|
this.thinkingWriter.append(events, delta.text);
|
|
50178
49991
|
break;
|
|
@@ -50193,10 +50006,6 @@ var AnthropicStreamTranslator = class {
|
|
|
50193
50006
|
});
|
|
50194
50007
|
break;
|
|
50195
50008
|
case "message_stop":
|
|
50196
|
-
this.state.lastMetadata = {
|
|
50197
|
-
...this.state.lastMetadata,
|
|
50198
|
-
...delta.metadata
|
|
50199
|
-
};
|
|
50200
50009
|
this.state.pendingStopReason = delta.stopReason;
|
|
50201
50010
|
this.closeAllBlocks(events);
|
|
50202
50011
|
break;
|
|
@@ -50273,13 +50082,7 @@ var AnthropicStreamTranslator = class {
|
|
|
50273
50082
|
});
|
|
50274
50083
|
if (choice.delta.reasoning_text) deltas.push({
|
|
50275
50084
|
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
|
-
}
|
|
50085
|
+
text: choice.delta.reasoning_text
|
|
50283
50086
|
});
|
|
50284
50087
|
if (choice.delta.content) deltas.push({
|
|
50285
50088
|
kind: "text_delta",
|
|
@@ -50295,13 +50098,7 @@ var AnthropicStreamTranslator = class {
|
|
|
50295
50098
|
if (choice.finish_reason) deltas.push({
|
|
50296
50099
|
kind: "message_stop",
|
|
50297
50100
|
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
|
-
}
|
|
50101
|
+
usage: chunk.usage
|
|
50305
50102
|
});
|
|
50306
50103
|
return deltas;
|
|
50307
50104
|
}
|
|
@@ -50417,13 +50214,7 @@ function normalizeAssistantTurn(message) {
|
|
|
50417
50214
|
}] : [],
|
|
50418
50215
|
...contentBlocks,
|
|
50419
50216
|
...toolBlocks
|
|
50420
|
-
]
|
|
50421
|
-
meta: {
|
|
50422
|
-
reasoningOpaque: message.reasoning_opaque,
|
|
50423
|
-
encryptedContent: message.encrypted_content,
|
|
50424
|
-
phase: message.phase,
|
|
50425
|
-
copilotAnnotations: message.copilot_annotations
|
|
50426
|
-
}
|
|
50217
|
+
]
|
|
50427
50218
|
};
|
|
50428
50219
|
}
|
|
50429
50220
|
function normalizeOpenAIResponse(response, context) {
|
|
@@ -50597,7 +50388,7 @@ var AnthropicMessagesAdapter = class {
|
|
|
50597
50388
|
constructor(options = {}) {
|
|
50598
50389
|
this.options = {
|
|
50599
50390
|
modelResolver: options.modelResolver ?? ((model) => model),
|
|
50600
|
-
getModelCapabilities: options.getModelCapabilities ?? ((model) => ({ supportsThinkingBudget: model
|
|
50391
|
+
getModelCapabilities: options.getModelCapabilities ?? ((model) => ({ supportsThinkingBudget: inferModelFamily(model) === "claude" })),
|
|
50601
50392
|
policy: options.policy ?? defaultTranslationPolicy
|
|
50602
50393
|
};
|
|
50603
50394
|
}
|
|
@@ -50633,21 +50424,6 @@ var AnthropicMessagesAdapter = class {
|
|
|
50633
50424
|
}
|
|
50634
50425
|
};
|
|
50635
50426
|
//#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
50427
|
//#region src/adapters/openai-chat-adapter.ts
|
|
50652
50428
|
function toConversationBlocks(content) {
|
|
50653
50429
|
if (content === null) return [];
|
|
@@ -50796,280 +50572,6 @@ var OpenAIChatAdapter = class {
|
|
|
50796
50572
|
}
|
|
50797
50573
|
};
|
|
50798
50574
|
//#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
50575
|
//#region src/dispatch/strategy-registry.ts
|
|
51074
50576
|
var StrategyRegistry = class {
|
|
51075
50577
|
entries = [];
|
|
@@ -51141,19 +50643,21 @@ function normalizeOutputs(value) {
|
|
|
51141
50643
|
*/
|
|
51142
50644
|
function passthroughSSEChunk(chunk, data) {
|
|
51143
50645
|
return {
|
|
51144
|
-
...chunk.comment ? { comment: chunk.comment } : {},
|
|
51145
50646
|
...chunk.event ? { event: chunk.event } : {},
|
|
51146
50647
|
...chunk.id !== void 0 ? { id: String(chunk.id) } : {},
|
|
51147
|
-
...chunk.retry !== void 0 ? { retry: chunk.retry } : {},
|
|
51148
50648
|
data
|
|
51149
50649
|
};
|
|
51150
50650
|
}
|
|
51151
50651
|
//#endregion
|
|
51152
50652
|
//#region src/routes/chat-completions/strategy.ts
|
|
51153
|
-
function createChatCompletionsStrategy(
|
|
50653
|
+
function createChatCompletionsStrategy(client, adapter, plan, signal) {
|
|
51154
50654
|
return {
|
|
51155
50655
|
execute() {
|
|
51156
|
-
return
|
|
50656
|
+
return client.createChatCompletions(plan.payload, {
|
|
50657
|
+
signal,
|
|
50658
|
+
initiator: plan.initiator,
|
|
50659
|
+
requestContext: plan.requestContext
|
|
50660
|
+
});
|
|
51157
50661
|
},
|
|
51158
50662
|
isStream(result) {
|
|
51159
50663
|
return !isNonStreamingResponse(result);
|
|
@@ -51180,9 +50684,8 @@ const chatCompletionsEntry$1 = {
|
|
|
51180
50684
|
const adapter = new OpenAIChatAdapter();
|
|
51181
50685
|
const plan = adapter.toCapiPlan(ctx.payload, { requestContext: ctx.requestContext });
|
|
51182
50686
|
appendModelStepInPlace(ctx.modelMapping, "MODEL_RESOLVE", plan.resolvedModel);
|
|
51183
|
-
const transport = new CopilotTransport(ctx.copilotClient);
|
|
51184
50687
|
consola.debug("Streaming response");
|
|
51185
|
-
return await runStrategy(createChatCompletionsStrategy(
|
|
50688
|
+
return await runStrategy(createChatCompletionsStrategy(ctx.copilotClient, adapter, plan, ctx.upstreamSignal.signal), ctx.upstreamSignal);
|
|
51186
50689
|
}
|
|
51187
50690
|
};
|
|
51188
50691
|
const chatCompletionsStrategyRegistry = new StrategyRegistry();
|
|
@@ -51200,6 +50703,7 @@ async function handleCompletionCore({ body, signal, headers }) {
|
|
|
51200
50703
|
strategyRegistry: chatCompletionsStrategyRegistry,
|
|
51201
50704
|
afterIngest({ payload }) {
|
|
51202
50705
|
consola.debug("Request payload:", JSON.stringify(payload).slice(-400));
|
|
50706
|
+
return payload;
|
|
51203
50707
|
},
|
|
51204
50708
|
async afterTransform({ payload, selectedModel }) {
|
|
51205
50709
|
try {
|
|
@@ -51275,7 +50779,7 @@ function createAnthropicAdapter() {
|
|
|
51275
50779
|
const fallbackConfig = getModelFallbackConfig();
|
|
51276
50780
|
return new AnthropicMessagesAdapter({
|
|
51277
50781
|
modelResolver: (model) => resolveModel(model, knownModelIds, fallbackConfig),
|
|
51278
|
-
getModelCapabilities: (model) => ({ supportsThinkingBudget: model
|
|
50782
|
+
getModelCapabilities: (model) => ({ supportsThinkingBudget: inferModelFamily(model) === "claude" })
|
|
51279
50783
|
});
|
|
51280
50784
|
}
|
|
51281
50785
|
//#endregion
|
|
@@ -51314,7 +50818,123 @@ async function handleCountTokensCore({ body, headers }) {
|
|
|
51314
50818
|
return { input_tokens: finalTokenCount };
|
|
51315
50819
|
}
|
|
51316
50820
|
//#endregion
|
|
51317
|
-
//#region src/
|
|
50821
|
+
//#region src/transform/context-management.ts
|
|
50822
|
+
/** Default token threshold when model limits are unknown. */
|
|
50823
|
+
const DEFAULT_COMPACT_THRESHOLD = 5e4;
|
|
50824
|
+
/** Fraction of max prompt tokens to use as compact threshold. */
|
|
50825
|
+
const COMPACT_THRESHOLD_RATIO = .9;
|
|
50826
|
+
function getResponsesRequestOptions(payload) {
|
|
50827
|
+
return {
|
|
50828
|
+
vision: hasVisionInput(payload),
|
|
50829
|
+
initiator: hasAgentInitiator(payload) ? "agent" : "user"
|
|
50830
|
+
};
|
|
50831
|
+
}
|
|
50832
|
+
function hasAgentInitiator(payload) {
|
|
50833
|
+
const lastItem = getPayloadItems(payload).at(-1);
|
|
50834
|
+
if (!lastItem) return false;
|
|
50835
|
+
if (!("role" in lastItem) || !lastItem.role) return true;
|
|
50836
|
+
return String(lastItem.role).toLowerCase() === "assistant";
|
|
50837
|
+
}
|
|
50838
|
+
function hasVisionInput(payload) {
|
|
50839
|
+
return getPayloadItems(payload).some((item) => containsVisionContent(item));
|
|
50840
|
+
}
|
|
50841
|
+
function resolveResponsesCompactThreshold(maxPromptTokens) {
|
|
50842
|
+
if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * COMPACT_THRESHOLD_RATIO);
|
|
50843
|
+
return DEFAULT_COMPACT_THRESHOLD;
|
|
50844
|
+
}
|
|
50845
|
+
function createCompactionContextManagement(compactThreshold) {
|
|
50846
|
+
return [{
|
|
50847
|
+
type: "compaction",
|
|
50848
|
+
compact_threshold: compactThreshold
|
|
50849
|
+
}];
|
|
50850
|
+
}
|
|
50851
|
+
function applyContextManagement(payload, maxPromptTokens) {
|
|
50852
|
+
if (payload.context_management !== void 0) return;
|
|
50853
|
+
if (!configStore.isContextManagementModel(payload.model)) return;
|
|
50854
|
+
payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
|
|
50855
|
+
}
|
|
50856
|
+
function compactInputByLatestCompaction(payload) {
|
|
50857
|
+
if (!configStore.isAutoCompactResponsesInputEnabled()) return;
|
|
50858
|
+
if (!Array.isArray(payload.input) || payload.input.length === 0) return;
|
|
50859
|
+
const latestCompactionMessageIndex = getLatestCompactionMessageIndex(payload.input);
|
|
50860
|
+
if (latestCompactionMessageIndex === void 0) return;
|
|
50861
|
+
payload.input = payload.input.slice(latestCompactionMessageIndex);
|
|
50862
|
+
}
|
|
50863
|
+
function getLatestCompactionMessageIndex(input) {
|
|
50864
|
+
for (let index = input.length - 1; index >= 0; index--) if (isCompactionInputItem(input[index])) return index;
|
|
50865
|
+
}
|
|
50866
|
+
function isCompactionInputItem(value) {
|
|
50867
|
+
return "type" in value && value.type === "compaction";
|
|
50868
|
+
}
|
|
50869
|
+
function getPayloadItems(payload) {
|
|
50870
|
+
return Array.isArray(payload.input) ? payload.input : [];
|
|
50871
|
+
}
|
|
50872
|
+
function containsVisionContent(value) {
|
|
50873
|
+
if (!value) return false;
|
|
50874
|
+
if (Array.isArray(value)) return value.some((entry) => containsVisionContent(entry));
|
|
50875
|
+
if (typeof value !== "object") return false;
|
|
50876
|
+
const record = value;
|
|
50877
|
+
if (record.type === "input_image") return true;
|
|
50878
|
+
if (Array.isArray(record.content)) return record.content.some((entry) => containsVisionContent(entry));
|
|
50879
|
+
return false;
|
|
50880
|
+
}
|
|
50881
|
+
//#endregion
|
|
50882
|
+
//#region src/transform/parameter-filter.ts
|
|
50883
|
+
/**
|
|
50884
|
+
* Parameters the default rule strips for reasoning models on the Responses
|
|
50885
|
+
* boundary. Reasoning models (gpt-5 family, o-series, codex) reject sampling
|
|
50886
|
+
* parameters upstream with a 400 "Unsupported parameter" error, so the proxy
|
|
50887
|
+
* drops them instead of leaking the incompatibility to the client.
|
|
50888
|
+
*/
|
|
50889
|
+
const DEFAULT_REASONING_UNSUPPORTED_PARAMS = ["temperature", "top_p"];
|
|
50890
|
+
/**
|
|
50891
|
+
* A reasoning model is any model that advertises one or more
|
|
50892
|
+
* `reasoning_effort` levels. This dynamically covers the full reasoning
|
|
50893
|
+
* family (mini, codex, future point releases) without a hardcoded ID list.
|
|
50894
|
+
*/
|
|
50895
|
+
function isReasoningModel(model) {
|
|
50896
|
+
return modelCache.supportsReasoningEffort(model);
|
|
50897
|
+
}
|
|
50898
|
+
/**
|
|
50899
|
+
* Resolve the set of request parameters to strip for a given model on the
|
|
50900
|
+
* Responses boundary.
|
|
50901
|
+
*
|
|
50902
|
+
* Rule composition:
|
|
50903
|
+
* 1. Built-in default: reasoning models strip {@link DEFAULT_REASONING_UNSUPPORTED_PARAMS}.
|
|
50904
|
+
* Disabled entirely when `responsesApiParameterFiltersReplaceDefault` is true.
|
|
50905
|
+
* 2. User rules (`responsesApiParameterFilters`): every rule whose `models`
|
|
50906
|
+
* glob matches the resolved model id contributes its `params`.
|
|
50907
|
+
*
|
|
50908
|
+
* The result is the union of all matching rules, so user rules ADD to the
|
|
50909
|
+
* default. Setting `responsesApiParameterFiltersReplaceDefault: true` disables
|
|
50910
|
+
* the default so user rules fully OVERWRITE it.
|
|
50911
|
+
*/
|
|
50912
|
+
function resolveStrippedResponsesParams(model) {
|
|
50913
|
+
const params = /* @__PURE__ */ new Set();
|
|
50914
|
+
if (!configStore.shouldReplaceDefaultParameterFilters() && isReasoningModel(model)) for (const param of DEFAULT_REASONING_UNSUPPORTED_PARAMS) params.add(param);
|
|
50915
|
+
const modelId = model?.id;
|
|
50916
|
+
if (modelId) {
|
|
50917
|
+
for (const rule of configStore.getResponsesParameterFilters()) if (rule.models.some((pattern) => matchesGlob(pattern, modelId))) for (const param of rule.params) params.add(param);
|
|
50918
|
+
}
|
|
50919
|
+
return params;
|
|
50920
|
+
}
|
|
50921
|
+
/**
|
|
50922
|
+
* Strip unsupported parameters from a Responses payload before dispatch.
|
|
50923
|
+
* Keys are deleted entirely (never set to null) because upstream rejects the
|
|
50924
|
+
* mere presence of the key, not just non-null values.
|
|
50925
|
+
*/
|
|
50926
|
+
function applyResponsesParameterFilters(payload, model) {
|
|
50927
|
+
const strip = resolveStrippedResponsesParams(model);
|
|
50928
|
+
if (strip.size === 0) return;
|
|
50929
|
+
const removed = [];
|
|
50930
|
+
for (const key of strip) if (key in payload) {
|
|
50931
|
+
delete payload[key];
|
|
50932
|
+
removed.push(key);
|
|
50933
|
+
}
|
|
50934
|
+
if (removed.length > 0) consola.debug(`Stripped unsupported responses params for model ${model?.id}: ${removed.join(", ")}`);
|
|
50935
|
+
}
|
|
50936
|
+
//#endregion
|
|
50937
|
+
//#region src/translator/responses/function-schema.ts
|
|
51318
50938
|
function isRecord$2(value) {
|
|
51319
50939
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
51320
50940
|
}
|
|
@@ -51356,147 +50976,9 @@ function normalizeFunctionParametersSchemaForCopilot(schema) {
|
|
|
51356
50976
|
return normalizeSchemaNode(schema);
|
|
51357
50977
|
}
|
|
51358
50978
|
//#endregion
|
|
51359
|
-
//#region src/translator/responses/
|
|
50979
|
+
//#region src/translator/responses/response-items.ts
|
|
51360
50980
|
const MESSAGE_TYPE = "message";
|
|
51361
|
-
const USER_ID_ACCOUNT_RE = /user_([^_]+)_account/;
|
|
51362
|
-
const USER_ID_SESSION_RE = /_session_(.+)$/;
|
|
51363
50981
|
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
50982
|
function translateUserContentBlock(block) {
|
|
51501
50983
|
switch (block.type) {
|
|
51502
50984
|
case "text": return createTextContent(block.text);
|
|
@@ -51595,7 +51077,7 @@ function createRedactedReasoningContent(block) {
|
|
|
51595
51077
|
};
|
|
51596
51078
|
}
|
|
51597
51079
|
function createCompactionContent(block) {
|
|
51598
|
-
const compaction =
|
|
51080
|
+
const compaction = SignatureCodec.decodeCompaction(block.signature ?? "");
|
|
51599
51081
|
if (!compaction) return;
|
|
51600
51082
|
return {
|
|
51601
51083
|
id: compaction.id,
|
|
@@ -51631,6 +51113,160 @@ function createServerFunctionCallOutput(block) {
|
|
|
51631
51113
|
function isServerToolResultBlock(block) {
|
|
51632
51114
|
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
51115
|
}
|
|
51116
|
+
function convertToolResultContent(content) {
|
|
51117
|
+
if (typeof content === "string") return content;
|
|
51118
|
+
const result = [];
|
|
51119
|
+
for (const block of content) switch (block.type) {
|
|
51120
|
+
case "text":
|
|
51121
|
+
result.push(createTextContent(block.text));
|
|
51122
|
+
break;
|
|
51123
|
+
case "image":
|
|
51124
|
+
result.push(createImageContent(block));
|
|
51125
|
+
break;
|
|
51126
|
+
case "search_result":
|
|
51127
|
+
result.push(createTextContent(formatSearchResultBlock(block)));
|
|
51128
|
+
break;
|
|
51129
|
+
default: break;
|
|
51130
|
+
}
|
|
51131
|
+
return result;
|
|
51132
|
+
}
|
|
51133
|
+
//#endregion
|
|
51134
|
+
//#region src/translator/responses/anthropic-to-responses.ts
|
|
51135
|
+
const USER_ID_ACCOUNT_RE = /user_([^_]+)_account/;
|
|
51136
|
+
const USER_ID_SESSION_RE = /_session_(.+)$/;
|
|
51137
|
+
function translateAnthropicToResponsesPayload(payload, options) {
|
|
51138
|
+
assertResponsesCompatibleRequest(payload);
|
|
51139
|
+
const input = [];
|
|
51140
|
+
for (const message of payload.messages) input.push(...translateMessage(message));
|
|
51141
|
+
const { safetyIdentifier, promptCacheKey } = parseUserId(payload.metadata?.user_id);
|
|
51142
|
+
const reasoning = resolveResponsesReasoningConfig(payload, options);
|
|
51143
|
+
const text = resolveResponsesTextConfig(payload);
|
|
51144
|
+
return {
|
|
51145
|
+
model: payload.model,
|
|
51146
|
+
input,
|
|
51147
|
+
instructions: translateSystemPrompt(payload.system),
|
|
51148
|
+
temperature: payload.temperature ?? null,
|
|
51149
|
+
top_p: payload.top_p ?? null,
|
|
51150
|
+
max_output_tokens: payload.max_tokens,
|
|
51151
|
+
tools: convertAnthropicTools(payload.tools),
|
|
51152
|
+
tool_choice: convertAnthropicToolChoice(payload.tool_choice),
|
|
51153
|
+
metadata: payload.metadata ? { ...payload.metadata } : null,
|
|
51154
|
+
safety_identifier: safetyIdentifier,
|
|
51155
|
+
prompt_cache_key: promptCacheKey,
|
|
51156
|
+
stream: payload.stream ?? null,
|
|
51157
|
+
store: false,
|
|
51158
|
+
parallel_tool_calls: true,
|
|
51159
|
+
...text ? { text } : {},
|
|
51160
|
+
...reasoning ? {
|
|
51161
|
+
reasoning,
|
|
51162
|
+
include: ["reasoning.encrypted_content"]
|
|
51163
|
+
} : {}
|
|
51164
|
+
};
|
|
51165
|
+
}
|
|
51166
|
+
function translateMessage(message) {
|
|
51167
|
+
switch (message.role) {
|
|
51168
|
+
case "user": return translateUserMessage(message);
|
|
51169
|
+
case "assistant": return translateAssistantMessage(message);
|
|
51170
|
+
case "system": return translateSystemMessage(message);
|
|
51171
|
+
}
|
|
51172
|
+
}
|
|
51173
|
+
function translateSystemMessage(message) {
|
|
51174
|
+
if (typeof message.content === "string") return [createMessage("system", message.content)];
|
|
51175
|
+
if (!Array.isArray(message.content)) return [];
|
|
51176
|
+
return [createMessage("system", message.content.map((block) => createTextContent(block.text)))];
|
|
51177
|
+
}
|
|
51178
|
+
function translateUserMessage(message) {
|
|
51179
|
+
if (typeof message.content === "string") return [createMessage("user", message.content)];
|
|
51180
|
+
if (!Array.isArray(message.content)) return [];
|
|
51181
|
+
const items = [];
|
|
51182
|
+
const pendingContent = [];
|
|
51183
|
+
for (const block of message.content) {
|
|
51184
|
+
if (block.type === "tool_result" || block.type === "mcp_tool_result") {
|
|
51185
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51186
|
+
items.push(createFunctionCallOutput(block));
|
|
51187
|
+
continue;
|
|
51188
|
+
}
|
|
51189
|
+
if (isServerToolResultBlock(block)) {
|
|
51190
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51191
|
+
items.push(createServerFunctionCallOutput(block));
|
|
51192
|
+
continue;
|
|
51193
|
+
}
|
|
51194
|
+
const converted = translateUserContentBlock(block);
|
|
51195
|
+
if (converted) pendingContent.push(converted);
|
|
51196
|
+
}
|
|
51197
|
+
flushPendingContent(pendingContent, items, { role: "user" });
|
|
51198
|
+
return items;
|
|
51199
|
+
}
|
|
51200
|
+
function translateAssistantMessage(message) {
|
|
51201
|
+
const assistantPhase = resolveAssistantPhase(message.content);
|
|
51202
|
+
if (typeof message.content === "string") return [createMessage("assistant", message.content, assistantPhase)];
|
|
51203
|
+
if (!Array.isArray(message.content)) return [];
|
|
51204
|
+
const items = [];
|
|
51205
|
+
const pendingContent = [];
|
|
51206
|
+
for (const block of message.content) {
|
|
51207
|
+
if (block.type === "tool_use" || block.type === "server_tool_use" || block.type === "mcp_tool_use") {
|
|
51208
|
+
flushPendingContent(pendingContent, items, {
|
|
51209
|
+
role: "assistant",
|
|
51210
|
+
phase: assistantPhase
|
|
51211
|
+
});
|
|
51212
|
+
items.push(createFunctionToolCall(block));
|
|
51213
|
+
continue;
|
|
51214
|
+
}
|
|
51215
|
+
if (block.type === "redacted_thinking") {
|
|
51216
|
+
flushPendingContent(pendingContent, items, {
|
|
51217
|
+
role: "assistant",
|
|
51218
|
+
phase: assistantPhase
|
|
51219
|
+
});
|
|
51220
|
+
items.push(createRedactedReasoningContent(block));
|
|
51221
|
+
continue;
|
|
51222
|
+
}
|
|
51223
|
+
if (block.type === "mcp_tool_result") {
|
|
51224
|
+
flushPendingContent(pendingContent, items, {
|
|
51225
|
+
role: "assistant",
|
|
51226
|
+
phase: assistantPhase
|
|
51227
|
+
});
|
|
51228
|
+
items.push(createFunctionCallOutput(block));
|
|
51229
|
+
continue;
|
|
51230
|
+
}
|
|
51231
|
+
if (isServerToolResultBlock(block)) {
|
|
51232
|
+
flushPendingContent(pendingContent, items, {
|
|
51233
|
+
role: "assistant",
|
|
51234
|
+
phase: assistantPhase
|
|
51235
|
+
});
|
|
51236
|
+
items.push(createServerFunctionCallOutput(block));
|
|
51237
|
+
continue;
|
|
51238
|
+
}
|
|
51239
|
+
if (block.type === "thinking" && block.signature) {
|
|
51240
|
+
const compaction = createCompactionContent(block);
|
|
51241
|
+
if (compaction) {
|
|
51242
|
+
flushPendingContent(pendingContent, items, {
|
|
51243
|
+
role: "assistant",
|
|
51244
|
+
phase: assistantPhase
|
|
51245
|
+
});
|
|
51246
|
+
items.push(compaction);
|
|
51247
|
+
continue;
|
|
51248
|
+
}
|
|
51249
|
+
if (SignatureCodec.isReasoningSignature(block.signature)) {
|
|
51250
|
+
const { id } = SignatureCodec.decodeReasoning(block.signature);
|
|
51251
|
+
if (id) {
|
|
51252
|
+
flushPendingContent(pendingContent, items, {
|
|
51253
|
+
role: "assistant",
|
|
51254
|
+
phase: assistantPhase
|
|
51255
|
+
});
|
|
51256
|
+
items.push(createReasoningContent(block));
|
|
51257
|
+
continue;
|
|
51258
|
+
}
|
|
51259
|
+
}
|
|
51260
|
+
}
|
|
51261
|
+
const converted = translateAssistantContentBlock(block);
|
|
51262
|
+
if (converted) pendingContent.push(converted);
|
|
51263
|
+
}
|
|
51264
|
+
flushPendingContent(pendingContent, items, {
|
|
51265
|
+
role: "assistant",
|
|
51266
|
+
phase: assistantPhase
|
|
51267
|
+
});
|
|
51268
|
+
return items;
|
|
51269
|
+
}
|
|
51634
51270
|
function translateSystemPrompt(system) {
|
|
51635
51271
|
if (!system) return null;
|
|
51636
51272
|
if (typeof system === "string") return system;
|
|
@@ -51716,92 +51352,18 @@ function parseUserId(userId) {
|
|
|
51716
51352
|
promptCacheKey: sessionMatch ? sessionMatch[1] : null
|
|
51717
51353
|
};
|
|
51718
51354
|
}
|
|
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
51355
|
//#endregion
|
|
51798
51356
|
//#region src/routes/messages/strategies/chat-completions.ts
|
|
51799
|
-
function createMessagesViaChatCompletionsStrategy(
|
|
51357
|
+
function createMessagesViaChatCompletionsStrategy(client, adapter, plan, signal) {
|
|
51800
51358
|
let streamTranslator;
|
|
51801
51359
|
let done = false;
|
|
51802
51360
|
return {
|
|
51803
51361
|
execute() {
|
|
51804
|
-
return
|
|
51362
|
+
return client.createChatCompletions(plan.payload, {
|
|
51363
|
+
signal,
|
|
51364
|
+
initiator: plan.initiator,
|
|
51365
|
+
requestContext: plan.requestContext
|
|
51366
|
+
});
|
|
51805
51367
|
},
|
|
51806
51368
|
isStream(result) {
|
|
51807
51369
|
return !isNonStreamingResponse(result);
|
|
@@ -51818,24 +51380,15 @@ function createMessagesViaChatCompletionsStrategy(transport, adapter, plan, sign
|
|
|
51818
51380
|
if (chunk.data === "[DONE]") {
|
|
51819
51381
|
const finalEvents = streamTranslator.onDone();
|
|
51820
51382
|
done = true;
|
|
51821
|
-
return finalEvents
|
|
51822
|
-
event: event.type,
|
|
51823
|
-
data: JSON.stringify(event)
|
|
51824
|
-
}));
|
|
51383
|
+
return serializeAnthropicSSE(finalEvents);
|
|
51825
51384
|
}
|
|
51826
51385
|
if (!chunk.data) return null;
|
|
51827
51386
|
const parsed = JSON.parse(chunk.data);
|
|
51828
|
-
return streamTranslator.onChunk(parsed)
|
|
51829
|
-
event: event.type,
|
|
51830
|
-
data: JSON.stringify(event)
|
|
51831
|
-
}));
|
|
51387
|
+
return serializeAnthropicSSE(streamTranslator.onChunk(parsed));
|
|
51832
51388
|
},
|
|
51833
51389
|
onStreamDone() {
|
|
51834
51390
|
if (!streamTranslator) return null;
|
|
51835
|
-
return streamTranslator.onDone()
|
|
51836
|
-
event: event.type,
|
|
51837
|
-
data: JSON.stringify(event)
|
|
51838
|
-
}));
|
|
51391
|
+
return serializeAnthropicSSE(streamTranslator.onDone());
|
|
51839
51392
|
},
|
|
51840
51393
|
shouldBreakStream() {
|
|
51841
51394
|
return done;
|
|
@@ -51843,15 +51396,12 @@ function createMessagesViaChatCompletionsStrategy(transport, adapter, plan, sign
|
|
|
51843
51396
|
onStreamError(error) {
|
|
51844
51397
|
consola.error("Error streaming Anthropic response:", error);
|
|
51845
51398
|
if (!streamTranslator) streamTranslator = adapter.createStreamSerializer();
|
|
51846
|
-
return streamTranslator.onError(error)
|
|
51847
|
-
event: event.type,
|
|
51848
|
-
data: JSON.stringify(event)
|
|
51849
|
-
}));
|
|
51399
|
+
return serializeAnthropicSSE(streamTranslator.onError(error));
|
|
51850
51400
|
}
|
|
51851
51401
|
};
|
|
51852
51402
|
}
|
|
51853
51403
|
//#endregion
|
|
51854
|
-
//#region src/
|
|
51404
|
+
//#region src/util/async-iterable.ts
|
|
51855
51405
|
function isAsyncIterable(value) {
|
|
51856
51406
|
return Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
51857
51407
|
}
|
|
@@ -51924,6 +51474,30 @@ function createNativeMessagesStrategy(copilotClient, payload, anthropicBetaHeade
|
|
|
51924
51474
|
}
|
|
51925
51475
|
};
|
|
51926
51476
|
}
|
|
51477
|
+
var FunctionCallArgumentsValidationError = class extends Error {
|
|
51478
|
+
constructor(message) {
|
|
51479
|
+
super(message);
|
|
51480
|
+
this.name = "FunctionCallArgumentsValidationError";
|
|
51481
|
+
}
|
|
51482
|
+
};
|
|
51483
|
+
function updateWhitespaceRunState(previousCount, chunk) {
|
|
51484
|
+
let count = previousCount;
|
|
51485
|
+
for (const char of chunk) {
|
|
51486
|
+
if (char === " " || char === "\r" || char === "\n" || char === " ") {
|
|
51487
|
+
count += 1;
|
|
51488
|
+
if (count > 20) return {
|
|
51489
|
+
nextCount: count,
|
|
51490
|
+
exceeded: true
|
|
51491
|
+
};
|
|
51492
|
+
continue;
|
|
51493
|
+
}
|
|
51494
|
+
count = 0;
|
|
51495
|
+
}
|
|
51496
|
+
return {
|
|
51497
|
+
nextCount: count,
|
|
51498
|
+
exceeded: false
|
|
51499
|
+
};
|
|
51500
|
+
}
|
|
51927
51501
|
//#endregion
|
|
51928
51502
|
//#region src/translator/responses/responses-to-anthropic.ts
|
|
51929
51503
|
function translateResponsesToAnthropic(response) {
|
|
@@ -51996,12 +51570,9 @@ function combineMessageTextContent(content) {
|
|
|
51996
51570
|
function extractReasoningText(item) {
|
|
51997
51571
|
if (!item.summary || item.summary.length === 0) return THINKING_TEXT;
|
|
51998
51572
|
const segments = [];
|
|
51999
|
-
|
|
51573
|
+
for (const block of item.summary) if (typeof block.text === "string") segments.push(block.text);
|
|
52000
51574
|
return segments.join("").trim();
|
|
52001
51575
|
}
|
|
52002
|
-
function collectReasoningSegments(blocks, segments) {
|
|
52003
|
-
for (const block of blocks) if (typeof block.text === "string") segments.push(block.text);
|
|
52004
|
-
}
|
|
52005
51576
|
function createToolUseContentBlock(call) {
|
|
52006
51577
|
if (!call.name || !call.call_id) return null;
|
|
52007
51578
|
return {
|
|
@@ -52061,31 +51632,6 @@ function isResponseOutputRefusal(block) {
|
|
|
52061
51632
|
}
|
|
52062
51633
|
//#endregion
|
|
52063
51634
|
//#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
51635
|
var ResponsesStreamTranslator = class {
|
|
52090
51636
|
state = {
|
|
52091
51637
|
messageStartSent: false,
|
|
@@ -52345,6 +51891,7 @@ var ResponsesStreamTranslator = class {
|
|
|
52345
51891
|
return events;
|
|
52346
51892
|
}
|
|
52347
51893
|
handleResponseCompleted(rawEvent) {
|
|
51894
|
+
if (this.state.messageCompleted) return [];
|
|
52348
51895
|
const events = [];
|
|
52349
51896
|
this.closeAllOpenBlocks(events);
|
|
52350
51897
|
const anthropic = translateResponsesToAnthropic(rawEvent.response);
|
|
@@ -52505,27 +52052,18 @@ function createMessagesViaResponsesStrategy(copilotClient, responsesPayload, opt
|
|
|
52505
52052
|
data: "{\"type\":\"ping\"}"
|
|
52506
52053
|
};
|
|
52507
52054
|
if (!chunk.data) return null;
|
|
52508
|
-
return translator.onEvent(JSON.parse(chunk.data))
|
|
52509
|
-
event: event.type,
|
|
52510
|
-
data: JSON.stringify(event)
|
|
52511
|
-
}));
|
|
52055
|
+
return serializeAnthropicSSE(translator.onEvent(JSON.parse(chunk.data)));
|
|
52512
52056
|
},
|
|
52513
52057
|
shouldBreakStream() {
|
|
52514
52058
|
return translator.isCompleted;
|
|
52515
52059
|
},
|
|
52516
52060
|
onStreamDone() {
|
|
52517
52061
|
if (translator.isCompleted) return null;
|
|
52518
|
-
return translator.onDone()
|
|
52519
|
-
event: event.type,
|
|
52520
|
-
data: JSON.stringify(event)
|
|
52521
|
-
}));
|
|
52062
|
+
return serializeAnthropicSSE(translator.onDone());
|
|
52522
52063
|
},
|
|
52523
52064
|
onStreamError(error) {
|
|
52524
52065
|
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
|
-
}));
|
|
52066
|
+
return serializeAnthropicSSE(translator.onError(error));
|
|
52529
52067
|
}
|
|
52530
52068
|
};
|
|
52531
52069
|
}
|
|
@@ -52551,6 +52089,7 @@ const responsesApiEntry = {
|
|
|
52551
52089
|
const responsesPayload = withTranslationErrors(() => translateAnthropicToResponsesPayload(ctx.anthropicPayload, { reasoningEffortResolver: (model) => configStore.getReasoningEffort(model) }));
|
|
52552
52090
|
applyContextManagement(responsesPayload, ctx.selectedModel?.capabilities.limits.max_prompt_tokens);
|
|
52553
52091
|
compactInputByLatestCompaction(responsesPayload);
|
|
52092
|
+
applyResponsesParameterFilters(responsesPayload, ctx.selectedModel);
|
|
52554
52093
|
const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
|
|
52555
52094
|
return await runStrategy(createMessagesViaResponsesStrategy(ctx.copilotClient, responsesPayload, {
|
|
52556
52095
|
vision,
|
|
@@ -52570,7 +52109,7 @@ const chatCompletionsEntry = {
|
|
|
52570
52109
|
appendModelStepInPlace(ctx.modelMapping, "MODEL_RESOLVE", plan.resolvedModel);
|
|
52571
52110
|
consola.debug("Claude Code requested model:", ctx.anthropicPayload.model, "-> Copilot model:", plan.resolvedModel);
|
|
52572
52111
|
if (consola.level >= 4) consola.debug("Planned Copilot request payload:", JSON.stringify(plan.payload));
|
|
52573
|
-
return await runStrategy(createMessagesViaChatCompletionsStrategy(
|
|
52112
|
+
return await runStrategy(createMessagesViaChatCompletionsStrategy(ctx.copilotClient, adapter, plan, ctx.upstreamSignal.signal), ctx.upstreamSignal);
|
|
52574
52113
|
}
|
|
52575
52114
|
};
|
|
52576
52115
|
const defaultStrategyRegistry = new StrategyRegistry();
|
|
@@ -52589,10 +52128,10 @@ async function handleMessagesCore({ body, signal, headers }) {
|
|
|
52589
52128
|
protocol: "anthropic-messages",
|
|
52590
52129
|
transformChain: messagesModelChain,
|
|
52591
52130
|
strategyRegistry: defaultStrategyRegistry,
|
|
52592
|
-
contextRetry: true,
|
|
52593
52131
|
afterIngest({ payload, headers: reqHeaders }) {
|
|
52594
52132
|
if (consola.level >= 4) consola.debug("Anthropic request payload:", JSON.stringify(payload));
|
|
52595
|
-
anthropicBetaHeader = processAnthropicBetaHeader(reqHeaders.get("anthropic-beta")
|
|
52133
|
+
anthropicBetaHeader = processAnthropicBetaHeader(reqHeaders.get("anthropic-beta"));
|
|
52134
|
+
return payload;
|
|
52596
52135
|
},
|
|
52597
52136
|
buildStrategyContext({ payload, meta, headers: reqHeaders, selectedModel, copilotClient, upstreamSignal, modelMapping }) {
|
|
52598
52137
|
return {
|
|
@@ -52657,13 +52196,243 @@ function createModelRoutes() {
|
|
|
52657
52196
|
});
|
|
52658
52197
|
}
|
|
52659
52198
|
//#endregion
|
|
52199
|
+
//#region src/routes/responses/emulator.ts
|
|
52200
|
+
function cloneValue(value) {
|
|
52201
|
+
return structuredClone(value);
|
|
52202
|
+
}
|
|
52203
|
+
function rejectUnsupportedBackground(payload) {
|
|
52204
|
+
if (payload.background) throwInvalidRequestError("background mode is not supported by the responses official emulator.", "background", "unsupported_background_mode");
|
|
52205
|
+
}
|
|
52206
|
+
function prepareEmulatorRequest(payload) {
|
|
52207
|
+
rejectUnsupportedBackground(payload);
|
|
52208
|
+
const normalizedCurrentInput = normalizeResponsesInput(payload.input);
|
|
52209
|
+
const { continuationSourceResponseId, conversation: resolvedConversation, previousResponse } = resolveContinuation(payload);
|
|
52210
|
+
const conversation = resolvedConversation ?? createConversationRef();
|
|
52211
|
+
const effectiveInputItems = [...continuationSourceResponseId ? buildContinuationHistory(continuationSourceResponseId) : [], ...normalizedCurrentInput];
|
|
52212
|
+
const shouldStore = payload.store ?? true;
|
|
52213
|
+
return {
|
|
52214
|
+
upstreamPayload: {
|
|
52215
|
+
...payload,
|
|
52216
|
+
background: void 0,
|
|
52217
|
+
conversation: void 0,
|
|
52218
|
+
previous_response_id: void 0,
|
|
52219
|
+
store: void 0,
|
|
52220
|
+
input: effectiveInputItems
|
|
52221
|
+
},
|
|
52222
|
+
effectiveInputItems,
|
|
52223
|
+
previousResponseId: previousResponse?.id,
|
|
52224
|
+
conversation,
|
|
52225
|
+
shouldStore
|
|
52226
|
+
};
|
|
52227
|
+
}
|
|
52228
|
+
function decorateStoredResponse(upstreamResponse, requestPayload, prepared) {
|
|
52229
|
+
return {
|
|
52230
|
+
...cloneValue(upstreamResponse),
|
|
52231
|
+
previous_response_id: prepared.previousResponseId ?? null,
|
|
52232
|
+
conversation: prepared.conversation,
|
|
52233
|
+
truncation: requestPayload.truncation ?? null,
|
|
52234
|
+
store: prepared.shouldStore,
|
|
52235
|
+
user: normalizeNullableString(requestPayload.user),
|
|
52236
|
+
service_tier: normalizeServiceTier(requestPayload.service_tier)
|
|
52237
|
+
};
|
|
52238
|
+
}
|
|
52239
|
+
function persistEmulatorResponse(response, effectiveInputItems) {
|
|
52240
|
+
responsesEmulatorState.setResponse(response);
|
|
52241
|
+
if (response.conversation) {
|
|
52242
|
+
responsesEmulatorState.setConversation(response.conversation);
|
|
52243
|
+
responsesEmulatorState.setConversationHead(getConversationId(response.conversation), response.id);
|
|
52244
|
+
}
|
|
52245
|
+
responsesEmulatorState.setInputItems(response.id, effectiveInputItems);
|
|
52246
|
+
}
|
|
52247
|
+
function getStoredResponseOrThrow(responseId) {
|
|
52248
|
+
const response = responsesEmulatorState.getResponse(responseId);
|
|
52249
|
+
if (!response) throw new HTTPError(404, { error: {
|
|
52250
|
+
message: `No response found with id '${responseId}'.`,
|
|
52251
|
+
type: "invalid_request_error"
|
|
52252
|
+
} });
|
|
52253
|
+
return response;
|
|
52254
|
+
}
|
|
52255
|
+
function listStoredInputItemsOrThrow(responseId, params) {
|
|
52256
|
+
const items = responsesEmulatorState.getInputItems(responseId);
|
|
52257
|
+
if (!items) throw new HTTPError(404, { error: {
|
|
52258
|
+
message: `No response input items found for id '${responseId}'.`,
|
|
52259
|
+
type: "invalid_request_error"
|
|
52260
|
+
} });
|
|
52261
|
+
let orderedItems = cloneValue(items);
|
|
52262
|
+
if (params?.order === "desc") orderedItems.reverse();
|
|
52263
|
+
if (params?.after) {
|
|
52264
|
+
const afterIndex = orderedItems.findIndex((item) => getInputItemId(item) === params.after);
|
|
52265
|
+
if (afterIndex >= 0) orderedItems = orderedItems.slice(afterIndex + 1);
|
|
52266
|
+
}
|
|
52267
|
+
const limitedItems = orderedItems.slice(0, params?.limit ?? orderedItems.length);
|
|
52268
|
+
return {
|
|
52269
|
+
object: "list",
|
|
52270
|
+
data: limitedItems,
|
|
52271
|
+
first_id: getInputItemId(limitedItems[0]) ?? null,
|
|
52272
|
+
last_id: getInputItemId(limitedItems.at(-1)) ?? null,
|
|
52273
|
+
has_more: limitedItems.length < orderedItems.length
|
|
52274
|
+
};
|
|
52275
|
+
}
|
|
52276
|
+
function deleteStoredResponseOrThrow(responseId) {
|
|
52277
|
+
getStoredResponseOrThrow(responseId);
|
|
52278
|
+
return responsesEmulatorState.deleteResponse(responseId);
|
|
52279
|
+
}
|
|
52280
|
+
async function estimateEmulatorInputTokens(payload, selectedModel) {
|
|
52281
|
+
return {
|
|
52282
|
+
object: "response.input_tokens",
|
|
52283
|
+
input_tokens: await estimateResponsesInputTokens(resolveEffectiveInputForInputTokens(payload), selectedModel)
|
|
52284
|
+
};
|
|
52285
|
+
}
|
|
52286
|
+
function resolveEffectiveInputForInputTokens(payload) {
|
|
52287
|
+
const normalizedInput = normalizeResponsesInput(payload.input);
|
|
52288
|
+
const background = payload.background === null || typeof payload.background === "boolean" ? payload.background : void 0;
|
|
52289
|
+
const conversation = isConversationReference(payload.conversation) ? payload.conversation : void 0;
|
|
52290
|
+
const previousResponseId = typeof payload.previous_response_id === "string" ? payload.previous_response_id : void 0;
|
|
52291
|
+
rejectUnsupportedBackground({ background });
|
|
52292
|
+
const { continuationSourceResponseId } = resolveContinuation({
|
|
52293
|
+
conversation,
|
|
52294
|
+
previous_response_id: previousResponseId
|
|
52295
|
+
});
|
|
52296
|
+
if (continuationSourceResponseId) return [...buildContinuationHistory(continuationSourceResponseId), ...normalizedInput];
|
|
52297
|
+
return normalizedInput;
|
|
52298
|
+
}
|
|
52299
|
+
function resolveContinuation(payload) {
|
|
52300
|
+
const previousResponse = resolvePreviousResponse(payload.previous_response_id);
|
|
52301
|
+
const conversation = resolveConversation(payload.conversation, previousResponse);
|
|
52302
|
+
return {
|
|
52303
|
+
previousResponse,
|
|
52304
|
+
conversation,
|
|
52305
|
+
continuationSourceResponseId: resolveContinuationSourceResponseId(previousResponse, conversation)
|
|
52306
|
+
};
|
|
52307
|
+
}
|
|
52308
|
+
function resolvePreviousResponse(previousResponseId) {
|
|
52309
|
+
if (typeof previousResponseId !== "string" || previousResponseId.length === 0) return;
|
|
52310
|
+
const previousResponse = responsesEmulatorState.getResponse(previousResponseId);
|
|
52311
|
+
if (!previousResponse) throwInvalidRequestError("The selected previous_response_id could not be resolved.", "previous_response_id");
|
|
52312
|
+
return previousResponse;
|
|
52313
|
+
}
|
|
52314
|
+
function resolveConversation(conversation, previousResponse) {
|
|
52315
|
+
if (isConversationReference(conversation)) {
|
|
52316
|
+
const conversationId = getConversationId(conversation);
|
|
52317
|
+
const existingConversation = responsesEmulatorState.getConversation(conversationId);
|
|
52318
|
+
if (!existingConversation) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
52319
|
+
if (previousResponse?.conversation && getConversationId(previousResponse.conversation) !== conversationId) throwInvalidRequestError("The selected previous_response_id does not belong to the selected conversation.", "previous_response_id");
|
|
52320
|
+
return existingConversation;
|
|
52321
|
+
}
|
|
52322
|
+
return previousResponse?.conversation ?? void 0;
|
|
52323
|
+
}
|
|
52324
|
+
function resolveContinuationSourceResponseId(previousResponse, conversation) {
|
|
52325
|
+
if (previousResponse) return previousResponse.id;
|
|
52326
|
+
if (!conversation) return;
|
|
52327
|
+
const head = responsesEmulatorState.getConversationHead(getConversationId(conversation));
|
|
52328
|
+
if (!head) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
|
|
52329
|
+
return head;
|
|
52330
|
+
}
|
|
52331
|
+
function buildContinuationHistory(responseId) {
|
|
52332
|
+
const previousResponse = getStoredResponseOrThrow(responseId);
|
|
52333
|
+
const previousInput = responsesEmulatorState.getInputItems(responseId);
|
|
52334
|
+
if (!previousInput) throwInvalidRequestError("The selected previous_response_id is missing stored input items.", "previous_response_id");
|
|
52335
|
+
return [...cloneValue(previousInput), ...convertOutputItemsToInputItems(previousResponse.output)];
|
|
52336
|
+
}
|
|
52337
|
+
function normalizeResponsesInput(input) {
|
|
52338
|
+
if (!input) return [];
|
|
52339
|
+
if (typeof input === "string") return [{
|
|
52340
|
+
type: "message",
|
|
52341
|
+
role: "user",
|
|
52342
|
+
content: input
|
|
52343
|
+
}];
|
|
52344
|
+
if (Array.isArray(input)) return cloneValue(input);
|
|
52345
|
+
return [];
|
|
52346
|
+
}
|
|
52347
|
+
function convertOutputItemsToInputItems(output) {
|
|
52348
|
+
const items = [];
|
|
52349
|
+
for (const item of output) switch (item.type) {
|
|
52350
|
+
case "message":
|
|
52351
|
+
items.push(convertMessageOutputToInput(item));
|
|
52352
|
+
break;
|
|
52353
|
+
case "function_call":
|
|
52354
|
+
items.push(convertFunctionCallOutputToInput(item));
|
|
52355
|
+
break;
|
|
52356
|
+
case "reasoning": {
|
|
52357
|
+
const reasoningInput = convertReasoningOutputToInput(item);
|
|
52358
|
+
if (reasoningInput) items.push(reasoningInput);
|
|
52359
|
+
break;
|
|
52360
|
+
}
|
|
52361
|
+
case "compaction":
|
|
52362
|
+
items.push(convertCompactionOutputToInput(item));
|
|
52363
|
+
break;
|
|
52364
|
+
}
|
|
52365
|
+
return items;
|
|
52366
|
+
}
|
|
52367
|
+
function convertMessageOutputToInput(item) {
|
|
52368
|
+
return {
|
|
52369
|
+
type: "message",
|
|
52370
|
+
role: item.role,
|
|
52371
|
+
status: item.status,
|
|
52372
|
+
content: item.content?.map((content) => {
|
|
52373
|
+
if (content.type === "output_text" && typeof content.text === "string") return {
|
|
52374
|
+
type: "output_text",
|
|
52375
|
+
text: content.text
|
|
52376
|
+
};
|
|
52377
|
+
return cloneValue(content);
|
|
52378
|
+
}) ?? []
|
|
52379
|
+
};
|
|
52380
|
+
}
|
|
52381
|
+
function convertFunctionCallOutputToInput(item) {
|
|
52382
|
+
return {
|
|
52383
|
+
type: "function_call",
|
|
52384
|
+
call_id: item.call_id,
|
|
52385
|
+
name: item.name,
|
|
52386
|
+
arguments: item.arguments,
|
|
52387
|
+
status: item.status
|
|
52388
|
+
};
|
|
52389
|
+
}
|
|
52390
|
+
function convertReasoningOutputToInput(item) {
|
|
52391
|
+
if (!item.encrypted_content) return;
|
|
52392
|
+
return {
|
|
52393
|
+
id: item.id,
|
|
52394
|
+
type: "reasoning",
|
|
52395
|
+
summary: (item.summary ?? []).filter((summary) => typeof summary.text === "string").map((summary) => ({
|
|
52396
|
+
type: "summary_text",
|
|
52397
|
+
text: summary.text
|
|
52398
|
+
})),
|
|
52399
|
+
encrypted_content: item.encrypted_content
|
|
52400
|
+
};
|
|
52401
|
+
}
|
|
52402
|
+
function convertCompactionOutputToInput(item) {
|
|
52403
|
+
return {
|
|
52404
|
+
id: item.id,
|
|
52405
|
+
type: "compaction",
|
|
52406
|
+
encrypted_content: item.encrypted_content
|
|
52407
|
+
};
|
|
52408
|
+
}
|
|
52409
|
+
function normalizeNullableString(value) {
|
|
52410
|
+
return typeof value === "string" ? value : null;
|
|
52411
|
+
}
|
|
52412
|
+
function normalizeServiceTier(value) {
|
|
52413
|
+
if (value === "auto" || value === "default" || value === "flex" || value === "scale" || value === "priority") return value;
|
|
52414
|
+
return null;
|
|
52415
|
+
}
|
|
52416
|
+
function createConversationRef() {
|
|
52417
|
+
return { id: `conv_${randomUUID().replaceAll("-", "")}` };
|
|
52418
|
+
}
|
|
52419
|
+
function isConversationReference(value) {
|
|
52420
|
+
if (typeof value === "string") return value.length > 0;
|
|
52421
|
+
return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && value.id.length > 0;
|
|
52422
|
+
}
|
|
52423
|
+
function getConversationId(conversation) {
|
|
52424
|
+
return typeof conversation === "string" ? conversation : conversation.id;
|
|
52425
|
+
}
|
|
52426
|
+
function getInputItemId(item) {
|
|
52427
|
+
if (!item || typeof item !== "object") return;
|
|
52428
|
+
if ("id" in item && typeof item.id === "string") return item.id;
|
|
52429
|
+
if ("call_id" in item && typeof item.call_id === "string") return item.call_id;
|
|
52430
|
+
}
|
|
52431
|
+
//#endregion
|
|
52660
52432
|
//#region src/routes/responses/strategy.ts
|
|
52661
52433
|
function isRecord(value) {
|
|
52662
52434
|
return typeof value === "object" && value !== null;
|
|
52663
52435
|
}
|
|
52664
|
-
function createStreamIdTracker() {
|
|
52665
|
-
return { itemIdsByOutputIndex: /* @__PURE__ */ new Map() };
|
|
52666
|
-
}
|
|
52667
52436
|
function fixStreamIds(rawData, eventName, state) {
|
|
52668
52437
|
if (!rawData) return rawData;
|
|
52669
52438
|
let parsed;
|
|
@@ -52693,7 +52462,7 @@ function fixStreamIds(rawData, eventName, state) {
|
|
|
52693
52462
|
return JSON.stringify(parsed);
|
|
52694
52463
|
}
|
|
52695
52464
|
function createResponsesPassthroughStrategy(copilotClient, payload, options) {
|
|
52696
|
-
const tracker =
|
|
52465
|
+
const tracker = { itemIdsByOutputIndex: /* @__PURE__ */ new Map() };
|
|
52697
52466
|
return {
|
|
52698
52467
|
async execute() {
|
|
52699
52468
|
try {
|
|
@@ -52707,7 +52476,10 @@ function createResponsesPassthroughStrategy(copilotClient, payload, options) {
|
|
|
52707
52476
|
return Boolean(payload.stream) && isAsyncIterable(result);
|
|
52708
52477
|
},
|
|
52709
52478
|
translateResult(result) {
|
|
52710
|
-
|
|
52479
|
+
const response = result;
|
|
52480
|
+
const mapped = options.mapResponse ? options.mapResponse(response) : response;
|
|
52481
|
+
if (options.mapResponse) options.onTerminalResponse?.(mapped);
|
|
52482
|
+
return mapped;
|
|
52711
52483
|
},
|
|
52712
52484
|
translateStreamChunk(chunk) {
|
|
52713
52485
|
const fixedData = fixStreamIds(chunk.data ?? "", chunk.event, tracker);
|
|
@@ -52786,59 +52558,56 @@ responsesStrategyRegistry.register(responsesPassthroughEntry);
|
|
|
52786
52558
|
//#region src/routes/responses/handler.ts
|
|
52787
52559
|
const HTTP_URL_RE = /^https?:\/\//i;
|
|
52788
52560
|
/**
|
|
52789
|
-
* Core handler for responses endpoint.
|
|
52561
|
+
* Core handler for responses endpoint. Orchestrates the standard pipeline
|
|
52562
|
+
* (ingest → transform → dispatch) via runPipeline, with the responses-specific
|
|
52563
|
+
* emulator request prep, tool/input policies, and context management applied
|
|
52564
|
+
* through the afterIngest / afterTransform lifecycle hooks.
|
|
52790
52565
|
*/
|
|
52791
52566
|
async function handleResponsesCore({ body, signal, headers }) {
|
|
52792
|
-
const
|
|
52793
|
-
|
|
52794
|
-
|
|
52795
|
-
|
|
52796
|
-
|
|
52797
|
-
|
|
52798
|
-
payload: effectivePayload,
|
|
52567
|
+
const emulatorMode = configStore.isEmulatorEnabled();
|
|
52568
|
+
let originalPayload;
|
|
52569
|
+
let emulatorPrepared;
|
|
52570
|
+
return await runPipeline({
|
|
52571
|
+
body,
|
|
52572
|
+
signal,
|
|
52799
52573
|
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
|
-
|
|
52835
|
-
steps: transformResult.trace.map((r) => ({
|
|
52836
|
-
tag: r.tag,
|
|
52837
|
-
from: r.from,
|
|
52838
|
-
to: r.to
|
|
52839
|
-
}))
|
|
52574
|
+
}, {
|
|
52575
|
+
protocol: "responses",
|
|
52576
|
+
transformChain: responsesModelChain,
|
|
52577
|
+
strategyRegistry: responsesStrategyRegistry,
|
|
52578
|
+
afterIngest({ payload }) {
|
|
52579
|
+
originalPayload = payload;
|
|
52580
|
+
emulatorPrepared = emulatorMode ? prepareEmulatorRequest(payload) : void 0;
|
|
52581
|
+
return emulatorPrepared?.upstreamPayload ?? payload;
|
|
52582
|
+
},
|
|
52583
|
+
afterTransform({ payload, selectedModel }) {
|
|
52584
|
+
applyResponsesToolTransforms(payload);
|
|
52585
|
+
applyResponsesInputPolicies(payload);
|
|
52586
|
+
compactInputByLatestCompaction(payload);
|
|
52587
|
+
if (!selectedModel) throwInvalidRequestError("The selected model could not be resolved.", "model");
|
|
52588
|
+
if (!modelCache.supportsEndpoint(selectedModel, "/responses")) throwInvalidRequestError("The selected model does not support the responses endpoint.", "model");
|
|
52589
|
+
applyContextManagement(payload, selectedModel.capabilities.limits.max_prompt_tokens);
|
|
52590
|
+
applyResponsesParameterFilters(payload, selectedModel);
|
|
52591
|
+
},
|
|
52592
|
+
buildStrategyContext({ payload, meta, copilotClient, upstreamSignal }) {
|
|
52593
|
+
const { vision, initiator } = getResponsesRequestOptions(payload);
|
|
52594
|
+
const prepared = emulatorPrepared;
|
|
52595
|
+
const requestPayload = originalPayload ?? payload;
|
|
52596
|
+
return {
|
|
52597
|
+
copilotClient,
|
|
52598
|
+
payload,
|
|
52599
|
+
upstreamSignal,
|
|
52600
|
+
requestContext: meta.requestContext ?? {},
|
|
52601
|
+
vision,
|
|
52602
|
+
initiator,
|
|
52603
|
+
decorateResponse: prepared ? (response) => decorateStoredResponse(response, requestPayload, prepared) : void 0,
|
|
52604
|
+
onTerminalResponse: prepared ? (terminalResponse) => {
|
|
52605
|
+
if (!prepared.shouldStore) return;
|
|
52606
|
+
persistEmulatorResponse(terminalResponse, prepared.effectiveInputItems);
|
|
52607
|
+
} : void 0
|
|
52608
|
+
};
|
|
52840
52609
|
}
|
|
52841
|
-
};
|
|
52610
|
+
});
|
|
52842
52611
|
}
|
|
52843
52612
|
function applyResponsesToolTransforms(payload) {
|
|
52844
52613
|
applyFunctionApplyPatch(payload);
|
|
@@ -52944,6 +52713,46 @@ function containsRemoteImageUrl(value) {
|
|
|
52944
52713
|
return Object.values(record).some((entry) => containsRemoteImageUrl(entry));
|
|
52945
52714
|
}
|
|
52946
52715
|
//#endregion
|
|
52716
|
+
//#region src/routes/responses/resource-dispatcher.ts
|
|
52717
|
+
var EmulatorResourceDispatcher = class {
|
|
52718
|
+
retrieve(responseId) {
|
|
52719
|
+
return Promise.resolve(getStoredResponseOrThrow(responseId));
|
|
52720
|
+
}
|
|
52721
|
+
listInputItems(responseId, params) {
|
|
52722
|
+
return Promise.resolve(listStoredInputItemsOrThrow(responseId, params));
|
|
52723
|
+
}
|
|
52724
|
+
async createInputTokens(payload) {
|
|
52725
|
+
return estimateEmulatorInputTokens(payload, resolveModelOrThrow(payload.model ?? ""));
|
|
52726
|
+
}
|
|
52727
|
+
delete(responseId) {
|
|
52728
|
+
return Promise.resolve(deleteStoredResponseOrThrow(responseId));
|
|
52729
|
+
}
|
|
52730
|
+
};
|
|
52731
|
+
var UpstreamResourceDispatcher = class {
|
|
52732
|
+
client;
|
|
52733
|
+
constructor(client) {
|
|
52734
|
+
this.client = client;
|
|
52735
|
+
}
|
|
52736
|
+
retrieve(responseId, params, options) {
|
|
52737
|
+
return this.client.getResponse(responseId, {
|
|
52738
|
+
params,
|
|
52739
|
+
...options
|
|
52740
|
+
});
|
|
52741
|
+
}
|
|
52742
|
+
listInputItems(responseId, params, options) {
|
|
52743
|
+
return this.client.getResponseInputItems(responseId, params, options);
|
|
52744
|
+
}
|
|
52745
|
+
createInputTokens(payload, options) {
|
|
52746
|
+
return this.client.createResponseInputTokens(payload, options);
|
|
52747
|
+
}
|
|
52748
|
+
delete(responseId, options) {
|
|
52749
|
+
return this.client.deleteResponse(responseId, options);
|
|
52750
|
+
}
|
|
52751
|
+
};
|
|
52752
|
+
function createResourceDispatcher() {
|
|
52753
|
+
return configStore.isEmulatorEnabled() ? new EmulatorResourceDispatcher() : new UpstreamResourceDispatcher(createCopilotClient());
|
|
52754
|
+
}
|
|
52755
|
+
//#endregion
|
|
52947
52756
|
//#region src/routes/responses/resource-handler.ts
|
|
52948
52757
|
async function handleRetrieveResponseCore({ params, url, headers, signal }) {
|
|
52949
52758
|
const responseId = requireResponseId(params.responseId);
|
|
@@ -53312,7 +53121,7 @@ const start = defineCommand({
|
|
|
53312
53121
|
},
|
|
53313
53122
|
"upstream-queue-retries": {
|
|
53314
53123
|
type: "string",
|
|
53315
|
-
description: "Maximum retries for upstream 429 responses (default:
|
|
53124
|
+
description: "Maximum retries for upstream 429 responses (default: 5)"
|
|
53316
53125
|
},
|
|
53317
53126
|
"upstream-queue-base-delay": {
|
|
53318
53127
|
type: "string",
|