@fased/fased 0.1.58 → 0.1.59

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.
Files changed (167) hide show
  1. package/dist/agents/anthropic-payload-policy.js +188 -0
  2. package/dist/agents/anthropic-transport-stream.js +736 -0
  3. package/dist/agents/copilot-dynamic-headers.js +1 -1
  4. package/dist/agents/custom-api-registry.js +21 -0
  5. package/dist/agents/google-transport-stream.js +543 -0
  6. package/dist/agents/models-config.js +2 -1
  7. package/dist/agents/openai-completions-compat.js +49 -0
  8. package/dist/agents/openai-responses-payload-policy.js +100 -0
  9. package/dist/agents/openai-tool-schema.js +130 -0
  10. package/dist/agents/openai-transport-stream.js +1040 -0
  11. package/dist/agents/pi-embedded-runner/compact.js +9 -0
  12. package/dist/agents/pi-embedded-runner/run/attempt.js +9 -0
  13. package/dist/agents/provider-request-config.js +1 -1
  14. package/dist/agents/provider-stream.js +29 -0
  15. package/dist/agents/provider-transport-fetch.js +89 -0
  16. package/dist/agents/provider-transport-stream.js +72 -0
  17. package/dist/agents/system-prompt-cache-boundary.js +1 -1
  18. package/dist/agents/system-prompt.js +1 -1
  19. package/dist/agents/transport-message-transform.js +143 -0
  20. package/dist/agents/transport-stream-shared.js +81 -0
  21. package/dist/brand.js +1 -1
  22. package/dist/build-info.json +3 -3
  23. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  24. package/dist/channels/delivery.js +78 -0
  25. package/dist/channels/plugins/catalog.js +10 -5
  26. package/dist/cli/components-cli.js +16 -13
  27. package/dist/cli/program/register.subclis.js +9 -0
  28. package/dist/cli/providers-cli.js +79 -6
  29. package/dist/cli/services-cli.js +28 -0
  30. package/dist/commands/auth-choice.js +1 -1
  31. package/dist/commands/models/list.auth-overview.js +12 -0
  32. package/dist/commands/onboard-channels.js +5 -0
  33. package/dist/commands/onboard-helpers.js +1 -1
  34. package/dist/commands/vllm-setup.js +12 -3
  35. package/dist/control-ui/assets/{app-CpgQGqe6.js → app-S_jg-ADS.js} +1706 -1675
  36. package/dist/control-ui/assets/{index-DiBBflpv.js → index-C22rDOFm.js} +3 -3
  37. package/dist/control-ui/assets/{providers-Cc89iMdx.js → providers-QMn4w2_f.js} +3 -3
  38. package/dist/control-ui/index.html +1 -1
  39. package/dist/control-ui/version.json +1 -1
  40. package/dist/gateway/control-reply-text.js +10 -1
  41. package/dist/gateway/method-scopes.js +2 -0
  42. package/dist/gateway/protocol/schema/agents-models-skills.js +1 -0
  43. package/dist/gateway/server-chat.js +3 -3
  44. package/dist/gateway/server-methods/channels.js +10 -2
  45. package/dist/gateway/server-methods/chat.js +19 -12
  46. package/dist/gateway/server-methods/models.js +4 -0
  47. package/dist/gateway/server-methods/services.js +47 -2
  48. package/dist/gateway/server-methods-list.js +2 -0
  49. package/dist/gateway/session-event-payloads.js +20 -9
  50. package/dist/infra/google-api-base-url.js +29 -0
  51. package/dist/plugin-sdk/{accounts-BJuN64m-.js → accounts-DxblobYM.js} +1 -1
  52. package/dist/plugin-sdk/{actions-DaEvM9Bl.js → actions-D4UNimWa.js} +2 -2
  53. package/dist/plugin-sdk/{active-listener-B8Kuanet.js → active-listener-CFuy106s.js} +1 -1
  54. package/dist/plugin-sdk/{audio-preflight-D7tCO0EH.js → audio-preflight-CxZixyhW.js} +25 -25
  55. package/dist/plugin-sdk/{audit-CVWH4BVP.js → audit-Cs0K7LBp.js} +1 -1
  56. package/dist/plugin-sdk/{channel-access-CH9FAS-I.js → channel-access-D5aHoTY8.js} +1 -1
  57. package/dist/plugin-sdk/{channel-access-configure-CI0je66H.js → channel-access-configure-Dvch9mMQ.js} +1 -1
  58. package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
  59. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  60. package/dist/plugin-sdk/{chunk-01oBnQjh.js → chunk-B0FUGc5A.js} +1 -1
  61. package/dist/plugin-sdk/{chunk-items-D2zDJ8q8.js → chunk-items-Cy9a3X7x.js} +1 -1
  62. package/dist/plugin-sdk/command-status.js +25 -25
  63. package/dist/plugin-sdk/{commands-registry-ckg4fhYa.js → commands-registry-DmDRhRAU.js} +2 -2
  64. package/dist/plugin-sdk/{common-zHvdO8ly.js → common-CfUOowOp.js} +1 -1
  65. package/dist/plugin-sdk/{config-DrhYEiCM.js → config-mxULv0fQ.js} +1 -1
  66. package/dist/plugin-sdk/{config-schema-BtjeV5Hm.js → config-schema-D8E0LX8X.js} +4405 -460
  67. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  68. package/dist/plugin-sdk/discord.d.ts +3 -3
  69. package/dist/plugin-sdk/discord.js +19 -19
  70. package/dist/plugin-sdk/{handle-action-5dhYpMbP.js → handle-action-DbVCF9HZ.js} +13 -13
  71. package/dist/plugin-sdk/{helpers-E9aafRzA.js → helpers-BXbdgs5H.js} +1 -1
  72. package/dist/plugin-sdk/{image-ops-D2U9ctmu.js → image-ops-D7jPxaph.js} +1 -1
  73. package/dist/plugin-sdk/index.d.ts +4 -4
  74. package/dist/plugin-sdk/index.js +27 -27
  75. package/dist/plugin-sdk/{login-hql0fNuL.js → login-BRxww6nv.js} +3 -3
  76. package/dist/plugin-sdk/{login-qr-DJJ0svux.js → login-qr-DJXsk9XH.js} +3 -3
  77. package/dist/plugin-sdk/{manager-ciNnAMBn.js → manager-Y2S_5IlI.js} +2 -2
  78. package/dist/plugin-sdk/{markdown-tables-BKxbua_h.js → markdown-tables-DHLFQqaF.js} +1 -1
  79. package/dist/plugin-sdk/{media-DUIZ6x9H.js → media-Czo4carg.js} +2 -2
  80. package/dist/plugin-sdk/{monitor-D-giXewh.js → monitor-CFHFAUOj.js} +30 -30
  81. package/dist/plugin-sdk/{monitor-CNSGw4uQ.js → monitor-xS9A8Upr.js} +29 -29
  82. package/dist/plugin-sdk/ollama-runtime.js +970 -0
  83. package/dist/plugin-sdk/{openresponses-http-dbTd8UMk.js → openresponses-http-BcUbeVV6.js} +25 -25
  84. package/dist/plugin-sdk/{optional-runtime-dependency-CKsJL1PD.js → optional-runtime-dependency-DdMbxS24.js} +1 -1
  85. package/dist/plugin-sdk/{outbound-DhGrjRft.js → outbound-Db8mRN6P.js} +6 -6
  86. package/dist/plugin-sdk/{outbound-attachment-DAF8huFz.js → outbound-attachment-BqFjcypb.js} +2 -2
  87. package/dist/plugin-sdk/{pairing-message-BsJVvXkb.js → pairing-message-B3GC_7CD.js} +1 -1
  88. package/dist/plugin-sdk/{pairing-message-C403mq4K.d.ts → pairing-message-CxonJmwM.d.ts} +1 -1
  89. package/dist/plugin-sdk/{pairing-store-DwM-BNbj.js → pairing-store-CQikgIbw.js} +2 -2
  90. package/dist/plugin-sdk/{pi-model-discovery-DkIdlJvJ.js → pi-model-discovery-CY3m5zJP.js} +1 -1
  91. package/dist/plugin-sdk/{pi-model-discovery-runtime-Cv7okUMt.js → pi-model-discovery-runtime-DSh1T2pn.js} +2 -2
  92. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
  93. package/dist/plugin-sdk/{pw-ai-Dxd87W3J.js → pw-ai-AFUqn-tQ.js} +3 -3
  94. package/dist/plugin-sdk/{replies-Bx61SvAC.js → replies-Fzh9PhXl.js} +2 -2
  95. package/dist/plugin-sdk/{resolve-outbound-target-bc-FpPZg.js → resolve-outbound-target-KpF3co6T.js} +1 -1
  96. package/dist/plugin-sdk/{resolve-route-D0eBYPtb.js → resolve-route-CDl74O19.js} +1 -1
  97. package/dist/plugin-sdk/{retry-policy-HTrC4zfC.js → retry-policy-D4uiqUOG.js} +1 -1
  98. package/dist/plugin-sdk/{runtime-BVkIrYLQ.js → runtime-Bb6KRnCC.js} +6 -4
  99. package/dist/plugin-sdk/{runtime-dependency-B2PqMdBu.js → runtime-dependency-DLDmB94f.js} +2 -2
  100. package/dist/plugin-sdk/sat-runtime.d.ts +2 -2
  101. package/dist/plugin-sdk/sat-runtime.js +25 -25
  102. package/dist/plugin-sdk/{send-DgzZUx2i.js → send-5nFktR1n.js} +5 -5
  103. package/dist/plugin-sdk/{send-DT2egZNK.js → send-Bfzf11VY.js} +7 -7
  104. package/dist/plugin-sdk/{send-BGDGzxUu.js → send-C4k4JuJN.js} +6 -6
  105. package/dist/plugin-sdk/{send-KJy3ajA3.js → send-D-uDKGIq.js} +6 -6
  106. package/dist/plugin-sdk/{send-C3QWSYLR.js → send-Du8ykP1k.js} +8 -8
  107. package/dist/plugin-sdk/{session-BCIEFOu1.js → session-CS-Td9EM.js} +2 -2
  108. package/dist/plugin-sdk/{skill-commands-CyIkcR8P.js → skill-commands-CFAlXWHk.js} +2 -2
  109. package/dist/plugin-sdk/{slack-DjKNh2uh.js → slack-DXYGbizH.js} +37 -37
  110. package/dist/plugin-sdk/{slack-actions-CeM9LWDp.js → slack-actions-BcMkNv1Z.js} +11 -11
  111. package/dist/plugin-sdk/slack.d.ts +3 -3
  112. package/dist/plugin-sdk/slack.js +9 -9
  113. package/dist/plugin-sdk/{sticker-cache-DcWzQ2wx.js → sticker-cache-Dr3rYfU1.js} +3 -3
  114. package/dist/plugin-sdk/{tables-B2iehyjG.js → tables-bFXyRpkx.js} +1 -1
  115. package/dist/plugin-sdk/{targets-BPket0SF.js → targets-DH7a9lKB.js} +1 -1
  116. package/dist/plugin-sdk/{telegram-actions-Cx_HWVht.js → telegram-actions-Besbw_Hg.js} +28 -28
  117. package/dist/plugin-sdk/telegram.d.ts +3 -3
  118. package/dist/plugin-sdk/telegram.js +8 -8
  119. package/dist/plugin-sdk/{thread-bindings.lifecycle-CYH69SIw.js → thread-bindings.lifecycle-CgOvvdw8.js} +3 -3
  120. package/dist/plugin-sdk/{thread-bindings.state-BN6461WG.js → thread-bindings.state-CQpk44Hq.js} +2 -2
  121. package/dist/plugin-sdk/{tmp-fased-dir-Ouj58axY.d.ts → tmp-fased-dir-DQ00xQ5D.d.ts} +1 -1
  122. package/dist/plugin-sdk/{types-B4hj6HgR.d.ts → types-B6zx-Dl2.d.ts} +1 -1
  123. package/dist/plugin-sdk/{types-dWZFX1fk.d.ts → types-eUM7hcDz.d.ts} +1 -1
  124. package/dist/plugin-sdk/{web-vR-oNiBv.js → web-Q1-G--JH.js} +30 -30
  125. package/dist/plugin-sdk/{whatsapp-actions-BYNf8ceY.js → whatsapp-actions-BtSc2CBv.js} +13 -13
  126. package/dist/plugin-sdk/{whatsapp-heartbeat-DZwa8MF0.js → whatsapp-heartbeat-Bg9TuYzl.js} +2 -2
  127. package/dist/plugin-sdk/whatsapp.d.ts +3 -3
  128. package/dist/plugin-sdk/whatsapp.js +12 -12
  129. package/dist/plugin-sdk/{wsl-WGtdw_6h.js → wsl-C4DGFkOd.js} +3 -3
  130. package/dist/plugins/provider-runtime.js +79 -0
  131. package/dist/providers/refresh.js +14 -0
  132. package/extensions/acpx/package.json +1 -1
  133. package/extensions/bluebubbles/package.json +1 -1
  134. package/extensions/copilot-proxy/package.json +1 -1
  135. package/extensions/diagnostics-otel/package.json +1 -1
  136. package/extensions/fased-federation/package.json +1 -1
  137. package/extensions/google-gemini-cli-auth/package.json +1 -1
  138. package/extensions/imessage/package.json +1 -1
  139. package/extensions/irc/package.json +1 -1
  140. package/extensions/line/package.json +1 -1
  141. package/extensions/llm-task/package.json +1 -1
  142. package/extensions/lobster/package.json +1 -1
  143. package/extensions/matrix/CHANGELOG.md +6 -0
  144. package/extensions/matrix/package.json +1 -1
  145. package/extensions/mattermost/package.json +1 -1
  146. package/extensions/memory-core/package.json +2 -2
  147. package/extensions/memory-lancedb/package.json +1 -1
  148. package/extensions/minimax-portal-auth/package.json +1 -1
  149. package/extensions/msteams/CHANGELOG.md +6 -0
  150. package/extensions/msteams/package.json +1 -1
  151. package/extensions/nextcloud-talk/package.json +1 -1
  152. package/extensions/nostr/CHANGELOG.md +6 -0
  153. package/extensions/nostr/package.json +1 -1
  154. package/extensions/open-prose/package.json +1 -1
  155. package/extensions/sat-mining/package.json +1 -1
  156. package/extensions/signal/package.json +1 -1
  157. package/extensions/synology-chat/package.json +1 -1
  158. package/extensions/tlon/package.json +1 -1
  159. package/extensions/twitch/CHANGELOG.md +6 -0
  160. package/extensions/twitch/package.json +1 -1
  161. package/extensions/voice-call/CHANGELOG.md +6 -0
  162. package/extensions/voice-call/package.json +1 -1
  163. package/extensions/zalo/CHANGELOG.md +6 -0
  164. package/extensions/zalo/package.json +1 -1
  165. package/extensions/zalouser/CHANGELOG.md +6 -0
  166. package/extensions/zalouser/package.json +1 -1
  167. package/package.json +1 -1
