ghc-proxy 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.mjs CHANGED
@@ -5378,7 +5378,11 @@ const configFileSchema = object({
5378
5378
  smallModel: string().optional(),
5379
5379
  compactUseSmallModel: boolean().optional(),
5380
5380
  useFunctionApplyPatch: boolean().optional(),
5381
+ responsesApiAutoCompactInput: boolean().optional(),
5382
+ responsesApiAutoContextManagement: boolean().optional(),
5381
5383
  responsesApiContextManagementModels: array(string()).optional(),
5384
+ responsesOfficialEmulator: boolean().optional(),
5385
+ responsesOfficialEmulatorTtlSeconds: number().int().positive().optional(),
5382
5386
  modelReasoningEfforts: record(string(), reasoningEffortSchema).optional(),
5383
5387
  modelRewrites: array(object({
5384
5388
  from: string(),
@@ -5392,6 +5396,10 @@ let cachedConfig = {};
5392
5396
  const DEFAULT_REASONING_EFFORT = "high";
5393
5397
  const DEFAULT_USE_FUNCTION_APPLY_PATCH = true;
5394
5398
  const DEFAULT_COMPACT_USE_SMALL_MODEL = false;
5399
+ const DEFAULT_RESPONSES_API_AUTO_COMPACT_INPUT = false;
5400
+ const DEFAULT_RESPONSES_API_AUTO_CONTEXT_MANAGEMENT = false;
5401
+ const DEFAULT_RESPONSES_OFFICIAL_EMULATOR = false;
5402
+ const DEFAULT_RESPONSES_OFFICIAL_EMULATOR_TTL_SECONDS = 14400;
5395
5403
  const DEFAULT_CONTEXT_UPGRADE = true;
5396
5404
  const DEFAULT_CONTEXT_UPGRADE_TOKEN_THRESHOLD = 16e4;
5397
5405
  async function readConfig() {
@@ -5439,9 +5447,19 @@ function shouldCompactUseSmallModel() {
5439
5447
  function shouldUseFunctionApplyPatch() {
5440
5448
  return cachedConfig.useFunctionApplyPatch ?? DEFAULT_USE_FUNCTION_APPLY_PATCH;
5441
5449
  }
5450
+ function shouldAutoCompactResponsesInput() {
5451
+ return cachedConfig.responsesApiAutoCompactInput ?? DEFAULT_RESPONSES_API_AUTO_COMPACT_INPUT;
5452
+ }
5442
5453
  function isResponsesApiContextManagementModel(model) {
5454
+ if (!(cachedConfig.responsesApiAutoContextManagement ?? DEFAULT_RESPONSES_API_AUTO_CONTEXT_MANAGEMENT)) return false;
5443
5455
  return cachedConfig.responsesApiContextManagementModels?.includes(model) ?? false;
5444
5456
  }
5457
+ function shouldUseResponsesOfficialEmulator() {
5458
+ return cachedConfig.responsesOfficialEmulator ?? DEFAULT_RESPONSES_OFFICIAL_EMULATOR;
5459
+ }
5460
+ function getResponsesOfficialEmulatorTtlSeconds() {
5461
+ return cachedConfig.responsesOfficialEmulatorTtlSeconds ?? DEFAULT_RESPONSES_OFFICIAL_EMULATOR_TTL_SECONDS;
5462
+ }
5445
5463
  function shouldContextUpgrade() {
5446
5464
  return cachedConfig.contextUpgrade ?? DEFAULT_CONTEXT_UPGRADE;
5447
5465
  }
@@ -6029,6 +6047,221 @@ async function getVSCodeVersion() {
6029
6047
  return remoteVersion ?? localVersion ?? FALLBACK;
6030
6048
  }
6031
6049
 
6050
+ //#endregion
6051
+ //#region src/lib/responses-emulator-state.ts
6052
+ function cloneValue$1(value) {
6053
+ if (typeof globalThis.structuredClone === "function") return globalThis.structuredClone(value);
6054
+ return JSON.parse(JSON.stringify(value));
6055
+ }
6056
+ function currentTime() {
6057
+ return Date.now();
6058
+ }
6059
+ function resolveTtlSeconds(ttlSeconds) {
6060
+ const resolved = ttlSeconds ?? getResponsesOfficialEmulatorTtlSeconds();
6061
+ if (!Number.isFinite(resolved) || resolved <= 0) return getResponsesOfficialEmulatorTtlSeconds();
6062
+ return Math.floor(resolved);
6063
+ }
6064
+ function toExpiresAt(ttlSeconds, at = currentTime()) {
6065
+ return at + resolveTtlSeconds(ttlSeconds) * 1e3;
6066
+ }
6067
+ function responseKeyFromConversation(conversation) {
6068
+ return typeof conversation === "string" ? conversation : conversation.id;
6069
+ }
6070
+ function createResponsesEmulatorState() {
6071
+ const responseRecords = /* @__PURE__ */ new Map();
6072
+ const conversationRecords = /* @__PURE__ */ new Map();
6073
+ const conversationHeadRecords = /* @__PURE__ */ new Map();
6074
+ const inputItemRecords = /* @__PURE__ */ new Map();
6075
+ const responseDeletionFlags = /* @__PURE__ */ new Map();
6076
+ const conversationDeletionFlags = /* @__PURE__ */ new Map();
6077
+ const inputItemDeletionFlags = /* @__PURE__ */ new Map();
6078
+ function pruneMap(map, at = currentTime()) {
6079
+ for (const [key, entry] of map) if (entry.expiresAt <= at) map.delete(key);
6080
+ }
6081
+ function readMap(map, key, at = currentTime()) {
6082
+ const entry = map.get(key);
6083
+ if (!entry) return;
6084
+ if (entry.expiresAt <= at) {
6085
+ map.delete(key);
6086
+ return;
6087
+ }
6088
+ return cloneValue$1(entry.value);
6089
+ }
6090
+ function writeMap(map, key, value, ttlSeconds, at = currentTime()) {
6091
+ const cloned = cloneValue$1(value);
6092
+ map.set(key, {
6093
+ expiresAt: toExpiresAt(ttlSeconds, at),
6094
+ value: cloned
6095
+ });
6096
+ return cloneValue$1(cloned);
6097
+ }
6098
+ function deleteMapEntry(map, key) {
6099
+ return map.delete(key);
6100
+ }
6101
+ function putDeletionFlag(map, id, ttlSeconds, at = currentTime()) {
6102
+ const flag = {
6103
+ deleted: true,
6104
+ deletedAt: at,
6105
+ expiresAt: toExpiresAt(ttlSeconds, at)
6106
+ };
6107
+ map.set(id, {
6108
+ expiresAt: flag.expiresAt,
6109
+ value: flag
6110
+ });
6111
+ return cloneValue$1(flag);
6112
+ }
6113
+ function readDeletionFlag(map, id, at = currentTime()) {
6114
+ return readMap(map, id, at);
6115
+ }
6116
+ function removeDeletionFlag(map, id) {
6117
+ map.delete(id);
6118
+ }
6119
+ function deletionMap(kind) {
6120
+ switch (kind) {
6121
+ case "response": return responseDeletionFlags;
6122
+ case "conversation": return conversationDeletionFlags;
6123
+ case "input_items": return inputItemDeletionFlags;
6124
+ }
6125
+ }
6126
+ function pruneExpiredRecords(at = currentTime()) {
6127
+ pruneMap(responseRecords, at);
6128
+ pruneMap(conversationRecords, at);
6129
+ pruneMap(conversationHeadRecords, at);
6130
+ pruneMap(inputItemRecords, at);
6131
+ pruneMap(responseDeletionFlags, at);
6132
+ pruneMap(conversationDeletionFlags, at);
6133
+ pruneMap(inputItemDeletionFlags, at);
6134
+ }
6135
+ return {
6136
+ isEnabled() {
6137
+ return shouldUseResponsesOfficialEmulator();
6138
+ },
6139
+ getDefaultTtlSeconds() {
6140
+ return getResponsesOfficialEmulatorTtlSeconds();
6141
+ },
6142
+ clear() {
6143
+ responseRecords.clear();
6144
+ conversationRecords.clear();
6145
+ conversationHeadRecords.clear();
6146
+ inputItemRecords.clear();
6147
+ responseDeletionFlags.clear();
6148
+ conversationDeletionFlags.clear();
6149
+ inputItemDeletionFlags.clear();
6150
+ },
6151
+ pruneExpired(nowValue) {
6152
+ pruneExpiredRecords(nowValue ?? currentTime());
6153
+ },
6154
+ snapshot(nowValue) {
6155
+ pruneExpiredRecords(nowValue ?? currentTime());
6156
+ return {
6157
+ responses: responseRecords.size,
6158
+ conversations: conversationRecords.size,
6159
+ conversationHeads: conversationHeadRecords.size,
6160
+ inputItems: inputItemRecords.size,
6161
+ deletions: responseDeletionFlags.size + conversationDeletionFlags.size + inputItemDeletionFlags.size
6162
+ };
6163
+ },
6164
+ setResponse(response, options) {
6165
+ pruneExpiredRecords();
6166
+ removeDeletionFlag(responseDeletionFlags, response.id);
6167
+ if (response.conversation !== void 0 && response.conversation !== null) {
6168
+ const conversationId = responseKeyFromConversation(response.conversation);
6169
+ writeMap(conversationRecords, conversationId, response.conversation, options?.ttlSeconds);
6170
+ writeMap(conversationHeadRecords, conversationId, response.id, options?.ttlSeconds);
6171
+ removeDeletionFlag(conversationDeletionFlags, conversationId);
6172
+ }
6173
+ return writeMap(responseRecords, response.id, response, options?.ttlSeconds);
6174
+ },
6175
+ getResponse(responseId) {
6176
+ pruneExpiredRecords();
6177
+ if (readDeletionFlag(responseDeletionFlags, responseId)) return;
6178
+ return readMap(responseRecords, responseId);
6179
+ },
6180
+ deleteResponse(responseId, options) {
6181
+ pruneExpiredRecords();
6182
+ const existing = readMap(responseRecords, responseId);
6183
+ deleteMapEntry(responseRecords, responseId);
6184
+ deleteMapEntry(inputItemRecords, responseId);
6185
+ putDeletionFlag(responseDeletionFlags, responseId, options?.ttlSeconds);
6186
+ putDeletionFlag(inputItemDeletionFlags, responseId, options?.ttlSeconds);
6187
+ if (existing?.conversation) {
6188
+ const conversationId = responseKeyFromConversation(existing.conversation);
6189
+ if (readMap(conversationHeadRecords, conversationId) === responseId) deleteMapEntry(conversationHeadRecords, conversationId);
6190
+ }
6191
+ return {
6192
+ id: responseId,
6193
+ object: "response.deleted",
6194
+ deleted: true
6195
+ };
6196
+ },
6197
+ setConversation(conversation, options) {
6198
+ pruneExpiredRecords();
6199
+ const conversationId = responseKeyFromConversation(conversation);
6200
+ removeDeletionFlag(conversationDeletionFlags, conversationId);
6201
+ return writeMap(conversationRecords, conversationId, conversation, options?.ttlSeconds);
6202
+ },
6203
+ getConversation(conversationId) {
6204
+ pruneExpiredRecords();
6205
+ if (readDeletionFlag(conversationDeletionFlags, conversationId)) return;
6206
+ return readMap(conversationRecords, conversationId);
6207
+ },
6208
+ deleteConversation(conversationId, options) {
6209
+ pruneExpiredRecords();
6210
+ deleteMapEntry(conversationRecords, conversationId);
6211
+ deleteMapEntry(conversationHeadRecords, conversationId);
6212
+ putDeletionFlag(conversationDeletionFlags, conversationId, options?.ttlSeconds);
6213
+ return {
6214
+ id: conversationId,
6215
+ object: "conversation.deleted",
6216
+ deleted: true
6217
+ };
6218
+ },
6219
+ setConversationHead(conversationId, responseId, options) {
6220
+ pruneExpiredRecords();
6221
+ return writeMap(conversationHeadRecords, conversationId, responseId, options?.ttlSeconds);
6222
+ },
6223
+ getConversationHead(conversationId) {
6224
+ pruneExpiredRecords();
6225
+ return readMap(conversationHeadRecords, conversationId);
6226
+ },
6227
+ clearConversationHead(conversationId) {
6228
+ deleteMapEntry(conversationHeadRecords, conversationId);
6229
+ },
6230
+ setInputItems(responseId, inputItems, options) {
6231
+ pruneExpiredRecords();
6232
+ removeDeletionFlag(inputItemDeletionFlags, responseId);
6233
+ return writeMap(inputItemRecords, responseId, inputItems, options?.ttlSeconds);
6234
+ },
6235
+ getInputItems(responseId) {
6236
+ pruneExpiredRecords();
6237
+ if (readDeletionFlag(inputItemDeletionFlags, responseId)) return;
6238
+ return readMap(inputItemRecords, responseId);
6239
+ },
6240
+ deleteInputItems(responseId, options) {
6241
+ pruneExpiredRecords();
6242
+ deleteMapEntry(inputItemRecords, responseId);
6243
+ putDeletionFlag(inputItemDeletionFlags, responseId, options?.ttlSeconds);
6244
+ return {
6245
+ id: responseId,
6246
+ object: "response.input_items.deleted",
6247
+ deleted: true
6248
+ };
6249
+ },
6250
+ setDeletionFlag(kind, id, options) {
6251
+ pruneExpiredRecords();
6252
+ return putDeletionFlag(deletionMap(kind), id, options?.ttlSeconds);
6253
+ },
6254
+ getDeletionFlag(kind, id) {
6255
+ pruneExpiredRecords();
6256
+ return readDeletionFlag(deletionMap(kind), id);
6257
+ },
6258
+ clearDeletionFlag(kind, id) {
6259
+ removeDeletionFlag(deletionMap(kind), id);
6260
+ }
6261
+ };
6262
+ }
6263
+ const responsesEmulatorState = createResponsesEmulatorState();
6264
+
6032
6265
  //#endregion
6033
6266
  //#region src/lib/state.ts
6034
6267
  const state = {
@@ -6040,7 +6273,8 @@ const state = {
6040
6273
  showToken: false
6041
6274
  },
6042
6275
  cache: {},
6043
- rateLimit: {}
6276
+ rateLimit: {},
6277
+ responsesEmulator: responsesEmulatorState
6044
6278
  };
6045
6279
  function getClientConfig() {
6046
6280
  return {
@@ -6232,7 +6466,7 @@ const checkUsage = defineCommand({
6232
6466
 
6233
6467
  //#endregion
6234
6468
  //#region src/lib/version.ts
6235
- const VERSION = "0.5.2";
6469
+ const VERSION = "0.5.4";
6236
6470
 
6237
6471
  //#endregion
6238
6472
  //#region src/debug.ts
@@ -46747,6 +46981,9 @@ function selectCapiProfile(model) {
46747
46981
 
46748
46982
  //#endregion
46749
46983
  //#region src/core/capi/request-context.ts
46984
+ const SUBAGENT_MARKER_PREFIX = "__SUBAGENT_MARKER__";
46985
+ const SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
46986
+ const SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
46750
46987
  function readHeader(headers, name) {
46751
46988
  return headers.get(name) ?? void 0;
46752
46989
  }
@@ -46758,11 +46995,20 @@ function readCapiRequestContext(headers) {
46758
46995
  interactionType: readHeader(headers, "x-interaction-type"),
46759
46996
  agentTaskId: readHeader(headers, "x-agent-task-id"),
46760
46997
  parentAgentTaskId: readHeader(headers, "x-parent-agent-id"),
46761
- clientSessionId: readHeader(headers, "x-client-session-id"),
46998
+ clientSessionId: readHeader(headers, "x-client-session-id") ?? readHeader(headers, "x-session-id"),
46762
46999
  interactionId: readHeader(headers, "x-interaction-id"),
46763
47000
  clientMachineId: readHeader(headers, "x-client-machine-id")
46764
47001
  };
46765
47002
  }
47003
+ function resolveInitiator(defaultInitiator, requestContext) {
47004
+ switch (requestContext?.interactionType) {
47005
+ case "conversation-agent":
47006
+ case "conversation-subagent":
47007
+ case "conversation-background": return "agent";
47008
+ case "conversation-user": return "user";
47009
+ default: return defaultInitiator;
47010
+ }
47011
+ }
46766
47012
  function buildCapiRequestContext(initiator, overrides = {}) {
46767
47013
  return {
46768
47014
  interactionType: overrides.interactionType ?? (initiator === "agent" ? "conversation-agent" : "conversation-user"),
@@ -46773,6 +47019,269 @@ function buildCapiRequestContext(initiator, overrides = {}) {
46773
47019
  clientMachineId: overrides.clientMachineId
46774
47020
  };
46775
47021
  }
47022
+ function normalizeAnthropicRequestContext(payload, headers) {
47023
+ return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromAnthropicPayload(payload));
47024
+ }
47025
+ function normalizeChatRequestContext(payload, headers) {
47026
+ return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromChatPayload(payload));
47027
+ }
47028
+ function normalizeResponsesRequestContext(payload, headers) {
47029
+ return withSubagentMarker(readCapiRequestContext(headers), headers, stripSubagentMarkerFromResponsesPayload(payload));
47030
+ }
47031
+ function withSubagentMarker(baseContext, headers, marker) {
47032
+ if (!marker) return baseContext;
47033
+ const rootSessionId = readHeader(headers, "x-session-id") ?? baseContext.clientSessionId;
47034
+ return {
47035
+ ...baseContext,
47036
+ interactionType: baseContext.interactionType && baseContext.interactionType !== "conversation-user" ? baseContext.interactionType : "conversation-subagent",
47037
+ agentTaskId: baseContext.agentTaskId ?? marker.agent_id ?? marker.session_id,
47038
+ clientSessionId: baseContext.clientSessionId ?? rootSessionId ?? marker.session_id
47039
+ };
47040
+ }
47041
+ function stripSubagentMarkerFromAnthropicPayload(payload) {
47042
+ let marker;
47043
+ if (typeof payload.system === "string") {
47044
+ const result = stripSubagentMarkerFromText(payload.system);
47045
+ payload.system = result.text || void 0;
47046
+ marker ??= result.marker;
47047
+ } else if (Array.isArray(payload.system)) {
47048
+ payload.system = payload.system.map((block) => {
47049
+ const result = stripSubagentMarkerFromText(block.text);
47050
+ marker ??= result.marker;
47051
+ return result.text ? {
47052
+ ...block,
47053
+ text: result.text
47054
+ } : void 0;
47055
+ }).filter((block) => block !== void 0);
47056
+ if (payload.system.length === 0) payload.system = void 0;
47057
+ }
47058
+ payload.messages = payload.messages.map((message) => {
47059
+ const sanitized = sanitizeAnthropicMessage(message);
47060
+ marker ??= sanitized.marker;
47061
+ return sanitized.message;
47062
+ }).filter((message) => message !== void 0);
47063
+ return marker;
47064
+ }
47065
+ function sanitizeAnthropicMessage(message) {
47066
+ if (typeof message.content === "string") {
47067
+ const result = stripSubagentMarkerFromText(message.content);
47068
+ return {
47069
+ marker: result.marker,
47070
+ message: result.text ? {
47071
+ ...message,
47072
+ content: result.text
47073
+ } : void 0
47074
+ };
47075
+ }
47076
+ if (message.role === "user") {
47077
+ let marker;
47078
+ const content = message.content.map((block) => {
47079
+ if (block.type !== "text") return block;
47080
+ const result = stripSubagentMarkerFromText(block.text);
47081
+ marker ??= result.marker;
47082
+ return result.text ? {
47083
+ ...block,
47084
+ text: result.text
47085
+ } : void 0;
47086
+ }).filter((block) => block !== void 0);
47087
+ return {
47088
+ marker,
47089
+ message: content.length > 0 ? {
47090
+ ...message,
47091
+ content
47092
+ } : void 0
47093
+ };
47094
+ }
47095
+ let marker;
47096
+ const content = message.content.map((block) => {
47097
+ if (block.type !== "text") return block;
47098
+ const result = stripSubagentMarkerFromText(block.text);
47099
+ marker ??= result.marker;
47100
+ return result.text ? {
47101
+ ...block,
47102
+ text: result.text
47103
+ } : void 0;
47104
+ }).filter((block) => block !== void 0);
47105
+ return {
47106
+ marker,
47107
+ message: content.length > 0 ? {
47108
+ ...message,
47109
+ content
47110
+ } : void 0
47111
+ };
47112
+ }
47113
+ function stripSubagentMarkerFromChatPayload(payload) {
47114
+ let marker;
47115
+ payload.messages = payload.messages.map((message) => {
47116
+ const sanitized = sanitizeChatMessage(message);
47117
+ marker ??= sanitized.marker;
47118
+ return sanitized.message;
47119
+ }).filter((message) => message !== void 0);
47120
+ return marker;
47121
+ }
47122
+ function sanitizeChatMessage(message) {
47123
+ if (typeof message.content === "string") {
47124
+ const result = stripSubagentMarkerFromText(message.content);
47125
+ return {
47126
+ marker: result.marker,
47127
+ message: result.text || message.tool_calls?.length ? {
47128
+ ...message,
47129
+ content: result.text
47130
+ } : void 0
47131
+ };
47132
+ }
47133
+ if (message.content === null) return { message };
47134
+ let marker;
47135
+ const content = message.content.map((part) => {
47136
+ if (part.type !== "text") return part;
47137
+ const result = stripSubagentMarkerFromText(part.text);
47138
+ marker ??= result.marker;
47139
+ return result.text ? {
47140
+ ...part,
47141
+ text: result.text
47142
+ } : void 0;
47143
+ }).filter((part) => part !== void 0);
47144
+ return {
47145
+ marker,
47146
+ message: content.length > 0 || message.tool_calls?.length ? {
47147
+ ...message,
47148
+ content
47149
+ } : void 0
47150
+ };
47151
+ }
47152
+ function stripSubagentMarkerFromResponsesPayload(payload) {
47153
+ let marker;
47154
+ if (typeof payload.instructions === "string") {
47155
+ const result = stripSubagentMarkerFromText(payload.instructions);
47156
+ payload.instructions = result.text || void 0;
47157
+ marker ??= result.marker;
47158
+ }
47159
+ if (typeof payload.input === "string") {
47160
+ const result = stripSubagentMarkerFromText(payload.input);
47161
+ payload.input = result.text || null;
47162
+ marker ??= result.marker;
47163
+ return marker;
47164
+ }
47165
+ if (!Array.isArray(payload.input)) return marker;
47166
+ payload.input = payload.input.map((item) => {
47167
+ const sanitized = sanitizeResponsesInputItem(item);
47168
+ marker ??= sanitized.marker;
47169
+ return sanitized.item;
47170
+ }).filter((item) => item !== void 0);
47171
+ return marker;
47172
+ }
47173
+ function sanitizeResponsesInputItem(item) {
47174
+ if (!("type" in item) || item.type !== "message") return { item };
47175
+ if (typeof item.content === "string") {
47176
+ const result = stripSubagentMarkerFromText(item.content);
47177
+ return {
47178
+ marker: result.marker,
47179
+ item: result.text ? {
47180
+ ...item,
47181
+ content: result.text
47182
+ } : void 0
47183
+ };
47184
+ }
47185
+ if (!Array.isArray(item.content)) return { item };
47186
+ let marker;
47187
+ const content = item.content.map((part) => {
47188
+ const sanitized = sanitizeResponsesInputContent(part);
47189
+ marker ??= sanitized.marker;
47190
+ return sanitized.content;
47191
+ }).filter((part) => part !== void 0);
47192
+ return {
47193
+ marker,
47194
+ item: content.length > 0 ? {
47195
+ ...item,
47196
+ content
47197
+ } : void 0
47198
+ };
47199
+ }
47200
+ function sanitizeResponsesInputContent(content) {
47201
+ if (!("type" in content)) return { content };
47202
+ if (content.type !== "input_text" && content.type !== "output_text") return { content };
47203
+ if (typeof content.text !== "string") return { content };
47204
+ const result = stripSubagentMarkerFromText(content.text);
47205
+ return {
47206
+ marker: result.marker,
47207
+ content: result.text ? {
47208
+ ...content,
47209
+ text: result.text
47210
+ } : void 0
47211
+ };
47212
+ }
47213
+ function stripSubagentMarkerFromText(text) {
47214
+ const markerMatch = findSubagentMarker(text);
47215
+ if (!markerMatch) return { text };
47216
+ const removalRange = findReminderRange(text, markerMatch.start, markerMatch.end);
47217
+ const before = text.slice(0, removalRange.start).trimEnd();
47218
+ const after = text.slice(removalRange.end).trimStart();
47219
+ return {
47220
+ marker: markerMatch.marker,
47221
+ text: before && after ? `${before}\n${after}` : `${before}${after}`
47222
+ };
47223
+ }
47224
+ function findSubagentMarker(text) {
47225
+ const markerIndex = text.indexOf(SUBAGENT_MARKER_PREFIX);
47226
+ if (markerIndex < 0) return;
47227
+ const jsonStart = text.indexOf("{", markerIndex + 19);
47228
+ if (jsonStart < 0) return;
47229
+ const jsonEnd = findJsonObjectEnd(text, jsonStart);
47230
+ if (jsonEnd < 0) return;
47231
+ try {
47232
+ const parsed = JSON.parse(text.slice(jsonStart, jsonEnd));
47233
+ if (!parsed || typeof parsed !== "object") return;
47234
+ return {
47235
+ marker: parsed,
47236
+ start: markerIndex,
47237
+ end: jsonEnd
47238
+ };
47239
+ } catch {
47240
+ return;
47241
+ }
47242
+ }
47243
+ function findReminderRange(text, markerStart, markerEnd) {
47244
+ const reminderStart = text.lastIndexOf(SYSTEM_REMINDER_OPEN_TAG, markerStart);
47245
+ const reminderEnd = text.indexOf(SYSTEM_REMINDER_CLOSE_TAG, markerEnd);
47246
+ if (reminderStart >= 0 && reminderEnd >= 0) return {
47247
+ start: reminderStart,
47248
+ end: reminderEnd + 18
47249
+ };
47250
+ return {
47251
+ start: markerStart,
47252
+ end: markerEnd
47253
+ };
47254
+ }
47255
+ function findJsonObjectEnd(text, start) {
47256
+ let depth = 0;
47257
+ let inString = false;
47258
+ let escaped = false;
47259
+ for (let index = start; index < text.length; index++) {
47260
+ const char = text[index];
47261
+ if (escaped) {
47262
+ escaped = false;
47263
+ continue;
47264
+ }
47265
+ if (char === "\\") {
47266
+ escaped = true;
47267
+ continue;
47268
+ }
47269
+ if (char === "\"") {
47270
+ inString = !inString;
47271
+ continue;
47272
+ }
47273
+ if (inString) continue;
47274
+ if (char === "{") {
47275
+ depth++;
47276
+ continue;
47277
+ }
47278
+ if (char === "}") {
47279
+ depth--;
47280
+ if (depth === 0) return index + 1;
47281
+ }
47282
+ }
47283
+ return -1;
47284
+ }
46776
47285
 
46777
47286
  //#endregion
46778
47287
  //#region src/core/capi/plan-builder.ts
@@ -46951,7 +47460,7 @@ function stripTransportFields(payload) {
46951
47460
  function buildCapiExecutionPlan(request, options = {}) {
46952
47461
  const resolvedModel = options.resolveModel?.(request.model) ?? request.model;
46953
47462
  const profile = selectCapiProfile(resolvedModel);
46954
- const initiator = inferInitiator(request.turns);
47463
+ const initiator = resolveInitiator(inferInitiator(request.turns), options.requestContext);
46955
47464
  const payload = {
46956
47465
  model: resolvedModel,
46957
47466
  messages: serializeTurns(request.turns),
@@ -48269,6 +48778,9 @@ async function getTokenCount(payload, model) {
48269
48778
  output: outputTokens
48270
48779
  };
48271
48780
  }
48781
+ async function estimateResponsesInputTokens(inputItems, model) {
48782
+ return (await getEncoder(getTokenizerFromModel(model))).encode(JSON.stringify(inputItems)).length;
48783
+ }
48272
48784
  /**
48273
48785
  * Fast character-based token estimate for Anthropic payloads.
48274
48786
  * Uses ~3.5 chars/token ratio (conservative for Claude's tokenizer).
@@ -48735,7 +49247,7 @@ const responsesFunctionToolSchema = object({
48735
49247
  type: literal("function"),
48736
49248
  name: string().min(1),
48737
49249
  parameters: jsonObjectSchema.nullable().optional(),
48738
- strict: boolean().nullable().optional(),
49250
+ strict: boolean().optional(),
48739
49251
  description: string().nullable().optional()
48740
49252
  }).loose();
48741
49253
  const responsesUnknownToolSchema = object({ type: string().min(1) }).catchall(unknown()).superRefine((tool, ctx) => {
@@ -48749,9 +49261,33 @@ const responsesToolChoiceSchema = union([
48749
49261
  literal("none"),
48750
49262
  literal("auto"),
48751
49263
  literal("required"),
49264
+ object({
49265
+ type: literal("allowed_tools"),
49266
+ mode: _enum(["auto", "required"]),
49267
+ tools: array(jsonObjectSchema)
49268
+ }).loose(),
49269
+ object({ type: _enum([
49270
+ "file_search",
49271
+ "web_search_preview",
49272
+ "web_search_preview_2025_03_11",
49273
+ "computer_use_preview",
49274
+ "code_interpreter",
49275
+ "image_generation",
49276
+ "apply_patch",
49277
+ "shell"
49278
+ ]) }).loose(),
48752
49279
  object({
48753
49280
  type: literal("function"),
48754
49281
  name: string().min(1)
49282
+ }).loose(),
49283
+ object({
49284
+ type: literal("mcp"),
49285
+ server_label: string().min(1),
49286
+ name: string().min(1).optional()
49287
+ }).loose(),
49288
+ object({
49289
+ type: literal("custom"),
49290
+ name: string().min(1)
48755
49291
  }).loose()
48756
49292
  ]);
48757
49293
  const responsesReasoningConfigSchema = object({
@@ -48763,6 +49299,11 @@ const responsesReasoningConfigSchema = object({
48763
49299
  "high",
48764
49300
  "xhigh"
48765
49301
  ]).nullable().optional(),
49302
+ generate_summary: _enum([
49303
+ "auto",
49304
+ "concise",
49305
+ "detailed"
49306
+ ]).nullable().optional(),
48766
49307
  summary: _enum([
48767
49308
  "auto",
48768
49309
  "concise",
@@ -48776,7 +49317,7 @@ const responsesTextFormatJsonSchemaSchema = object({
48776
49317
  name: string().min(1),
48777
49318
  schema: jsonObjectSchema,
48778
49319
  description: string().nullable().optional(),
48779
- strict: boolean().nullable().optional()
49320
+ strict: boolean().optional()
48780
49321
  }).loose();
48781
49322
  const responsesTextConfigSchema = object({
48782
49323
  format: union([
@@ -48794,9 +49335,10 @@ const responsesContextManagementSchema = object({
48794
49335
  type: literal("compaction"),
48795
49336
  compact_threshold: nonNegativeIntegerSchema
48796
49337
  }).loose();
48797
- const responsesConversationSchema = union([string().min(1), object({ id: string().nullable().optional() }).loose()]);
49338
+ const responsesConversationSchema = union([string().min(1), object({ id: string().min(1) }).loose()]);
48798
49339
  function createResponsesPayloadSchema(options) {
48799
49340
  return object({
49341
+ background: boolean().nullable().optional(),
48800
49342
  model: options.requireModel ? string().min(1) : string().min(1).nullable().optional(),
48801
49343
  instructions: string().nullable().optional(),
48802
49344
  input: union([
@@ -48814,19 +49356,36 @@ function createResponsesPayloadSchema(options) {
48814
49356
  max_tool_calls: nonNegativeIntegerSchema.nullable().optional(),
48815
49357
  metadata: record(string(), string()).nullable().optional(),
48816
49358
  stream: boolean().nullable().optional(),
49359
+ stream_options: object({ include_obfuscation: boolean().nullable().optional() }).loose().nullable().optional(),
48817
49360
  safety_identifier: string().nullable().optional(),
48818
49361
  prompt_cache_key: string().nullable().optional(),
49362
+ prompt_cache_retention: _enum(["in-memory", "24h"]).nullable().optional(),
48819
49363
  truncation: _enum(["auto", "disabled"]).nullable().optional(),
48820
49364
  parallel_tool_calls: boolean().nullable().optional(),
48821
49365
  store: boolean().nullable().optional(),
48822
49366
  user: string().nullable().optional(),
48823
- prompt: union([string().min(1), jsonObjectSchema]).nullable().optional(),
49367
+ prompt: object({
49368
+ id: string().min(1),
49369
+ variables: record(string(), unknown()).optional(),
49370
+ version: string().min(1).optional()
49371
+ }).loose().nullable().optional(),
48824
49372
  text: responsesTextConfigSchema.nullable().optional(),
48825
49373
  reasoning: responsesReasoningConfigSchema.nullable().optional(),
48826
49374
  context_management: array(responsesContextManagementSchema).nullable().optional(),
48827
49375
  include: array(string().min(1)).nullable().optional(),
48828
- service_tier: string().nullable().optional()
49376
+ service_tier: _enum([
49377
+ "auto",
49378
+ "default",
49379
+ "flex",
49380
+ "scale",
49381
+ "priority"
49382
+ ]).nullable().optional()
48829
49383
  }).loose().superRefine((payload, ctx) => {
49384
+ if (payload.previous_response_id && payload.conversation) ctx.addIssue({
49385
+ code: "custom",
49386
+ message: "previous_response_id cannot be used together with conversation",
49387
+ path: ["previous_response_id"]
49388
+ });
48830
49389
  const toolChoice = payload.tool_choice;
48831
49390
  if (toolChoice && typeof toolChoice === "object" && "name" in toolChoice && typeof toolChoice.name === "string" && Array.isArray(payload.tools)) {
48832
49391
  if (!payload.tools.filter((tool) => {
@@ -48881,6 +49440,7 @@ function createChatCompletionsStrategy(transport, adapter, plan, signal) {
48881
49440
  async function handleCompletionCore({ body, signal, headers }) {
48882
49441
  const adapter = new OpenAIChatAdapter();
48883
49442
  let payload = parseOpenAIChatPayload(body);
49443
+ const requestContext = normalizeChatRequestContext(payload, headers);
48884
49444
  consola.debug("Request payload:", JSON.stringify(payload).slice(-400));
48885
49445
  const rewrite = applyModelRewrite(payload);
48886
49446
  const originalModel = rewrite.originalModel;
@@ -48901,7 +49461,7 @@ async function handleCompletionCore({ body, signal, headers }) {
48901
49461
  consola.debug("Set max_tokens to:", JSON.stringify(payload.max_tokens));
48902
49462
  }
48903
49463
  const upstreamSignal = createUpstreamSignalFromConfig(signal);
48904
- const plan = adapter.toCapiPlan(payload, { requestContext: readCapiRequestContext(headers) });
49464
+ const plan = adapter.toCapiPlan(payload, { requestContext });
48905
49465
  const modelMapping = {
48906
49466
  originalModel,
48907
49467
  rewrittenModel: rewrite.model,
@@ -48988,6 +49548,7 @@ const ESTIMATION_FACTOR = {
48988
49548
  async function handleCountTokensCore({ body, headers }) {
48989
49549
  const anthropicBeta = headers.get("anthropic-beta") ?? void 0;
48990
49550
  const anthropicPayload = parseAnthropicCountTokensPayload(body);
49551
+ normalizeAnthropicRequestContext(anthropicPayload, headers);
48991
49552
  const adapter = createAnthropicAdapter();
48992
49553
  let openAIPayload;
48993
49554
  try {
@@ -49078,6 +49639,49 @@ function containsVisionContent$1(content) {
49078
49639
  return content.some((block) => block.type === "image");
49079
49640
  }
49080
49641
 
49642
+ //#endregion
49643
+ //#region src/lib/function-schema.ts
49644
+ function isRecord$2(value) {
49645
+ return typeof value === "object" && value !== null && !Array.isArray(value);
49646
+ }
49647
+ const COPILOT_UNSUPPORTED_SCHEMA_ANNOTATIONS = new Set([
49648
+ "$schema",
49649
+ "$id",
49650
+ "id",
49651
+ "title",
49652
+ "format",
49653
+ "default",
49654
+ "example",
49655
+ "examples",
49656
+ "deprecated",
49657
+ "readOnly",
49658
+ "writeOnly",
49659
+ "contentEncoding",
49660
+ "contentMediaType"
49661
+ ]);
49662
+ function normalizeSchemaNode(node) {
49663
+ if (Array.isArray(node)) return node.map(normalizeSchemaNode);
49664
+ if (!isRecord$2(node)) return node;
49665
+ const normalized = {};
49666
+ for (const [key, value] of Object.entries(node)) {
49667
+ if (COPILOT_UNSUPPORTED_SCHEMA_ANNOTATIONS.has(key)) continue;
49668
+ if (key === "properties" && isRecord$2(value)) {
49669
+ normalized[key] = Object.fromEntries(Object.entries(value).map(([propertyName, propertySchema]) => [propertyName, normalizeSchemaNode(propertySchema)]));
49670
+ continue;
49671
+ }
49672
+ normalized[key] = normalizeSchemaNode(value);
49673
+ }
49674
+ if (node.type === "object" || isRecord$2(normalized.properties)) {
49675
+ normalized.required = isRecord$2(normalized.properties) ? Object.keys(normalized.properties) : [];
49676
+ normalized.additionalProperties = false;
49677
+ }
49678
+ return normalized;
49679
+ }
49680
+ function normalizeFunctionParametersSchemaForCopilot(schema) {
49681
+ if (!schema) return schema;
49682
+ return normalizeSchemaNode(schema);
49683
+ }
49684
+
49081
49685
  //#endregion
49082
49686
  //#region src/translator/responses/signature-codec.ts
49083
49687
  const COMPACTION_PREFIX = "cm1#";
@@ -49338,7 +49942,7 @@ function convertAnthropicTools(tools) {
49338
49942
  return tools.map((tool) => ({
49339
49943
  type: "function",
49340
49944
  name: tool.name,
49341
- parameters: tool.input_schema,
49945
+ parameters: normalizeFunctionParametersSchemaForCopilot(tool.input_schema),
49342
49946
  strict: false,
49343
49947
  ...tool.description ? { description: tool.description } : {}
49344
49948
  }));
@@ -49451,6 +50055,7 @@ function applyContextManagement(payload, maxPromptTokens) {
49451
50055
  payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
49452
50056
  }
49453
50057
  function compactInputByLatestCompaction(payload) {
50058
+ if (!shouldAutoCompactResponsesInput()) return;
49454
50059
  if (!Array.isArray(payload.input) || payload.input.length === 0) return;
49455
50060
  const latestCompactionMessageIndex = getLatestCompactionMessageIndex(payload.input);
49456
50061
  if (latestCompactionMessageIndex === void 0) return;
@@ -49686,14 +50291,14 @@ function mapResponsesUsage(response) {
49686
50291
  ...cachedTokens !== void 0 ? { cache_read_input_tokens: cachedTokens } : {}
49687
50292
  };
49688
50293
  }
49689
- function isRecord(value) {
50294
+ function isRecord$1(value) {
49690
50295
  return typeof value === "object" && value !== null;
49691
50296
  }
49692
50297
  function isResponseOutputText(block) {
49693
- return isRecord(block) && block.type === "output_text";
50298
+ return isRecord$1(block) && block.type === "output_text";
49694
50299
  }
49695
50300
  function isResponseOutputRefusal(block) {
49696
- return isRecord(block) && block.type === "refusal";
50301
+ return isRecord$1(block) && block.type === "refusal";
49697
50302
  }
49698
50303
 
49699
50304
  //#endregion
@@ -50192,12 +50797,32 @@ function filterThinkingBlocksForNativeMessages(anthropicPayload) {
50192
50797
  function sanitizeOutputConfig(payload, model) {
50193
50798
  if (payload.output_config && !modelSupportsOutputConfig(model)) delete payload.output_config;
50194
50799
  }
50800
+ function normalizeCacheControlBlock(obj) {
50801
+ if (obj.cache_control && typeof obj.cache_control === "object") obj.cache_control = { type: obj.cache_control.type };
50802
+ }
50803
+ /**
50804
+ * Normalize `cache_control` to strip extra fields (e.g. `scope`) that
50805
+ * the upstream Copilot API does not yet accept.
50806
+ *
50807
+ * Temporary workaround — when Copilot supports `scope`, this filter
50808
+ * should be removed. The smoke-cache-control script tests whether the
50809
+ * upstream accepts `scope`.
50810
+ */
50811
+ function sanitizeCacheControl(payload) {
50812
+ if (Array.isArray(payload.system)) for (const block of payload.system) normalizeCacheControlBlock(block);
50813
+ for (const message of payload.messages) {
50814
+ normalizeCacheControlBlock(message);
50815
+ if (Array.isArray(message.content)) for (const block of message.content) normalizeCacheControlBlock(block);
50816
+ }
50817
+ if (payload.tools) for (const tool of payload.tools) normalizeCacheControlBlock(tool);
50818
+ }
50195
50819
  const nativeMessagesEntry = {
50196
50820
  name: "native-messages",
50197
50821
  canHandle: (model) => modelSupportsEndpoint(model, MESSAGES_ENDPOINT),
50198
50822
  async execute(ctx) {
50199
50823
  filterThinkingBlocksForNativeMessages(ctx.anthropicPayload);
50200
50824
  sanitizeOutputConfig(ctx.anthropicPayload, ctx.selectedModel);
50825
+ sanitizeCacheControl(ctx.anthropicPayload);
50201
50826
  return {
50202
50827
  result: await runStrategy(createNativeMessagesStrategy(ctx.copilotClient, ctx.anthropicPayload, ctx.anthropicBetaHeader, {
50203
50828
  signal: ctx.upstreamSignal.signal,
@@ -50298,6 +50923,7 @@ function processAnthropicBetaHeader(rawHeader, model) {
50298
50923
  */
50299
50924
  async function handleMessagesCore({ body, signal, headers }) {
50300
50925
  const anthropicPayload = parseAnthropicMessagesPayload(body);
50926
+ const requestContext = normalizeAnthropicRequestContext(anthropicPayload, headers);
50301
50927
  if (consola.level >= 4) consola.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
50302
50928
  const rewrite = applyModelRewrite(anthropicPayload);
50303
50929
  const betaResult = processAnthropicBetaHeader(headers.get("anthropic-beta"), anthropicPayload.model);
@@ -50324,7 +50950,7 @@ async function handleMessagesCore({ body, signal, headers }) {
50324
50950
  selectedModel,
50325
50951
  upstreamSignal,
50326
50952
  headers,
50327
- requestContext: readCapiRequestContext(headers),
50953
+ requestContext,
50328
50954
  modelMapping
50329
50955
  };
50330
50956
  let strategyResult;
@@ -50406,8 +51032,246 @@ function createModelRoutes() {
50406
51032
  });
50407
51033
  }
50408
51034
 
51035
+ //#endregion
51036
+ //#region src/routes/responses/emulator.ts
51037
+ function cloneValue(value) {
51038
+ if (typeof globalThis.structuredClone === "function") return globalThis.structuredClone(value);
51039
+ return JSON.parse(JSON.stringify(value));
51040
+ }
51041
+ function rejectUnsupportedBackground(payload) {
51042
+ if (payload.background) throwInvalidRequestError("background mode is not supported by the responses official emulator.", "background", "unsupported_background_mode");
51043
+ }
51044
+ function prepareEmulatorRequest(payload) {
51045
+ rejectUnsupportedBackground(payload);
51046
+ const normalizedCurrentInput = normalizeResponsesInput(payload.input);
51047
+ const { continuationSourceResponseId, conversation: resolvedConversation, previousResponse } = resolveContinuation(payload);
51048
+ const conversation = resolvedConversation ?? createConversationRef();
51049
+ const effectiveInputItems = [...continuationSourceResponseId ? buildContinuationHistory(continuationSourceResponseId) : [], ...normalizedCurrentInput];
51050
+ const shouldStore = payload.store ?? true;
51051
+ return {
51052
+ upstreamPayload: {
51053
+ ...payload,
51054
+ background: void 0,
51055
+ conversation: void 0,
51056
+ previous_response_id: void 0,
51057
+ store: void 0,
51058
+ input: effectiveInputItems
51059
+ },
51060
+ effectiveInputItems,
51061
+ previousResponseId: previousResponse?.id,
51062
+ conversation,
51063
+ shouldStore
51064
+ };
51065
+ }
51066
+ function decorateStoredResponse(upstreamResponse, requestPayload, prepared) {
51067
+ return {
51068
+ ...cloneValue(upstreamResponse),
51069
+ previous_response_id: prepared.previousResponseId ?? null,
51070
+ conversation: prepared.conversation,
51071
+ truncation: requestPayload.truncation ?? null,
51072
+ store: prepared.shouldStore,
51073
+ user: normalizeNullableString(requestPayload.user),
51074
+ service_tier: normalizeServiceTier(requestPayload.service_tier)
51075
+ };
51076
+ }
51077
+ function persistEmulatorResponse(response, effectiveInputItems) {
51078
+ state.responsesEmulator.setResponse(response);
51079
+ if (response.conversation) {
51080
+ state.responsesEmulator.setConversation(response.conversation);
51081
+ state.responsesEmulator.setConversationHead(getConversationId(response.conversation), response.id);
51082
+ }
51083
+ state.responsesEmulator.setInputItems(response.id, effectiveInputItems);
51084
+ }
51085
+ function getStoredResponseOrThrow(responseId) {
51086
+ const response = state.responsesEmulator.getResponse(responseId);
51087
+ if (!response) throw new HTTPError(404, { error: {
51088
+ message: `No response found with id '${responseId}'.`,
51089
+ type: "invalid_request_error"
51090
+ } });
51091
+ return response;
51092
+ }
51093
+ function listStoredInputItemsOrThrow(responseId, params) {
51094
+ const items = state.responsesEmulator.getInputItems(responseId);
51095
+ if (!items) throw new HTTPError(404, { error: {
51096
+ message: `No response input items found for id '${responseId}'.`,
51097
+ type: "invalid_request_error"
51098
+ } });
51099
+ let orderedItems = cloneValue(items);
51100
+ if (params?.order === "desc") orderedItems.reverse();
51101
+ if (params?.after) {
51102
+ const afterIndex = orderedItems.findIndex((item) => getInputItemId(item) === params.after);
51103
+ if (afterIndex >= 0) orderedItems = orderedItems.slice(afterIndex + 1);
51104
+ }
51105
+ const limitedItems = orderedItems.slice(0, params?.limit ?? orderedItems.length);
51106
+ return {
51107
+ object: "list",
51108
+ data: limitedItems,
51109
+ first_id: getInputItemId(limitedItems[0]) ?? null,
51110
+ last_id: getInputItemId(limitedItems.at(-1)) ?? null,
51111
+ has_more: limitedItems.length < orderedItems.length
51112
+ };
51113
+ }
51114
+ function deleteStoredResponseOrThrow(responseId) {
51115
+ getStoredResponseOrThrow(responseId);
51116
+ return state.responsesEmulator.deleteResponse(responseId);
51117
+ }
51118
+ async function estimateEmulatorInputTokens(payload, selectedModel) {
51119
+ return {
51120
+ object: "response.input_tokens",
51121
+ input_tokens: await estimateResponsesInputTokens(resolveEffectiveInputForInputTokens(payload), selectedModel)
51122
+ };
51123
+ }
51124
+ function resolveEffectiveInputForInputTokens(payload) {
51125
+ const normalizedInput = normalizeResponsesInput(payload.input);
51126
+ const background = payload.background === null || typeof payload.background === "boolean" ? payload.background : void 0;
51127
+ const conversation = isConversationReference(payload.conversation) ? payload.conversation : void 0;
51128
+ const previousResponseId = typeof payload.previous_response_id === "string" ? payload.previous_response_id : void 0;
51129
+ rejectUnsupportedBackground({ background });
51130
+ const { continuationSourceResponseId } = resolveContinuation({
51131
+ conversation,
51132
+ previous_response_id: previousResponseId
51133
+ });
51134
+ if (continuationSourceResponseId) return [...buildContinuationHistory(continuationSourceResponseId), ...normalizedInput];
51135
+ return normalizedInput;
51136
+ }
51137
+ function resolveContinuation(payload) {
51138
+ const previousResponse = resolvePreviousResponse(payload.previous_response_id);
51139
+ const conversation = resolveConversation(payload.conversation, previousResponse);
51140
+ return {
51141
+ previousResponse,
51142
+ conversation,
51143
+ continuationSourceResponseId: resolveContinuationSourceResponseId(previousResponse, conversation)
51144
+ };
51145
+ }
51146
+ function resolvePreviousResponse(previousResponseId) {
51147
+ if (typeof previousResponseId !== "string" || previousResponseId.length === 0) return;
51148
+ const previousResponse = state.responsesEmulator.getResponse(previousResponseId);
51149
+ if (!previousResponse) throwInvalidRequestError("The selected previous_response_id could not be resolved.", "previous_response_id");
51150
+ return previousResponse;
51151
+ }
51152
+ function resolveConversation(conversation, previousResponse) {
51153
+ if (isConversationReference(conversation)) {
51154
+ const conversationId = getConversationId(conversation);
51155
+ const existingConversation = state.responsesEmulator.getConversation(conversationId);
51156
+ if (!existingConversation) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
51157
+ if (previousResponse?.conversation && getConversationId(previousResponse.conversation) !== conversationId) throwInvalidRequestError("The selected previous_response_id does not belong to the selected conversation.", "previous_response_id");
51158
+ return existingConversation;
51159
+ }
51160
+ return previousResponse?.conversation ?? void 0;
51161
+ }
51162
+ function resolveContinuationSourceResponseId(previousResponse, conversation) {
51163
+ if (previousResponse) return previousResponse.id;
51164
+ if (!conversation) return;
51165
+ const head = state.responsesEmulator.getConversationHead(getConversationId(conversation));
51166
+ if (!head) throwInvalidRequestError("The selected conversation could not be resolved.", "conversation");
51167
+ return head;
51168
+ }
51169
+ function buildContinuationHistory(responseId) {
51170
+ const previousResponse = getStoredResponseOrThrow(responseId);
51171
+ const previousInput = state.responsesEmulator.getInputItems(responseId);
51172
+ if (!previousInput) throwInvalidRequestError("The selected previous_response_id is missing stored input items.", "previous_response_id");
51173
+ return [...cloneValue(previousInput), ...convertOutputItemsToInputItems(previousResponse.output)];
51174
+ }
51175
+ function normalizeResponsesInput(input) {
51176
+ if (!input) return [];
51177
+ if (typeof input === "string") return [{
51178
+ type: "message",
51179
+ role: "user",
51180
+ content: input
51181
+ }];
51182
+ if (Array.isArray(input)) return cloneValue(input);
51183
+ return [];
51184
+ }
51185
+ function convertOutputItemsToInputItems(output) {
51186
+ const items = [];
51187
+ for (const item of output) switch (item.type) {
51188
+ case "message":
51189
+ items.push(convertMessageOutputToInput(item));
51190
+ break;
51191
+ case "function_call":
51192
+ items.push(convertFunctionCallOutputToInput(item));
51193
+ break;
51194
+ case "reasoning": {
51195
+ const reasoningInput = convertReasoningOutputToInput(item);
51196
+ if (reasoningInput) items.push(reasoningInput);
51197
+ break;
51198
+ }
51199
+ case "compaction":
51200
+ items.push(convertCompactionOutputToInput(item));
51201
+ break;
51202
+ }
51203
+ return items;
51204
+ }
51205
+ function convertMessageOutputToInput(item) {
51206
+ return {
51207
+ type: "message",
51208
+ role: item.role,
51209
+ status: item.status,
51210
+ content: item.content?.map((content) => {
51211
+ if (content.type === "output_text" && typeof content.text === "string") return {
51212
+ type: "output_text",
51213
+ text: content.text
51214
+ };
51215
+ return cloneValue(content);
51216
+ }) ?? []
51217
+ };
51218
+ }
51219
+ function convertFunctionCallOutputToInput(item) {
51220
+ return {
51221
+ type: "function_call",
51222
+ call_id: item.call_id,
51223
+ name: item.name,
51224
+ arguments: item.arguments,
51225
+ status: item.status
51226
+ };
51227
+ }
51228
+ function convertReasoningOutputToInput(item) {
51229
+ if (!item.encrypted_content) return;
51230
+ return {
51231
+ id: item.id,
51232
+ type: "reasoning",
51233
+ summary: (item.summary ?? []).filter((summary) => typeof summary.text === "string").map((summary) => ({
51234
+ type: "summary_text",
51235
+ text: summary.text
51236
+ })),
51237
+ encrypted_content: item.encrypted_content
51238
+ };
51239
+ }
51240
+ function convertCompactionOutputToInput(item) {
51241
+ return {
51242
+ id: item.id,
51243
+ type: "compaction",
51244
+ encrypted_content: item.encrypted_content
51245
+ };
51246
+ }
51247
+ function normalizeNullableString(value) {
51248
+ return typeof value === "string" ? value : null;
51249
+ }
51250
+ function normalizeServiceTier(value) {
51251
+ if (value === "auto" || value === "default" || value === "flex" || value === "scale" || value === "priority") return value;
51252
+ return null;
51253
+ }
51254
+ function createConversationRef() {
51255
+ return { id: `conv_${randomUUID().replaceAll("-", "")}` };
51256
+ }
51257
+ function isConversationReference(value) {
51258
+ if (typeof value === "string") return value.length > 0;
51259
+ return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && value.id.length > 0;
51260
+ }
51261
+ function getConversationId(conversation) {
51262
+ return typeof conversation === "string" ? conversation : conversation.id;
51263
+ }
51264
+ function getInputItemId(item) {
51265
+ if (!item || typeof item !== "object") return;
51266
+ if ("id" in item && typeof item.id === "string") return item.id;
51267
+ if ("call_id" in item && typeof item.call_id === "string") return item.call_id;
51268
+ }
51269
+
50409
51270
  //#endregion
50410
51271
  //#region src/routes/responses/strategy.ts
51272
+ function isRecord(value) {
51273
+ return typeof value === "object" && value !== null;
51274
+ }
50411
51275
  function createStreamIdTracker() {
50412
51276
  return { itemIdsByOutputIndex: /* @__PURE__ */ new Map() };
50413
51277
  }
@@ -50419,23 +51283,24 @@ function fixStreamIds(rawData, eventName, state) {
50419
51283
  } catch {
50420
51284
  return rawData;
50421
51285
  }
50422
- if (eventName === "response.created" || eventName === "response.completed" || eventName === "response.incomplete") {
50423
- const response = parsed.response;
50424
- if (response?.id && typeof response.id === "string") state.responseId = response.id;
51286
+ const response = isRecord(parsed.response) ? parsed.response : void 0;
51287
+ if (typeof response?.id === "string") {
51288
+ if (!state.responseId) state.responseId = response.id;
51289
+ else if (response.id !== state.responseId) response.id = state.responseId;
50425
51290
  }
50426
51291
  if (eventName === "response.output_item.added" || eventName === "response.output_item.done") {
50427
51292
  const outputIndex = typeof parsed.output_index === "number" ? parsed.output_index : void 0;
50428
- const item = parsed.item;
50429
- if (outputIndex !== void 0 && typeof item?.id === "string") state.itemIdsByOutputIndex.set(outputIndex, item.id);
51293
+ const item = isRecord(parsed.item) ? parsed.item : void 0;
51294
+ if (outputIndex !== void 0 && typeof item?.id === "string") {
51295
+ const stableId = state.itemIdsByOutputIndex.get(outputIndex);
51296
+ if (!stableId) state.itemIdsByOutputIndex.set(outputIndex, item.id);
51297
+ else if (item.id !== stableId) item.id = stableId;
51298
+ }
50430
51299
  }
50431
- if ((eventName === "response.function_call_arguments.delta" || eventName === "response.function_call_arguments.done" || eventName === "response.output_text.delta" || eventName === "response.output_text.done" || eventName === "response.reasoning_summary_text.delta" || eventName === "response.reasoning_summary_text.done") && typeof parsed.output_index === "number") {
51300
+ if (typeof parsed.output_index === "number" && typeof parsed.item_id === "string") {
50432
51301
  const stableId = state.itemIdsByOutputIndex.get(parsed.output_index);
50433
51302
  if (stableId && parsed.item_id !== stableId) parsed.item_id = stableId;
50434
51303
  }
50435
- if (state.responseId && parsed.response && typeof parsed.response === "object") {
50436
- const response = parsed.response;
50437
- if (response.id !== state.responseId) response.id = state.responseId;
50438
- }
50439
51304
  return JSON.stringify(parsed);
50440
51305
  }
50441
51306
  function createResponsesPassthroughStrategy(copilotClient, payload, options) {
@@ -50451,10 +51316,34 @@ function createResponsesPassthroughStrategy(copilotClient, payload, options) {
50451
51316
  return result;
50452
51317
  },
50453
51318
  translateStreamChunk(chunk) {
50454
- return passthroughSSEChunk(chunk, fixStreamIds(chunk.data ?? "", chunk.event, tracker));
51319
+ const fixedData = fixStreamIds(chunk.data ?? "", chunk.event, tracker);
51320
+ const mappedData = options.mapResponse ? mapChunkResponse(fixedData, options.mapResponse) : fixedData;
51321
+ const parsedResponse = tryExtractTerminalResponse(mappedData);
51322
+ if (parsedResponse) options.onTerminalResponse?.(parsedResponse);
51323
+ return passthroughSSEChunk(chunk, mappedData);
50455
51324
  }
50456
51325
  };
50457
51326
  }
51327
+ function mapChunkResponse(rawData, mapResponse) {
51328
+ if (!rawData) return rawData;
51329
+ try {
51330
+ const parsed = JSON.parse(rawData);
51331
+ if (isRecord(parsed.response)) {
51332
+ parsed.response = mapResponse(parsed.response);
51333
+ return JSON.stringify(parsed);
51334
+ }
51335
+ } catch {}
51336
+ return rawData;
51337
+ }
51338
+ function tryExtractTerminalResponse(rawData) {
51339
+ if (!rawData) return;
51340
+ try {
51341
+ const parsed = JSON.parse(rawData);
51342
+ if (parsed.type !== "response.completed" && parsed.type !== "response.incomplete" && parsed.type !== "response.failed") return;
51343
+ const response = parsed.response;
51344
+ if (response && typeof response === "object") return response;
51345
+ } catch {}
51346
+ }
50458
51347
 
50459
51348
  //#endregion
50460
51349
  //#region src/routes/responses/handler.ts
@@ -50464,34 +51353,65 @@ const HTTP_URL_RE = /^https?:\/\//i;
50464
51353
  */
50465
51354
  async function handleResponsesCore({ body, signal, headers }) {
50466
51355
  const payload = parseResponsesPayload(body);
50467
- const rewrite = applyModelRewrite(payload);
50468
- applyResponsesToolTransforms(payload);
50469
- applyResponsesInputPolicies(payload);
50470
- compactInputByLatestCompaction(payload);
50471
- const selectedModel = findModelById(payload.model);
51356
+ const requestContext = normalizeResponsesRequestContext(payload, headers);
51357
+ const emulatorPrepared = shouldUseResponsesOfficialEmulator() ? prepareEmulatorRequest(payload) : void 0;
51358
+ const rewrite = applyModelRewrite(emulatorPrepared?.upstreamPayload ?? payload);
51359
+ const effectivePayload = emulatorPrepared?.upstreamPayload ?? payload;
51360
+ applyResponsesToolTransforms(effectivePayload);
51361
+ applyResponsesInputPolicies(effectivePayload);
51362
+ compactInputByLatestCompaction(effectivePayload);
51363
+ const selectedModel = findModelById(effectivePayload.model);
50472
51364
  if (!selectedModel) throwInvalidRequestError("The selected model could not be resolved.", "model");
50473
51365
  if (!modelSupportsEndpoint(selectedModel, RESPONSES_ENDPOINT)) throwInvalidRequestError("The selected model does not support the responses endpoint.", "model");
50474
- applyContextManagement(payload, selectedModel.capabilities.limits.max_prompt_tokens);
50475
- const { vision, initiator } = getResponsesRequestOptions(payload);
51366
+ applyContextManagement(effectivePayload, selectedModel.capabilities.limits.max_prompt_tokens);
51367
+ const { vision, initiator } = getResponsesRequestOptions(effectivePayload);
50476
51368
  const upstreamSignal = createUpstreamSignalFromConfig(signal);
51369
+ const copilotClient = createCopilotClient();
51370
+ const decorateResponse = emulatorPrepared ? (response) => decorateStoredResponse(response, payload, emulatorPrepared) : void 0;
51371
+ const result = await runStrategy(createResponsesPassthroughStrategy(copilotClient, effectivePayload, {
51372
+ vision,
51373
+ initiator: resolveInitiator(initiator, requestContext),
51374
+ requestContext,
51375
+ signal: upstreamSignal.signal,
51376
+ mapResponse: decorateResponse,
51377
+ onTerminalResponse: emulatorPrepared ? (terminalResponse) => {
51378
+ if (!emulatorPrepared?.shouldStore) return;
51379
+ persistEmulatorResponse(terminalResponse, emulatorPrepared.effectiveInputItems);
51380
+ } : void 0
51381
+ }), upstreamSignal);
51382
+ if (emulatorPrepared && result.kind === "json") {
51383
+ const emulatedResponse = decorateStoredResponse(result.data, payload, emulatorPrepared);
51384
+ if (emulatorPrepared.shouldStore) persistEmulatorResponse(emulatedResponse, emulatorPrepared.effectiveInputItems);
51385
+ result.data = emulatedResponse;
51386
+ }
50477
51387
  return {
50478
- result: await runStrategy(createResponsesPassthroughStrategy(createCopilotClient(), payload, {
50479
- vision,
50480
- initiator,
50481
- requestContext: readCapiRequestContext(headers),
50482
- signal: upstreamSignal.signal
50483
- }), upstreamSignal),
51388
+ result,
50484
51389
  modelMapping: {
50485
51390
  originalModel: rewrite.originalModel,
50486
51391
  rewrittenModel: rewrite.model,
50487
- mappedModel: payload.model
51392
+ mappedModel: effectivePayload.model
50488
51393
  }
50489
51394
  };
50490
51395
  }
50491
51396
  function applyResponsesToolTransforms(payload) {
50492
51397
  applyFunctionApplyPatch(payload);
51398
+ applyFunctionToolCompatibilityDefaults(payload);
50493
51399
  rejectUnsupportedBuiltinTools(payload);
50494
51400
  }
51401
+ function applyFunctionToolCompatibilityDefaults(payload) {
51402
+ if (!Array.isArray(payload.tools)) return;
51403
+ payload.tools = payload.tools.map((tool) => {
51404
+ if (!isResponseFunctionTool(tool)) return tool;
51405
+ return {
51406
+ ...tool,
51407
+ parameters: normalizeFunctionParametersSchemaForCopilot(tool.parameters),
51408
+ strict: tool.strict ?? true
51409
+ };
51410
+ });
51411
+ }
51412
+ function isResponseFunctionTool(tool) {
51413
+ return tool.type === "function";
51414
+ }
50495
51415
  function applyFunctionApplyPatch(payload) {
50496
51416
  if (!shouldUseFunctionApplyPatch() || !Array.isArray(payload.tools)) return;
50497
51417
  payload.tools = payload.tools.map((tool) => {
@@ -50513,6 +51433,7 @@ function applyFunctionApplyPatch(payload) {
50513
51433
  });
50514
51434
  }
50515
51435
  function rejectUnsupportedBuiltinTools(payload) {
51436
+ if (payload.tool_choice && typeof payload.tool_choice === "object" && "type" in payload.tool_choice && (payload.tool_choice.type === "web_search_preview" || payload.tool_choice.type === "web_search_preview_2025_03_11")) throwInvalidRequestError("The selected Copilot endpoint does not support the Responses web_search tool.", "tool_choice", "unsupported_tool_web_search");
50516
51437
  if (!Array.isArray(payload.tools)) return;
50517
51438
  for (const tool of payload.tools) if (tool.type === "web_search") throwInvalidRequestError("The selected Copilot endpoint does not support the Responses web_search tool.", "tools", "unsupported_tool_web_search");
50518
51439
  }
@@ -50536,6 +51457,7 @@ function containsRemoteImageUrl(value) {
50536
51457
  //#region src/routes/responses/resource-handler.ts
50537
51458
  async function handleRetrieveResponseCore({ params, url, headers, signal }) {
50538
51459
  const responseId = requireResponseId(params.responseId);
51460
+ if (shouldUseResponsesOfficialEmulator()) return getStoredResponseOrThrow(responseId);
50539
51461
  return await createCopilotClient().getResponse(responseId, {
50540
51462
  params: getRetrieveParamsFromUrl(url),
50541
51463
  requestContext: readCapiRequestContext(headers),
@@ -50544,6 +51466,7 @@ async function handleRetrieveResponseCore({ params, url, headers, signal }) {
50544
51466
  }
50545
51467
  async function handleListResponseInputItemsCore({ params, url, headers, signal }) {
50546
51468
  const responseId = requireResponseId(params.responseId);
51469
+ if (shouldUseResponsesOfficialEmulator()) return listStoredInputItemsOrThrow(responseId, getInputItemsParamsFromUrl(url));
50547
51470
  return await createCopilotClient().getResponseInputItems(responseId, getInputItemsParamsFromUrl(url), {
50548
51471
  requestContext: readCapiRequestContext(headers),
50549
51472
  signal
@@ -50551,13 +51474,22 @@ async function handleListResponseInputItemsCore({ params, url, headers, signal }
50551
51474
  }
50552
51475
  async function handleCreateResponseInputTokensCore({ body, headers, signal }) {
50553
51476
  const payload = parseResponsesInputTokensPayload(body);
51477
+ const requestContext = normalizeResponsesRequestContext(payload, headers);
51478
+ if (shouldUseResponsesOfficialEmulator()) {
51479
+ const model = payload.model;
51480
+ if (!model) throwInvalidRequestError("The selected model could not be resolved.", "model");
51481
+ const selectedModel = findModelById(model);
51482
+ if (!selectedModel) throwInvalidRequestError("The selected model could not be resolved.", "model");
51483
+ return await estimateEmulatorInputTokens(payload, selectedModel);
51484
+ }
50554
51485
  return await createCopilotClient().createResponseInputTokens(payload, {
50555
- requestContext: readCapiRequestContext(headers),
51486
+ requestContext,
50556
51487
  signal
50557
51488
  });
50558
51489
  }
50559
51490
  async function handleDeleteResponseCore({ params, headers, signal }) {
50560
51491
  const responseId = requireResponseId(params.responseId);
51492
+ if (shouldUseResponsesOfficialEmulator()) return deleteStoredResponseOrThrow(responseId);
50561
51493
  return await createCopilotClient().deleteResponse(responseId, {
50562
51494
  requestContext: readCapiRequestContext(headers),
50563
51495
  signal