@avasis-ai/synthcode 1.0.0

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/chunk-53ZOIXM4.js +624 -0
  4. package/dist/chunk-53ZOIXM4.js.map +1 -0
  5. package/dist/chunk-BWXHO6UJ.js +115 -0
  6. package/dist/chunk-BWXHO6UJ.js.map +1 -0
  7. package/dist/chunk-CARUMOML.js +123 -0
  8. package/dist/chunk-CARUMOML.js.map +1 -0
  9. package/dist/chunk-DGUM43GV.js +11 -0
  10. package/dist/chunk-DGUM43GV.js.map +1 -0
  11. package/dist/chunk-F34HO4RA.js +487 -0
  12. package/dist/chunk-F34HO4RA.js.map +1 -0
  13. package/dist/chunk-FK7S2S7V.js +132 -0
  14. package/dist/chunk-FK7S2S7V.js.map +1 -0
  15. package/dist/chunk-MQ7XP6VT.js +174 -0
  16. package/dist/chunk-MQ7XP6VT.js.map +1 -0
  17. package/dist/chunk-TLPOO6C3.js +176 -0
  18. package/dist/chunk-TLPOO6C3.js.map +1 -0
  19. package/dist/chunk-W6OLZ2OI.js +56 -0
  20. package/dist/chunk-W6OLZ2OI.js.map +1 -0
  21. package/dist/cli/index.cjs +151 -0
  22. package/dist/cli/index.cjs.map +1 -0
  23. package/dist/cli/index.d.cts +1 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +8 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/run.cjs +128 -0
  28. package/dist/cli/run.cjs.map +1 -0
  29. package/dist/cli/run.d.cts +1 -0
  30. package/dist/cli/run.d.ts +1 -0
  31. package/dist/cli/run.js +126 -0
  32. package/dist/cli/run.js.map +1 -0
  33. package/dist/index-D-K6sx8s.d.cts +8 -0
  34. package/dist/index-D-K6sx8s.d.ts +8 -0
  35. package/dist/index.cjs +2909 -0
  36. package/dist/index.cjs.map +1 -0
  37. package/dist/index.d.cts +274 -0
  38. package/dist/index.d.ts +274 -0
  39. package/dist/index.js +1048 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/llm/index.cjs +531 -0
  42. package/dist/llm/index.cjs.map +1 -0
  43. package/dist/llm/index.d.cts +70 -0
  44. package/dist/llm/index.d.ts +70 -0
  45. package/dist/llm/index.js +24 -0
  46. package/dist/llm/index.js.map +1 -0
  47. package/dist/mcp/index.cjs +323 -0
  48. package/dist/mcp/index.cjs.map +1 -0
  49. package/dist/mcp/index.d.cts +39 -0
  50. package/dist/mcp/index.d.ts +39 -0
  51. package/dist/mcp/index.js +11 -0
  52. package/dist/mcp/index.js.map +1 -0
  53. package/dist/memory/index.cjs +146 -0
  54. package/dist/memory/index.cjs.map +1 -0
  55. package/dist/memory/index.d.cts +51 -0
  56. package/dist/memory/index.d.ts +51 -0
  57. package/dist/memory/index.js +10 -0
  58. package/dist/memory/index.js.map +1 -0
  59. package/dist/tools/fuzzy-edit.cjs +200 -0
  60. package/dist/tools/fuzzy-edit.cjs.map +1 -0
  61. package/dist/tools/fuzzy-edit.d.cts +9 -0
  62. package/dist/tools/fuzzy-edit.d.ts +9 -0
  63. package/dist/tools/fuzzy-edit.js +12 -0
  64. package/dist/tools/fuzzy-edit.js.map +1 -0
  65. package/dist/tools/index.cjs +1032 -0
  66. package/dist/tools/index.cjs.map +1 -0
  67. package/dist/tools/index.d.cts +4 -0
  68. package/dist/tools/index.d.ts +4 -0
  69. package/dist/tools/index.js +39 -0
  70. package/dist/tools/index.js.map +1 -0
  71. package/dist/types-C11cw5ZD.d.cts +177 -0
  72. package/dist/types-C11cw5ZD.d.ts +177 -0
  73. package/dist/utils-TF4TBXQJ.js +10 -0
  74. package/dist/utils-TF4TBXQJ.js.map +1 -0
  75. package/dist/web-fetch-B42QzYD2.d.cts +85 -0
  76. package/dist/web-fetch-EDdhxmEf.d.ts +85 -0
  77. package/package.json +134 -0
