@bubblebrain-ai/bubble 0.0.15 → 0.0.17

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 (51) hide show
  1. package/README.md +24 -0
  2. package/dist/agent/discovery-barrier.d.ts +21 -0
  3. package/dist/agent/discovery-barrier.js +173 -0
  4. package/dist/agent/internal-reminder-sanitizer.d.ts +9 -0
  5. package/dist/agent/internal-reminder-sanitizer.js +198 -0
  6. package/dist/agent/task-classifier.js +23 -5
  7. package/dist/agent.js +215 -30
  8. package/dist/context/budget.js +15 -0
  9. package/dist/context/projector.js +4 -3
  10. package/dist/debug-trace.js +14 -0
  11. package/dist/feishu/serve.js +1 -0
  12. package/dist/main.js +2 -0
  13. package/dist/model-catalog.d.ts +3 -0
  14. package/dist/model-catalog.js +44 -0
  15. package/dist/model-config.d.ts +3 -0
  16. package/dist/model-config.js +3 -0
  17. package/dist/model-pricing.d.ts +3 -2
  18. package/dist/model-pricing.js +8 -0
  19. package/dist/network/chatgpt-transport.d.ts +16 -0
  20. package/dist/network/chatgpt-transport.js +240 -0
  21. package/dist/oauth/openai-codex.d.ts +7 -2
  22. package/dist/oauth/openai-codex.js +7 -4
  23. package/dist/orchestrator/default-hooks.js +13 -2
  24. package/dist/orchestrator/hooks.d.ts +2 -0
  25. package/dist/prompt/compose.js +1 -1
  26. package/dist/prompt/reminders.js +3 -3
  27. package/dist/prompt/runtime.js +1 -0
  28. package/dist/provider-anthropic.d.ts +77 -0
  29. package/dist/provider-anthropic.js +544 -0
  30. package/dist/provider-openai-codex.d.ts +3 -0
  31. package/dist/provider-openai-codex.js +11 -2
  32. package/dist/provider-registry.d.ts +2 -0
  33. package/dist/provider-registry.js +29 -3
  34. package/dist/provider-transform.d.ts +1 -1
  35. package/dist/provider-transform.js +23 -0
  36. package/dist/provider.d.ts +4 -1
  37. package/dist/provider.js +119 -40
  38. package/dist/reasoning-debug.js +4 -1
  39. package/dist/session-log.js +17 -2
  40. package/dist/slash-commands/commands.js +4 -2
  41. package/dist/stats/usage.d.ts +4 -0
  42. package/dist/stats/usage.js +48 -11
  43. package/dist/tools/glob.js +3 -0
  44. package/dist/tools/grep.js +7 -0
  45. package/dist/tui/run.js +22 -12
  46. package/dist/tui-ink/app.js +3 -0
  47. package/dist/tui-ink/message-list.js +6 -3
  48. package/dist/tui-opentui/app.js +3 -0
  49. package/dist/tui-opentui/message-list.js +6 -3
  50. package/dist/types.d.ts +14 -1
  51. package/package.json +2 -1
