@codehz/ai 0.4.3 → 0.4.5
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/.github/workflows/publish.yml +56 -0
- package/README.md +32 -4
- package/dist/index.d.mts +133 -32
- package/dist/index.mjs +209 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -1
- package/src/adapters/chat-completions.ts +24 -5
- package/src/adapters/messages.ts +24 -7
- package/src/adapters/mock.ts +7 -3
- package/src/adapters/ollama.ts +19 -2
- package/src/adapters/responses.ts +189 -55
- package/src/core/validation.ts +13 -0
- package/src/helpers/index.ts +14 -0
- package/src/helpers/provider-request-options.ts +25 -0
- package/src/helpers/reasoning-level.ts +85 -0
- package/src/types/index.ts +1 -1
- package/src/types/request.ts +11 -0
package/dist/index.mjs
CHANGED
|
@@ -80,6 +80,14 @@ const TOOL_RESULT_OUTCOMES = /* @__PURE__ */ new Set([
|
|
|
80
80
|
"rejected"
|
|
81
81
|
]);
|
|
82
82
|
const INCLUDE_MODES = /* @__PURE__ */ new Set(["off", "best_effort"]);
|
|
83
|
+
const REASONING_LEVELS$1 = /* @__PURE__ */ new Set([
|
|
84
|
+
"none",
|
|
85
|
+
"minimal",
|
|
86
|
+
"low",
|
|
87
|
+
"medium",
|
|
88
|
+
"high",
|
|
89
|
+
"xhigh"
|
|
90
|
+
]);
|
|
83
91
|
function isRecord(value) {
|
|
84
92
|
return typeof value === "object" && value !== null;
|
|
85
93
|
}
|
|
@@ -248,6 +256,9 @@ function validateRequest(request) {
|
|
|
248
256
|
message: "maxOutputTokens must be a positive integer"
|
|
249
257
|
});
|
|
250
258
|
}
|
|
259
|
+
if (request.reasoningLevel !== void 0) {
|
|
260
|
+
if (typeof request.reasoningLevel !== "string" || !REASONING_LEVELS$1.has(request.reasoningLevel)) pushIssue(issues, "reasoningLevel", "REASONING_LEVEL_INVALID", "reasoningLevel must be one of: none, minimal, low, medium, high, xhigh");
|
|
261
|
+
}
|
|
251
262
|
if (request.include !== void 0) validateInclude(request.include, issues);
|
|
252
263
|
if (request.metadata !== void 0) {
|
|
253
264
|
if (!isRecord(request.metadata)) pushIssue(issues, "metadata", "METADATA_INVALID", "metadata must be an object");
|
|
@@ -1660,6 +1671,102 @@ function createCompletionGate() {
|
|
|
1660
1671
|
};
|
|
1661
1672
|
}
|
|
1662
1673
|
//#endregion
|
|
1674
|
+
//#region src/helpers/provider-request-options.ts
|
|
1675
|
+
/**
|
|
1676
|
+
* Provider 请求 headers / body 扩展合并
|
|
1677
|
+
*
|
|
1678
|
+
* 供真实后端 adapter 构造选项 `headers` / `extraBody` 使用:
|
|
1679
|
+
* - headers:内置鉴权头为基,自定义后写覆盖
|
|
1680
|
+
* - extraBody:已构建 body 为基,额外字段浅层 spread,同名顶层键可覆盖
|
|
1681
|
+
*/
|
|
1682
|
+
/** 合并内置 headers 与自定义 headers;自定义后写覆盖同名键。 */
|
|
1683
|
+
function mergeProviderHeaders(base, custom) {
|
|
1684
|
+
if (!custom) return base;
|
|
1685
|
+
return {
|
|
1686
|
+
...base,
|
|
1687
|
+
...custom
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* 将构造期 extraBody 浅层合并到已构建的 provider body。
|
|
1692
|
+
* 无 extraBody 时原样返回;有则允许覆盖同名顶层键。
|
|
1693
|
+
*/
|
|
1694
|
+
function applyExtraBody(body, extraBody) {
|
|
1695
|
+
if (!extraBody) return body;
|
|
1696
|
+
return {
|
|
1697
|
+
...body,
|
|
1698
|
+
...extraBody
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
//#endregion
|
|
1702
|
+
//#region src/helpers/reasoning-level.ts
|
|
1703
|
+
/**
|
|
1704
|
+
* Portable reasoningLevel → provider wire 字段映射
|
|
1705
|
+
*
|
|
1706
|
+
* 第一版只处理 level 枚举;budget/summary 等特化字段不在此层。
|
|
1707
|
+
* 无法映射的 level 抛 AIRequestError(UNSUPPORTED_REASONING_LEVEL)。
|
|
1708
|
+
*/
|
|
1709
|
+
const REASONING_LEVELS = [
|
|
1710
|
+
"none",
|
|
1711
|
+
"minimal",
|
|
1712
|
+
"low",
|
|
1713
|
+
"medium",
|
|
1714
|
+
"high",
|
|
1715
|
+
"xhigh"
|
|
1716
|
+
];
|
|
1717
|
+
const REASONING_LEVEL_SET = new Set(REASONING_LEVELS);
|
|
1718
|
+
const MESSAGES_BUDGET_RATIOS = {
|
|
1719
|
+
minimal: .02,
|
|
1720
|
+
low: .1,
|
|
1721
|
+
medium: .3,
|
|
1722
|
+
high: .6,
|
|
1723
|
+
xhigh: .9
|
|
1724
|
+
};
|
|
1725
|
+
const OLLAMA_SUPPORTED = /* @__PURE__ */ new Set([
|
|
1726
|
+
"none",
|
|
1727
|
+
"low",
|
|
1728
|
+
"medium",
|
|
1729
|
+
"high"
|
|
1730
|
+
]);
|
|
1731
|
+
/** 若 level 不在 supported 集合内则抛 AIRequestError。 */
|
|
1732
|
+
function assertSupportedReasoningLevel(level, supported, adapterKind) {
|
|
1733
|
+
if (supported.has(level)) return;
|
|
1734
|
+
throw new AIRequestError(`reasoningLevel "${level}" is not supported by the ${adapterKind} adapter`, "UNSUPPORTED_REASONING_LEVEL");
|
|
1735
|
+
}
|
|
1736
|
+
/** Responses API:`reasoning: { effort }` */
|
|
1737
|
+
function mapResponsesReasoning(level) {
|
|
1738
|
+
return { effort: level };
|
|
1739
|
+
}
|
|
1740
|
+
/** Chat Completions:顶层 `reasoning_effort` */
|
|
1741
|
+
function mapChatCompletionsReasoningEffort(level) {
|
|
1742
|
+
return level;
|
|
1743
|
+
}
|
|
1744
|
+
/**
|
|
1745
|
+
* Messages thinking budget。
|
|
1746
|
+
* 基于 maxTokens 按比例推导,clamp 到 [1024, max(1024, maxTokens - 1)],
|
|
1747
|
+
* 满足 Anthropic budget_tokens < max_tokens。
|
|
1748
|
+
*/
|
|
1749
|
+
function mapMessagesThinkingBudget(level, maxTokens) {
|
|
1750
|
+
const ratio = MESSAGES_BUDGET_RATIOS[level];
|
|
1751
|
+
const raw = Math.round(maxTokens * ratio);
|
|
1752
|
+
const upper = Math.max(1024, maxTokens - 1);
|
|
1753
|
+
return Math.min(Math.max(raw, 1024), upper);
|
|
1754
|
+
}
|
|
1755
|
+
/** Messages API:`thinking` 字段 */
|
|
1756
|
+
function mapMessagesThinking(level, maxTokens) {
|
|
1757
|
+
if (level === "none") return { type: "disabled" };
|
|
1758
|
+
return {
|
|
1759
|
+
type: "enabled",
|
|
1760
|
+
budget_tokens: mapMessagesThinkingBudget(level, maxTokens)
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
/** Ollama:`think` 字段;minimal/xhigh 不支持 */
|
|
1764
|
+
function mapOllamaThink(level) {
|
|
1765
|
+
assertSupportedReasoningLevel(level, OLLAMA_SUPPORTED, "ollama");
|
|
1766
|
+
if (level === "none") return false;
|
|
1767
|
+
return level;
|
|
1768
|
+
}
|
|
1769
|
+
//#endregion
|
|
1663
1770
|
//#region src/helpers/request-mapper.ts
|
|
1664
1771
|
var NormalizedRequestMapper = class {
|
|
1665
1772
|
kind;
|
|
@@ -1795,16 +1902,40 @@ function hasReplayCanonicalInput(input) {
|
|
|
1795
1902
|
function extractFailureMessage(response) {
|
|
1796
1903
|
return response.error?.message ?? response.failure?.message ?? "unknown";
|
|
1797
1904
|
}
|
|
1798
|
-
function
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1801
|
-
|
|
1905
|
+
function readNonEmptyString(value, maxLen = 256) {
|
|
1906
|
+
if (typeof value !== "string" || value.length === 0 || value.length > maxLen) return void 0;
|
|
1907
|
+
return value;
|
|
1908
|
+
}
|
|
1909
|
+
/** 将 canonical text/json blocks 压成 EasyInputMessage 的 string content。 */
|
|
1910
|
+
function messageContentAsString(blocks, field) {
|
|
1911
|
+
return mapper$3.textFromBlocks(blocks, field);
|
|
1912
|
+
}
|
|
1913
|
+
function mapReasoningInput(item, index) {
|
|
1914
|
+
const text = mapper$3.textFromBlocks(mapper$3.ensureReasoningBlocks(item.content, "reasoning content"), "reasoning content");
|
|
1915
|
+
const id = item.id && item.id.length > 0 ? item.id : `reasoning_replay_${index}`;
|
|
1916
|
+
if (item.visibility === "full") return {
|
|
1917
|
+
type: "reasoning",
|
|
1918
|
+
id,
|
|
1919
|
+
summary: [],
|
|
1920
|
+
content: text ? [{
|
|
1921
|
+
type: "reasoning_text",
|
|
1922
|
+
text
|
|
1923
|
+
}] : void 0
|
|
1802
1924
|
};
|
|
1803
|
-
|
|
1804
|
-
type: "
|
|
1805
|
-
|
|
1925
|
+
return {
|
|
1926
|
+
type: "reasoning",
|
|
1927
|
+
id,
|
|
1928
|
+
summary: text ? [{
|
|
1929
|
+
type: "summary_text",
|
|
1930
|
+
text
|
|
1931
|
+
}] : []
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
function extractOpaqueContinuationId(payload) {
|
|
1935
|
+
return {
|
|
1936
|
+
previousResponseId: readNonEmptyString(payload.previous_response_id) ?? (typeof payload.item_id === "string" ? void 0 : readNonEmptyString(payload.id)),
|
|
1937
|
+
itemReferenceId: readNonEmptyString(payload.item_id)
|
|
1806
1938
|
};
|
|
1807
|
-
throw new AIRequestError(`responses does not support content block type "${b.type}" in canonical mapping`, "UNSUPPORTED_CONTENT_BLOCK");
|
|
1808
1939
|
}
|
|
1809
1940
|
var ResponsesAdapter = class extends AdapterBase {
|
|
1810
1941
|
kind = "responses";
|
|
@@ -1812,44 +1943,35 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1812
1943
|
apiKey;
|
|
1813
1944
|
baseUrl;
|
|
1814
1945
|
fetchFn;
|
|
1946
|
+
headers;
|
|
1947
|
+
extraBody;
|
|
1815
1948
|
constructor(options) {
|
|
1816
1949
|
super();
|
|
1817
1950
|
this.apiKey = options.apiKey;
|
|
1818
1951
|
this.baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
|
|
1819
1952
|
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
1953
|
+
this.headers = options.headers;
|
|
1954
|
+
this.extraBody = options.extraBody;
|
|
1820
1955
|
}
|
|
1821
1956
|
buildRequest(request) {
|
|
1822
1957
|
const input = [];
|
|
1958
|
+
let previousResponseId;
|
|
1959
|
+
let reasoningIndex = 0;
|
|
1823
1960
|
for (const item of request.input) switch (item.type) {
|
|
1824
1961
|
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({
|
|
1962
|
+
input.push({
|
|
1833
1963
|
type: "message",
|
|
1834
1964
|
role: item.role,
|
|
1835
|
-
content:
|
|
1965
|
+
content: messageContentAsString(item.content, `input message (${item.role}) content`)
|
|
1836
1966
|
});
|
|
1837
1967
|
break;
|
|
1838
|
-
case "reasoning":
|
|
1839
|
-
|
|
1840
|
-
type: "reasoning",
|
|
1841
|
-
text: b.text
|
|
1842
|
-
}));
|
|
1843
|
-
input.push({
|
|
1844
|
-
type: "reasoning",
|
|
1845
|
-
content: blocks
|
|
1846
|
-
});
|
|
1968
|
+
case "reasoning":
|
|
1969
|
+
input.push(mapReasoningInput(item, reasoningIndex++));
|
|
1847
1970
|
break;
|
|
1848
|
-
}
|
|
1849
1971
|
case "tool_call":
|
|
1850
1972
|
input.push({
|
|
1851
1973
|
type: "function_call",
|
|
1852
|
-
|
|
1974
|
+
call_id: item.id,
|
|
1853
1975
|
name: item.name,
|
|
1854
1976
|
arguments: item.argumentsText
|
|
1855
1977
|
});
|
|
@@ -1867,11 +1989,17 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1867
1989
|
if (item.source !== "responses" || item.purpose !== "replay") break;
|
|
1868
1990
|
assertOpaqueReplayEnvelope(item.payload);
|
|
1869
1991
|
const payload = item.payload;
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1992
|
+
for (const key of [
|
|
1993
|
+
"id",
|
|
1994
|
+
"previous_response_id",
|
|
1995
|
+
"item_id"
|
|
1996
|
+
]) 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");
|
|
1997
|
+
const { previousResponseId: prevId, itemReferenceId } = extractOpaqueContinuationId(payload);
|
|
1998
|
+
if (!hasReplayCanonicalInput(input)) {
|
|
1999
|
+
if (prevId && !previousResponseId) previousResponseId = prevId;
|
|
2000
|
+
else if (itemReferenceId) input.push({
|
|
1873
2001
|
type: "item_reference",
|
|
1874
|
-
id:
|
|
2002
|
+
id: itemReferenceId
|
|
1875
2003
|
});
|
|
1876
2004
|
}
|
|
1877
2005
|
break;
|
|
@@ -1882,6 +2010,7 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1882
2010
|
input,
|
|
1883
2011
|
stream: true
|
|
1884
2012
|
};
|
|
2013
|
+
if (previousResponseId) body.previous_response_id = previousResponseId;
|
|
1885
2014
|
if (request.instructions) body.instructions = mapper$3.mapInstructions(request.instructions);
|
|
1886
2015
|
body.tools = mapper$3.mapToolsIfPresent(request.tools, (t) => ({
|
|
1887
2016
|
type: "function",
|
|
@@ -1900,7 +2029,8 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1900
2029
|
if (request.temperature !== void 0) body.temperature = request.temperature;
|
|
1901
2030
|
if (request.maxOutputTokens !== void 0) body.max_output_tokens = request.maxOutputTokens;
|
|
1902
2031
|
if (request.metadata) body.metadata = request.metadata;
|
|
1903
|
-
|
|
2032
|
+
if (request.reasoningLevel !== void 0) body.reasoning = mapResponsesReasoning(request.reasoningLevel);
|
|
2033
|
+
return applyExtraBody(body, this.extraBody);
|
|
1904
2034
|
}
|
|
1905
2035
|
async *runStream(providerRequest, factory, request) {
|
|
1906
2036
|
const auxiliary = this.createAuxiliaryState(request);
|
|
@@ -1908,10 +2038,10 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1908
2038
|
const { reader } = await openProviderJsonStream({
|
|
1909
2039
|
fetchFn: this.fetchFn,
|
|
1910
2040
|
url: `${this.baseUrl}/responses`,
|
|
1911
|
-
headers: {
|
|
2041
|
+
headers: mergeProviderHeaders({
|
|
1912
2042
|
"Content-Type": "application/json",
|
|
1913
2043
|
Authorization: `Bearer ${this.apiKey}`
|
|
1914
|
-
},
|
|
2044
|
+
}, this.headers),
|
|
1915
2045
|
body: providerRequest,
|
|
1916
2046
|
signal: request.signal
|
|
1917
2047
|
});
|
|
@@ -1920,8 +2050,12 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1920
2050
|
let completedResponse;
|
|
1921
2051
|
let unknownEventsWarned = false;
|
|
1922
2052
|
const messageItemsWithDelta = /* @__PURE__ */ new Set();
|
|
2053
|
+
/** item_id → function name */
|
|
1923
2054
|
const toolCallNames = /* @__PURE__ */ new Map();
|
|
2055
|
+
/** item_id → call_id(canonical ToolCallItem.id / function_call_output.call_id) */
|
|
2056
|
+
const toolCallIds = /* @__PURE__ */ new Map();
|
|
1924
2057
|
const reasoningStates = /* @__PURE__ */ new Map();
|
|
2058
|
+
const resolveToolCallId = (itemId) => toolCallIds.get(itemId) ?? itemId;
|
|
1925
2059
|
const ensureReasoningState = (itemId, visibility = "summary") => {
|
|
1926
2060
|
let state = reasoningStates.get(itemId);
|
|
1927
2061
|
if (!state) {
|
|
@@ -1967,8 +2101,10 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1967
2101
|
}
|
|
1968
2102
|
case "function_call": {
|
|
1969
2103
|
const name = typeof item.name === "string" ? item.name : "unknown";
|
|
2104
|
+
const callId = typeof item.call_id === "string" && item.call_id.length > 0 ? item.call_id : item.id;
|
|
1970
2105
|
toolCallNames.set(item.id, name);
|
|
1971
|
-
|
|
2106
|
+
toolCallIds.set(item.id, callId);
|
|
2107
|
+
yield factory.toolCallStarted(callId, name);
|
|
1972
2108
|
break;
|
|
1973
2109
|
}
|
|
1974
2110
|
}
|
|
@@ -2057,13 +2193,15 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
2057
2193
|
}
|
|
2058
2194
|
if (sseEvent.type === "response.function_call_arguments.delta") {
|
|
2059
2195
|
const data = sseEvent.data;
|
|
2060
|
-
if (data.delta) yield factory.toolCallDelta(data.item_id, { argumentsText: data.delta });
|
|
2196
|
+
if (data.delta) yield factory.toolCallDelta(resolveToolCallId(data.item_id), { argumentsText: data.delta });
|
|
2061
2197
|
continue;
|
|
2062
2198
|
}
|
|
2063
2199
|
if (sseEvent.type === "response.function_call_arguments.done") {
|
|
2064
2200
|
const data = sseEvent.data;
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2201
|
+
const callId = resolveToolCallId(data.item_id);
|
|
2202
|
+
if (!toolCallIds.has(data.item_id)) toolCallIds.set(data.item_id, callId);
|
|
2203
|
+
const tcItem = toolCallItem(callId, toolCallNames.get(data.item_id) ?? "unknown", data.arguments);
|
|
2204
|
+
yield factory.toolCallCompleted(callId);
|
|
2067
2205
|
output.push(tcItem);
|
|
2068
2206
|
continue;
|
|
2069
2207
|
}
|
|
@@ -2097,7 +2235,10 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
2097
2235
|
if (completedResponse.usage) auxiliary.recordUsage(usageFromOpenAIResponses(completedResponse.usage), "final", completedResponse.usage);
|
|
2098
2236
|
}
|
|
2099
2237
|
const replay = [...replayFromOutput(output)];
|
|
2100
|
-
if (completedResponse?.id) replay.push(opaqueItem("responses", "replay", {
|
|
2238
|
+
if (completedResponse?.id) replay.push(opaqueItem("responses", "replay", {
|
|
2239
|
+
id: completedResponse.id,
|
|
2240
|
+
previous_response_id: completedResponse.id
|
|
2241
|
+
}));
|
|
2101
2242
|
const stopReason = completedResponse ? this.inferStopReason(completedResponse) : void 0;
|
|
2102
2243
|
if (gate.tryComplete()) yield* this.emitStreamCompleted(factory, request, auxiliary, {
|
|
2103
2244
|
output,
|
|
@@ -2211,12 +2352,16 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
2211
2352
|
apiVersion;
|
|
2212
2353
|
baseUrl;
|
|
2213
2354
|
fetchFn;
|
|
2355
|
+
headers;
|
|
2356
|
+
extraBody;
|
|
2214
2357
|
constructor(options) {
|
|
2215
2358
|
super();
|
|
2216
2359
|
this.apiKey = options.apiKey;
|
|
2217
2360
|
this.apiVersion = options.apiVersion ?? "2023-06-01";
|
|
2218
2361
|
this.baseUrl = options.baseUrl ?? "https://api.anthropic.com/v1";
|
|
2219
2362
|
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
2363
|
+
this.headers = options.headers;
|
|
2364
|
+
this.extraBody = options.extraBody;
|
|
2220
2365
|
}
|
|
2221
2366
|
buildRequest(request) {
|
|
2222
2367
|
const messages = [];
|
|
@@ -2322,7 +2467,8 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
2322
2467
|
})
|
|
2323
2468
|
});
|
|
2324
2469
|
if (request.temperature !== void 0) body.temperature = request.temperature;
|
|
2325
|
-
|
|
2470
|
+
if (request.reasoningLevel !== void 0) body.thinking = mapMessagesThinking(request.reasoningLevel, body.max_tokens);
|
|
2471
|
+
return applyExtraBody(body, this.extraBody);
|
|
2326
2472
|
}
|
|
2327
2473
|
async *runStream(providerRequest, factory, request) {
|
|
2328
2474
|
const auxiliary = this.createAuxiliaryState(request);
|
|
@@ -2331,11 +2477,11 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
2331
2477
|
const { reader, headers } = await openProviderJsonStream({
|
|
2332
2478
|
fetchFn: this.fetchFn,
|
|
2333
2479
|
url: `${this.baseUrl}/messages`,
|
|
2334
|
-
headers: {
|
|
2480
|
+
headers: mergeProviderHeaders({
|
|
2335
2481
|
"Content-Type": "application/json",
|
|
2336
2482
|
"x-api-key": this.apiKey,
|
|
2337
2483
|
"anthropic-version": this.apiVersion
|
|
2338
|
-
},
|
|
2484
|
+
}, this.headers),
|
|
2339
2485
|
body: providerRequest,
|
|
2340
2486
|
signal: request.signal
|
|
2341
2487
|
});
|
|
@@ -2610,11 +2756,15 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2610
2756
|
apiKey;
|
|
2611
2757
|
baseUrl;
|
|
2612
2758
|
fetchFn;
|
|
2759
|
+
headers;
|
|
2760
|
+
extraBody;
|
|
2613
2761
|
constructor(options) {
|
|
2614
2762
|
super();
|
|
2615
2763
|
this.apiKey = options.apiKey;
|
|
2616
2764
|
this.baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
|
|
2617
2765
|
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
2766
|
+
this.headers = options.headers;
|
|
2767
|
+
this.extraBody = options.extraBody;
|
|
2618
2768
|
}
|
|
2619
2769
|
buildRequest(request) {
|
|
2620
2770
|
const messages = [];
|
|
@@ -2708,7 +2858,8 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2708
2858
|
if (request.temperature !== void 0) body.temperature = request.temperature;
|
|
2709
2859
|
if (request.maxOutputTokens !== void 0) body.max_tokens = request.maxOutputTokens;
|
|
2710
2860
|
if (request.metadata) body.metadata = request.metadata;
|
|
2711
|
-
|
|
2861
|
+
if (request.reasoningLevel !== void 0) body.reasoning_effort = mapChatCompletionsReasoningEffort(request.reasoningLevel);
|
|
2862
|
+
return applyExtraBody(body, this.extraBody);
|
|
2712
2863
|
}
|
|
2713
2864
|
async *runStream(providerRequest, factory, request) {
|
|
2714
2865
|
const auxiliary = this.createAuxiliaryState(request);
|
|
@@ -2716,10 +2867,10 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2716
2867
|
const { reader } = await openProviderJsonStream({
|
|
2717
2868
|
fetchFn: this.fetchFn,
|
|
2718
2869
|
url: `${this.baseUrl}/chat/completions`,
|
|
2719
|
-
headers: {
|
|
2870
|
+
headers: mergeProviderHeaders({
|
|
2720
2871
|
"Content-Type": "application/json",
|
|
2721
2872
|
Authorization: `Bearer ${this.apiKey}`
|
|
2722
|
-
},
|
|
2873
|
+
}, this.headers),
|
|
2723
2874
|
body: providerRequest,
|
|
2724
2875
|
signal: request.signal
|
|
2725
2876
|
});
|
|
@@ -2945,11 +3096,15 @@ var OllamaAdapter = class extends AdapterBase {
|
|
|
2945
3096
|
baseUrl;
|
|
2946
3097
|
apiKey;
|
|
2947
3098
|
fetchFn;
|
|
3099
|
+
headers;
|
|
3100
|
+
extraBody;
|
|
2948
3101
|
constructor(options = {}) {
|
|
2949
3102
|
super();
|
|
2950
3103
|
this.baseUrl = options.baseUrl ?? "http://localhost:11434";
|
|
2951
3104
|
this.apiKey = options.apiKey;
|
|
2952
3105
|
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
3106
|
+
this.headers = options.headers;
|
|
3107
|
+
this.extraBody = options.extraBody;
|
|
2953
3108
|
}
|
|
2954
3109
|
buildRequest(request) {
|
|
2955
3110
|
const messages = [];
|
|
@@ -3047,7 +3202,8 @@ var OllamaAdapter = class extends AdapterBase {
|
|
|
3047
3202
|
if (request.temperature !== void 0) body.options.temperature = request.temperature;
|
|
3048
3203
|
if (request.maxOutputTokens !== void 0) body.options.num_predict = request.maxOutputTokens;
|
|
3049
3204
|
}
|
|
3050
|
-
|
|
3205
|
+
if (request.reasoningLevel !== void 0) body.think = mapOllamaThink(request.reasoningLevel);
|
|
3206
|
+
return applyExtraBody(body, this.extraBody);
|
|
3051
3207
|
}
|
|
3052
3208
|
async *runStream(providerRequest, factory, request) {
|
|
3053
3209
|
const auxiliary = this.createAuxiliaryState(request);
|
|
@@ -3059,7 +3215,7 @@ var OllamaAdapter = class extends AdapterBase {
|
|
|
3059
3215
|
const { reader } = await openProviderJsonStream({
|
|
3060
3216
|
fetchFn: this.fetchFn,
|
|
3061
3217
|
url: `${this.baseUrl}/api/chat`,
|
|
3062
|
-
headers,
|
|
3218
|
+
headers: mergeProviderHeaders(headers, this.headers),
|
|
3063
3219
|
body: providerRequest,
|
|
3064
3220
|
signal: request.signal
|
|
3065
3221
|
});
|
|
@@ -3228,7 +3384,7 @@ var MockAdapter = class extends AdapterBase {
|
|
|
3228
3384
|
}
|
|
3229
3385
|
async buildRequest(request) {
|
|
3230
3386
|
const turnIndex = this.cursor;
|
|
3231
|
-
const context = this.buildHandlerContext(turnIndex, request
|
|
3387
|
+
const context = this.buildHandlerContext(turnIndex, request);
|
|
3232
3388
|
const remainingPendingToolCalls = consumePendingToolCalls(this.pendingToolCalls, request.input);
|
|
3233
3389
|
const handlerResult = this.handler(request, context);
|
|
3234
3390
|
this.cursor += 1;
|
|
@@ -3367,7 +3523,7 @@ var MockAdapter = class extends AdapterBase {
|
|
|
3367
3523
|
rawResponseId: completion.rawResponseId
|
|
3368
3524
|
}, factory);
|
|
3369
3525
|
}
|
|
3370
|
-
buildHandlerContext(turnIndex,
|
|
3526
|
+
buildHandlerContext(turnIndex, request) {
|
|
3371
3527
|
return {
|
|
3372
3528
|
turnIndex,
|
|
3373
3529
|
previousReplay: this.previousReplay.map(cloneItem),
|
|
@@ -3377,7 +3533,8 @@ var MockAdapter = class extends AdapterBase {
|
|
|
3377
3533
|
replay: record.replay.map(cloneItem),
|
|
3378
3534
|
toolCalls: record.toolCalls.map(cloneItem)
|
|
3379
3535
|
})),
|
|
3380
|
-
signal
|
|
3536
|
+
signal: request.signal,
|
|
3537
|
+
reasoningLevel: request.reasoningLevel
|
|
3381
3538
|
};
|
|
3382
3539
|
}
|
|
3383
3540
|
};
|
|
@@ -3603,6 +3760,6 @@ function cloneItem(item) {
|
|
|
3603
3760
|
return structuredClone(item);
|
|
3604
3761
|
}
|
|
3605
3762
|
//#endregion
|
|
3606
|
-
export { AIError, AIMappingError, AIProviderError, AIRequestError, AIStreamError, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, ChatCompletionsAdapter, IncrementalStreamParser, MAX_OPAQUE_JSON_DEPTH, MAX_OPAQUE_PAYLOAD_BYTES, MessagesAdapter, MockAdapter, NormalizedRequestMapper, OllamaAdapter, PROVIDER_ERROR_MESSAGE_MAX_LEN, PROVIDER_ERROR_RAW_BODY_THRESHOLD, ResponsesAdapter, WarningCode, aggregateEvents, assertMockRequest, assertOpaqueReplayEnvelope, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createChatCompletionsSseParser, createCompletionGate, createEventFactory, createNdjsonLineParser, createSseJsonParser, emitMalformedStreamWarning, extractProviderErrorMessage, extractText, imageBlock, iterateProviderStreamBatches, jsonBlock, mapReasoningVisibility, mapStopReason, measureJsonDepth, messageItem, normalizeRequest, opaqueBlock, opaqueItem, openProviderJsonStream, parseChatCompletionsDataLine, parseSseJsonFrame, providerHttpError, reasoningItem, replayFromOutput, splitLines, splitSSEFrames, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateOpaqueReplayEnvelope, validateRequest, withMockStreaming };
|
|
3763
|
+
export { AIError, AIMappingError, AIProviderError, AIRequestError, AIStreamError, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, ChatCompletionsAdapter, IncrementalStreamParser, MAX_OPAQUE_JSON_DEPTH, MAX_OPAQUE_PAYLOAD_BYTES, MessagesAdapter, MockAdapter, NormalizedRequestMapper, OllamaAdapter, PROVIDER_ERROR_MESSAGE_MAX_LEN, PROVIDER_ERROR_RAW_BODY_THRESHOLD, REASONING_LEVELS, REASONING_LEVEL_SET, ResponsesAdapter, WarningCode, aggregateEvents, applyExtraBody, assertMockRequest, assertOpaqueReplayEnvelope, assertSupportedReasoningLevel, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createChatCompletionsSseParser, createCompletionGate, createEventFactory, createNdjsonLineParser, createSseJsonParser, emitMalformedStreamWarning, extractProviderErrorMessage, extractText, imageBlock, iterateProviderStreamBatches, jsonBlock, mapChatCompletionsReasoningEffort, mapMessagesThinking, mapMessagesThinkingBudget, mapOllamaThink, mapReasoningVisibility, mapResponsesReasoning, mapStopReason, measureJsonDepth, mergeProviderHeaders, messageItem, normalizeRequest, opaqueBlock, opaqueItem, openProviderJsonStream, parseChatCompletionsDataLine, parseSseJsonFrame, providerHttpError, reasoningItem, replayFromOutput, splitLines, splitSSEFrames, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateOpaqueReplayEnvelope, validateRequest, withMockStreaming };
|
|
3607
3764
|
|
|
3608
3765
|
//# sourceMappingURL=index.mjs.map
|