@jeffreycao/copilot-api 1.6.2 → 1.6.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.js CHANGED
@@ -23,7 +23,7 @@ if (typeof args["enterprise-url"] === "string") process.env.COPILOT_API_ENTERPRI
23
23
  const { auth } = await import("./auth-I-jV5RwF.js");
24
24
  const { checkUsage } = await import("./check-usage-DYLFqYhN.js");
25
25
  const { debug } = await import("./debug-DcC7ZPH0.js");
26
- const { start } = await import("./start-CcPjJUMF.js");
26
+ const { start } = await import("./start-6DUmwwg0.js");
27
27
  const main = defineCommand({
28
28
  meta: {
29
29
  name: "copilot-api",
@@ -756,6 +756,9 @@ function mapContent(content) {
756
756
  image_url: { url: `data:${block.source.media_type};base64,${block.source.data}` }
757
757
  });
758
758
  break;
759
+ case "document":
760
+ contentParts.push(createDocumentTextPart());
761
+ break;
759
762
  case "tool_reference":
760
763
  contentParts.push({
761
764
  type: "text",
@@ -765,6 +768,12 @@ function mapContent(content) {
765
768
  }
766
769
  return contentParts;
767
770
  }
771
+ function createDocumentTextPart() {
772
+ return {
773
+ type: "text",
774
+ text: "A PDF document was attached, but this api cannot send PDF inputs directly. Analyze using other tools."
775
+ };
776
+ }
768
777
  function translateAnthropicToolsToOpenAI(anthropicTools) {
769
778
  if (!anthropicTools) return;
770
779
  return anthropicTools.map((tool) => ({
@@ -1026,7 +1035,7 @@ const translateUserMessage = (message) => {
1026
1035
  continue;
1027
1036
  }
1028
1037
  const converted = translateUserContentBlock(block);
1029
- if (converted) pendingContent.push(converted);
1038
+ if (converted.length > 0) pendingContent.push(...converted);
1030
1039
  }
1031
1040
  flushPendingContent(pendingContent, items, { role: "user" });
1032
1041
  return items;
@@ -1076,9 +1085,10 @@ const translateAssistantMessage = (message, model, applyPhase) => {
1076
1085
  };
1077
1086
  const translateUserContentBlock = (block) => {
1078
1087
  switch (block.type) {
1079
- case "text": return createTextContent(block.text);
1080
- case "image": return createImageContent(block);
1081
- default: return;
1088
+ case "text": return [createTextContent(block.text)];
1089
+ case "image": return [createImageContent(block)];
1090
+ case "document": return [createFileContent(block)];
1091
+ default: return [];
1082
1092
  }
1083
1093
  };
1084
1094
  const translateAssistantContentBlock = (block) => {
@@ -1122,6 +1132,11 @@ const createImageContent = (block) => ({
1122
1132
  image_url: `data:${block.source.media_type};base64,${block.source.data}`,
1123
1133
  detail: "auto"
1124
1134
  });
1135
+ const createFileContent = (block) => ({
1136
+ type: "input_file",
1137
+ file_data: `data:${block.source.media_type};base64,${block.source.data}`,
1138
+ filename: block.title ?? "document.pdf"
1139
+ });
1125
1140
  const createReasoningContent = (block) => {
1126
1141
  const { encryptedContent, id } = parseReasoningSignature(block.signature);
1127
1142
  const thinking = block.thinking === THINKING_TEXT$1 ? "" : block.thinking;
@@ -1373,6 +1388,9 @@ const convertToolResultContent = (content) => {
1373
1388
  case "image":
1374
1389
  result.push(createImageContent(block));
1375
1390
  break;
1391
+ case "document":
1392
+ result.push(createFileContent(block));
1393
+ break;
1376
1394
  case "tool_reference":
1377
1395
  result.push(createTextContent(`Tool ${block.tool_name} loaded`));
1378
1396
  break;
@@ -1940,6 +1958,7 @@ const TOOL_REFERENCE_TURN_BOUNDARY = "Tool loaded.";
1940
1958
  const IDE_EXECUTE_CODE_TOOL = "mcp__ide__executeCode";
1941
1959
  const IDE_GET_DIAGNOSTICS_TOOL = "mcp__ide__getDiagnostics";
1942
1960
  const IDE_GET_DIAGNOSTICS_DESCRIPTION = "Get language diagnostics from VS Code. Returns errors, warnings, information, and hints for files in the workspace.";
1961
+ const PDF_FILE_READ_PREFIX = "PDF file read:";
1943
1962
  const getCompactCandidateText = (message) => {
1944
1963
  if (message.role !== "user") return "";
1945
1964
  if (typeof message.content === "string") return message.content;
@@ -1989,6 +2008,126 @@ const mergeContentWithTexts = (tr, textBlocks) => {
1989
2008
  content: [...tr.content, ...textBlocks]
1990
2009
  };
1991
2010
  };
2011
+ const mergeContentWithAttachments = (tr, attachments) => {
2012
+ if (typeof tr.content === "string") return {
2013
+ ...tr,
2014
+ content: [{
2015
+ type: "text",
2016
+ text: tr.content
2017
+ }, ...attachments]
2018
+ };
2019
+ return {
2020
+ ...tr,
2021
+ content: [...tr.content, ...attachments]
2022
+ };
2023
+ };
2024
+ const isAttachmentBlock = (block) => {
2025
+ return block.type === "image" || block.type === "document";
2026
+ };
2027
+ const getMergeableToolResultIndices = (toolResults) => {
2028
+ return toolResults.flatMap((block, index) => hasToolRef(block) ? [] : [index]);
2029
+ };
2030
+ const mergeAttachmentsIntoToolResults = (toolResults, attachmentsByToolResultIndex) => {
2031
+ if (attachmentsByToolResultIndex.size === 0) return toolResults;
2032
+ return toolResults.map((block, index) => {
2033
+ const matchedAttachments = attachmentsByToolResultIndex.get(index);
2034
+ if (!matchedAttachments) return block;
2035
+ const orderedAttachments = [...matchedAttachments].sort((left, right) => left.order - right.order).map(({ attachment }) => attachment);
2036
+ return mergeContentWithAttachments(block, orderedAttachments);
2037
+ });
2038
+ };
2039
+ const assignAttachmentsToToolResults = (target, attachments, options) => {
2040
+ const { toolResultIndices } = options;
2041
+ const fallbackToolResultIndices = options.fallbackToolResultIndices ?? toolResultIndices;
2042
+ if (attachments.length === 0) return;
2043
+ if (toolResultIndices.length > 0 && toolResultIndices.length === attachments.length) {
2044
+ for (const [index, toolResultIndex] of toolResultIndices.entries()) {
2045
+ const currentAttachments$1 = target.get(toolResultIndex);
2046
+ if (currentAttachments$1) {
2047
+ currentAttachments$1.push(attachments[index]);
2048
+ continue;
2049
+ }
2050
+ target.set(toolResultIndex, [attachments[index]]);
2051
+ }
2052
+ return;
2053
+ }
2054
+ const lastToolResultIndex = fallbackToolResultIndices.at(-1);
2055
+ if (lastToolResultIndex === void 0) return;
2056
+ const currentAttachments = target.get(lastToolResultIndex);
2057
+ if (currentAttachments) {
2058
+ currentAttachments.push(...attachments);
2059
+ return;
2060
+ }
2061
+ target.set(lastToolResultIndex, [...attachments]);
2062
+ };
2063
+ const startsWithPdfFileRead = (toolResult) => {
2064
+ if (typeof toolResult.content === "string") return toolResult.content.startsWith(PDF_FILE_READ_PREFIX);
2065
+ if (toolResult.content.some((block) => block.type === "document")) return false;
2066
+ if (toolResult.content.length === 0) return false;
2067
+ const firstBlock = toolResult.content[0];
2068
+ if (firstBlock.type !== "text") return false;
2069
+ return firstBlock.text.startsWith(PDF_FILE_READ_PREFIX);
2070
+ };
2071
+ const collectMergeableUserContent = (content) => {
2072
+ const toolResults = [];
2073
+ const textBlocks = [];
2074
+ const attachments = [];
2075
+ for (const [order, block] of content.entries()) {
2076
+ if (block.type === "tool_result") {
2077
+ toolResults.push(block);
2078
+ continue;
2079
+ }
2080
+ if (block.type === "text") {
2081
+ textBlocks.push(block);
2082
+ continue;
2083
+ }
2084
+ if (isAttachmentBlock(block)) {
2085
+ attachments.push({
2086
+ attachment: block,
2087
+ order
2088
+ });
2089
+ continue;
2090
+ }
2091
+ return null;
2092
+ }
2093
+ return {
2094
+ toolResults,
2095
+ textBlocks,
2096
+ attachments
2097
+ };
2098
+ };
2099
+ const mergeAttachmentsForToolResults = (toolResults, attachments) => {
2100
+ if (attachments.length === 0) return toolResults;
2101
+ const documentBlocks = attachments.filter(({ attachment }) => attachment.type === "document");
2102
+ const mergeableToolResultIndices = getMergeableToolResultIndices(toolResults);
2103
+ const pdfReadToolResultIndices = mergeableToolResultIndices.filter((index) => startsWithPdfFileRead(toolResults[index]));
2104
+ const attachmentsByToolResultIndex = /* @__PURE__ */ new Map();
2105
+ let remainingAttachments = attachments;
2106
+ let countMatchToolResultIndices = mergeableToolResultIndices;
2107
+ if (documentBlocks.length > 0 && pdfReadToolResultIndices.length > 0) {
2108
+ const matchedDocumentCount = Math.min(pdfReadToolResultIndices.length, documentBlocks.length);
2109
+ const matchedDocuments = documentBlocks.slice(0, matchedDocumentCount);
2110
+ const matchedDocumentOrders = new Set(matchedDocuments.map(({ order }) => order));
2111
+ const matchedPdfToolResultIndices = pdfReadToolResultIndices.slice(0, matchedDocumentCount);
2112
+ const matchedPdfToolResultIndexSet = new Set(matchedPdfToolResultIndices);
2113
+ assignAttachmentsToToolResults(attachmentsByToolResultIndex, matchedDocuments, { toolResultIndices: matchedPdfToolResultIndices });
2114
+ countMatchToolResultIndices = mergeableToolResultIndices.filter((index) => !matchedPdfToolResultIndexSet.has(index));
2115
+ remainingAttachments = attachments.filter(({ attachment, order }) => attachment.type !== "document" || !matchedDocumentOrders.has(order));
2116
+ }
2117
+ assignAttachmentsToToolResults(attachmentsByToolResultIndex, remainingAttachments, {
2118
+ toolResultIndices: countMatchToolResultIndices,
2119
+ fallbackToolResultIndices: mergeableToolResultIndices
2120
+ });
2121
+ return mergeAttachmentsIntoToolResults(toolResults, attachmentsByToolResultIndex);
2122
+ };
2123
+ const mergeUserMessageContent = (content) => {
2124
+ const mergeableContent = collectMergeableUserContent(content);
2125
+ if (!mergeableContent) return null;
2126
+ const { toolResults, textBlocks, attachments } = mergeableContent;
2127
+ if (toolResults.length === 0 || textBlocks.length === 0 && attachments.length === 0) return null;
2128
+ const mergedToolResults = textBlocks.length === 0 ? toolResults : mergeToolResult(toolResults, textBlocks);
2129
+ return mergeAttachmentsForToolResults(mergedToolResults, attachments);
2130
+ };
1992
2131
  const mergeToolResult = (toolResults, textBlocks) => {
1993
2132
  if (toolResults.length === textBlocks.length) return toolResults.map((tr, i) => mergeContentWithText(tr, textBlocks[i]));
1994
2133
  const lastIndex = toolResults.length - 1;
@@ -2006,23 +2145,14 @@ const mergeToolResultForClaude = (anthropicPayload, options) => {
2006
2145
  for (const [index, msg] of anthropicPayload.messages.entries()) {
2007
2146
  if (options?.skipLastMessage && index === lastMessageIndex) continue;
2008
2147
  if (msg.role !== "user" || !Array.isArray(msg.content)) continue;
2009
- const toolResults = [];
2010
- const textBlocks = [];
2011
- let valid = true;
2012
- for (const block of msg.content) if (block.type === "tool_result") toolResults.push(block);
2013
- else if (block.type === "text") textBlocks.push(block);
2014
- else {
2015
- valid = false;
2016
- break;
2017
- }
2018
- if (!valid || toolResults.length === 0 || textBlocks.length === 0) continue;
2019
- msg.content = mergeToolResult(toolResults, textBlocks);
2148
+ const mergedContent = mergeUserMessageContent(msg.content);
2149
+ if (mergedContent) msg.content = mergedContent;
2020
2150
  }
2021
2151
  };
2022
2152
  const sanitizeIdeTools = (payload) => {
2023
2153
  if (!payload.tools || payload.tools.length === 0) return;
2024
2154
  payload.tools = payload.tools.flatMap((tool) => {
2025
- if (tool.name === IDE_EXECUTE_CODE_TOOL) return [];
2155
+ if (tool.name === IDE_EXECUTE_CODE_TOOL && !tool.defer_loading) return [];
2026
2156
  if (tool.name === IDE_GET_DIAGNOSTICS_TOOL) return [{
2027
2157
  ...tool,
2028
2158
  description: IDE_GET_DIAGNOSTICS_DESCRIPTION
@@ -3035,4 +3165,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
3035
3165
 
3036
3166
  //#endregion
3037
3167
  export { server };
3038
- //# sourceMappingURL=server-ABtVTO7w.js.map
3168
+ //# sourceMappingURL=server-DS5Brc8C.js.map