@jeffreycao/copilot-api 1.11.1 → 1.11.3
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.js +1 -1
- package/dist/{server-BxCf-DN5.js → server-CSpOUSFF.js} +221 -35
- package/dist/server-CSpOUSFF.js.map +1 -0
- package/dist/{start-CFeefs3X.js → start-t4js93GE.js} +2 -2
- package/dist/{start-CFeefs3X.js.map → start-t4js93GE.js.map} +1 -1
- package/package.json +1 -1
- package/dist/server-BxCf-DN5.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -43,7 +43,7 @@ const { auth } = await import("./auth-D3ta3JW0.js");
|
|
|
43
43
|
const { checkUsage } = await import("./check-usage-Dh0WqiLC.js");
|
|
44
44
|
const { debug } = await import("./debug-BiX0ewij.js");
|
|
45
45
|
const { mcp } = await import("./mcp-DZgcvqQY.js");
|
|
46
|
-
const { start } = await import("./start-
|
|
46
|
+
const { start } = await import("./start-t4js93GE.js");
|
|
47
47
|
await runMain(defineCommand({
|
|
48
48
|
meta: {
|
|
49
49
|
name: "copilot-api",
|
|
@@ -2343,7 +2343,7 @@ const prepareMessagesApiPayload = (payload, selectedModel) => {
|
|
|
2343
2343
|
payload.thinking = { type: "adaptive" };
|
|
2344
2344
|
if (!hasThinking) payload.thinking.display = "summarized";
|
|
2345
2345
|
if (shouldSummarizeThinkingDisplayForModel(payload.model)) payload.thinking.display = "summarized";
|
|
2346
|
-
let effort = getReasoningEffortForModel(payload.model);
|
|
2346
|
+
let effort = payload.output_config?.effort ?? getReasoningEffortForModel(payload.model);
|
|
2347
2347
|
if (effort === "none" || effort === "minimal") effort = "low";
|
|
2348
2348
|
const reasoningEffort = selectedModel.capabilities.supports.reasoning_effort;
|
|
2349
2349
|
if (reasoningEffort && !reasoningEffort.includes(effort)) effort = reasoningEffort.at(-1);
|
|
@@ -4351,7 +4351,7 @@ const prepareWebSearchResponsesPayload = (payload, options = {}) => {
|
|
|
4351
4351
|
...payload,
|
|
4352
4352
|
model: options.model ?? payload.model,
|
|
4353
4353
|
tools: [],
|
|
4354
|
-
stream:
|
|
4354
|
+
stream: true
|
|
4355
4355
|
}, options.subagentAgentId);
|
|
4356
4356
|
responsesPayload.tools = [buildResponsesWebSearchTool(config)];
|
|
4357
4357
|
responsesPayload.tool_choice = void 0;
|
|
@@ -4377,6 +4377,143 @@ const reconstructWebSearchResponse = (payload, result, options) => {
|
|
|
4377
4377
|
}
|
|
4378
4378
|
};
|
|
4379
4379
|
};
|
|
4380
|
+
const collectWebSearchResponsesStreamResult = async ({ errorMessagePrefix = "Web search responses stream", parseEvent = parseWebSearchResponsesStreamEvent, upstreamResponse, logger }) => {
|
|
4381
|
+
const state = createWebSearchResponsesStreamCollection();
|
|
4382
|
+
for await (const chunk of upstreamResponse) {
|
|
4383
|
+
debugJson(logger, "Received web search responses stream chunk:", chunk.data);
|
|
4384
|
+
if (chunk.event === "ping") continue;
|
|
4385
|
+
if (!chunk.data || chunk.data === "[DONE]") continue;
|
|
4386
|
+
const parsed = parseEvent(chunk.data);
|
|
4387
|
+
if (!parsed) continue;
|
|
4388
|
+
collectWebSearchResponsesStreamEvent(parsed, state);
|
|
4389
|
+
if (parsed.type === "error") throw new Error(getStreamErrorMessage(parsed) ?? `${errorMessagePrefix} failed`);
|
|
4390
|
+
if (isResponsesTerminalEvent(parsed)) return buildWebSearchResponsesStreamResult(state);
|
|
4391
|
+
}
|
|
4392
|
+
throw new Error(`${errorMessagePrefix} ended without a terminal event`);
|
|
4393
|
+
};
|
|
4394
|
+
const parseWebSearchResponsesStreamEvent = (data) => {
|
|
4395
|
+
try {
|
|
4396
|
+
return JSON.parse(data);
|
|
4397
|
+
} catch {
|
|
4398
|
+
return null;
|
|
4399
|
+
}
|
|
4400
|
+
};
|
|
4401
|
+
const isWebSearchResponsesStream = (value) => {
|
|
4402
|
+
return Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
4403
|
+
};
|
|
4404
|
+
const isResponsesTerminalEvent = (event) => (event.type === "response.completed" || event.type === "response.failed" || event.type === "response.incomplete") && getResponsesResult(event.response) !== void 0;
|
|
4405
|
+
const createWebSearchResponsesStreamCollection = () => ({
|
|
4406
|
+
outputItemsByIndex: /* @__PURE__ */ new Map(),
|
|
4407
|
+
textPartsByKey: /* @__PURE__ */ new Map()
|
|
4408
|
+
});
|
|
4409
|
+
const collectWebSearchResponsesStreamEvent = (event, state) => {
|
|
4410
|
+
if (event.type === "response.created") {
|
|
4411
|
+
state.createdResponse = getResponsesResult(event.response);
|
|
4412
|
+
return;
|
|
4413
|
+
}
|
|
4414
|
+
if (isResponsesTerminalEvent(event)) {
|
|
4415
|
+
state.terminalResponse = event.response;
|
|
4416
|
+
return;
|
|
4417
|
+
}
|
|
4418
|
+
if (event.type === "response.output_item.added" || event.type === "response.output_item.done") {
|
|
4419
|
+
const outputIndex = getNumber(event.output_index);
|
|
4420
|
+
const item = getRecord(event.item);
|
|
4421
|
+
if (outputIndex !== void 0 && item) state.outputItemsByIndex.set(outputIndex, item);
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
4424
|
+
if (event.type === "response.output_text.delta") {
|
|
4425
|
+
const part = getOrCreateOutputTextPart(event, state);
|
|
4426
|
+
const delta = getString(event.delta);
|
|
4427
|
+
if (part && delta) part.text += delta;
|
|
4428
|
+
return;
|
|
4429
|
+
}
|
|
4430
|
+
if (event.type === "response.output_text.done") {
|
|
4431
|
+
const part = getOrCreateOutputTextPart(event, state);
|
|
4432
|
+
const text = getString(event.text);
|
|
4433
|
+
if (part && text !== void 0) part.text = text;
|
|
4434
|
+
return;
|
|
4435
|
+
}
|
|
4436
|
+
if (event.type === "response.output_text.annotation.added") {
|
|
4437
|
+
const part = getOrCreateOutputTextPart(event, state);
|
|
4438
|
+
const annotation = event.annotation;
|
|
4439
|
+
if (part && annotation !== void 0) part.annotations.push(annotation);
|
|
4440
|
+
return;
|
|
4441
|
+
}
|
|
4442
|
+
if (event.type === "response.content_part.done") collectDoneContentPart(event, state);
|
|
4443
|
+
};
|
|
4444
|
+
const buildWebSearchResponsesStreamResult = (state) => {
|
|
4445
|
+
const response = state.terminalResponse ?? state.createdResponse;
|
|
4446
|
+
if (!response) throw new Error("Web search responses stream ended without a response");
|
|
4447
|
+
const output = buildCollectedWebSearchOutput(state);
|
|
4448
|
+
return {
|
|
4449
|
+
...response,
|
|
4450
|
+
output: output.length > 0 ? output : response.output
|
|
4451
|
+
};
|
|
4452
|
+
};
|
|
4453
|
+
const buildCollectedWebSearchOutput = (state) => [...state.outputItemsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([outputIndex, item]) => mergeOutputItemWithCollectedText(outputIndex, item, state));
|
|
4454
|
+
const mergeOutputItemWithCollectedText = (outputIndex, item, state) => {
|
|
4455
|
+
if (item.type !== "message") return item;
|
|
4456
|
+
const collectedParts = getCollectedTextParts(outputIndex, state);
|
|
4457
|
+
if (collectedParts.length === 0) return item;
|
|
4458
|
+
const content = getArray(item.content);
|
|
4459
|
+
for (const part of collectedParts) {
|
|
4460
|
+
const existingPart = getRecord(content[part.contentIndex]);
|
|
4461
|
+
content[part.contentIndex] = {
|
|
4462
|
+
...existingPart,
|
|
4463
|
+
type: "output_text",
|
|
4464
|
+
text: part.text,
|
|
4465
|
+
annotations: mergeAnnotations(existingPart?.annotations, part.annotations)
|
|
4466
|
+
};
|
|
4467
|
+
}
|
|
4468
|
+
return {
|
|
4469
|
+
...item,
|
|
4470
|
+
content
|
|
4471
|
+
};
|
|
4472
|
+
};
|
|
4473
|
+
const collectDoneContentPart = (event, state) => {
|
|
4474
|
+
const partRecord = getRecord(getRecord(event)?.part);
|
|
4475
|
+
if (partRecord?.type !== "output_text") return;
|
|
4476
|
+
const part = getOrCreateOutputTextPart(event, state);
|
|
4477
|
+
if (!part) return;
|
|
4478
|
+
const text = getString(partRecord.text);
|
|
4479
|
+
if (text !== void 0) part.text = text;
|
|
4480
|
+
const annotations = getArray(partRecord.annotations);
|
|
4481
|
+
if (annotations.length > 0) part.annotations.push(...annotations);
|
|
4482
|
+
};
|
|
4483
|
+
const getOrCreateOutputTextPart = (event, state) => {
|
|
4484
|
+
const eventRecord = getRecord(event);
|
|
4485
|
+
const outputIndex = getNumber(eventRecord?.output_index);
|
|
4486
|
+
const contentIndex = getNumber(eventRecord?.content_index);
|
|
4487
|
+
if (outputIndex === void 0 || contentIndex === void 0) return;
|
|
4488
|
+
const key = `${outputIndex}:${contentIndex}`;
|
|
4489
|
+
let part = state.textPartsByKey.get(key);
|
|
4490
|
+
if (!part) {
|
|
4491
|
+
part = {
|
|
4492
|
+
annotations: [],
|
|
4493
|
+
contentIndex,
|
|
4494
|
+
itemId: getString(eventRecord?.item_id),
|
|
4495
|
+
outputIndex,
|
|
4496
|
+
text: ""
|
|
4497
|
+
};
|
|
4498
|
+
state.textPartsByKey.set(key, part);
|
|
4499
|
+
}
|
|
4500
|
+
return part;
|
|
4501
|
+
};
|
|
4502
|
+
const getCollectedTextParts = (outputIndex, state) => [...state.textPartsByKey.values()].filter((part) => part.outputIndex === outputIndex).sort((left, right) => left.contentIndex - right.contentIndex || (left.itemId ?? "").localeCompare(right.itemId ?? ""));
|
|
4503
|
+
const mergeAnnotations = (existingAnnotations, collectedAnnotations) => {
|
|
4504
|
+
const annotations = getArray(existingAnnotations);
|
|
4505
|
+
annotations.push(...collectedAnnotations);
|
|
4506
|
+
return annotations;
|
|
4507
|
+
};
|
|
4508
|
+
const getResponsesResult = (value) => getRecord(value);
|
|
4509
|
+
const getRecord = (value) => value && typeof value === "object" ? value : void 0;
|
|
4510
|
+
const getArray = (value) => Array.isArray(value) ? Array.from(value) : [];
|
|
4511
|
+
const getStreamErrorMessage = (event) => {
|
|
4512
|
+
const eventRecord = getRecord(event);
|
|
4513
|
+
return getString(getRecord(eventRecord?.error)?.message) ?? getString(eventRecord?.message);
|
|
4514
|
+
};
|
|
4515
|
+
const getNumber = (value) => typeof value === "number" ? value : void 0;
|
|
4516
|
+
const getString = (value) => typeof value === "string" ? value : void 0;
|
|
4380
4517
|
const createUsageRecorder = (payload, sessionId, webSearchModel) => webSearchFlowDependencies.createUsageRecorder(payload, sessionId, webSearchModel);
|
|
4381
4518
|
/**
|
|
4382
4519
|
* Entry point for web-search detection and routing on /v1/messages.
|
|
@@ -4432,8 +4569,8 @@ const handleWebSearchViaResponses = async (c, payload, options) => {
|
|
|
4432
4569
|
const selectedModel = findEndpointModel(webSearchModel);
|
|
4433
4570
|
const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
|
|
4434
4571
|
const transport = getResponsesTransportForModel(selectedModel, { compactType: options.compactType }) ?? "http";
|
|
4435
|
-
logger
|
|
4436
|
-
const
|
|
4572
|
+
debugJson(logger, `Switching web search request to model: ${webSearchModel}`, responsesPayload);
|
|
4573
|
+
const upstreamResult = await webSearchFlowDependencies.createResponses(responsesPayload, {
|
|
4437
4574
|
vision,
|
|
4438
4575
|
initiator,
|
|
4439
4576
|
transport,
|
|
@@ -4442,8 +4579,13 @@ const handleWebSearchViaResponses = async (c, payload, options) => {
|
|
|
4442
4579
|
sessionId: options.sessionId,
|
|
4443
4580
|
compactType: options.compactType
|
|
4444
4581
|
});
|
|
4582
|
+
const result = isWebSearchResponsesStream(upstreamResult) ? await collectWebSearchResponsesStreamResult({
|
|
4583
|
+
errorMessagePrefix: "Web search responses stream",
|
|
4584
|
+
upstreamResponse: upstreamResult,
|
|
4585
|
+
logger
|
|
4586
|
+
}) : upstreamResult;
|
|
4445
4587
|
const { extract, response } = reconstructWebSearchResponse(payload, result, { requestId: options.requestId });
|
|
4446
|
-
logger
|
|
4588
|
+
debugJson(logger, `Web search via responses: ${extract.queries.length} quer(y/ies), ${extract.sources.length} source(s)`, result);
|
|
4447
4589
|
createUsageRecorder(payload, options.sessionId, webSearchModel)(normalizeResponsesUsage(result.usage));
|
|
4448
4590
|
if (!wantsStream) return c.json(response);
|
|
4449
4591
|
return streamSSE(c, async (stream) => {
|
|
@@ -4701,17 +4843,31 @@ const handleOpenAIResponsesProviderWebSearchMessages = async (c, options) => {
|
|
|
4701
4843
|
const { payload, provider, providerConfig } = options;
|
|
4702
4844
|
const selectedModel = providerConfig.name === "codex" ? getModels().data.find((model) => model.id === payload.model) : void 0;
|
|
4703
4845
|
const responsesPayload = prepareWebSearchResponsesPayload(payload);
|
|
4846
|
+
responsesPayload.stream = true;
|
|
4704
4847
|
applyResponsesApiContextManagement(responsesPayload, selectedModel?.capabilities.limits.max_prompt_tokens);
|
|
4705
4848
|
compactInputByLatestCompaction(responsesPayload);
|
|
4706
4849
|
debugJson(logger$5, "provider.messages.responses.web_search.request", {
|
|
4707
4850
|
payload: responsesPayload,
|
|
4708
4851
|
provider
|
|
4709
4852
|
});
|
|
4710
|
-
if (providerConfig.name === "codex")
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4853
|
+
if (providerConfig.name === "codex") {
|
|
4854
|
+
const upstreamResponse = await forwardCodexResponses(responsesPayload, c.req.raw.headers, providerConfig.baseUrl);
|
|
4855
|
+
if (isResponsesStream$1(upstreamResponse)) return respondWebSearchProviderMessagesJson(c, {
|
|
4856
|
+
body: await collectWebSearchResponsesStreamResult({
|
|
4857
|
+
errorMessagePrefix: `${provider} web search responses stream`,
|
|
4858
|
+
parseEvent: (data) => parseResponsesProviderStreamChunk(data, providerConfig),
|
|
4859
|
+
upstreamResponse,
|
|
4860
|
+
logger: logger$5
|
|
4861
|
+
}),
|
|
4862
|
+
payload,
|
|
4863
|
+
provider
|
|
4864
|
+
});
|
|
4865
|
+
return respondWebSearchProviderMessagesJson(c, {
|
|
4866
|
+
body: upstreamResponse,
|
|
4867
|
+
payload,
|
|
4868
|
+
provider
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4715
4871
|
const upstreamResponse = await forwardProviderResponses(providerConfig, responsesPayload, c.req.raw.headers);
|
|
4716
4872
|
if (!upstreamResponse.ok) {
|
|
4717
4873
|
logger$5.error("Failed to create provider web search responses", {
|
|
@@ -4720,6 +4876,16 @@ const handleOpenAIResponsesProviderWebSearchMessages = async (c, options) => {
|
|
|
4720
4876
|
});
|
|
4721
4877
|
throw new HTTPError("Failed to create provider web search responses", upstreamResponse);
|
|
4722
4878
|
}
|
|
4879
|
+
if ((upstreamResponse.headers.get("content-type") ?? "").includes("text/event-stream")) return respondWebSearchProviderMessagesJson(c, {
|
|
4880
|
+
body: await collectWebSearchResponsesStreamResult({
|
|
4881
|
+
errorMessagePrefix: `${provider} web search responses stream`,
|
|
4882
|
+
parseEvent: (data) => parseResponsesProviderStreamChunk(data, providerConfig),
|
|
4883
|
+
upstreamResponse: events(upstreamResponse),
|
|
4884
|
+
logger: logger$5
|
|
4885
|
+
}),
|
|
4886
|
+
payload,
|
|
4887
|
+
provider
|
|
4888
|
+
});
|
|
4723
4889
|
return respondWebSearchProviderMessagesJson(c, {
|
|
4724
4890
|
body: await upstreamResponse.json(),
|
|
4725
4891
|
payload,
|
|
@@ -5625,34 +5791,54 @@ const createProviderResponsesUsageRecorder = (payload, provider) => {
|
|
|
5625
5791
|
sessionId: sessionAffinity ?? ""
|
|
5626
5792
|
});
|
|
5627
5793
|
};
|
|
5628
|
-
const streamProviderResponses = (c, upstreamResponse, options) => {
|
|
5794
|
+
const streamProviderResponses = async (c, upstreamResponse, options) => {
|
|
5795
|
+
const iterator = upstreamResponse[Symbol.asyncIterator]();
|
|
5796
|
+
const firstResult = await iterator.next();
|
|
5797
|
+
if (firstResult.done) throw new HTTPError(`Empty stream from ${options.provider} responses`, new Response("", { status: 502 }));
|
|
5798
|
+
const firstChunk = firstResult.value;
|
|
5799
|
+
if (firstChunk.data && firstChunk.data !== "[DONE]") {
|
|
5800
|
+
const event = parseProviderResponsesStreamEvent(firstChunk.data, {
|
|
5801
|
+
normalizeCodex: options.normalizeCodex,
|
|
5802
|
+
provider: options.provider
|
|
5803
|
+
});
|
|
5804
|
+
if (event?.type === "error") {
|
|
5805
|
+
const errorEvent = event;
|
|
5806
|
+
const statusCode = errorEvent.status_code ?? 500;
|
|
5807
|
+
return c.json({ error: {
|
|
5808
|
+
message: errorEvent.message,
|
|
5809
|
+
...errorEvent.error
|
|
5810
|
+
} }, statusCode, errorEvent.headers ?? void 0);
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5629
5813
|
return streamSSE(c, async (stream) => {
|
|
5630
5814
|
let usage = {};
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
provider: options.provider
|
|
5640
|
-
});
|
|
5641
|
-
if (event && options.normalizeCodex) responseChunk = {
|
|
5642
|
-
...chunk,
|
|
5643
|
-
data: JSON.stringify(event),
|
|
5644
|
-
event: event.type
|
|
5645
|
-
};
|
|
5646
|
-
}
|
|
5647
|
-
if (event) {
|
|
5648
|
-
const nextUsage = getResponsesStreamEventUsage(event);
|
|
5649
|
-
if (nextUsage) usage = nextUsage;
|
|
5650
|
-
}
|
|
5651
|
-
await stream.writeSSE({
|
|
5652
|
-
data: responseChunk.data ?? "",
|
|
5653
|
-
event: responseChunk.event
|
|
5815
|
+
const writeChunk = async (chunk) => {
|
|
5816
|
+
debugJson(logger$2, "Responses stream chunk:", chunk);
|
|
5817
|
+
let responseChunk = chunk;
|
|
5818
|
+
let event = null;
|
|
5819
|
+
if (chunk.data && chunk.data !== "[DONE]") {
|
|
5820
|
+
event = parseProviderResponsesStreamEvent(chunk.data, {
|
|
5821
|
+
normalizeCodex: options.normalizeCodex,
|
|
5822
|
+
provider: options.provider
|
|
5654
5823
|
});
|
|
5824
|
+
if (event && options.normalizeCodex) responseChunk = {
|
|
5825
|
+
...chunk,
|
|
5826
|
+
data: JSON.stringify(event),
|
|
5827
|
+
event: event.type
|
|
5828
|
+
};
|
|
5829
|
+
}
|
|
5830
|
+
if (event) {
|
|
5831
|
+
const nextUsage = getResponsesStreamEventUsage(event);
|
|
5832
|
+
if (nextUsage) usage = nextUsage;
|
|
5655
5833
|
}
|
|
5834
|
+
await stream.writeSSE({
|
|
5835
|
+
data: responseChunk.data ?? "",
|
|
5836
|
+
event: responseChunk.event
|
|
5837
|
+
});
|
|
5838
|
+
};
|
|
5839
|
+
try {
|
|
5840
|
+
await writeChunk(firstChunk);
|
|
5841
|
+
for await (const chunk of { [Symbol.asyncIterator]: () => iterator }) await writeChunk(chunk);
|
|
5656
5842
|
} finally {
|
|
5657
5843
|
options.recordUsage(usage);
|
|
5658
5844
|
}
|
|
@@ -5970,4 +6156,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
|
|
|
5970
6156
|
//#endregion
|
|
5971
6157
|
export { server };
|
|
5972
6158
|
|
|
5973
|
-
//# sourceMappingURL=server-
|
|
6159
|
+
//# sourceMappingURL=server-CSpOUSFF.js.map
|