@dianshuv/copilot-api 0.4.0 → 0.4.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/dist/main.mjs +224 -29
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -1020,7 +1020,7 @@ const patchClaude = defineCommand({
|
|
|
1020
1020
|
|
|
1021
1021
|
//#endregion
|
|
1022
1022
|
//#region package.json
|
|
1023
|
-
var version = "0.4.
|
|
1023
|
+
var version = "0.4.1";
|
|
1024
1024
|
|
|
1025
1025
|
//#endregion
|
|
1026
1026
|
//#region src/lib/adaptive-rate-limiter.ts
|
|
@@ -7445,50 +7445,229 @@ const containsVisionContent = (value) => {
|
|
|
7445
7445
|
if (Array.isArray(record.content)) return record.content.some((entry) => containsVisionContent(entry));
|
|
7446
7446
|
return false;
|
|
7447
7447
|
};
|
|
7448
|
+
/** Convert Responses API input to history MessageContent format */
|
|
7449
|
+
function convertResponsesInputToMessages(input) {
|
|
7450
|
+
if (!input) return [];
|
|
7451
|
+
if (typeof input === "string") return [{
|
|
7452
|
+
role: "user",
|
|
7453
|
+
content: input
|
|
7454
|
+
}];
|
|
7455
|
+
const messages = [];
|
|
7456
|
+
for (const item of input) {
|
|
7457
|
+
const record = item;
|
|
7458
|
+
switch (record.type) {
|
|
7459
|
+
case "function_call": {
|
|
7460
|
+
const fc = item;
|
|
7461
|
+
messages.push({
|
|
7462
|
+
role: "assistant",
|
|
7463
|
+
content: "",
|
|
7464
|
+
tool_calls: [{
|
|
7465
|
+
id: fc.call_id,
|
|
7466
|
+
type: "function",
|
|
7467
|
+
function: {
|
|
7468
|
+
name: fc.name,
|
|
7469
|
+
arguments: fc.arguments
|
|
7470
|
+
}
|
|
7471
|
+
}]
|
|
7472
|
+
});
|
|
7473
|
+
break;
|
|
7474
|
+
}
|
|
7475
|
+
case "function_call_output": {
|
|
7476
|
+
const fco = item;
|
|
7477
|
+
messages.push({
|
|
7478
|
+
role: "tool",
|
|
7479
|
+
content: typeof fco.output === "string" ? fco.output : JSON.stringify(fco.output),
|
|
7480
|
+
tool_call_id: fco.call_id
|
|
7481
|
+
});
|
|
7482
|
+
break;
|
|
7483
|
+
}
|
|
7484
|
+
case "reasoning": break;
|
|
7485
|
+
default: if ("role" in record) {
|
|
7486
|
+
const msg = item;
|
|
7487
|
+
messages.push({
|
|
7488
|
+
role: msg.role,
|
|
7489
|
+
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
7490
|
+
});
|
|
7491
|
+
}
|
|
7492
|
+
}
|
|
7493
|
+
}
|
|
7494
|
+
return messages;
|
|
7495
|
+
}
|
|
7496
|
+
/** Convert Responses API tools to history ToolDefinition format */
|
|
7497
|
+
function convertResponsesToolsToDefinitions(tools) {
|
|
7498
|
+
if (!tools) return [];
|
|
7499
|
+
return tools.filter((t) => t.type === "function").map((t) => {
|
|
7500
|
+
const ft = t;
|
|
7501
|
+
const def = { name: ft.name };
|
|
7502
|
+
if (ft.description) def.description = ft.description;
|
|
7503
|
+
return def;
|
|
7504
|
+
});
|
|
7505
|
+
}
|
|
7506
|
+
/** Extract response content and tool calls from ResponsesResult output in a single pass */
|
|
7507
|
+
function extractResponseData(result) {
|
|
7508
|
+
if (result.output.length === 0) return {
|
|
7509
|
+
content: null,
|
|
7510
|
+
toolCalls: void 0
|
|
7511
|
+
};
|
|
7512
|
+
let text = "";
|
|
7513
|
+
const contentToolCalls = [];
|
|
7514
|
+
const historyToolCalls = [];
|
|
7515
|
+
for (const item of result.output) if (item.type === "message" && "content" in item && item.content) {
|
|
7516
|
+
for (const block of item.content) if ("text" in block && typeof block.text === "string") text += block.text;
|
|
7517
|
+
else if ("refusal" in block && typeof block.refusal === "string") text += block.refusal;
|
|
7518
|
+
} else if (item.type === "function_call") {
|
|
7519
|
+
const fc = item;
|
|
7520
|
+
contentToolCalls.push({
|
|
7521
|
+
id: fc.call_id,
|
|
7522
|
+
type: "function",
|
|
7523
|
+
function: {
|
|
7524
|
+
name: fc.name,
|
|
7525
|
+
arguments: fc.arguments
|
|
7526
|
+
}
|
|
7527
|
+
});
|
|
7528
|
+
historyToolCalls.push({
|
|
7529
|
+
id: fc.call_id,
|
|
7530
|
+
name: fc.name,
|
|
7531
|
+
input: fc.arguments
|
|
7532
|
+
});
|
|
7533
|
+
}
|
|
7534
|
+
if (!text && contentToolCalls.length === 0) return {
|
|
7535
|
+
content: null,
|
|
7536
|
+
toolCalls: void 0
|
|
7537
|
+
};
|
|
7538
|
+
const content = {
|
|
7539
|
+
role: "assistant",
|
|
7540
|
+
content: text
|
|
7541
|
+
};
|
|
7542
|
+
if (contentToolCalls.length > 0) content.tool_calls = contentToolCalls;
|
|
7543
|
+
return {
|
|
7544
|
+
content,
|
|
7545
|
+
toolCalls: historyToolCalls.length > 0 ? historyToolCalls : void 0
|
|
7546
|
+
};
|
|
7547
|
+
}
|
|
7548
|
+
/** Map ResponsesResult.status to a stop_reason string */
|
|
7549
|
+
function extractResponseStopReason(result) {
|
|
7550
|
+
switch (result.status) {
|
|
7551
|
+
case "completed": return "stop";
|
|
7552
|
+
case "incomplete": return "length";
|
|
7553
|
+
case "failed": return "error";
|
|
7554
|
+
default: return result.status;
|
|
7555
|
+
}
|
|
7556
|
+
}
|
|
7448
7557
|
|
|
7449
7558
|
//#endregion
|
|
7450
7559
|
//#region src/routes/responses/handler.ts
|
|
7451
7560
|
const RESPONSES_ENDPOINT = "/responses";
|
|
7561
|
+
const TERMINAL_EVENTS = new Set([
|
|
7562
|
+
"response.completed",
|
|
7563
|
+
"response.incomplete",
|
|
7564
|
+
"response.failed",
|
|
7565
|
+
"error"
|
|
7566
|
+
]);
|
|
7452
7567
|
const handleResponses = async (c) => {
|
|
7453
7568
|
const payload = await c.req.json();
|
|
7454
7569
|
consola.debug("Responses request payload:", JSON.stringify(payload));
|
|
7455
7570
|
const trackingId = c.get("trackingId");
|
|
7571
|
+
const startTime = (trackingId ? requestTracker.getRequest(trackingId) : void 0)?.startTime ?? Date.now();
|
|
7456
7572
|
updateTrackerModel(trackingId, payload.model);
|
|
7457
7573
|
useFunctionApplyPatch(payload);
|
|
7458
7574
|
removeWebSearchTool(payload);
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7575
|
+
const model = payload.model;
|
|
7576
|
+
const stream = payload.stream ?? false;
|
|
7577
|
+
const tools = convertResponsesToolsToDefinitions(payload.tools);
|
|
7578
|
+
const historyId = recordRequest("openai", {
|
|
7579
|
+
model,
|
|
7580
|
+
messages: convertResponsesInputToMessages(payload.input),
|
|
7581
|
+
stream,
|
|
7582
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
7583
|
+
max_tokens: payload.max_output_tokens ?? void 0,
|
|
7584
|
+
temperature: payload.temperature ?? void 0,
|
|
7585
|
+
system: payload.instructions ?? void 0
|
|
7586
|
+
});
|
|
7587
|
+
const ctx = {
|
|
7588
|
+
historyId,
|
|
7589
|
+
trackingId,
|
|
7590
|
+
startTime
|
|
7591
|
+
};
|
|
7592
|
+
if (!((state.models?.data.find((m) => m.id === payload.model))?.supported_endpoints?.includes(RESPONSES_ENDPOINT) ?? false)) {
|
|
7593
|
+
recordErrorResponse(ctx, model, /* @__PURE__ */ new Error("This model does not support the responses endpoint."));
|
|
7594
|
+
return c.json({ error: {
|
|
7595
|
+
message: "This model does not support the responses endpoint. Please choose a different model.",
|
|
7596
|
+
type: "invalid_request_error"
|
|
7597
|
+
} }, 400);
|
|
7598
|
+
}
|
|
7463
7599
|
const { vision, initiator } = getResponsesRequestOptions(payload);
|
|
7464
7600
|
if (state.manualApprove) await awaitApproval();
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7601
|
+
try {
|
|
7602
|
+
const { result: response, queueWaitMs } = await executeWithAdaptiveRateLimit(() => createResponses(payload, {
|
|
7603
|
+
vision,
|
|
7604
|
+
initiator
|
|
7605
|
+
}));
|
|
7606
|
+
ctx.queueWaitMs = queueWaitMs;
|
|
7607
|
+
if (isStreamingRequested(payload) && isAsyncIterable(response)) {
|
|
7608
|
+
consola.debug("Forwarding native Responses stream");
|
|
7609
|
+
updateTrackerStatus(trackingId, "streaming");
|
|
7610
|
+
return streamSSE(c, async (stream) => {
|
|
7611
|
+
const idTracker = createStreamIdTracker();
|
|
7612
|
+
let finalResult;
|
|
7613
|
+
let streamErrorMessage;
|
|
7614
|
+
try {
|
|
7615
|
+
for await (const chunk of response) {
|
|
7616
|
+
consola.debug("Responses stream chunk:", JSON.stringify(chunk));
|
|
7617
|
+
const eventType = chunk.event;
|
|
7618
|
+
const rawData = chunk.data ?? "";
|
|
7619
|
+
if (eventType && TERMINAL_EVENTS.has(eventType)) try {
|
|
7620
|
+
const parsed = JSON.parse(rawData);
|
|
7621
|
+
if ("response" in parsed) finalResult = parsed.response;
|
|
7622
|
+
else if (eventType === "error" && "message" in parsed) streamErrorMessage = parsed.message;
|
|
7623
|
+
} catch {}
|
|
7624
|
+
const processedData = fixStreamIds(rawData, eventType, idTracker);
|
|
7625
|
+
await stream.writeSSE({
|
|
7626
|
+
id: chunk.id,
|
|
7627
|
+
event: eventType,
|
|
7628
|
+
data: processedData
|
|
7629
|
+
});
|
|
7630
|
+
}
|
|
7631
|
+
if (finalResult) {
|
|
7632
|
+
recordResponseResult(finalResult, model, historyId, startTime);
|
|
7633
|
+
const usage = finalResult.usage;
|
|
7634
|
+
completeTracking(trackingId, usage?.input_tokens ?? 0, usage?.output_tokens ?? 0, queueWaitMs);
|
|
7635
|
+
} else if (streamErrorMessage) {
|
|
7636
|
+
recordResponse(historyId, {
|
|
7637
|
+
success: false,
|
|
7638
|
+
model,
|
|
7639
|
+
usage: {
|
|
7640
|
+
input_tokens: 0,
|
|
7641
|
+
output_tokens: 0
|
|
7642
|
+
},
|
|
7643
|
+
error: streamErrorMessage,
|
|
7644
|
+
content: null
|
|
7645
|
+
}, Date.now() - startTime);
|
|
7646
|
+
completeTracking(trackingId, 0, 0, queueWaitMs);
|
|
7647
|
+
} else completeTracking(trackingId, 0, 0, queueWaitMs);
|
|
7648
|
+
} catch (error) {
|
|
7649
|
+
recordStreamError({
|
|
7650
|
+
acc: { model: finalResult?.model || model },
|
|
7651
|
+
fallbackModel: model,
|
|
7652
|
+
ctx,
|
|
7653
|
+
error
|
|
7481
7654
|
});
|
|
7655
|
+
failTracking(trackingId, error);
|
|
7656
|
+
throw error;
|
|
7482
7657
|
}
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7658
|
+
});
|
|
7659
|
+
}
|
|
7660
|
+
const result = response;
|
|
7661
|
+
const usage = result.usage;
|
|
7662
|
+
recordResponseResult(result, model, historyId, startTime);
|
|
7663
|
+
completeTracking(trackingId, usage?.input_tokens ?? 0, usage?.output_tokens ?? 0, ctx.queueWaitMs);
|
|
7664
|
+
consola.debug("Forwarding native Responses result:", JSON.stringify(result).slice(-400));
|
|
7665
|
+
return c.json(result);
|
|
7666
|
+
} catch (error) {
|
|
7667
|
+
recordErrorResponse(ctx, model, error);
|
|
7668
|
+
failTracking(trackingId, error);
|
|
7669
|
+
throw error;
|
|
7489
7670
|
}
|
|
7490
|
-
consola.debug("Forwarding native Responses result:", JSON.stringify(response).slice(-400));
|
|
7491
|
-
return c.json(response);
|
|
7492
7671
|
};
|
|
7493
7672
|
const isAsyncIterable = (value) => Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
7494
7673
|
const isStreamingRequested = (payload) => Boolean(payload.stream);
|
|
@@ -7523,6 +7702,22 @@ const removeWebSearchTool = (payload) => {
|
|
|
7523
7702
|
return t.type !== "web_search";
|
|
7524
7703
|
});
|
|
7525
7704
|
};
|
|
7705
|
+
/** Record a ResponsesResult to history */
|
|
7706
|
+
function recordResponseResult(result, fallbackModel, historyId, startTime) {
|
|
7707
|
+
const usage = result.usage;
|
|
7708
|
+
const { content, toolCalls } = extractResponseData(result);
|
|
7709
|
+
recordResponse(historyId, {
|
|
7710
|
+
success: result.status !== "failed",
|
|
7711
|
+
model: result.model || fallbackModel,
|
|
7712
|
+
usage: {
|
|
7713
|
+
input_tokens: usage?.input_tokens ?? 0,
|
|
7714
|
+
output_tokens: usage?.output_tokens ?? 0
|
|
7715
|
+
},
|
|
7716
|
+
stop_reason: extractResponseStopReason(result),
|
|
7717
|
+
content,
|
|
7718
|
+
toolCalls
|
|
7719
|
+
}, Date.now() - startTime);
|
|
7720
|
+
}
|
|
7526
7721
|
|
|
7527
7722
|
//#endregion
|
|
7528
7723
|
//#region src/routes/responses/route.ts
|