@codehz/ai 0.4.3 → 0.4.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/index.d.mts +46 -23
- package/dist/index.mjs +66 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/responses.ts +165 -50
package/dist/index.d.mts
CHANGED
|
@@ -564,49 +564,72 @@ type ResponsesAPIRequest = {
|
|
|
564
564
|
};
|
|
565
565
|
metadata?: Record<string, string>;
|
|
566
566
|
temperature?: number;
|
|
567
|
-
max_output_tokens?: number;
|
|
567
|
+
max_output_tokens?: number; /** 服务端多轮续写;opaque replay 的 response id 映射到此字段,而非 item_reference */
|
|
568
|
+
previous_response_id?: string;
|
|
568
569
|
stream: true;
|
|
569
570
|
};
|
|
570
|
-
|
|
571
|
+
/** EasyInputMessage:content 可为 string,或 input_* content parts */
|
|
572
|
+
type ResponsesEasyMessage = {
|
|
571
573
|
type: "message";
|
|
572
|
-
role: "user" | "assistant";
|
|
573
|
-
content: string;
|
|
574
|
+
role: "user" | "assistant" | "system" | "developer";
|
|
575
|
+
content: string | ResponsesInputContentPart[];
|
|
576
|
+
};
|
|
577
|
+
type ResponsesInputContentPart = {
|
|
578
|
+
type: "input_text";
|
|
579
|
+
text: string;
|
|
574
580
|
} | {
|
|
575
|
-
type: "
|
|
576
|
-
|
|
577
|
-
|
|
581
|
+
type: "input_image";
|
|
582
|
+
image_url: string;
|
|
583
|
+
detail?: "auto" | "low" | "high";
|
|
578
584
|
} | {
|
|
585
|
+
type: "input_file";
|
|
586
|
+
file_url?: string;
|
|
587
|
+
file_id?: string;
|
|
588
|
+
filename?: string;
|
|
589
|
+
};
|
|
590
|
+
/** function_call:call_id 必填;id 是可选的 item id */
|
|
591
|
+
type ResponsesFunctionCall = {
|
|
579
592
|
type: "function_call";
|
|
580
|
-
|
|
593
|
+
call_id: string;
|
|
581
594
|
name: string;
|
|
582
595
|
arguments: string;
|
|
583
|
-
|
|
584
|
-
|
|
596
|
+
id?: string;
|
|
597
|
+
status?: "in_progress" | "completed" | "incomplete";
|
|
598
|
+
};
|
|
599
|
+
type ResponsesFunctionCallOutput = {
|
|
585
600
|
type: "function_call_output";
|
|
586
601
|
call_id: string;
|
|
587
602
|
output: string;
|
|
588
|
-
|
|
603
|
+
id?: string;
|
|
604
|
+
status?: "in_progress" | "completed" | "incomplete";
|
|
605
|
+
};
|
|
606
|
+
/** reasoning:id + summary/content/encrypted_content,不是任意 content blocks */
|
|
607
|
+
type ResponsesReasoningInput = {
|
|
589
608
|
type: "reasoning";
|
|
590
|
-
content: ResponsesContentBlock[];
|
|
591
|
-
} | {
|
|
592
|
-
type: "item_reference";
|
|
593
609
|
id: string;
|
|
610
|
+
summary: Array<{
|
|
611
|
+
type: "summary_text";
|
|
612
|
+
text: string;
|
|
613
|
+
}>;
|
|
614
|
+
content?: Array<{
|
|
615
|
+
type: "reasoning_text";
|
|
616
|
+
text: string;
|
|
617
|
+
}>;
|
|
618
|
+
encrypted_content?: string | null;
|
|
619
|
+
status?: "in_progress" | "completed" | "incomplete";
|
|
594
620
|
};
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
type: "reasoning";
|
|
600
|
-
text: string;
|
|
601
|
-
} | {
|
|
602
|
-
type: "refusal";
|
|
603
|
-
refusal: string;
|
|
621
|
+
/** 引用既有 item(不是 response id) */
|
|
622
|
+
type ResponsesItemReference = {
|
|
623
|
+
type: "item_reference";
|
|
624
|
+
id: string;
|
|
604
625
|
};
|
|
626
|
+
type ResponsesInputItem = ResponsesEasyMessage | ResponsesFunctionCall | ResponsesFunctionCallOutput | ResponsesReasoningInput | ResponsesItemReference;
|
|
605
627
|
type ResponsesTool = {
|
|
606
628
|
type: "function";
|
|
607
629
|
name: string;
|
|
608
630
|
description?: string;
|
|
609
631
|
parameters: Record<string, unknown>;
|
|
632
|
+
strict?: boolean | null;
|
|
610
633
|
};
|
|
611
634
|
declare class ResponsesAdapter extends AdapterBase {
|
|
612
635
|
readonly kind: "responses";
|
package/dist/index.mjs
CHANGED
|
@@ -1795,16 +1795,40 @@ function hasReplayCanonicalInput(input) {
|
|
|
1795
1795
|
function extractFailureMessage(response) {
|
|
1796
1796
|
return response.error?.message ?? response.failure?.message ?? "unknown";
|
|
1797
1797
|
}
|
|
1798
|
-
function
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1801
|
-
|
|
1798
|
+
function readNonEmptyString(value, maxLen = 256) {
|
|
1799
|
+
if (typeof value !== "string" || value.length === 0 || value.length > maxLen) return void 0;
|
|
1800
|
+
return value;
|
|
1801
|
+
}
|
|
1802
|
+
/** 将 canonical text/json blocks 压成 EasyInputMessage 的 string content。 */
|
|
1803
|
+
function messageContentAsString(blocks, field) {
|
|
1804
|
+
return mapper$3.textFromBlocks(blocks, field);
|
|
1805
|
+
}
|
|
1806
|
+
function mapReasoningInput(item, index) {
|
|
1807
|
+
const text = mapper$3.textFromBlocks(mapper$3.ensureReasoningBlocks(item.content, "reasoning content"), "reasoning content");
|
|
1808
|
+
const id = item.id && item.id.length > 0 ? item.id : `reasoning_replay_${index}`;
|
|
1809
|
+
if (item.visibility === "full") return {
|
|
1810
|
+
type: "reasoning",
|
|
1811
|
+
id,
|
|
1812
|
+
summary: [],
|
|
1813
|
+
content: text ? [{
|
|
1814
|
+
type: "reasoning_text",
|
|
1815
|
+
text
|
|
1816
|
+
}] : void 0
|
|
1802
1817
|
};
|
|
1803
|
-
|
|
1804
|
-
type: "
|
|
1805
|
-
|
|
1818
|
+
return {
|
|
1819
|
+
type: "reasoning",
|
|
1820
|
+
id,
|
|
1821
|
+
summary: text ? [{
|
|
1822
|
+
type: "summary_text",
|
|
1823
|
+
text
|
|
1824
|
+
}] : []
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
function extractOpaqueContinuationId(payload) {
|
|
1828
|
+
return {
|
|
1829
|
+
previousResponseId: readNonEmptyString(payload.previous_response_id) ?? (typeof payload.item_id === "string" ? void 0 : readNonEmptyString(payload.id)),
|
|
1830
|
+
itemReferenceId: readNonEmptyString(payload.item_id)
|
|
1806
1831
|
};
|
|
1807
|
-
throw new AIRequestError(`responses does not support content block type "${b.type}" in canonical mapping`, "UNSUPPORTED_CONTENT_BLOCK");
|
|
1808
1832
|
}
|
|
1809
1833
|
var ResponsesAdapter = class extends AdapterBase {
|
|
1810
1834
|
kind = "responses";
|
|
@@ -1820,36 +1844,23 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1820
1844
|
}
|
|
1821
1845
|
buildRequest(request) {
|
|
1822
1846
|
const input = [];
|
|
1847
|
+
let previousResponseId;
|
|
1848
|
+
let reasoningIndex = 0;
|
|
1823
1849
|
for (const item of request.input) switch (item.type) {
|
|
1824
1850
|
case "message":
|
|
1825
|
-
|
|
1826
|
-
const blocks = mapper$3.ensureTextBlocks(item.content, `assistant message (${item.role}) content`).map(canonicalToResponsesBlock);
|
|
1827
|
-
input.push({
|
|
1828
|
-
type: "message",
|
|
1829
|
-
role: item.role,
|
|
1830
|
-
content: blocks
|
|
1831
|
-
});
|
|
1832
|
-
} else input.push({
|
|
1851
|
+
input.push({
|
|
1833
1852
|
type: "message",
|
|
1834
1853
|
role: item.role,
|
|
1835
|
-
content:
|
|
1854
|
+
content: messageContentAsString(item.content, `input message (${item.role}) content`)
|
|
1836
1855
|
});
|
|
1837
1856
|
break;
|
|
1838
|
-
case "reasoning":
|
|
1839
|
-
|
|
1840
|
-
type: "reasoning",
|
|
1841
|
-
text: b.text
|
|
1842
|
-
}));
|
|
1843
|
-
input.push({
|
|
1844
|
-
type: "reasoning",
|
|
1845
|
-
content: blocks
|
|
1846
|
-
});
|
|
1857
|
+
case "reasoning":
|
|
1858
|
+
input.push(mapReasoningInput(item, reasoningIndex++));
|
|
1847
1859
|
break;
|
|
1848
|
-
}
|
|
1849
1860
|
case "tool_call":
|
|
1850
1861
|
input.push({
|
|
1851
1862
|
type: "function_call",
|
|
1852
|
-
|
|
1863
|
+
call_id: item.id,
|
|
1853
1864
|
name: item.name,
|
|
1854
1865
|
arguments: item.argumentsText
|
|
1855
1866
|
});
|
|
@@ -1867,11 +1878,17 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1867
1878
|
if (item.source !== "responses" || item.purpose !== "replay") break;
|
|
1868
1879
|
assertOpaqueReplayEnvelope(item.payload);
|
|
1869
1880
|
const payload = item.payload;
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1881
|
+
for (const key of [
|
|
1882
|
+
"id",
|
|
1883
|
+
"previous_response_id",
|
|
1884
|
+
"item_id"
|
|
1885
|
+
]) if (key in payload && (typeof payload[key] !== "string" || payload[key].length === 0 || payload[key].length > 256)) throw new AIRequestError(`Invalid opaque replay payload: ${key} must be a non-empty string (max 256)`, "INVALID_OPAQUE_REPLAY");
|
|
1886
|
+
const { previousResponseId: prevId, itemReferenceId } = extractOpaqueContinuationId(payload);
|
|
1887
|
+
if (!hasReplayCanonicalInput(input)) {
|
|
1888
|
+
if (prevId && !previousResponseId) previousResponseId = prevId;
|
|
1889
|
+
else if (itemReferenceId) input.push({
|
|
1873
1890
|
type: "item_reference",
|
|
1874
|
-
id:
|
|
1891
|
+
id: itemReferenceId
|
|
1875
1892
|
});
|
|
1876
1893
|
}
|
|
1877
1894
|
break;
|
|
@@ -1882,6 +1899,7 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1882
1899
|
input,
|
|
1883
1900
|
stream: true
|
|
1884
1901
|
};
|
|
1902
|
+
if (previousResponseId) body.previous_response_id = previousResponseId;
|
|
1885
1903
|
if (request.instructions) body.instructions = mapper$3.mapInstructions(request.instructions);
|
|
1886
1904
|
body.tools = mapper$3.mapToolsIfPresent(request.tools, (t) => ({
|
|
1887
1905
|
type: "function",
|
|
@@ -1920,8 +1938,12 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1920
1938
|
let completedResponse;
|
|
1921
1939
|
let unknownEventsWarned = false;
|
|
1922
1940
|
const messageItemsWithDelta = /* @__PURE__ */ new Set();
|
|
1941
|
+
/** item_id → function name */
|
|
1923
1942
|
const toolCallNames = /* @__PURE__ */ new Map();
|
|
1943
|
+
/** item_id → call_id(canonical ToolCallItem.id / function_call_output.call_id) */
|
|
1944
|
+
const toolCallIds = /* @__PURE__ */ new Map();
|
|
1924
1945
|
const reasoningStates = /* @__PURE__ */ new Map();
|
|
1946
|
+
const resolveToolCallId = (itemId) => toolCallIds.get(itemId) ?? itemId;
|
|
1925
1947
|
const ensureReasoningState = (itemId, visibility = "summary") => {
|
|
1926
1948
|
let state = reasoningStates.get(itemId);
|
|
1927
1949
|
if (!state) {
|
|
@@ -1967,8 +1989,10 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1967
1989
|
}
|
|
1968
1990
|
case "function_call": {
|
|
1969
1991
|
const name = typeof item.name === "string" ? item.name : "unknown";
|
|
1992
|
+
const callId = typeof item.call_id === "string" && item.call_id.length > 0 ? item.call_id : item.id;
|
|
1970
1993
|
toolCallNames.set(item.id, name);
|
|
1971
|
-
|
|
1994
|
+
toolCallIds.set(item.id, callId);
|
|
1995
|
+
yield factory.toolCallStarted(callId, name);
|
|
1972
1996
|
break;
|
|
1973
1997
|
}
|
|
1974
1998
|
}
|
|
@@ -2057,13 +2081,15 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
2057
2081
|
}
|
|
2058
2082
|
if (sseEvent.type === "response.function_call_arguments.delta") {
|
|
2059
2083
|
const data = sseEvent.data;
|
|
2060
|
-
if (data.delta) yield factory.toolCallDelta(data.item_id, { argumentsText: data.delta });
|
|
2084
|
+
if (data.delta) yield factory.toolCallDelta(resolveToolCallId(data.item_id), { argumentsText: data.delta });
|
|
2061
2085
|
continue;
|
|
2062
2086
|
}
|
|
2063
2087
|
if (sseEvent.type === "response.function_call_arguments.done") {
|
|
2064
2088
|
const data = sseEvent.data;
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2089
|
+
const callId = resolveToolCallId(data.item_id);
|
|
2090
|
+
if (!toolCallIds.has(data.item_id)) toolCallIds.set(data.item_id, callId);
|
|
2091
|
+
const tcItem = toolCallItem(callId, toolCallNames.get(data.item_id) ?? "unknown", data.arguments);
|
|
2092
|
+
yield factory.toolCallCompleted(callId);
|
|
2067
2093
|
output.push(tcItem);
|
|
2068
2094
|
continue;
|
|
2069
2095
|
}
|
|
@@ -2097,7 +2123,10 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
2097
2123
|
if (completedResponse.usage) auxiliary.recordUsage(usageFromOpenAIResponses(completedResponse.usage), "final", completedResponse.usage);
|
|
2098
2124
|
}
|
|
2099
2125
|
const replay = [...replayFromOutput(output)];
|
|
2100
|
-
if (completedResponse?.id) replay.push(opaqueItem("responses", "replay", {
|
|
2126
|
+
if (completedResponse?.id) replay.push(opaqueItem("responses", "replay", {
|
|
2127
|
+
id: completedResponse.id,
|
|
2128
|
+
previous_response_id: completedResponse.id
|
|
2129
|
+
}));
|
|
2101
2130
|
const stopReason = completedResponse ? this.inferStopReason(completedResponse) : void 0;
|
|
2102
2131
|
if (gate.tryComplete()) yield* this.emitStreamCompleted(factory, request, auxiliary, {
|
|
2103
2132
|
output,
|