@@ -0,0 +1,736 @@
1
+ import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./copilot-dynamic-headers.js";
2
+ import { applyAnthropicPayloadPolicyToParams, resolveAnthropicPayloadPolicy } from "./anthropic-payload-policy.js";
3
+ import { buildGuardedModelFetch } from "./provider-transport-fetch.js";
4
+ import { transformTransportMessages } from "./transport-message-transform.js";
5
+ import { createEmptyTransportUsage, createWritableTransportEventStream, failTransportStream, finalizeTransportStream, mergeTransportHeaders, sanitizeTransportPayloadText } from "./transport-stream-shared.js";
6
+ import { calculateCost, getEnvApiKey, parseStreamingJson } from "@mariozechner/pi-ai/compat";
7
+
8
+ //#region src/agents/anthropic-transport-stream.ts
9
+ const CLAUDE_CODE_VERSION = "2.1.75";
10
+ const CLAUDE_CODE_TOOLS = [
11
+ "Read",
12
+ "Write",
13
+ "Edit",
14
+ "Bash",
15
+ "Grep",
16
+ "Glob",
17
+ "AskUserQuestion",
18
+ "EnterPlanMode",
19
+ "ExitPlanMode",
20
+ "KillShell",
21
+ "NotebookEdit",
22
+ "Skill",
23
+ "Task",
24
+ "TaskOutput",
25
+ "TodoWrite",
26
+ "WebFetch",
27
+ "WebSearch"
28
+ ];
29
+ const CLAUDE_CODE_TOOL_LOOKUP = new Map(CLAUDE_CODE_TOOLS.map((tool) => [tool.toLowerCase(), tool]));
30
+ function supportsAdaptiveThinking(modelId) {
31
+ return modelId.includes("opus-4-6") || modelId.includes("opus-4.6") || modelId.includes("sonnet-4-6") || modelId.includes("sonnet-4.6");
32
+ }
33
+ function mapThinkingLevelToEffort(level, modelId) {
34
+ switch (level) {
35
+ case "minimal":
36
+ case "low": return "low";
37
+ case "medium": return "medium";
38
+ case "xhigh": return modelId.includes("opus-4-6") || modelId.includes("opus-4.6") ? "max" : "high";
39
+ default: return "high";
40
+ }
41
+ }
42
+ function clampReasoningLevel(level) {
43
+ return level === "xhigh" ? "high" : level;
44
+ }
45
+ function adjustMaxTokensForThinking(params) {
46
+ const budgets = {
47
+ minimal: 1024,
48
+ low: 2048,
49
+ medium: 8192,
50
+ high: 16384,
51
+ ...params.customBudgets
52
+ };
53
+ const minOutputTokens = 1024;
54
+ const level = clampReasoningLevel(params.reasoningLevel);
55
+ let thinkingBudget = budgets[level];
56
+ const maxTokens = Math.min(params.baseMaxTokens + thinkingBudget, params.modelMaxTokens);
57
+ if (maxTokens <= thinkingBudget) {
58
+ thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
59
+ }
60
+ return {
61
+ maxTokens,
62
+ thinkingBudget
63
+ };
64
+ }
65
+ function isAnthropicOAuthToken(apiKey) {
66
+ return apiKey.includes("sk-ant-oat");
67
+ }
68
+ function toClaudeCodeName(name) {
69
+ return CLAUDE_CODE_TOOL_LOOKUP.get(name.toLowerCase()) ?? name;
70
+ }
71
+ function fromClaudeCodeName(name, tools) {
72
+ if (tools && tools.length > 0) {
73
+ const lowerName = name.toLowerCase();
74
+ const matchedTool = tools.find((tool) => tool.name.toLowerCase() === lowerName);
75
+ if (matchedTool) {
76
+ return matchedTool.name;
77
+ }
78
+ }
79
+ return name;
80
+ }
81
+ function resolveAnthropicMessagesEndpoint(baseURL) {
82
+ const base = (baseURL?.trim() || "https://api.anthropic.com").replace(/\/+$/, "");
83
+ return base.endsWith("/v1") ? `${base}/messages` : `${base}/v1/messages`;
84
+ }
85
+ async function* parseAnthropicServerSentJson(response) {
86
+ if (!response.body) {
87
+ const text = await response.text();
88
+ for (const line of text.split(/\r?\n/)) {
89
+ const trimmed = line.trim();
90
+ if (!trimmed || trimmed === "[DONE]") {
91
+ continue;
92
+ }
93
+ yield JSON.parse(trimmed);
94
+ }
95
+ return;
96
+ }
97
+ const reader = response.body.getReader();
98
+ const decoder = new TextDecoder();
99
+ let buffer = "";
100
+ const emitBlock = function* (block) {
101
+ const data = block.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice("data:".length).trim()).join("\n").trim();
102
+ if (!data || data === "[DONE]") {
103
+ return;
104
+ }
105
+ yield JSON.parse(data);
106
+ };
107
+ while (true) {
108
+ const chunk = await reader.read();
109
+ if (chunk.done) {
110
+ break;
111
+ }
112
+ buffer += decoder.decode(chunk.value, { stream: true });
113
+ let boundary = buffer.indexOf("\n\n");
114
+ while (boundary >= 0) {
115
+ const block = buffer.slice(0, boundary);
116
+ buffer = buffer.slice(boundary + 2);
117
+ for (const event of emitBlock(block)) {
118
+ yield event;
119
+ }
120
+ boundary = buffer.indexOf("\n\n");
121
+ }
122
+ }
123
+ buffer += decoder.decode();
124
+ if (buffer.trim()) {
125
+ for (const event of emitBlock(buffer)) {
126
+ yield event;
127
+ }
128
+ }
129
+ }
130
+ function createAnthropicMessagesClient(params) {
131
+ return { messages: { stream: async (payload, options) => {
132
+ const response = await params.fetch(resolveAnthropicMessagesEndpoint(params.baseURL), {
133
+ method: "POST",
134
+ headers: {
135
+ accept: "text/event-stream",
136
+ "content-type": "application/json",
137
+ "anthropic-version": "2023-06-01",
138
+ ...params.authKind === "bearer" ? { authorization: `Bearer ${params.apiKey}` } : { "x-api-key": params.apiKey },
139
+ ...params.defaultHeaders
140
+ },
141
+ body: JSON.stringify(payload),
142
+ signal: options?.signal
143
+ });
144
+ if (!response.ok) {
145
+ const text = await response.text().catch(() => "");
146
+ throw new Error(`Anthropic transport request failed (${response.status} ${response.statusText})${text ? `: ${text.slice(0, 500)}` : ""}`);
147
+ }
148
+ return parseAnthropicServerSentJson(response);
149
+ } } };
150
+ }
151
+ function convertContentBlocks(content) {
152
+ const hasImages = content.some((item) => item.type === "image");
153
+ if (!hasImages) {
154
+ return sanitizeTransportPayloadText(content.map((item) => "text" in item ? item.text : "").join("\n"));
155
+ }
156
+ const blocks = content.map((block) => {
157
+ if (block.type === "text") {
158
+ return {
159
+ type: "text",
160
+ text: sanitizeTransportPayloadText(block.text)
161
+ };
162
+ }
163
+ return {
164
+ type: "image",
165
+ source: {
166
+ type: "base64",
167
+ media_type: block.mimeType,
168
+ data: block.data
169
+ }
170
+ };
171
+ });
172
+ if (!blocks.some((block) => block.type === "text")) {
173
+ blocks.unshift({
174
+ type: "text",
175
+ text: "(see attached image)"
176
+ });
177
+ }
178
+ return blocks;
179
+ }
180
+ function normalizeToolCallId(id) {
181
+ return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
182
+ }
183
+ function convertAnthropicMessages(messages, model, isOAuthToken) {
184
+ const params = [];
185
+ const transformedMessages = transformTransportMessages(messages, model, normalizeToolCallId);
186
+ for (let i = 0; i < transformedMessages.length; i += 1) {
187
+ const msg = transformedMessages[i];
188
+ if (msg.role === "user") {
189
+ if (typeof msg.content === "string") {
190
+ if (msg.content.trim().length > 0) {
191
+ params.push({
192
+ role: "user",
193
+ content: sanitizeTransportPayloadText(msg.content)
194
+ });
195
+ }
196
+ continue;
197
+ }
198
+ const blocks = msg.content.map((item) => item.type === "text" ? {
199
+ type: "text",
200
+ text: sanitizeTransportPayloadText(item.text)
201
+ } : {
202
+ type: "image",
203
+ source: {
204
+ type: "base64",
205
+ media_type: item.mimeType,
206
+ data: item.data
207
+ }
208
+ });
209
+ let filteredBlocks = model.input.includes("image") ? blocks : blocks.filter((block) => block.type !== "image");
210
+ filteredBlocks = filteredBlocks.filter((block) => block.type !== "text" || block.text.trim().length > 0);
211
+ if (filteredBlocks.length === 0) {
212
+ continue;
213
+ }
214
+ params.push({
215
+ role: "user",
216
+ content: filteredBlocks
217
+ });
218
+ continue;
219
+ }
220
+ if (msg.role === "assistant") {
221
+ const blocks = [];
222
+ for (const block of msg.content) {
223
+ if (block.type === "text") {
224
+ if (block.text.trim().length > 0) {
225
+ blocks.push({
226
+ type: "text",
227
+ text: sanitizeTransportPayloadText(block.text)
228
+ });
229
+ }
230
+ continue;
231
+ }
232
+ if (block.type === "thinking") {
233
+ const thinkingBlock = block;
234
+ if (thinkingBlock.redacted) {
235
+ blocks.push({
236
+ type: "redacted_thinking",
237
+ data: thinkingBlock.thinkingSignature
238
+ });
239
+ continue;
240
+ }
241
+ if (block.thinking.trim().length === 0) {
242
+ continue;
243
+ }
244
+ if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {
245
+ blocks.push({
246
+ type: "text",
247
+ text: sanitizeTransportPayloadText(block.thinking)
248
+ });
249
+ } else {
250
+ blocks.push({
251
+ type: "thinking",
252
+ thinking: sanitizeTransportPayloadText(block.thinking),
253
+ signature: block.thinkingSignature
254
+ });
255
+ }
256
+ continue;
257
+ }
258
+ if (block.type === "toolCall") {
259
+ blocks.push({
260
+ type: "tool_use",
261
+ id: block.id,
262
+ name: isOAuthToken ? toClaudeCodeName(block.name) : block.name,
263
+ input: block.arguments ?? {}
264
+ });
265
+ }
266
+ }
267
+ if (blocks.length > 0) {
268
+ params.push({
269
+ role: "assistant",
270
+ content: blocks
271
+ });
272
+ }
273
+ continue;
274
+ }
275
+ if (msg.role === "toolResult") {
276
+ const toolResult = msg;
277
+ const toolResults = [{
278
+ type: "tool_result",
279
+ tool_use_id: toolResult.toolCallId,
280
+ content: convertContentBlocks(toolResult.content),
281
+ is_error: toolResult.isError
282
+ }];
283
+ let j = i + 1;
284
+ while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
285
+ const nextMsg = transformedMessages[j];
286
+ toolResults.push({
287
+ type: "tool_result",
288
+ tool_use_id: nextMsg.toolCallId,
289
+ content: convertContentBlocks(nextMsg.content),
290
+ is_error: nextMsg.isError
291
+ });
292
+ j += 1;
293
+ }
294
+ i = j - 1;
295
+ params.push({
296
+ role: "user",
297
+ content: toolResults
298
+ });
299
+ }
300
+ }
301
+ return params;
302
+ }
303
+ function convertAnthropicTools(tools, isOAuthToken) {
304
+ if (!tools) {
305
+ return [];
306
+ }
307
+ return tools.map((tool) => ({
308
+ name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name,
309
+ description: tool.description,
310
+ input_schema: {
311
+ type: "object",
312
+ properties: tool.parameters.properties || {},
313
+ required: tool.parameters.required || []
314
+ }
315
+ }));
316
+ }
317
+ function mapStopReason(reason) {
318
+ switch (reason) {
319
+ case "end_turn": return "stop";
320
+ case "max_tokens": return "length";
321
+ case "tool_use": return "toolUse";
322
+ case "pause_turn": return "stop";
323
+ case "refusal":
324
+ case "sensitive": return "error";
325
+ case "stop_sequence": return "stop";
326
+ default: throw new Error(`Unhandled stop reason: ${String(reason)}`);
327
+ }
328
+ }
329
+ function createAnthropicTransportClient(params) {
330
+ const { model, context, apiKey, options } = params;
331
+ const needsInterleavedBeta = (options?.interleavedThinking ?? true) && !supportsAdaptiveThinking(model.id);
332
+ const fetch = buildGuardedModelFetch(model);
333
+ if (model.provider === "github-copilot") {
334
+ const betaFeatures = needsInterleavedBeta ? ["interleaved-thinking-2025-05-14"] : [];
335
+ return {
336
+ client: createAnthropicMessagesClient({
337
+ apiKey,
338
+ authKind: "bearer",
339
+ baseURL: model.baseUrl,
340
+ defaultHeaders: mergeTransportHeaders({
341
+ accept: "application/json",
342
+ "anthropic-dangerous-direct-browser-access": "true",
343
+ ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
344
+ }, model.headers, buildCopilotDynamicHeaders({
345
+ messages: context.messages,
346
+ hasImages: hasCopilotVisionInput(context.messages)
347
+ }), options?.headers),
348
+ fetch
349
+ }),
350
+ isOAuthToken: false
351
+ };
352
+ }
353
+ const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
354
+ if (needsInterleavedBeta) {
355
+ betaFeatures.push("interleaved-thinking-2025-05-14");
356
+ }
357
+ if (isAnthropicOAuthToken(apiKey)) {
358
+ return {
359
+ client: createAnthropicMessagesClient({
360
+ apiKey,
361
+ authKind: "bearer",
362
+ baseURL: model.baseUrl,
363
+ defaultHeaders: mergeTransportHeaders({
364
+ accept: "application/json",
365
+ "anthropic-dangerous-direct-browser-access": "true",
366
+ "anthropic-beta": `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}`,
367
+ "user-agent": `claude-cli/${CLAUDE_CODE_VERSION}`,
368
+ "x-app": "cli"
369
+ }, model.headers, options?.headers),
370
+ fetch
371
+ }),
372
+ isOAuthToken: true
373
+ };
374
+ }
375
+ return {
376
+ client: createAnthropicMessagesClient({
377
+ apiKey,
378
+ authKind: "api_key",
379
+ baseURL: model.baseUrl,
380
+ defaultHeaders: mergeTransportHeaders({
381
+ accept: "application/json",
382
+ "anthropic-dangerous-direct-browser-access": "true",
383
+ "anthropic-beta": betaFeatures.join(",")
384
+ }, model.headers, options?.headers),
385
+ fetch
386
+ }),
387
+ isOAuthToken: false
388
+ };
389
+ }
390
+ function buildAnthropicParams(model, context, isOAuthToken, options) {
391
+ const payloadPolicy = resolveAnthropicPayloadPolicy({
392
+ provider: model.provider,
393
+ api: model.api,
394
+ baseUrl: model.baseUrl,
395
+ cacheRetention: options?.cacheRetention,
396
+ enableCacheControl: true
397
+ });
398
+ const defaultMaxTokens = Math.min(model.maxTokens, 32e3);
399
+ const params = {
400
+ model: model.id,
401
+ messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
402
+ max_tokens: options?.maxTokens || defaultMaxTokens,
403
+ stream: true
404
+ };
405
+ if (isOAuthToken) {
406
+ params.system = [{
407
+ type: "text",
408
+ text: "You are Claude Code, Anthropic's official CLI for Claude."
409
+ }, ...context.systemPrompt ? [{
410
+ type: "text",
411
+ text: sanitizeTransportPayloadText(context.systemPrompt)
412
+ }] : []];
413
+ } else if (context.systemPrompt) {
414
+ params.system = [{
415
+ type: "text",
416
+ text: sanitizeTransportPayloadText(context.systemPrompt)
417
+ }];
418
+ }
419
+ if (options?.temperature !== undefined && !options.thinkingEnabled) {
420
+ params.temperature = options.temperature;
421
+ }
422
+ if (context.tools) {
423
+ params.tools = convertAnthropicTools(context.tools, isOAuthToken);
424
+ }
425
+ if (model.reasoning) {
426
+ if (options?.thinkingEnabled) {
427
+ if (supportsAdaptiveThinking(model.id)) {
428
+ params.thinking = { type: "adaptive" };
429
+ if (options.effort) {
430
+ params.output_config = { effort: options.effort };
431
+ }
432
+ } else {
433
+ params.thinking = {
434
+ type: "enabled",
435
+ budget_tokens: options.thinkingBudgetTokens || 1024
436
+ };
437
+ }
438
+ } else if (options?.thinkingEnabled === false) {
439
+ params.thinking = { type: "disabled" };
440
+ }
441
+ }
442
+ if (options?.metadata && typeof options.metadata.user_id === "string") {
443
+ params.metadata = { user_id: options.metadata.user_id };
444
+ }
445
+ if (options?.toolChoice) {
446
+ params.tool_choice = typeof options.toolChoice === "string" ? { type: options.toolChoice } : options.toolChoice;
447
+ }
448
+ applyAnthropicPayloadPolicyToParams(params, payloadPolicy);
449
+ return params;
450
+ }
451
+ function resolveAnthropicTransportOptions(model, options, apiKey) {
452
+ const baseMaxTokens = options?.maxTokens || Math.min(model.maxTokens, 32e3);
453
+ const resolved = {
454
+ temperature: options?.temperature,
455
+ maxTokens: baseMaxTokens,
456
+ signal: options?.signal,
457
+ apiKey,
458
+ cacheRetention: options?.cacheRetention,
459
+ sessionId: options?.sessionId,
460
+ headers: options?.headers,
461
+ onPayload: options?.onPayload,
462
+ maxRetryDelayMs: options?.maxRetryDelayMs,
463
+ metadata: options?.metadata,
464
+ interleavedThinking: options?.interleavedThinking,
465
+ toolChoice: options?.toolChoice,
466
+ thinkingBudgets: options?.thinkingBudgets,
467
+ reasoning: options?.reasoning
468
+ };
469
+ if (!options?.reasoning) {
470
+ resolved.thinkingEnabled = false;
471
+ return resolved;
472
+ }
473
+ if (supportsAdaptiveThinking(model.id)) {
474
+ resolved.thinkingEnabled = true;
475
+ resolved.effort = mapThinkingLevelToEffort(options.reasoning, model.id);
476
+ return resolved;
477
+ }
478
+ const adjusted = adjustMaxTokensForThinking({
479
+ baseMaxTokens,
480
+ modelMaxTokens: model.maxTokens,
481
+ reasoningLevel: options.reasoning,
482
+ customBudgets: options.thinkingBudgets
483
+ });
484
+ resolved.maxTokens = adjusted.maxTokens;
485
+ resolved.thinkingEnabled = true;
486
+ resolved.thinkingBudgetTokens = adjusted.thinkingBudget;
487
+ return resolved;
488
+ }
489
+ function createAnthropicMessagesTransportStreamFn() {
490
+ return (rawModel, context, rawOptions) => {
491
+ const model = rawModel;
492
+ const options = rawOptions;
493
+ const { eventStream, stream } = createWritableTransportEventStream();
494
+ void (async () => {
495
+ const output = {
496
+ role: "assistant",
497
+ content: [],
498
+ api: "anthropic-messages",
499
+ provider: model.provider,
500
+ model: model.id,
501
+ usage: createEmptyTransportUsage(),
502
+ stopReason: "stop",
503
+ timestamp: Date.now()
504
+ };
505
+ try {
506
+ const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
507
+ if (!apiKey) {
508
+ throw new Error(`No API key for provider: ${model.provider}`);
509
+ }
510
+ const transportOptions = resolveAnthropicTransportOptions(model, options, apiKey);
511
+ const { client, isOAuthToken } = createAnthropicTransportClient({
512
+ model,
513
+ context,
514
+ apiKey,
515
+ options: transportOptions
516
+ });
517
+ let params = buildAnthropicParams(model, context, isOAuthToken, transportOptions);
518
+ const onPayload = transportOptions.onPayload;
519
+ const nextParams = await Promise.resolve(onPayload?.(params, model));
520
+ if (nextParams !== undefined) {
521
+ params = nextParams;
522
+ }
523
+ const anthropicStream = await client.messages.stream({
524
+ ...params,
525
+ stream: true
526
+ }, transportOptions.signal ? { signal: transportOptions.signal } : undefined);
527
+ stream.push({
528
+ type: "start",
529
+ partial: output
530
+ });
531
+ const blocks = output.content;
532
+ for await (const event of anthropicStream) {
533
+ if (event.type === "message_start") {
534
+ const message = event.message;
535
+ const usage = message?.usage ?? {};
536
+ output.responseId = typeof message?.id === "string" ? message.id : undefined;
537
+ output.usage.input = typeof usage.input_tokens === "number" ? usage.input_tokens : 0;
538
+ output.usage.output = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
539
+ output.usage.cacheRead = typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0;
540
+ output.usage.cacheWrite = typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0;
541
+ output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
542
+ calculateCost(model, output.usage);
543
+ continue;
544
+ }
545
+ if (event.type === "content_block_start") {
546
+ const contentBlock = event.content_block;
547
+ const index = typeof event.index === "number" ? event.index : -1;
548
+ if (contentBlock?.type === "text") {
549
+ const block = {
550
+ type: "text",
551
+ text: "",
552
+ index
553
+ };
554
+ output.content.push(block);
555
+ stream.push({
556
+ type: "text_start",
557
+ contentIndex: output.content.length - 1,
558
+ partial: output
559
+ });
560
+ continue;
561
+ }
562
+ if (contentBlock?.type === "thinking") {
563
+ const block = {
564
+ type: "thinking",
565
+ thinking: "",
566
+ thinkingSignature: "",
567
+ index
568
+ };
569
+ output.content.push(block);
570
+ stream.push({
571
+ type: "thinking_start",
572
+ contentIndex: output.content.length - 1,
573
+ partial: output
574
+ });
575
+ continue;
576
+ }
577
+ if (contentBlock?.type === "redacted_thinking") {
578
+ const block = {
579
+ type: "thinking",
580
+ thinking: "[Reasoning redacted]",
581
+ thinkingSignature: typeof contentBlock.data === "string" ? contentBlock.data : "",
582
+ redacted: true,
583
+ index
584
+ };
585
+ output.content.push(block);
586
+ stream.push({
587
+ type: "thinking_start",
588
+ contentIndex: output.content.length - 1,
589
+ partial: output
590
+ });
591
+ continue;
592
+ }
593
+ if (contentBlock?.type === "tool_use") {
594
+ const block = {
595
+ type: "toolCall",
596
+ id: typeof contentBlock.id === "string" ? contentBlock.id : "",
597
+ name: typeof contentBlock.name === "string" ? isOAuthToken ? fromClaudeCodeName(contentBlock.name, context.tools) : contentBlock.name : "",
598
+ arguments: contentBlock.input && typeof contentBlock.input === "object" ? contentBlock.input : {},
599
+ partialJson: "",
600
+ index
601
+ };
602
+ output.content.push(block);
603
+ stream.push({
604
+ type: "toolcall_start",
605
+ contentIndex: output.content.length - 1,
606
+ partial: output
607
+ });
608
+ }
609
+ continue;
610
+ }
611
+ if (event.type === "content_block_delta") {
612
+ const index = blocks.findIndex((block) => block.index === event.index);
613
+ const block = blocks[index];
614
+ const delta = event.delta;
615
+ if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
616
+ block.text += delta.text;
617
+ stream.push({
618
+ type: "text_delta",
619
+ contentIndex: index,
620
+ delta: delta.text,
621
+ partial: output
622
+ });
623
+ continue;
624
+ }
625
+ if (block?.type === "thinking" && delta?.type === "thinking_delta" && typeof delta.thinking === "string") {
626
+ block.thinking += delta.thinking;
627
+ stream.push({
628
+ type: "thinking_delta",
629
+ contentIndex: index,
630
+ delta: delta.thinking,
631
+ partial: output
632
+ });
633
+ continue;
634
+ }
635
+ if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
636
+ block.partialJson += delta.partial_json;
637
+ block.arguments = parseStreamingJson(block.partialJson);
638
+ stream.push({
639
+ type: "toolcall_delta",
640
+ contentIndex: index,
641
+ delta: delta.partial_json,
642
+ partial: output
643
+ });
644
+ continue;
645
+ }
646
+ if (block?.type === "thinking" && delta?.type === "signature_delta" && typeof delta.signature === "string") {
647
+ block.thinkingSignature = `${String(block.thinkingSignature ?? "")}${delta.signature}`;
648
+ }
649
+ continue;
650
+ }
651
+ if (event.type === "content_block_stop") {
652
+ const index = blocks.findIndex((block) => block.index === event.index);
653
+ const block = blocks[index];
654
+ if (!block) {
655
+ continue;
656
+ }
657
+ delete block.index;
658
+ if (block.type === "text") {
659
+ stream.push({
660
+ type: "text_end",
661
+ contentIndex: index,
662
+ content: block.text,
663
+ partial: output
664
+ });
665
+ continue;
666
+ }
667
+ if (block.type === "thinking") {
668
+ stream.push({
669
+ type: "thinking_end",
670
+ contentIndex: index,
671
+ content: block.thinking,
672
+ partial: output
673
+ });
674
+ continue;
675
+ }
676
+ if (block.type === "toolCall") {
677
+ if (typeof block.partialJson === "string" && block.partialJson.length > 0) {
678
+ block.arguments = parseStreamingJson(block.partialJson);
679
+ }
680
+ delete block.partialJson;
681
+ stream.push({
682
+ type: "toolcall_end",
683
+ contentIndex: index,
684
+ toolCall: block,
685
+ partial: output
686
+ });
687
+ }
688
+ continue;
689
+ }
690
+ if (event.type === "message_delta") {
691
+ const delta = event.delta;
692
+ const usage = event.usage;
693
+ if (delta?.stop_reason) {
694
+ output.stopReason = mapStopReason(delta.stop_reason);
695
+ }
696
+ if (typeof usage?.input_tokens === "number") {
697
+ output.usage.input = usage.input_tokens;
698
+ }
699
+ if (typeof usage?.output_tokens === "number") {
700
+ output.usage.output = usage.output_tokens;
701
+ }
702
+ if (typeof usage?.cache_read_input_tokens === "number") {
703
+ output.usage.cacheRead = usage.cache_read_input_tokens;
704
+ }
705
+ if (typeof usage?.cache_creation_input_tokens === "number") {
706
+ output.usage.cacheWrite = usage.cache_creation_input_tokens;
707
+ }
708
+ output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
709
+ calculateCost(model, output.usage);
710
+ }
711
+ }
712
+ finalizeTransportStream({
713
+ stream,
714
+ output,
715
+ signal: transportOptions.signal
716
+ });
717
+ } catch (error) {
718
+ failTransportStream({
719
+ stream,
720
+ output,
721
+ signal: options?.signal,
722
+ error,
723
+ cleanup: () => {
724
+ for (const block of output.content) {
725
+ delete block.index;
726
+ }
727
+ }
728
+ });
729
+ }
730
+ })();
731
+ return eventStream;
732
+ };
733
+ }
734
+
735
+ //#endregion
736
+ export { createAnthropicMessagesTransportStreamFn };