@@ -0,0 +1,240 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { delimiter } from "node:path";
3
+ import { rootCertificates } from "node:tls";
4
+ import { Agent, ProxyAgent } from "undici";
5
+ let cachedDefaultFetch;
6
+ export function chatGptFetch(input, init) {
7
+ return getChatGptFetch()(input, init);
8
+ }
9
+ export function getChatGptFetch(env = process.env) {
10
+ const signature = networkEnvSignature(env);
11
+ if (!cachedDefaultFetch || cachedDefaultFetch.signature !== signature) {
12
+ cachedDefaultFetch = {
13
+ signature,
14
+ fetch: createChatGptFetch({ env }),
15
+ };
16
+ }
17
+ return cachedDefaultFetch.fetch;
18
+ }
19
+ export function createChatGptFetch(options = {}) {
20
+ const env = options.env ?? process.env;
21
+ const fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
22
+ const dispatcher = createChatGptDispatcher(env);
23
+ return async (input, init) => {
24
+ const requestInit = withChatGptNetworkOptions(input, init, env, dispatcher);
25
+ try {
26
+ return await fetchImpl(input, requestInit);
27
+ }
28
+ catch (error) {
29
+ throw normalizeChatGptNetworkError(error, env);
30
+ }
31
+ };
32
+ }
33
+ export function createChatGptDispatcher(env = process.env, input) {
34
+ if (isBunRuntime())
35
+ return undefined;
36
+ const ca = loadExtraCaCertificates(env);
37
+ if (!hasProxyEnv(env) && ca.length === 0)
38
+ return undefined;
39
+ const proxy = input ? nodeProxyForUrl(input, env) : defaultNodeProxy(env);
40
+ const caOptions = ca.length > 0 ? { ca: [...rootCertificates, ...ca] } : undefined;
41
+ if (proxy) {
42
+ return new ProxyAgent({
43
+ uri: proxy,
44
+ ...(caOptions ? { requestTls: caOptions, proxyTls: caOptions } : {}),
45
+ });
46
+ }
47
+ return caOptions ? new Agent({ connect: caOptions }) : undefined;
48
+ }
49
+ export function withChatGptNetworkOptions(input, init, env = process.env, dispatcher = createChatGptDispatcher(env, input)) {
50
+ const next = { ...(init ?? {}) };
51
+ if (isBunRuntime()) {
52
+ const proxy = bunProxyForUrl(input, env);
53
+ if (proxy)
54
+ next.proxy = proxy;
55
+ const ca = bunExtraCaFiles(env);
56
+ if (ca.length > 0)
57
+ next.tls = { ...(next.tls ?? {}), ca };
58
+ return next;
59
+ }
60
+ if (dispatcher)
61
+ next.dispatcher = dispatcher;
62
+ return next;
63
+ }
64
+ export function normalizeChatGptNetworkError(error, env = process.env) {
65
+ const text = errorMessageChain(error).join("\n");
66
+ if (!isChatGptNetworkErrorText(text)) {
67
+ return error instanceof Error ? error : new Error(String(error));
68
+ }
69
+ const message = [
70
+ "ChatGPT connection failed before Bubble received a response.",
71
+ isCertificateErrorText(text)
72
+ ? "TLS certificate verification failed. If you are on a corporate proxy, VPN, or HTTPS inspection network, start Bubble with NODE_EXTRA_CA_CERTS=/absolute/path/to/ca.pem or BUBBLE_EXTRA_CA_CERTS=/absolute/path/to/ca.pem."
73
+ : "This looks like a proxy or network transport failure.",
74
+ hasProxyEnv(env)
75
+ ? "Bubble is using proxy environment variables for ChatGPT requests. Make sure NO_PROXY includes localhost,127.0.0.1."
76
+ : "If your network requires a proxy, set HTTPS_PROXY or HTTP_PROXY, and set NO_PROXY=localhost,127.0.0.1.",
77
+ "Do not disable TLS verification with NODE_TLS_REJECT_UNAUTHORIZED=0.",
78
+ `Original error: ${firstMeaningfulErrorMessage(error) || "unknown network error"}`,
79
+ ].join(" ");
80
+ return new Error(message, { cause: error });
81
+ }
82
+ function hasProxyEnv(env) {
83
+ return Boolean(env.HTTPS_PROXY || env.https_proxy || env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy);
84
+ }
85
+ function isBunRuntime() {
86
+ return typeof globalThis.Bun !== "undefined";
87
+ }
88
+ function bunProxyForUrl(input, env) {
89
+ const url = urlFromInput(input);
90
+ if (!url || shouldBypassProxy(url, env))
91
+ return undefined;
92
+ const allProxy = env.ALL_PROXY ?? env.all_proxy;
93
+ if (url.protocol === "https:")
94
+ return env.HTTPS_PROXY ?? env.https_proxy ?? allProxy;
95
+ if (url.protocol === "http:")
96
+ return env.HTTP_PROXY ?? env.http_proxy ?? allProxy;
97
+ return undefined;
98
+ }
99
+ function nodeProxyForUrl(input, env) {
100
+ const url = urlFromInput(input);
101
+ if (!url || shouldBypassProxy(url, env))
102
+ return undefined;
103
+ if (url.protocol === "https:")
104
+ return env.HTTPS_PROXY ?? env.https_proxy ?? env.ALL_PROXY ?? env.all_proxy;
105
+ if (url.protocol === "http:")
106
+ return env.HTTP_PROXY ?? env.http_proxy ?? env.ALL_PROXY ?? env.all_proxy;
107
+ return defaultNodeProxy(env);
108
+ }
109
+ function defaultNodeProxy(env) {
110
+ return env.HTTPS_PROXY ?? env.https_proxy ?? env.HTTP_PROXY ?? env.http_proxy ?? env.ALL_PROXY ?? env.all_proxy;
111
+ }
112
+ function bunExtraCaFiles(env) {
113
+ const bun = globalThis.Bun;
114
+ if (!bun?.file)
115
+ return [];
116
+ return extraCaCertificatePaths(env).map((path) => bun.file(path));
117
+ }
118
+ function urlFromInput(input) {
119
+ if (input instanceof URL)
120
+ return input;
121
+ if (typeof input === "string")
122
+ return URL.canParse(input) ? new URL(input) : undefined;
123
+ const url = input.url;
124
+ return URL.canParse(url) ? new URL(url) : undefined;
125
+ }
126
+ function shouldBypassProxy(url, env) {
127
+ const noProxy = (env.NO_PROXY ?? env.no_proxy ?? "").trim();
128
+ if (!noProxy)
129
+ return false;
130
+ if (noProxy === "*")
131
+ return true;
132
+ const hostname = url.hostname.toLowerCase();
133
+ const port = url.port;
134
+ return noProxy
135
+ .split(/[,\s]+/)
136
+ .filter(Boolean)
137
+ .some((entry) => noProxyEntryMatches(entry.toLowerCase(), hostname, port));
138
+ }
139
+ function noProxyEntryMatches(entry, hostname, port) {
140
+ const [entryHost, entryPort] = entry.includes(":") ? entry.split(":") : [entry, ""];
141
+ if (entryPort && entryPort !== port)
142
+ return false;
143
+ if (entryHost === hostname)
144
+ return true;
145
+ if (entryHost.startsWith("*."))
146
+ return hostname.endsWith(entryHost.slice(1));
147
+ if (entryHost.startsWith("."))
148
+ return hostname.endsWith(entryHost);
149
+ return false;
150
+ }
151
+ function loadExtraCaCertificates(env) {
152
+ const paths = extraCaCertificatePaths(env);
153
+ return paths.map((path) => {
154
+ try {
155
+ return readFileSync(path, "utf-8");
156
+ }
157
+ catch (error) {
158
+ throw new Error(`Failed to read ChatGPT custom CA certificate at ${path}. Check NODE_EXTRA_CA_CERTS or BUBBLE_EXTRA_CA_CERTS.`, {
159
+ cause: error,
160
+ });
161
+ }
162
+ });
163
+ }
164
+ function extraCaCertificatePaths(env) {
165
+ const bubbleValue = env.BUBBLE_EXTRA_CA_CERTS?.trim();
166
+ if (bubbleValue) {
167
+ return bubbleValue.split(delimiter).map((item) => item.trim()).filter(Boolean);
168
+ }
169
+ const nodeValue = env.NODE_EXTRA_CA_CERTS?.trim();
170
+ return nodeValue ? [nodeValue] : [];
171
+ }
172
+ function networkEnvSignature(env) {
173
+ return [
174
+ env.HTTP_PROXY,
175
+ env.http_proxy,
176
+ env.HTTPS_PROXY,
177
+ env.https_proxy,
178
+ env.ALL_PROXY,
179
+ env.all_proxy,
180
+ env.NO_PROXY,
181
+ env.no_proxy,
182
+ env.NODE_EXTRA_CA_CERTS,
183
+ env.BUBBLE_EXTRA_CA_CERTS,
184
+ ].join("\0");
185
+ }
186
+ function isChatGptNetworkErrorText(text) {
187
+ return [
188
+ /fetch failed/i,
189
+ /network.*failed/i,
190
+ /socket connection was closed unexpectedly/i,
191
+ /\bConnectionClosed\b/i,
192
+ /\bECONNRESET\b/i,
193
+ /\bECONNREFUSED\b/i,
194
+ /\bETIMEDOUT\b/i,
195
+ /\bEPIPE\b/i,
196
+ /\bUND_ERR_/i,
197
+ /socket hang up/i,
198
+ /certificate/i,
199
+ /unable to verify/i,
200
+ /self[- ]signed/i,
201
+ ].some((pattern) => pattern.test(text));
202
+ }
203
+ function isCertificateErrorText(text) {
204
+ return [
205
+ /unknown certificate verification error/i,
206
+ /certificate (?:verify|verification) (?:failed|error)/i,
207
+ /unable to verify (?:the )?(?:first )?certificate/i,
208
+ /UNABLE_TO_(?:VERIFY_LEAF_SIGNATURE|GET_ISSUER_CERT_LOCALLY)/i,
209
+ /SELF_SIGNED_CERT_IN_CHAIN/i,
210
+ /DEPTH_ZERO_SELF_SIGNED_CERT/i,
211
+ /CERT_(?:HAS_EXPIRED|UNTRUSTED|INVALID)/i,
212
+ /self[- ]signed certificate/i,
213
+ ].some((pattern) => pattern.test(text));
214
+ }
215
+ function firstMeaningfulErrorMessage(error) {
216
+ return errorMessageChain(error).find((item) => item && item !== "Error");
217
+ }
218
+ function errorMessageChain(error) {
219
+ const messages = [];
220
+ let current = error;
221
+ for (let depth = 0; current && depth < 8; depth++) {
222
+ if (current instanceof Error) {
223
+ messages.push(current.name, current.message);
224
+ current = current.cause;
225
+ continue;
226
+ }
227
+ if (typeof current === "object") {
228
+ const record = current;
229
+ for (const key of ["name", "code", "message"]) {
230
+ if (typeof record[key] === "string")
231
+ messages.push(record[key]);
232
+ }
233
+ current = record.cause;
234
+ continue;
235
+ }
236
+ messages.push(String(current));
237
+ break;
238
+ }
239
+ return messages;
240
+ }
@@ -2,8 +2,13 @@
2
2
  * OpenAI Codex OAuth login (PKCE + local callback).