package/dist/index.js ADDED
@@ -0,0 +1,1048 @@
1
+ import {
2
+ AnthropicProvider,
3
+ BaseProvider,
4
+ OllamaProvider,
5
+ OpenAIProvider,
6
+ RetryableError,
7
+ anthropic,
8
+ createProvider,
9
+ ollama,
10
+ openai
11
+ } from "./chunk-F34HO4RA.js";
12
+ import {
13
+ BashTool,
14
+ FileEditTool,
15
+ FileReadTool,
16
+ FileWriteTool,
17
+ GlobTool,
18
+ GrepTool,
19
+ ToolRegistry,
20
+ WebFetchTool,
21
+ orchestrateTools
22
+ } from "./chunk-53ZOIXM4.js";
23
+ import "./chunk-W6OLZ2OI.js";
24
+ import {
25
+ InMemoryStore,
26
+ SQLiteStore
27
+ } from "./chunk-CARUMOML.js";
28
+ import {
29
+ MCPClient,
30
+ loadMCPTools
31
+ } from "./chunk-TLPOO6C3.js";
32
+ import {
33
+ defineTool,
34
+ defineToolFromClass
35
+ } from "./chunk-FK7S2S7V.js";
36
+ import {
37
+ init
38
+ } from "./chunk-BWXHO6UJ.js";
39
+ import "./chunk-MQ7XP6VT.js";
40
+ import "./chunk-DGUM43GV.js";
41
+
42
+ // src/types.ts
43
+ var DEFAULT_CONTEXT_WINDOW = 2e5;
44
+ var DEFAULT_MAX_OUTPUT_TOKENS = 16384;
45
+ var DEFAULT_COMPACT_THRESHOLD = 0.85;
46
+ var DEFAULT_MAX_TURNS = 100;
47
+ var MAX_CONCURRENT_TOOLS = 10;
48
+
49
+ // src/hooks.ts
50
+ var HookRunner = class {
51
+ hooks;
52
+ constructor(hooks) {
53
+ this.hooks = hooks ?? {};
54
+ }
55
+ async runOnTurnStart(turn, messages) {
56
+ if (!this.hooks.onTurnStart) return messages;
57
+ const result = await this.hooks.onTurnStart(turn, messages);
58
+ return Array.isArray(result) ? result : messages;
59
+ }
60
+ async runOnTurnEnd(turn, messages) {
61
+ await this.hooks.onTurnEnd?.(turn, messages);
62
+ }
63
+ async runOnToolUse(name, input) {
64
+ if (!this.hooks.onToolUse) return { allow: true, input };
65
+ const result = await this.hooks.onToolUse(name, input);
66
+ return {
67
+ allow: result?.allow ?? true,
68
+ input: result?.input ?? input
69
+ };
70
+ }
71
+ async runOnToolResult(result) {
72
+ if (!this.hooks.onToolResult) return result.output;
73
+ const modified = await this.hooks.onToolResult(result);
74
+ return modified ?? result.output;
75
+ }
76
+ async runOnError(error, turn) {
77
+ if (!this.hooks.onError) return { retry: false };
78
+ const result = await this.hooks.onError(error, turn);
79
+ return { retry: result?.retry ?? false, message: result?.message };
80
+ }
81
+ async runOnCompact(result) {
82
+ await this.hooks.onCompact?.(result);
83
+ }
84
+ };
85
+
86
+ // src/loop.ts
87
+ var DEFAULT_MAX_RETRIES = 5;
88
+ var INITIAL_RETRY_DELAY_MS = 1e3;
89
+ var MAX_RETRY_DELAY_MS = 3e4;
90
+ var DOOM_LOOP_THRESHOLD = 3;
91
+ var PRE_OVERFLOW_BUFFER = 2e4;
92
+ var OUTPUT_MAX_LINES = 2e3;
93
+ var OUTPUT_MAX_BYTES = 5e4;
94
+ function parseRetryAfterMs(error) {
95
+ const msg = error.message ?? "";
96
+ const retryAfterMsMatch = msg.match(/retry-after-ms:\s*(\d+)/i);
97
+ if (retryAfterMsMatch) return parseInt(retryAfterMsMatch[1], 10);
98
+ const retryAfterMatch = msg.match(/retry-after:\s*(\d+)/i);
99
+ if (retryAfterMatch) return parseInt(retryAfterMatch[1], 10) * 1e3;
100
+ return null;
101
+ }
102
+ function truncateOutput(output, toolName, hasSubAgent) {
103
+ const lines = output.split("\n");
104
+ if (lines.length <= OUTPUT_MAX_LINES && output.length <= OUTPUT_MAX_BYTES) return output;
105
+ let truncated = "";
106
+ let byteCount = 0;
107
+ for (const line of lines) {
108
+ if (byteCount + line.length > OUTPUT_MAX_BYTES) break;
109
+ truncated += line + "\n";
110
+ byteCount += line.length;
111
+ if (byteCount > OUTPUT_MAX_BYTES) break;
112
+ }
113
+ const lineCount = truncated.split("\n").filter((l) => l.length > 0).length;
114
+ const suffix = hasSubAgent ? `
115
+
116
+ [Output truncated: ${lineCount}/${lines.length} lines shown. Use the Task tool to have a sub-agent process the full output.]` : `
117
+
118
+ [Output truncated: ${lineCount}/${lines.length} lines shown. Use Grep to search or Read with offset/limit for the full content.]`;
119
+ return truncated.trimEnd() + suffix;
120
+ }
121
+ function detectDoomLoop(messages) {
122
+ const recentToolCalls = [];
123
+ for (let i = messages.length - 1; i >= 0; i--) {
124
+ const msg = messages[i];
125
+ if (msg.role !== "assistant") continue;
126
+ if (typeof msg.content === "string") continue;
127
+ for (const block of msg.content) {
128
+ if (block.type === "tool_use") recentToolCalls.push(block);
129
+ }
130
+ if (recentToolCalls.length >= DOOM_LOOP_THRESHOLD) break;
131
+ }
132
+ if (recentToolCalls.length < DOOM_LOOP_THRESHOLD) return null;
133
+ const last = recentToolCalls[0];
134
+ return recentToolCalls.every(
135
+ (tc) => tc.name === last.name && JSON.stringify(tc.input) === JSON.stringify(last.input)
136
+ ) ? last : null;
137
+ }
138
+ async function* agentLoop(config) {
139
+ const {
140
+ model,
141
+ tools,
142
+ messages,
143
+ systemPrompt,
144
+ maxTurns = DEFAULT_MAX_TURNS,
145
+ contextManager,
146
+ permissionEngine,
147
+ cwd = process.cwd(),
148
+ abortSignal,
149
+ hooks,
150
+ costTracker
151
+ } = config;
152
+ const hookRunner = new HookRunner(hooks);
153
+ const context = { cwd, env: { ...process.env } };
154
+ let turns = 0;
155
+ let consecutiveRetries = 0;
156
+ const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
157
+ let totalUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
158
+ let inFlightText = "";
159
+ let inFlightReasoning = "";
160
+ let inFlightToolCalls = [];
161
+ while (turns < maxTurns) {
162
+ if (abortSignal?.aborted) {
163
+ yield finalizeLoop("Aborted");
164
+ return;
165
+ }
166
+ const messagesAfterHook = await hookRunner.runOnTurnStart(turns + 1, messages);
167
+ if (messagesAfterHook !== messages) {
168
+ messages.length = 0;
169
+ messages.push(...messagesAfterHook);
170
+ }
171
+ const contextCheck = contextManager.check(messages);
172
+ if (contextCheck.needsCompact) {
173
+ const result = await contextManager.compact(messages);
174
+ messages.length = 0;
175
+ messages.push(...result.messages);
176
+ if (result.tokensSaved > 0) {
177
+ const thinking = `Context ${result.method}: saved ~${result.tokensSaved} tokens (${contextCheck.totalTokens} \u2192 ${contextCheck.totalTokens - result.tokensSaved})`;
178
+ yield { type: "thinking", thinking };
179
+ await hookRunner.runOnCompact(result);
180
+ }
181
+ const pruned = contextManager.pruneToolOutputs(messages);
182
+ if (pruned.length !== messages.length) {
183
+ messages.length = 0;
184
+ messages.push(...pruned);
185
+ yield { type: "thinking", thinking: "Pruned large tool outputs to free additional context" };
186
+ }
187
+ }
188
+ const estimatedTotal = totalUsage.inputTokens + totalUsage.outputTokens + (totalUsage.cacheReadTokens ?? 0) + (totalUsage.cacheWriteTokens ?? 0);
189
+ const maxContext = contextManager.maxTokens;
190
+ const maxOutput = contextManager.maxOutputTokens;
191
+ if (maxContext > 0 && estimatedTotal + maxOutput + PRE_OVERFLOW_BUFFER >= maxContext) {
192
+ yield { type: "thinking", thinking: "Approaching context limit, compacting preemptively..." };
193
+ const result = await contextManager.compact(messages);
194
+ messages.length = 0;
195
+ messages.push(...result.messages);
196
+ if (result.tokensSaved > 0) {
197
+ yield { type: "thinking", thinking: `Pre-overflow compact: freed ~${result.tokensSaved} tokens` };
198
+ }
199
+ }
200
+ const available = contextManager.getAvailableTokens(messages);
201
+ const maxTokens = Math.min(available, contextManager.maxOutputTokens);
202
+ if (maxTokens < 1024) {
203
+ yield finalizeLoop("Insufficient context window for next turn");
204
+ return;
205
+ }
206
+ inFlightText = "";
207
+ inFlightReasoning = "";
208
+ inFlightToolCalls = [];
209
+ let response;
210
+ try {
211
+ const mappedMessages = messages.map((m) => {
212
+ if (m.role === "tool") {
213
+ const toolCall = inFlightToolCalls.find((tc) => tc.id === m.tool_use_id);
214
+ if (toolCall) {
215
+ return {
216
+ role: "tool",
217
+ tool_use_id: m.role === "tool" ? m.tool_use_id : void 0,
218
+ is_error: m.role === "tool" ? m.is_error : void 0,
219
+ content: truncateOutput(
220
+ m.content,
221
+ toolCall.name,
222
+ tools.has("delegate_agent")
223
+ )
224
+ };
225
+ }
226
+ }
227
+ return {
228
+ role: m.role,
229
+ content: m.role === "tool" ? m.content : m.role === "user" ? m.content : m.content,
230
+ tool_use_id: m.role === "tool" ? m.tool_use_id : void 0,
231
+ is_error: m.role === "tool" ? m.is_error : void 0
232
+ };
233
+ });
234
+ response = await model.chat({
235
+ messages: mappedMessages,
236
+ tools: tools.getAPI(),
237
+ systemPrompt,
238
+ maxOutputTokens: maxTokens,
239
+ abortSignal
240
+ });
241
+ } catch (err) {
242
+ yield* flushInFlight();
243
+ const error = err instanceof Error ? err : new Error(String(err));
244
+ const hookResult = await hookRunner.runOnError(error, turns + 1);
245
+ if (hookResult.retry && hookResult.message) {
246
+ messages.push({ role: "user", content: hookResult.message });
247
+ turns++;
248
+ continue;
249
+ }
250
+ if (error.message.includes("429") || error.message.includes("529") || error.message.includes("overloaded")) {
251
+ consecutiveRetries++;
252
+ if (consecutiveRetries > maxRetries) {
253
+ yield { type: "error", error: new Error(`Max retries (${maxRetries}) exceeded`) };
254
+ return;
255
+ }
256
+ const headerDelay = parseRetryAfterMs(error);
257
+ const backoffDelay = headerDelay ?? Math.min(INITIAL_RETRY_DELAY_MS * 2 ** (consecutiveRetries - 1) + Math.random() * 500, MAX_RETRY_DELAY_MS);
258
+ yield { type: "thinking", thinking: `Rate limited, retry ${consecutiveRetries}/${maxRetries} in ${Math.round(backoffDelay)}ms...` };
259
+ await new Promise((r) => setTimeout(r, backoffDelay));
260
+ continue;
261
+ }
262
+ yield { type: "error", error };
263
+ return;
264
+ }
265
+ totalUsage.inputTokens += response.usage.inputTokens;
266
+ totalUsage.outputTokens += response.usage.outputTokens;
267
+ totalUsage.cacheReadTokens = (totalUsage.cacheReadTokens ?? 0) + (response.usage.cacheReadTokens ?? 0);
268
+ totalUsage.cacheWriteTokens = (totalUsage.cacheWriteTokens ?? 0) + (response.usage.cacheWriteTokens ?? 0);
269
+ if (costTracker) {
270
+ costTracker.record(model.model, response.usage, turns + 1);
271
+ }
272
+ const toolCalls = [];
273
+ for (const block of response.content) {
274
+ if (block.type === "text") {
275
+ inFlightText += block.text;
276
+ yield { type: "text", text: block.text };
277
+ } else if (block.type === "thinking") {
278
+ inFlightReasoning += block.thinking;
279
+ yield { type: "thinking", thinking: block.thinking };
280
+ } else if (block.type === "tool_use") {
281
+ const resolvedName = tools.has(block.name) ? block.name : tools.findCaseInsensitive(block.name);
282
+ if (!resolvedName) {
283
+ yield { type: "tool_result", id: block.id, name: block.name, output: `Unknown tool: ${block.name}. Available: ${tools.listNames().join(", ")}`, isError: true };
284
+ messages.push({ role: "assistant", content: response.content });
285
+ messages.push({ role: "tool", tool_use_id: block.id, content: `Unknown tool: ${block.name}`, is_error: true });
286
+ continue;
287
+ }
288
+ const modifiedBlock = resolvedName !== block.name ? { ...block, name: resolvedName } : block;
289
+ const hookToolResult = await hookRunner.runOnToolUse(modifiedBlock.name, modifiedBlock.input);
290
+ if (!hookToolResult.allow) {
291
+ yield { type: "tool_result", id: modifiedBlock.id, name: modifiedBlock.name, output: "Tool denied by hook", isError: true };
292
+ messages.push({ role: "assistant", content: response.content });
293
+ messages.push({ role: "tool", tool_use_id: modifiedBlock.id, content: "Tool denied by hook", is_error: true });
294
+ continue;
295
+ }
296
+ const finalBlock = { ...modifiedBlock, input: hookToolResult.input };
297
+ toolCalls.push(finalBlock);
298
+ inFlightToolCalls.push(finalBlock);
299
+ yield { type: "tool_use", id: finalBlock.id, name: finalBlock.name, input: finalBlock.input };
300
+ }
301
+ }
302
+ const hasNonToolContent = inFlightText.length > 0 || inFlightReasoning.length > 0;
303
+ if (!hasNonToolContent && toolCalls.length === 0) {
304
+ yield finalizeLoop("Assistant produced no content");
305
+ return;
306
+ }
307
+ const assistantContent = response.content.filter((b) => {
308
+ if (b.type !== "tool_use") return true;
309
+ return toolCalls.some((tc) => tc.id === b.id);
310
+ });
311
+ messages.push({ role: "assistant", content: assistantContent });
312
+ turns++;
313
+ consecutiveRetries = 0;
314
+ inFlightText = "";
315
+ inFlightReasoning = "";
316
+ inFlightToolCalls = [];
317
+ await hookRunner.runOnTurnEnd(turns, messages);
318
+ if (response.stopReason !== "tool_use" || toolCalls.length === 0) {
319
+ yield {
320
+ type: "done",
321
+ usage: {
322
+ inputTokens: totalUsage.inputTokens,
323
+ outputTokens: totalUsage.outputTokens,
324
+ cacheReadTokens: totalUsage.cacheReadTokens,
325
+ cacheWriteTokens: totalUsage.cacheWriteTokens
326
+ },
327
+ messages: [...messages]
328
+ };
329
+ return;
330
+ }
331
+ const doomLoopCall = detectDoomLoop(messages);
332
+ if (doomLoopCall) {
333
+ yield { type: "thinking", thinking: `Detected repetitive tool calls: ${doomLoopCall.name} called ${DOOM_LOOP_THRESHOLD} times with identical input. Breaking the loop.` };
334
+ messages.push({ role: "user", content: `STOP. You have called ${doomLoopCall.name} ${DOOM_LOOP_THRESHOLD} times in a row with the same input. This indicates a loop. Try a different approach or tool.` });
335
+ turns++;
336
+ continue;
337
+ }
338
+ const results = await orchestrateTools(
339
+ tools,
340
+ toolCalls,
341
+ context,
342
+ async (name, _input) => {
343
+ const perm = permissionEngine.check(name);
344
+ return perm.allowed;
345
+ },
346
+ abortSignal
347
+ );
348
+ for (const result of results) {
349
+ let output = truncateOutput(result.output, result.name, tools.has("delegate_agent"));
350
+ const toolResult = await hookRunner.runOnToolResult({
351
+ id: result.id,
352
+ name: result.name,
353
+ output: result.output,
354
+ isError: result.isError,
355
+ durationMs: result.durationMs
356
+ });
357
+ output = toolResult;
358
+ messages.push({
359
+ role: "tool",
360
+ tool_use_id: result.id,
361
+ content: output,
362
+ is_error: result.isError
363
+ });
364
+ yield {
365
+ type: "tool_result",
366
+ id: result.id,
367
+ name: result.name,
368
+ output,
369
+ isError: result.isError
370
+ };
371
+ }
372
+ }
373
+ yield { type: "error", error: new Error(`Max turns (${maxTurns}) reached`) };
374
+ function* flushInFlight() {
375
+ if (inFlightText.length > 0) {
376
+ yield { type: "text", text: inFlightText };
377
+ }
378
+ if (inFlightReasoning.length > 0) {
379
+ yield { type: "thinking", thinking: inFlightReasoning };
380
+ }
381
+ for (const tc of inFlightToolCalls) {
382
+ yield { type: "tool_result", id: tc.id, name: tc.name, output: "[Tool execution was interrupted]", isError: true };
383
+ messages.push({ role: "assistant", content: [{ type: "tool_use", id: tc.id, name: tc.name, input: tc.input }] });
384
+ messages.push({ role: "tool", tool_use_id: tc.id, content: "[Tool execution was interrupted]", is_error: true });
385
+ }
386
+ }
387
+ function finalizeLoop(reason) {
388
+ if (totalUsage.inputTokens > 0 || totalUsage.outputTokens > 0) {
389
+ return {
390
+ type: "done",
391
+ usage: {
392
+ inputTokens: totalUsage.inputTokens,
393
+ outputTokens: totalUsage.outputTokens,
394
+ cacheReadTokens: totalUsage.cacheReadTokens,
395
+ cacheWriteTokens: totalUsage.cacheWriteTokens
396
+ },
397
+ messages: [...messages]
398
+ };
399
+ }
400
+ return { type: "error", error: new Error(reason) };
401
+ }
402
+ }
403
+
404
+ // src/context/tokenizer.ts
405
+ function estimateTokens(text) {
406
+ const chars = text.length;
407
+ const words = text.split(/\s+/).filter(Boolean).length;
408
+ return Math.max(Math.ceil(chars / 4), Math.ceil(words * 1.3));
409
+ }
410
+ function estimateMessageTokens(message) {
411
+ if (message.role === "user") {
412
+ return estimateTokens(message.content) + 4;
413
+ }
414
+ if (message.role === "tool") {
415
+ return estimateTokens(message.content) + 4;
416
+ }
417
+ let tokens = 0;
418
+ for (const block of message.content) {
419
+ if (block.type === "text") {
420
+ tokens += estimateTokens(block.text) + 4;
421
+ } else if (block.type === "tool_use") {
422
+ tokens += estimateTokens(block.name) + estimateTokens(JSON.stringify(block.input)) + 4;
423
+ } else if (block.type === "thinking") {
424
+ tokens += estimateTokens(block.thinking) + 4;
425
+ }
426
+ }
427
+ return tokens;
428
+ }
429
+ function estimateConversationTokens(messages) {
430
+ const byRole = {};
431
+ let total = 0;
432
+ for (const message of messages) {
433
+ const msgTokens = estimateMessageTokens(message) + 10;
434
+ total += msgTokens;
435
+ byRole[message.role] = (byRole[message.role] ?? 0) + msgTokens;
436
+ }
437
+ return { total, byRole };
438
+ }
439
+
440
+ // src/context/manager.ts
441
+ var PRUNE_MINIMUM = 2e4;
442
+ var PRUNE_PROTECT_TOKENS = 4e4;
443
+ var PROTECTED_TOOL_TYPES = /* @__PURE__ */ new Set(["skill", "delegate_agent"]);
444
+ var RECENT_TURNS_TO_PROTECT = 2;
445
+ var ContextManager = class {
446
+ maxTokens;
447
+ maxOutputTokens;
448
+ compactThreshold;
449
+ constructor(config) {
450
+ this.maxTokens = config?.maxTokens ?? DEFAULT_CONTEXT_WINDOW;
451
+ this.maxOutputTokens = config?.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
452
+ this.compactThreshold = config?.compactThreshold ?? DEFAULT_COMPACT_THRESHOLD;
453
+ }
454
+ check(messages) {
455
+ const { total: totalTokens } = estimateConversationTokens(messages);
456
+ const availableTokens = this.maxTokens - totalTokens - this.maxOutputTokens;
457
+ const usagePercent = totalTokens / this.maxTokens;
458
+ const needsCompact = usagePercent >= this.compactThreshold;
459
+ let recommendedMethod;
460
+ if (usagePercent > 0.95) {
461
+ recommendedMethod = "compact";
462
+ } else {
463
+ recommendedMethod = "snip";
464
+ }
465
+ return { totalTokens, availableTokens, usagePercent, needsCompact, recommendedMethod };
466
+ }
467
+ async compact(messages, summaryFn) {
468
+ const contextCheck = this.check(messages);
469
+ if (!contextCheck.needsCompact) {
470
+ return { messages: [...messages], tokensSaved: 0, method: "none" };
471
+ }
472
+ const originalTokens = contextCheck.totalTokens;
473
+ if (summaryFn && contextCheck.recommendedMethod === "compact") {
474
+ const recentCount = Math.max(Math.ceil(messages.length * 0.2), 1);
475
+ const cutoffIndex = messages.length - recentCount;
476
+ const oldMessages = messages.slice(0, cutoffIndex);
477
+ const recentMessages = messages.slice(cutoffIndex);
478
+ const summary = await summaryFn(oldMessages);
479
+ const summaryMessage = {
480
+ role: "user",
481
+ content: `Here is a summary of our previous conversation:
482
+ ${summary}`
483
+ };
484
+ const compacted = [summaryMessage, ...recentMessages];
485
+ const newTokens2 = estimateConversationTokens(compacted).total;
486
+ return {
487
+ messages: compacted,
488
+ tokensSaved: originalTokens - newTokens2,
489
+ method: "compact"
490
+ };
491
+ }
492
+ const keepFirst = 1;
493
+ const keepLast = 20;
494
+ const keepMin = keepFirst + keepLast;
495
+ if (messages.length <= keepMin) {
496
+ return { messages: [...messages], tokensSaved: 0, method: "none" };
497
+ }
498
+ let result = [...messages];
499
+ const targetUsage = 0.6;
500
+ while (result.length > keepMin) {
501
+ const { total } = estimateConversationTokens(result);
502
+ if (total / this.maxTokens < targetUsage) break;
503
+ const removeCount = Math.max(1, Math.floor((result.length - keepMin) * 0.3));
504
+ const removeEnd = Math.min(keepFirst + removeCount, result.length - keepLast);
505
+ result = [result[0], ...result.slice(removeEnd)];
506
+ }
507
+ const newTokens = estimateConversationTokens(result).total;
508
+ return {
509
+ messages: result,
510
+ tokensSaved: originalTokens - newTokens,
511
+ method: "snip"
512
+ };
513
+ }
514
+ pruneToolOutputs(messages) {
515
+ let totalPruned = 0;
516
+ let turnCount = 0;
517
+ const result = [...messages];
518
+ for (let i = result.length - 1; i >= 0; i--) {
519
+ const msg = result[i];
520
+ if (msg.role === "user") {
521
+ turnCount++;
522
+ if (turnCount <= RECENT_TURNS_TO_PROTECT) continue;
523
+ }
524
+ if (msg.role !== "assistant" || !Array.isArray(msg.content)) continue;
525
+ for (const block of msg.content) {
526
+ if (block.type !== "tool_use") continue;
527
+ if (PROTECTED_TOOL_TYPES.has(block.name)) continue;
528
+ const toolResultIdx = result.findIndex(
529
+ (m, j) => j > i && m.role === "tool" && m.tool_use_id === block.id
530
+ );
531
+ if (toolResultIdx === -1) continue;
532
+ const toolResult = result[toolResultIdx];
533
+ const output = toolResult.content;
534
+ const estTokens = Math.ceil(output.length / 4);
535
+ if (totalPruned + estTokens >= PRUNE_MINIMUM && totalPruned >= PRUNE_PROTECT_TOKENS) {
536
+ return result;
537
+ }
538
+ totalPruned += estTokens;
539
+ result[toolResultIdx] = {
540
+ ...toolResult,
541
+ content: `[Output pruned: ${estTokens} tokens saved]`,
542
+ is_error: false
543
+ };
544
+ }
545
+ }
546
+ return result;
547
+ }
548
+ getAvailableTokens(messages) {
549
+ return this.maxTokens - estimateConversationTokens(messages).total - this.maxOutputTokens;
550
+ }
551
+ getUsagePercent(messages) {
552
+ return estimateConversationTokens(messages).total / this.maxTokens;
553
+ }
554
+ };
555
+
556
+ // src/permissions/engine.ts
557
+ function matchPattern(pattern, toolName) {
558
+ if (!pattern.includes("*")) {
559
+ return pattern === toolName;
560
+ }
561
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
562
+ const regex = new RegExp(`^${escaped}$`);
563
+ return regex.test(toolName);
564
+ }
565
+ var PermissionEngine = class {
566
+ allowedPatterns;
567
+ deniedPatterns;
568
+ askPatterns;
569
+ defaultAction;
570
+ constructor(config) {
571
+ this.allowedPatterns = config?.allowedTools ?? [];
572
+ this.deniedPatterns = config?.deniedTools ?? [];
573
+ this.askPatterns = config?.askTools ?? [];
574
+ this.defaultAction = config?.defaultAction ?? "allow";
575
+ }
576
+ check(toolName, _input) {
577
+ for (const pattern of this.deniedPatterns) {
578
+ if (matchPattern(pattern, toolName)) {
579
+ return { allowed: false, reason: `Tool '${toolName}' matches denied pattern '${pattern}'` };
580
+ }
581
+ }
582
+ for (const pattern of this.allowedPatterns) {
583
+ if (matchPattern(pattern, toolName)) {
584
+ return { allowed: true };
585
+ }
586
+ }
587
+ for (const pattern of this.askPatterns) {
588
+ if (matchPattern(pattern, toolName)) {
589
+ return { allowed: false, reason: "ask" };
590
+ }
591
+ }
592
+ if (this.defaultAction === "deny") {
593
+ return { allowed: false, reason: `Tool '${toolName}' not explicitly allowed` };
594
+ }
595
+ if (this.defaultAction === "ask") {
596
+ return { allowed: false, reason: "ask" };
597
+ }
598
+ return { allowed: true };
599
+ }
600
+ addAllowed(pattern) {
601
+ this.allowedPatterns.push(pattern);
602
+ }
603
+ addDenied(pattern) {
604
+ this.deniedPatterns.push(pattern);
605
+ }
606
+ addAsk(pattern) {
607
+ this.askPatterns.push(pattern);
608
+ }
609
+ };
610
+
611
+ // src/cost/tracker.ts
612
+ var DEFAULT_PRICING = {
613
+ "claude-sonnet-4-20250514": { inputCostPer1k: 3e-3, outputCostPer1k: 0.015 },
614
+ "claude-3-5-sonnet-20241022": { inputCostPer1k: 3e-3, outputCostPer1k: 0.015 },
615
+ "claude-3-5-haiku-20241022": { inputCostPer1k: 8e-4, outputCostPer1k: 4e-3 },
616
+ "claude-opus-4-20250514": { inputCostPer1k: 0.015, outputCostPer1k: 0.075 },
617
+ "gpt-4o": { inputCostPer1k: 25e-4, outputCostPer1k: 0.01 },
618
+ "gpt-4o-mini": { inputCostPer1k: 15e-5, outputCostPer1k: 6e-4 },
619
+ "gpt-4-turbo": { inputCostPer1k: 0.01, outputCostPer1k: 0.03 }
620
+ };
621
+ var CostTracker = class {
622
+ records = [];
623
+ pricing;
624
+ constructor(customPricing) {
625
+ this.pricing = { ...DEFAULT_PRICING, ...customPricing };
626
+ }
627
+ record(model, usage, turn, toolName) {
628
+ const pricing = this.pricing[model] ?? { inputCostPer1k: 1e-3, outputCostPer1k: 3e-3 };
629
+ this.records.push({
630
+ model,
631
+ inputTokens: usage.inputTokens,
632
+ outputTokens: usage.outputTokens,
633
+ cacheReadTokens: usage.cacheReadTokens ?? 0,
634
+ cacheWriteTokens: usage.cacheWriteTokens ?? 0,
635
+ inputCost: usage.inputTokens / 1e3 * pricing.inputCostPer1k,
636
+ outputCost: usage.outputTokens / 1e3 * pricing.outputCostPer1k,
637
+ timestamp: Date.now(),
638
+ turn,
639
+ toolName
640
+ });
641
+ }
642
+ getTotal() {
643
+ let cost = 0;
644
+ let input = 0;
645
+ let output = 0;
646
+ let cacheRead = 0;
647
+ let cacheWrite = 0;
648
+ for (const r of this.records) {
649
+ cost += r.inputCost + r.outputCost;
650
+ input += r.inputTokens;
651
+ output += r.outputTokens;
652
+ cacheRead += r.cacheReadTokens;
653
+ cacheWrite += r.cacheWriteTokens;
654
+ }
655
+ return { cost, inputTokens: input, outputTokens: output, cacheReadTokens: cacheRead, cacheWriteTokens: cacheWrite };
656
+ }
657
+ getByModel() {
658
+ const byModel = {};
659
+ for (const r of this.records) {
660
+ if (!byModel[r.model]) byModel[r.model] = { cost: 0, calls: 0 };
661
+ byModel[r.model].cost += r.inputCost + r.outputCost;
662
+ byModel[r.model].calls++;
663
+ }
664
+ return byModel;
665
+ }
666
+ getByTool() {
667
+ const byTool = {};
668
+ for (const r of this.records) {
669
+ const key = r.toolName ?? "llm";
670
+ if (!byTool[key]) byTool[key] = { cost: 0, calls: 0 };
671
+ byTool[key].cost += r.inputCost + r.outputCost;
672
+ byTool[key].calls++;
673
+ }
674
+ return byTool;
675
+ }
676
+ getRecords() {
677
+ return [...this.records];
678
+ }
679
+ reset() {
680
+ this.records = [];
681
+ }
682
+ setPricing(model, pricing) {
683
+ this.pricing[model] = pricing;
684
+ }
685
+ };
686
+
687
+ // src/agent.ts
688
+ var Agent = class _Agent {
689
+ model;
690
+ tools;
691
+ systemPrompt;
692
+ maxTurns;
693
+ contextManager;
694
+ permissionEngine;
695
+ permissionConfig;
696
+ cwd;
697
+ maxRetries;
698
+ messages = [];
699
+ hooks;
700
+ memory;
701
+ threadId;
702
+ costTracker;
703
+ _loaded = false;
704
+ _title;
705
+ _titleFetched = false;
706
+ _disableTitle = false;
707
+ constructor(config) {
708
+ this.model = config.model;
709
+ this.tools = new ToolRegistry(config.tools ?? []);
710
+ this.systemPrompt = config.systemPrompt ?? "";
711
+ this.maxTurns = config.maxTurns ?? DEFAULT_MAX_TURNS;
712
+ this.contextManager = new ContextManager({
713
+ maxTokens: config.context?.maxTokens ?? DEFAULT_CONTEXT_WINDOW,
714
+ maxOutputTokens: config.context?.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS,
715
+ compactThreshold: config.context?.compactThreshold ?? DEFAULT_COMPACT_THRESHOLD
716
+ });
717
+ this.permissionEngine = new PermissionEngine(config.permissions);
718
+ this.permissionConfig = config.permissions;
719
+ this.cwd = config.cwd ?? process.cwd();
720
+ this.maxRetries = config.maxRetries ?? 5;
721
+ const v2 = config;
722
+ this.hooks = v2.hooks;
723
+ this.memory = v2.memory;
724
+ this.threadId = v2.threadId;
725
+ this.costTracker = v2.costTracker ?? new CostTracker();
726
+ this._title = v2.title;
727
+ this._disableTitle = v2.disableTitle ?? false;
728
+ }
729
+ addTool(tool) {
730
+ this.tools.add(tool);
731
+ }
732
+ addMessage(message) {
733
+ this.messages.push(message);
734
+ }
735
+ reset() {
736
+ this.messages = [];
737
+ this._titleFetched = false;
738
+ }
739
+ getMessages() {
740
+ return [...this.messages];
741
+ }
742
+ getCostTracker() {
743
+ return this.costTracker;
744
+ }
745
+ get title() {
746
+ return this._title;
747
+ }
748
+ async loadMemory() {
749
+ if (this._loaded || !this.memory || !this.threadId) return;
750
+ const stored = await this.memory.getThread(this.threadId);
751
+ if (stored.length > 0) {
752
+ this.messages = stored;
753
+ }
754
+ this._loaded = true;
755
+ }
756
+ async saveMemory() {
757
+ if (!this.memory || !this.threadId) return;
758
+ await this.memory.saveThread(this.threadId, this.messages);
759
+ }
760
+ fork(newThreadId) {
761
+ const forked = new _Agent({
762
+ model: this.model,
763
+ tools: this.tools.getAll(),
764
+ systemPrompt: this.systemPrompt,
765
+ maxTurns: this.maxTurns,
766
+ cwd: this.cwd,
767
+ maxRetries: this.maxRetries,
768
+ permissions: this.permissionConfig,
769
+ hooks: this.hooks,
770
+ memory: this.memory,
771
+ threadId: newThreadId,
772
+ costTracker: this.costTracker,
773
+ title: this._title,
774
+ context: {
775
+ maxTokens: this.contextManager.maxTokens,
776
+ maxOutputTokens: this.contextManager.maxOutputTokens,
777
+ compactThreshold: this.contextManager.compactThreshold
778
+ }
779
+ });
780
+ forked.messages = [...this.messages];
781
+ return forked;
782
+ }
783
+ async *run(prompt, options) {
784
+ await this.loadMemory();
785
+ const loopMessages = [...this.messages, { role: "user", content: prompt }];
786
+ if (!this._titleFetched && this.messages.length === 0 && !this._disableTitle) {
787
+ this._titleFetched = true;
788
+ this.generateTitle(prompt).catch(() => {
789
+ });
790
+ }
791
+ const loop = agentLoop({
792
+ model: this.model,
793
+ tools: this.tools,
794
+ messages: loopMessages,
795
+ systemPrompt: this.systemPrompt || void 0,
796
+ maxTurns: this.maxTurns,
797
+ contextManager: this.contextManager,
798
+ permissionEngine: this.permissionEngine,
799
+ cwd: this.cwd,
800
+ abortSignal: options?.abortSignal,
801
+ maxRetries: this.maxRetries,
802
+ hooks: this.hooks,
803
+ costTracker: this.costTracker
804
+ });
805
+ const finalMessages = [];
806
+ for await (const event of loop) {
807
+ yield event;
808
+ if (event.type === "done") {
809
+ finalMessages.length = 0;
810
+ finalMessages.push(...event.messages);
811
+ }
812
+ }
813
+ if (finalMessages.length > 0) {
814
+ this.messages = finalMessages;
815
+ await this.saveMemory();
816
+ }
817
+ }
818
+ async chat(prompt, options) {
819
+ let text = "";
820
+ let usage = { inputTokens: 0, outputTokens: 0 };
821
+ for await (const event of this.run(prompt, options)) {
822
+ if (event.type === "text") {
823
+ text += event.text;
824
+ }
825
+ if (event.type === "done") {
826
+ usage = {
827
+ inputTokens: event.usage.inputTokens,
828
+ outputTokens: event.usage.outputTokens
829
+ };
830
+ }
831
+ }
832
+ const total = this.costTracker.getTotal();
833
+ return { text, usage, messages: this.getMessages(), cost: total.cost };
834
+ }
835
+ async structured(prompt, schema, options) {
836
+ const maxRetries = options?.maxRetries ?? 3;
837
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
838
+ const currentPrompt = attempt === 0 ? prompt : `${prompt}
839
+
840
+ Previous attempt returned invalid JSON. Please fix and respond with valid JSON only.`;
841
+ const agent = new _Agent({
842
+ model: this.model,
843
+ tools: [],
844
+ systemPrompt: "You must respond with valid JSON matching the requested schema.",
845
+ maxTurns: 1,
846
+ cwd: this.cwd,
847
+ permissions: this.permissionConfig,
848
+ context: {
849
+ maxTokens: this.contextManager.maxTokens,
850
+ maxOutputTokens: this.contextManager.maxOutputTokens,
851
+ compactThreshold: this.contextManager.compactThreshold
852
+ },
853
+ costTracker: this.costTracker,
854
+ disableTitle: true
855
+ });
856
+ const result = await agent.chat(currentPrompt, options);
857
+ const jsonMatch = result.text.match(/```(?:json)?\s*([\s\S]*?)```/) ?? [null, result.text];
858
+ const jsonStr = jsonMatch[1] ?? result.text;
859
+ try {
860
+ const parsed = JSON.parse(jsonStr);
861
+ const validated = schema.safeParse(parsed);
862
+ if (validated.success && validated.data !== void 0) {
863
+ return validated.data;
864
+ }
865
+ } catch {
866
+ continue;
867
+ }
868
+ }
869
+ throw new Error(`Failed to get valid structured output after ${maxRetries} attempts`);
870
+ }
871
+ async structuredViaTool(prompt, schema, options) {
872
+ const { z } = await import("zod");
873
+ const maxRetries = options?.maxRetries ?? 3;
874
+ let captured;
875
+ const structTool = defineTool({
876
+ name: "structured_output",
877
+ description: "Return your final response in the required structured format.",
878
+ inputSchema: z.object({
879
+ response: z.unknown().describe("The structured JSON response")
880
+ }),
881
+ isReadOnly: true,
882
+ isConcurrencySafe: true,
883
+ execute: async (input) => {
884
+ captured = input.response;
885
+ return "Structured output captured.";
886
+ }
887
+ });
888
+ const agent = new _Agent({
889
+ model: this.model,
890
+ tools: [structTool],
891
+ systemPrompt: [
892
+ this.systemPrompt,
893
+ "You MUST call the structured_output tool with your response. Do not return plain text."
894
+ ].filter(Boolean).join("\n\n"),
895
+ maxTurns: 1,
896
+ cwd: this.cwd,
897
+ permissions: this.permissionConfig,
898
+ context: {
899
+ maxTokens: this.contextManager.maxTokens,
900
+ maxOutputTokens: this.contextManager.maxOutputTokens,
901
+ compactThreshold: this.contextManager.compactThreshold
902
+ },
903
+ costTracker: this.costTracker,
904
+ disableTitle: true
905
+ });
906
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
907
+ captured = void 0;
908
+ const currentPrompt = attempt === 0 ? prompt : `${prompt}
909
+
910
+ Previous attempt failed validation. Fix your structured output and call the structured_output tool again.`;
911
+ await agent.chat(currentPrompt, options);
912
+ if (captured !== void 0) {
913
+ const validated = schema.safeParse(captured);
914
+ if (validated.success && validated.data !== void 0) {
915
+ return validated.data;
916
+ }
917
+ }
918
+ }
919
+ throw new Error(`Failed to get valid structured output via tool after ${maxRetries} attempts`);
920
+ }
921
+ async asTool(options) {
922
+ const { z } = await import("zod");
923
+ const allowSubAgents = options?.allowSubAgents ?? false;
924
+ return defineTool({
925
+ name: options?.name ?? "delegate_agent",
926
+ description: options?.description ?? `Delegate a task to a sub-agent with system prompt: ${this.systemPrompt?.slice(0, 100) ?? "none"}`,
927
+ inputSchema: z.object({
928
+ prompt: z.string().describe("The task to delegate")
929
+ }),
930
+ isReadOnly: true,
931
+ isConcurrencySafe: true,
932
+ execute: async (input) => {
933
+ const subAgent = this.fork();
934
+ if (!allowSubAgents) {
935
+ const forbiddenTools = ["delegate_agent", "task", "todowrite"];
936
+ const allowed = this.tools.getAll().filter((t) => !forbiddenTools.includes(t.name));
937
+ for (const tool of allowed) {
938
+ subAgent.addTool(tool);
939
+ }
940
+ }
941
+ const result = await subAgent.chat(input.prompt);
942
+ return result.text;
943
+ }
944
+ });
945
+ }
946
+ async generateTitle(prompt) {
947
+ try {
948
+ const firstLine = prompt.split("\n")[0].slice(0, 200);
949
+ const titleAgent = new _Agent({
950
+ model: this.model,
951
+ tools: [],
952
+ systemPrompt: "Generate a short, descriptive title (max 10 words) for a conversation that starts with this message. Return ONLY the title, nothing else.",
953
+ maxTurns: 1,
954
+ cwd: this.cwd,
955
+ costTracker: this.costTracker,
956
+ disableTitle: true
957
+ });
958
+ const result = await titleAgent.chat(firstLine);
959
+ const title = result.text.trim().replace(/^["']|["']$/g, "").slice(0, 80);
960
+ if (title.length > 0) {
961
+ this._title = title;
962
+ }
963
+ } catch {
964
+ this._title = prompt.slice(0, 50);
965
+ }
966
+ }
967
+ };
968
+
969
+ // src/stream.ts
970
+ function createStreamAggregator() {
971
+ let text = "";
972
+ const toolCalls = /* @__PURE__ */ new Map();
973
+ let usage;
974
+ let stopReason = "end_turn";
975
+ function push(event) {
976
+ switch (event.type) {
977
+ case "text_delta":
978
+ text += event.text ?? "";
979
+ break;
980
+ case "tool_use_start":
981
+ if (event.id) {
982
+ toolCalls.set(event.id, { id: event.id, name: event.name ?? "", input: event.input ?? "" });
983
+ }
984
+ stopReason = "tool_use";
985
+ break;
986
+ case "tool_use_delta":
987
+ if (event.id && toolCalls.has(event.id)) {
988
+ toolCalls.get(event.id).input += event.input ?? "";
989
+ }
990
+ break;
991
+ case "done":
992
+ usage = event.usage;
993
+ break;
994
+ case "tool_result":
995
+ break;
996
+ case "error":
997
+ break;
998
+ }
999
+ }
1000
+ function getResponse() {
1001
+ return { text, toolCalls: Array.from(toolCalls.values()), usage, stopReason };
1002
+ }
1003
+ return { push, getResponse };
1004
+ }
1005
+ export {
1006
+ Agent,
1007
+ AnthropicProvider,
1008
+ BaseProvider,
1009
+ BashTool,
1010
+ ContextManager,
1011
+ CostTracker,
1012
+ DEFAULT_COMPACT_THRESHOLD,
1013
+ DEFAULT_CONTEXT_WINDOW,
1014
+ DEFAULT_MAX_OUTPUT_TOKENS,
1015
+ DEFAULT_MAX_TURNS,
1016
+ DEFAULT_PRICING,
1017
+ FileEditTool,
1018
+ FileReadTool,
1019
+ FileWriteTool,
1020
+ GlobTool,
1021
+ GrepTool,
1022
+ HookRunner,
1023
+ InMemoryStore,
1024
+ MAX_CONCURRENT_TOOLS,
1025
+ MCPClient,
1026
+ OllamaProvider,
1027
+ OpenAIProvider,
1028
+ PermissionEngine,
1029
+ RetryableError,
1030
+ SQLiteStore,
1031
+ ToolRegistry,
1032
+ WebFetchTool,
1033
+ agentLoop,
1034
+ anthropic,
1035
+ createProvider,
1036
+ createStreamAggregator,
1037
+ defineTool,
1038
+ defineToolFromClass,
1039
+ estimateConversationTokens,
1040
+ estimateMessageTokens,
1041
+ estimateTokens,
1042
+ init,
1043
+ loadMCPTools,
1044
+ ollama,
1045
+ openai,
1046
+ orchestrateTools
1047
+ };
1048
+ //# sourceMappingURL=index.js.map