3
3
  */
4
4
  import type { OAuthTokens } from "./types.js";
5
+ import { type ChatGptFetch } from "../network/chatgpt-transport.js";
5
6
  export interface OpenAICodexLoginCallbacks {
6
7
  onStatus: (message: string) => void;
7
8
  }
8
- export declare function loginOpenAICodex(callbacks?: OpenAICodexLoginCallbacks): Promise<OAuthTokens>;
9
- export declare function refreshOpenAICodex(refreshToken: string): Promise<OAuthTokens>;
9
+ export declare function loginOpenAICodex(callbacks?: OpenAICodexLoginCallbacks, options?: {
10
+ fetch?: ChatGptFetch;
11
+ }): Promise<OAuthTokens>;
12
+ export declare function refreshOpenAICodex(refreshToken: string, options?: {
13
+ fetch?: ChatGptFetch;
14
+ }): Promise<OAuthTokens>;
@@ -4,6 +4,7 @@
4
4
  import { createServer } from "node:http";
5
5
  import { exec } from "node:child_process";
6
6
  import { randomBytes, createHash } from "node:crypto";
7
+ import { chatGptFetch } from "../network/chatgpt-transport.js";
7
8
  const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
8
9
  const AUTH_URL = "https://auth.openai.com/oauth/authorize";
9
10
  const TOKEN_URL = "https://auth.openai.com/oauth/token";
@@ -92,7 +93,8 @@ function extractAccountId(idToken) {
92
93
  const auth = claims?.["https://api.openai.com/auth"];
93
94
  return auth?.chatgpt_account_id || auth?.account_id || claims?.sub;
94
95
  }
95
- export async function loginOpenAICodex(callbacks) {
96
+ export async function loginOpenAICodex(callbacks, options = {}) {
97
+ const fetchImpl = options.fetch ?? chatGptFetch;
96
98
  callbacks?.onStatus("Starting OpenAI Codex OAuth login...");
97
99
  const pkce = generatePKCE();
98
100
  const state = generateState();
@@ -119,7 +121,7 @@ export async function loginOpenAICodex(callbacks) {
119
121
  throw new Error("OAuth state mismatch. Possible CSRF attack.");
120
122
  }
121
123
  callbacks?.onStatus("Exchanging authorization code for tokens...");
122
- const response = await fetch(TOKEN_URL, {
124
+ const response = await fetchImpl(TOKEN_URL, {
123
125
  method: "POST",
124
126
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
125
127
  body: new URLSearchParams({
@@ -146,8 +148,9 @@ export async function loginOpenAICodex(callbacks) {
146
148
  accountId,
147
149
  };
148
150
  }
149
- export async function refreshOpenAICodex(refreshToken) {
150
- const response = await fetch(TOKEN_URL, {
151
+ export async function refreshOpenAICodex(refreshToken, options = {}) {
152
+ const fetchImpl = options.fetch ?? chatGptFetch;
153
+ const response = await fetchImpl(TOKEN_URL, {
151
154
  method: "POST",
152
155
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
153
156
  body: new URLSearchParams({
@@ -2,6 +2,7 @@ import { classifyTask } from "../agent/task-classifier.js";
2
2
  import { classifyTaskSize } from "../agent/task-size.js";
3
3
  import { EvidenceTracker } from "../agent/evidence-tracker.js";
4
4
  import { ExecutionGovernor } from "../agent/execution-governor.js";
5
+ import { DiscoveryBarrier } from "../agent/discovery-barrier.js";
5
6
  import { arbitrateToolCall } from "../agent/tool-arbiter.js";
6
7
  import { buildEditRetryEscalationReminder, buildSmallTaskHint, buildTaskSummaryReminder, buildWorkflowPhaseReminder, } from "../prompt/reminders.js";
7
8
  import { reminderForTaskType } from "../prompt/task-reminders.js";
@@ -14,6 +15,11 @@ export function createDefaultHooks() {
14
15
  const taskType = classifyTask(ctx.input);
15
16
  ctx.state.taskType = taskType;
16
17
  ctx.state.governor = new ExecutionGovernor(taskType);
18
+ ctx.state.discoveryBarrier = new DiscoveryBarrier({
19
+ cwd: ctx.cwd,
20
+ input: ctx.input,
21
+ enabled: taskType === "repo_orientation",
22
+ });
17
23
  const taskReminder = reminderForTaskType(taskType);
18
24
  if (taskReminder) {
19
25
  ctx.queueReminder(taskReminder);
@@ -63,8 +69,12 @@ export function createDefaultHooks() {
63
69
  {
64
70
  beforeToolCall(ctx) {
65
71
  const arbitration = arbitrateToolCall(ctx.toolCall);
66
- ctx.replaceToolCall({ ...arbitration.toolCall, ...(arbitration.note ? { arbiterNote: arbitration.note } : {}) });
67
- ctx.state.governor?.beforeToolCall(ctx.toolCall);
72
+ const toolCall = { ...arbitration.toolCall, ...(arbitration.note ? { arbiterNote: arbitration.note } : {}) };
73
+ ctx.replaceToolCall(toolCall);
74
+ ctx.state.governor?.beforeToolCall(toolCall);
75
+ const blockedResult = ctx.state.discoveryBarrier?.beforeToolCall(toolCall);
76
+ if (blockedResult)
77
+ ctx.blockToolCall(blockedResult);
68
78
  },
69
79
  afterToolCall(ctx) {
70
80
  if (ctx.toolCall.arbiterNote) {
@@ -78,6 +88,7 @@ export function createDefaultHooks() {
78
88
  }
79
89
  ctx.state.evidenceTracker?.observe(ctx.toolCall, ctx.result);
80
90
  ctx.state.governor?.afterToolResult(ctx.toolCall, ctx.result);
91
+ ctx.state.discoveryBarrier?.afterToolCall(ctx.toolCall, ctx.result);
81
92
  // Edit/write retry-escalation: models can spiral on "identical content"
82
93
  // or "not found" errors. Nudge them to re-ground or switch strategy.
83
94
  if (isMutationTool(ctx.toolCall.name) && ctx.result.isError) {
@@ -3,10 +3,12 @@ import type { ContentPart, ParsedToolCall, ToolRegistryEntry, ToolResult } from
3
3
  import type { TaskType } from "../agent/task-classifier.js";
4
4
  import type { ExecutionGovernor } from "../agent/execution-governor.js";
5
5
  import type { EvidenceTracker } from "../agent/evidence-tracker.js";
6
+ import type { DiscoveryBarrier } from "../agent/discovery-barrier.js";
6
7
  import type { WorkflowPhase } from "./workflow.js";
7
8
  export interface TurnHookState {
8
9
  taskType?: TaskType;
9
10
  governor?: ExecutionGovernor;
11
+ discoveryBarrier?: DiscoveryBarrier;
10
12
  evidenceTracker?: EvidenceTracker;
11
13
  workflowPhase?: WorkflowPhase;
12
14
  workflowKey?: string;
@@ -38,7 +38,7 @@ function buildProviderPrompt(agentName, providerId, modelId, modelName) {
38
38
  const rawModel = modelId ?? modelName ?? "";
39
39
  const model = rawModel.includes(":") ? rawModel.split(":").slice(1).join(":") : rawModel;
40
40
  const lowerModel = model.toLowerCase();
41
- if (provider === "anthropic" || model.startsWith("claude")) {
41
+ if (provider === "anthropic" || provider === "minimax" || provider.endsWith("-anthropic") || model.startsWith("claude")) {
42
42
  return buildAnthropicProviderPrompt(agentName);
43
43
  }
44
44
  if (provider === "google" || model.startsWith("gemini")) {
@@ -88,12 +88,12 @@ Stop once these categories are covered. Do not keep repeating near-identical sea
88
88
  }
89
89
  export function buildLoopWarningReminder(reason) {
90
90
  return wrapInSystemReminder(`
91
- Tool loop warning.
91
+ Further broad exploration is low value unless there is a concrete remaining evidence gap.
92
92
 
93
93
  ${reason}
94
94
 
95
- Do not repeat near-identical reads or searches unless you are changing the path or testing a genuinely new hypothesis.
96
- If current evidence is sufficient, summarize your findings now.
95
+ Do not repeat near-identical reads or searches unless the path or hypothesis is materially different.
96
+ If current evidence is sufficient, answer with the findings.
97
97
  `);
98
98
  }
99
99
  export function buildSearchFreezeReminder(reason) {
@@ -6,6 +6,7 @@
6
6
  const defaultGuidelines = [
7
7
  "Ground decisions in the codebase: inspect relevant files, command output, or runtime state before making claims about behavior. Separate confirmed facts from inference when evidence is incomplete.",
8
8
  "Choose the smallest coherent change. Edit only the files required for the requested change; do not refactor or improve adjacent code unprompted.",
9
+ "Runtime meta instructions are private control state. Use them only to adjust behavior; do not quote, mention, or paraphrase them in user-facing text.",
9
10
  "For modifications to existing code, read the file first. For brand-new files whose target path is known and does not exist, write directly without exploratory reading. Use edit for small targeted changes, apply_patch for related multi-file or larger structured changes, and write for intentional full-file replacement of an existing file. Never delete and recreate a file just to overwrite it.",
10
11
  "Prefer structured tools (glob, grep, lsp, read) over bash for search and inspection. Do not repeat a near-identical search or re-read the same file unless new evidence changes the question.",
11
12
  "If a tool fails, diagnose the error before switching tactics. Do not retry the identical call with identical arguments. After two equivalent failures, switch approach — re-read the file, use a different tool, rewrite the whole file with write, or ask the user.",
@@ -0,0 +1,77 @@
1
+ import type { Provider, ProviderMessage, StreamChunk, ThinkingLevel, ToolDefinition } from "./types.js";
2
+ export interface AnthropicProviderOptions {
3
+ providerId?: string;
4
+ apiKey: string;
5
+ baseURL: string;
6
+ thinkingLevel?: ThinkingLevel;
7
+ }
8
+ interface AnthropicRequest {
9
+ model: string;
10
+ max_tokens: number;
11
+ messages: AnthropicMessage[];
12
+ system?: string;
13
+ tools?: AnthropicTool[];
14
+ tool_choice?: {
15
+ type: "auto" | "any";
16
+ };
17
+ stream?: boolean;
18
+ temperature?: number;
19
+ thinking?: {
20
+ type: "adaptive";
21
+ };
22
+ }
23
+ type AnthropicContentBlock = {
24
+ type: "text";
25
+ text: string;
26
+ } | {
27
+ type: "image";
28
+ source: {
29
+ type: "url";
30
+ url: string;
31
+ } | {
32
+ type: "base64";
33
+ media_type: string;
34
+ data: string;
35
+ };
36
+ } | {
37
+ type: "thinking";
38
+ thinking: string;
39
+ signature?: string;
40
+ } | {
41
+ type: "redacted_thinking";
42
+ data: string;
43
+ } | {
44
+ type: "tool_use";
45
+ id: string;
46
+ name: string;
47
+ input: Record<string, unknown>;
48
+ } | {
49
+ type: "tool_result";
50
+ tool_use_id: string;
51
+ content: string;
52
+ is_error?: boolean;
53
+ };
54
+ interface AnthropicMessage {
55
+ role: "user" | "assistant";
56
+ content: string | AnthropicContentBlock[];
57
+ }
58
+ interface AnthropicTool {
59
+ name: string;
60
+ description: string;
61
+ input_schema: ToolDefinition["parameters"];
62
+ }
63
+ export declare function createAnthropicMessagesProvider(options: AnthropicProviderOptions): Provider;
64
+ export declare function buildAnthropicRequest(options: AnthropicProviderOptions, messages: ProviderMessage[], chatOptions: {
65
+ model: string;
66
+ tools?: ToolDefinition[];
67
+ temperature?: number;
68
+ thinkingLevel?: ThinkingLevel;
69
+ stream?: boolean;
70
+ }): AnthropicRequest;
71
+ export declare function toAnthropicMessages(messages: ProviderMessage[], echoThinking?: boolean): {
72
+ system: string;
73
+ messages: AnthropicMessage[];
74
+ };
75
+ export declare function translateAnthropicStream(events: AsyncIterable<Record<string, unknown>>): AsyncIterable<StreamChunk>;
76
+ export declare function readSseEvents(response: Response): AsyncIterable<Record<string, unknown>>;
77
+ export {};