lobster-cli 0.1.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 (45) hide show
  1. package/README.md +389 -0
  2. package/dist/agent/core.js +1013 -0
  3. package/dist/agent/core.js.map +1 -0
  4. package/dist/agent/index.js +1027 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/brain/index.js +60 -0
  7. package/dist/brain/index.js.map +1 -0
  8. package/dist/browser/dom/index.js +1096 -0
  9. package/dist/browser/dom/index.js.map +1 -0
  10. package/dist/browser/index.js +2034 -0
  11. package/dist/browser/index.js.map +1 -0
  12. package/dist/browser/manager.js +86 -0
  13. package/dist/browser/manager.js.map +1 -0
  14. package/dist/browser/page-adapter.js +1345 -0
  15. package/dist/browser/page-adapter.js.map +1 -0
  16. package/dist/cascade/index.js +138 -0
  17. package/dist/cascade/index.js.map +1 -0
  18. package/dist/config/index.js +110 -0
  19. package/dist/config/index.js.map +1 -0
  20. package/dist/config/schema.js +66 -0
  21. package/dist/config/schema.js.map +1 -0
  22. package/dist/discover/index.js +545 -0
  23. package/dist/discover/index.js.map +1 -0
  24. package/dist/index.js +5529 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib.js +4206 -0
  27. package/dist/lib.js.map +1 -0
  28. package/dist/llm/client.js +379 -0
  29. package/dist/llm/client.js.map +1 -0
  30. package/dist/llm/index.js +397 -0
  31. package/dist/llm/index.js.map +1 -0
  32. package/dist/llm/openai-client.js +214 -0
  33. package/dist/llm/openai-client.js.map +1 -0
  34. package/dist/output/index.js +93 -0
  35. package/dist/output/index.js.map +1 -0
  36. package/dist/pipeline/index.js +802 -0
  37. package/dist/pipeline/index.js.map +1 -0
  38. package/dist/router/decision.js +80 -0
  39. package/dist/router/decision.js.map +1 -0
  40. package/dist/router/index.js +3443 -0
  41. package/dist/router/index.js.map +1 -0
  42. package/dist/types/index.js +23 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/logo.svg +11 -0
  45. package/package.json +65 -0
@@ -0,0 +1,379 @@
1
+ // src/llm/errors.ts
2
+ var InvokeError = class extends Error {
3
+ type;
4
+ retryable;
5
+ rawError;
6
+ rawResponse;
7
+ constructor(type, message, opts) {
8
+ super(message);
9
+ this.name = "InvokeError";
10
+ this.type = type;
11
+ this.retryable = opts?.retryable ?? isRetryable(type);
12
+ this.rawError = opts?.rawError;
13
+ this.rawResponse = opts?.rawResponse;
14
+ }
15
+ };
16
+ function isRetryable(type) {
17
+ switch (type) {
18
+ case "NETWORK_ERROR" /* NETWORK_ERROR */:
19
+ case "RATE_LIMIT" /* RATE_LIMIT */:
20
+ case "SERVER_ERROR" /* SERVER_ERROR */:
21
+ case "NO_TOOL_CALL" /* NO_TOOL_CALL */:
22
+ case "INVALID_TOOL_ARGS" /* INVALID_TOOL_ARGS */:
23
+ case "TOOL_EXECUTION_ERROR" /* TOOL_EXECUTION_ERROR */:
24
+ case "UNKNOWN" /* UNKNOWN */:
25
+ return true;
26
+ case "AUTH_ERROR" /* AUTH_ERROR */:
27
+ case "CONTEXT_LENGTH" /* CONTEXT_LENGTH */:
28
+ case "CONTENT_FILTER" /* CONTENT_FILTER */:
29
+ return false;
30
+ }
31
+ }
32
+
33
+ // src/llm/openai-client.ts
34
+ var OpenAIClient = class {
35
+ config;
36
+ constructor(config) {
37
+ this.config = config;
38
+ }
39
+ /**
40
+ * Build auth headers based on the provider.
41
+ * - OpenAI/Gemini/Ollama: Bearer token
42
+ * - Anthropic: x-api-key header + anthropic-version
43
+ */
44
+ buildHeaders() {
45
+ const headers = {
46
+ "Content-Type": "application/json"
47
+ };
48
+ if (!this.config.apiKey) return headers;
49
+ if (this.config.provider === "anthropic") {
50
+ headers["x-api-key"] = this.config.apiKey;
51
+ headers["anthropic-version"] = "2023-06-01";
52
+ } else {
53
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
54
+ }
55
+ return headers;
56
+ }
57
+ /**
58
+ * Build the request body based on provider.
59
+ * Anthropic Messages API is different from OpenAI chat completions.
60
+ */
61
+ buildBody(messages, tools, opts) {
62
+ if (this.config.provider === "anthropic") {
63
+ return this.buildAnthropicBody(messages, tools, opts);
64
+ }
65
+ const body = {
66
+ model: this.config.model,
67
+ messages,
68
+ temperature: this.config.temperature ?? 0.1
69
+ };
70
+ if (tools && tools.length > 0) {
71
+ body.tools = tools;
72
+ body.parallel_tool_calls = false;
73
+ if (opts?.toolChoice) {
74
+ body.tool_choice = typeof opts.toolChoice === "string" ? opts.toolChoice : opts.toolChoice;
75
+ }
76
+ }
77
+ return { url: `${this.config.baseURL}/chat/completions`, body };
78
+ }
79
+ /**
80
+ * Build Anthropic Messages API request.
81
+ * Converts OpenAI-style messages/tools to Anthropic format.
82
+ */
83
+ buildAnthropicBody(messages, tools, opts) {
84
+ let system;
85
+ const anthropicMessages = [];
86
+ for (const msg of messages) {
87
+ if (msg.role === "system") {
88
+ system = msg.content;
89
+ } else {
90
+ anthropicMessages.push({
91
+ role: msg.role === "assistant" ? "assistant" : "user",
92
+ content: msg.content
93
+ });
94
+ }
95
+ }
96
+ const body = {
97
+ model: this.config.model,
98
+ messages: anthropicMessages,
99
+ max_tokens: 4096,
100
+ temperature: this.config.temperature ?? 0.1
101
+ };
102
+ if (system) body.system = system;
103
+ if (tools && tools.length > 0) {
104
+ body.tools = tools.map((t) => {
105
+ const fn = t.function;
106
+ return {
107
+ name: fn.name,
108
+ description: fn.description,
109
+ input_schema: fn.parameters
110
+ };
111
+ });
112
+ if (opts?.toolChoice) {
113
+ if (typeof opts.toolChoice === "string") {
114
+ body.tool_choice = opts.toolChoice === "required" ? { type: "any" } : { type: opts.toolChoice };
115
+ } else {
116
+ body.tool_choice = { type: "tool", name: opts.toolChoice.function.name };
117
+ }
118
+ }
119
+ }
120
+ return { url: `${this.config.baseURL}/messages`, body };
121
+ }
122
+ /**
123
+ * Parse Anthropic response into our unified format.
124
+ */
125
+ parseAnthropicResponse(json) {
126
+ const content = json.content;
127
+ if (!content || !Array.isArray(content)) {
128
+ throw new InvokeError("UNKNOWN" /* UNKNOWN */, "No content in Anthropic response", { rawResponse: json });
129
+ }
130
+ let textContent;
131
+ const toolCalls = [];
132
+ for (const block of content) {
133
+ if (block.type === "text") {
134
+ textContent = block.text;
135
+ } else if (block.type === "tool_use") {
136
+ toolCalls.push({
137
+ id: block.id,
138
+ type: "function",
139
+ function: {
140
+ name: block.name,
141
+ arguments: JSON.stringify(block.input)
142
+ }
143
+ });
144
+ }
145
+ }
146
+ const usage = json.usage;
147
+ return {
148
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
149
+ content: textContent,
150
+ usage: usage ? {
151
+ promptTokens: usage.input_tokens ?? 0,
152
+ completionTokens: usage.output_tokens ?? 0,
153
+ totalTokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0)
154
+ } : void 0
155
+ };
156
+ }
157
+ async chatCompletion(messages, tools, opts) {
158
+ const { url, body } = this.buildBody(messages, tools, opts);
159
+ const headers = this.buildHeaders();
160
+ let response;
161
+ try {
162
+ response = await fetch(url, {
163
+ method: "POST",
164
+ headers,
165
+ body: JSON.stringify(body)
166
+ });
167
+ } catch (err) {
168
+ throw new InvokeError("NETWORK_ERROR" /* NETWORK_ERROR */, `Network error: ${err}`, { rawError: err });
169
+ }
170
+ if (!response.ok) {
171
+ const text = await response.text().catch(() => "");
172
+ if (response.status === 401) {
173
+ throw new InvokeError("AUTH_ERROR" /* AUTH_ERROR */, `Authentication failed: ${text}`, { retryable: false, rawResponse: text });
174
+ }
175
+ if (response.status === 429) {
176
+ throw new InvokeError("RATE_LIMIT" /* RATE_LIMIT */, `Rate limited: ${text}`, { rawResponse: text });
177
+ }
178
+ if (response.status >= 500) {
179
+ throw new InvokeError("SERVER_ERROR" /* SERVER_ERROR */, `Server error ${response.status}: ${text}`, { rawResponse: text });
180
+ }
181
+ throw new InvokeError("UNKNOWN" /* UNKNOWN */, `HTTP ${response.status}: ${text}`, { rawResponse: text });
182
+ }
183
+ const json = await response.json();
184
+ if (this.config.provider === "anthropic") {
185
+ return this.parseAnthropicResponse(json);
186
+ }
187
+ const choice = json.choices?.[0];
188
+ if (!choice) {
189
+ throw new InvokeError("UNKNOWN" /* UNKNOWN */, "No choices in response", { rawResponse: json });
190
+ }
191
+ const message = choice.message;
192
+ const finishReason = choice.finish_reason;
193
+ if (finishReason === "content_filter") {
194
+ throw new InvokeError("CONTENT_FILTER" /* CONTENT_FILTER */, "Content filtered", { retryable: false, rawResponse: json });
195
+ }
196
+ if (finishReason === "length") {
197
+ throw new InvokeError("CONTEXT_LENGTH" /* CONTEXT_LENGTH */, "Context length exceeded", { retryable: false, rawResponse: json });
198
+ }
199
+ const usage = json.usage;
200
+ return {
201
+ toolCalls: message.tool_calls,
202
+ content: message.content,
203
+ usage: usage ? {
204
+ promptTokens: usage.prompt_tokens ?? 0,
205
+ completionTokens: usage.completion_tokens ?? 0,
206
+ totalTokens: usage.total_tokens ?? 0
207
+ } : void 0
208
+ };
209
+ }
210
+ };
211
+
212
+ // src/llm/utils.ts
213
+ function zodToJsonSchema(schema) {
214
+ if ("_def" in schema) {
215
+ const def = schema._def;
216
+ const typeName = def.typeName;
217
+ if (typeName === "ZodObject") {
218
+ const shape = def.shape();
219
+ const properties = {};
220
+ const required = [];
221
+ for (const [key, value] of Object.entries(shape)) {
222
+ properties[key] = zodToJsonSchema(value);
223
+ if (!(value._def?.typeName === "ZodOptional")) {
224
+ required.push(key);
225
+ }
226
+ }
227
+ const result = { type: "object", properties };
228
+ if (required.length > 0) result.required = required;
229
+ if (def.description) result.description = def.description;
230
+ return result;
231
+ }
232
+ if (typeName === "ZodString") {
233
+ const result = { type: "string" };
234
+ if (def.description) result.description = def.description;
235
+ return result;
236
+ }
237
+ if (typeName === "ZodNumber") {
238
+ const result = { type: "number" };
239
+ if (def.description) result.description = def.description;
240
+ return result;
241
+ }
242
+ if (typeName === "ZodBoolean") {
243
+ const result = { type: "boolean" };
244
+ if (def.description) result.description = def.description;
245
+ return result;
246
+ }
247
+ if (typeName === "ZodEnum") {
248
+ return { type: "string", enum: def.values, ...def.description ? { description: def.description } : {} };
249
+ }
250
+ if (typeName === "ZodArray") {
251
+ return { type: "array", items: zodToJsonSchema(def.type), ...def.description ? { description: def.description } : {} };
252
+ }
253
+ if (typeName === "ZodOptional") {
254
+ return zodToJsonSchema(def.innerType);
255
+ }
256
+ if (typeName === "ZodDefault") {
257
+ const inner = zodToJsonSchema(def.innerType);
258
+ return { ...inner, default: def.defaultValue() };
259
+ }
260
+ if (typeName === "ZodUnion") {
261
+ return { oneOf: def.options.map((opt) => zodToJsonSchema(opt)) };
262
+ }
263
+ if (typeName === "ZodRecord") {
264
+ return { type: "object", additionalProperties: zodToJsonSchema(def.valueType) };
265
+ }
266
+ if (typeName === "ZodLiteral") {
267
+ return { const: def.value };
268
+ }
269
+ if (typeName === "ZodAny") {
270
+ return {};
271
+ }
272
+ }
273
+ return { type: "string" };
274
+ }
275
+ function zodToOpenAITool(name, description, schema) {
276
+ return {
277
+ type: "function",
278
+ function: {
279
+ name,
280
+ description,
281
+ parameters: zodToJsonSchema(schema)
282
+ }
283
+ };
284
+ }
285
+
286
+ // src/llm/client.ts
287
+ var LLM = class {
288
+ client;
289
+ config;
290
+ constructor(config) {
291
+ this.config = config;
292
+ this.client = new OpenAIClient({
293
+ baseURL: config.baseURL,
294
+ model: config.model,
295
+ apiKey: config.apiKey,
296
+ temperature: config.temperature,
297
+ provider: config.provider
298
+ });
299
+ }
300
+ async invoke(messages, tool, abortSignal) {
301
+ const openaiTool = zodToOpenAITool(tool.name, tool.description, tool.schema);
302
+ return this.withRetry(async () => {
303
+ if (abortSignal?.aborted) throw new Error("Aborted");
304
+ const response = await this.client.chatCompletion(
305
+ messages,
306
+ [openaiTool],
307
+ { toolChoice: { type: "function", function: { name: tool.name } } }
308
+ );
309
+ const toolCall = response.toolCalls?.[0];
310
+ if (!toolCall) {
311
+ if (response.content) {
312
+ const extracted = extractJsonFromString(response.content);
313
+ if (extracted) {
314
+ const args2 = typeof extracted === "string" ? JSON.parse(extracted) : extracted;
315
+ const result2 = await tool.execute(args2);
316
+ return {
317
+ toolCall: { name: tool.name, args: args2 },
318
+ toolResult: result2,
319
+ usage: response.usage
320
+ };
321
+ }
322
+ }
323
+ throw new InvokeError("NO_TOOL_CALL" /* NO_TOOL_CALL */, "No tool call in response");
324
+ }
325
+ let args;
326
+ try {
327
+ args = JSON.parse(toolCall.function.arguments);
328
+ } catch {
329
+ try {
330
+ args = JSON.parse(JSON.parse(toolCall.function.arguments));
331
+ } catch {
332
+ throw new InvokeError("INVALID_TOOL_ARGS" /* INVALID_TOOL_ARGS */, `Invalid JSON in tool args: ${toolCall.function.arguments}`);
333
+ }
334
+ }
335
+ let result;
336
+ try {
337
+ result = await tool.execute(args);
338
+ } catch (err) {
339
+ throw new InvokeError("TOOL_EXECUTION_ERROR" /* TOOL_EXECUTION_ERROR */, `Tool execution failed: ${err}`, { rawError: err });
340
+ }
341
+ return {
342
+ toolCall: { name: tool.name, args },
343
+ toolResult: result,
344
+ usage: response.usage
345
+ };
346
+ });
347
+ }
348
+ async withRetry(fn) {
349
+ const maxRetries = this.config.maxRetries ?? 3;
350
+ let lastError;
351
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
352
+ try {
353
+ return await fn();
354
+ } catch (err) {
355
+ lastError = err;
356
+ if (err instanceof InvokeError && !err.retryable) throw err;
357
+ if (err instanceof Error && err.name === "AbortError") throw err;
358
+ if (attempt < maxRetries) {
359
+ await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));
360
+ }
361
+ }
362
+ }
363
+ throw lastError;
364
+ }
365
+ };
366
+ function extractJsonFromString(str) {
367
+ const start = str.indexOf("{");
368
+ const end = str.lastIndexOf("}");
369
+ if (start === -1 || end === -1 || end <= start) return null;
370
+ try {
371
+ return JSON.parse(str.slice(start, end + 1));
372
+ } catch {
373
+ return null;
374
+ }
375
+ }
376
+ export {
377
+ LLM
378
+ };
379
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/llm/errors.ts","../../src/llm/openai-client.ts","../../src/llm/utils.ts","../../src/llm/client.ts"],"sourcesContent":["export enum InvokeErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n AUTH_ERROR = 'AUTH_ERROR',\n RATE_LIMIT = 'RATE_LIMIT',\n SERVER_ERROR = 'SERVER_ERROR',\n CONTEXT_LENGTH = 'CONTEXT_LENGTH',\n CONTENT_FILTER = 'CONTENT_FILTER',\n NO_TOOL_CALL = 'NO_TOOL_CALL',\n INVALID_TOOL_ARGS = 'INVALID_TOOL_ARGS',\n TOOL_EXECUTION_ERROR = 'TOOL_EXECUTION_ERROR',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport class InvokeError extends Error {\n type: InvokeErrorType;\n retryable: boolean;\n rawError?: unknown;\n rawResponse?: unknown;\n\n constructor(type: InvokeErrorType, message: string, opts?: { retryable?: boolean; rawError?: unknown; rawResponse?: unknown }) {\n super(message);\n this.name = 'InvokeError';\n this.type = type;\n this.retryable = opts?.retryable ?? isRetryable(type);\n this.rawError = opts?.rawError;\n this.rawResponse = opts?.rawResponse;\n }\n}\n\nfunction isRetryable(type: InvokeErrorType): boolean {\n switch (type) {\n case InvokeErrorType.NETWORK_ERROR:\n case InvokeErrorType.RATE_LIMIT:\n case InvokeErrorType.SERVER_ERROR:\n case InvokeErrorType.NO_TOOL_CALL:\n case InvokeErrorType.INVALID_TOOL_ARGS:\n case InvokeErrorType.TOOL_EXECUTION_ERROR:\n case InvokeErrorType.UNKNOWN:\n return true;\n case InvokeErrorType.AUTH_ERROR:\n case InvokeErrorType.CONTEXT_LENGTH:\n case InvokeErrorType.CONTENT_FILTER:\n return false;\n }\n}\n","import type { Message, ToolCall } from '../types/llm.js';\nimport type { LLMTool } from '../types/llm.js';\nimport { InvokeError, InvokeErrorType } from './errors.js';\nimport type { LLMProvider } from '../config/schema.js';\n\nexport interface OpenAIClientConfig {\n baseURL: string;\n model: string;\n apiKey?: string;\n temperature?: number;\n provider?: LLMProvider;\n}\n\nexport class OpenAIClient {\n private config: OpenAIClientConfig;\n\n constructor(config: OpenAIClientConfig) {\n this.config = config;\n }\n\n /**\n * Build auth headers based on the provider.\n * - OpenAI/Gemini/Ollama: Bearer token\n * - Anthropic: x-api-key header + anthropic-version\n */\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (!this.config.apiKey) return headers;\n\n if (this.config.provider === 'anthropic') {\n headers['x-api-key'] = this.config.apiKey;\n headers['anthropic-version'] = '2023-06-01';\n } else {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n\n return headers;\n }\n\n /**\n * Build the request body based on provider.\n * Anthropic Messages API is different from OpenAI chat completions.\n */\n private buildBody(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } },\n ): { url: string; body: Record<string, unknown> } {\n if (this.config.provider === 'anthropic') {\n return this.buildAnthropicBody(messages, tools, opts);\n }\n\n // OpenAI-compatible format (OpenAI, Gemini, Ollama all use this)\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages,\n temperature: this.config.temperature ?? 0.1,\n };\n\n if (tools && tools.length > 0) {\n body.tools = tools;\n body.parallel_tool_calls = false;\n if (opts?.toolChoice) {\n body.tool_choice = typeof opts.toolChoice === 'string'\n ? opts.toolChoice\n : opts.toolChoice;\n }\n }\n\n return { url: `${this.config.baseURL}/chat/completions`, body };\n }\n\n /**\n * Build Anthropic Messages API request.\n * Converts OpenAI-style messages/tools to Anthropic format.\n */\n private buildAnthropicBody(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } },\n ): { url: string; body: Record<string, unknown> } {\n // Extract system message\n let system: string | undefined;\n const anthropicMessages: Record<string, unknown>[] = [];\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n system = msg.content as string;\n } else {\n anthropicMessages.push({\n role: msg.role === 'assistant' ? 'assistant' : 'user',\n content: msg.content,\n });\n }\n }\n\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages: anthropicMessages,\n max_tokens: 4096,\n temperature: this.config.temperature ?? 0.1,\n };\n\n if (system) body.system = system;\n\n // Convert OpenAI tools format to Anthropic tools format\n if (tools && tools.length > 0) {\n body.tools = tools.map((t) => {\n const fn = (t as any).function;\n return {\n name: fn.name,\n description: fn.description,\n input_schema: fn.parameters,\n };\n });\n\n if (opts?.toolChoice) {\n if (typeof opts.toolChoice === 'string') {\n body.tool_choice = opts.toolChoice === 'required'\n ? { type: 'any' }\n : { type: opts.toolChoice };\n } else {\n body.tool_choice = { type: 'tool', name: opts.toolChoice.function.name };\n }\n }\n }\n\n return { url: `${this.config.baseURL}/messages`, body };\n }\n\n /**\n * Parse Anthropic response into our unified format.\n */\n private parseAnthropicResponse(json: Record<string, unknown>): {\n toolCalls?: ToolCall[];\n content?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n } {\n const content = json.content as any[];\n if (!content || !Array.isArray(content)) {\n throw new InvokeError(InvokeErrorType.UNKNOWN, 'No content in Anthropic response', { rawResponse: json });\n }\n\n let textContent: string | undefined;\n const toolCalls: ToolCall[] = [];\n\n for (const block of content) {\n if (block.type === 'text') {\n textContent = block.text;\n } else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n });\n }\n }\n\n const usage = json.usage as Record<string, number> | undefined;\n\n return {\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n content: textContent,\n usage: usage ? {\n promptTokens: usage.input_tokens ?? 0,\n completionTokens: usage.output_tokens ?? 0,\n totalTokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),\n } : undefined,\n };\n }\n\n async chatCompletion(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } }\n ): Promise<{\n toolCalls?: ToolCall[];\n content?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n }> {\n const { url, body } = this.buildBody(messages, tools, opts);\n const headers = this.buildHeaders();\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n } catch (err) {\n throw new InvokeError(InvokeErrorType.NETWORK_ERROR, `Network error: ${err}`, { rawError: err });\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n if (response.status === 401) {\n throw new InvokeError(InvokeErrorType.AUTH_ERROR, `Authentication failed: ${text}`, { retryable: false, rawResponse: text });\n }\n if (response.status === 429) {\n throw new InvokeError(InvokeErrorType.RATE_LIMIT, `Rate limited: ${text}`, { rawResponse: text });\n }\n if (response.status >= 500) {\n throw new InvokeError(InvokeErrorType.SERVER_ERROR, `Server error ${response.status}: ${text}`, { rawResponse: text });\n }\n throw new InvokeError(InvokeErrorType.UNKNOWN, `HTTP ${response.status}: ${text}`, { rawResponse: text });\n }\n\n const json = await response.json() as Record<string, unknown>;\n\n // Route to provider-specific parser\n if (this.config.provider === 'anthropic') {\n return this.parseAnthropicResponse(json);\n }\n\n // OpenAI-compatible response parsing (OpenAI, Gemini, Ollama)\n const choice = (json.choices as any[])?.[0];\n if (!choice) {\n throw new InvokeError(InvokeErrorType.UNKNOWN, 'No choices in response', { rawResponse: json });\n }\n\n const message = choice.message;\n const finishReason = choice.finish_reason;\n\n if (finishReason === 'content_filter') {\n throw new InvokeError(InvokeErrorType.CONTENT_FILTER, 'Content filtered', { retryable: false, rawResponse: json });\n }\n\n if (finishReason === 'length') {\n throw new InvokeError(InvokeErrorType.CONTEXT_LENGTH, 'Context length exceeded', { retryable: false, rawResponse: json });\n }\n\n const usage = json.usage as Record<string, number> | undefined;\n\n return {\n toolCalls: message.tool_calls as ToolCall[] | undefined,\n content: message.content as string | undefined,\n usage: usage ? {\n promptTokens: usage.prompt_tokens ?? 0,\n completionTokens: usage.completion_tokens ?? 0,\n totalTokens: usage.total_tokens ?? 0,\n } : undefined,\n };\n }\n}\n","import type { z } from 'zod';\nimport type { LLMTool } from '../types/llm.js';\n\nexport function zodToJsonSchema(schema: z.ZodType): Record<string, unknown> {\n // Simplified Zod-to-JSON-Schema converter for common types\n if ('_def' in schema) {\n const def = (schema as any)._def;\n const typeName = def.typeName;\n\n if (typeName === 'ZodObject') {\n const shape = def.shape();\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as z.ZodType);\n if (!((value as any)._def?.typeName === 'ZodOptional')) {\n required.push(key);\n }\n }\n const result: Record<string, unknown> = { type: 'object', properties };\n if (required.length > 0) result.required = required;\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodString') {\n const result: Record<string, unknown> = { type: 'string' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodNumber') {\n const result: Record<string, unknown> = { type: 'number' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodBoolean') {\n const result: Record<string, unknown> = { type: 'boolean' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodEnum') {\n return { type: 'string', enum: def.values, ...(def.description ? { description: def.description } : {}) };\n }\n\n if (typeName === 'ZodArray') {\n return { type: 'array', items: zodToJsonSchema(def.type), ...(def.description ? { description: def.description } : {}) };\n }\n\n if (typeName === 'ZodOptional') {\n return zodToJsonSchema(def.innerType);\n }\n\n if (typeName === 'ZodDefault') {\n const inner = zodToJsonSchema(def.innerType);\n return { ...inner, default: def.defaultValue() };\n }\n\n if (typeName === 'ZodUnion') {\n return { oneOf: def.options.map((opt: z.ZodType) => zodToJsonSchema(opt)) };\n }\n\n if (typeName === 'ZodRecord') {\n return { type: 'object', additionalProperties: zodToJsonSchema(def.valueType) };\n }\n\n if (typeName === 'ZodLiteral') {\n return { const: def.value };\n }\n\n if (typeName === 'ZodAny') {\n return {};\n }\n }\n\n return { type: 'string' };\n}\n\nexport function zodToOpenAITool(name: string, description: string, schema: z.ZodType): LLMTool {\n return {\n type: 'function',\n function: {\n name,\n description,\n parameters: zodToJsonSchema(schema),\n },\n };\n}\n","import type { z } from 'zod';\nimport type { Message, InvokeResult, LLMTool } from '../types/llm.js';\nimport type { LLMConfig } from '../types/llm.js';\nimport { OpenAIClient } from './openai-client.js';\nimport { InvokeError, InvokeErrorType } from './errors.js';\nimport { zodToOpenAITool } from './utils.js';\n\nexport interface MacroTool {\n name: string;\n description: string;\n schema: z.ZodType;\n execute: (args: Record<string, unknown>) => Promise<string>;\n}\n\nexport class LLM {\n private client: OpenAIClient;\n private config: LLMConfig;\n\n constructor(config: LLMConfig) {\n this.config = config;\n this.client = new OpenAIClient({\n baseURL: config.baseURL,\n model: config.model,\n apiKey: config.apiKey,\n temperature: config.temperature,\n provider: config.provider as any,\n });\n }\n\n async invoke(\n messages: Message[],\n tool: MacroTool,\n abortSignal?: AbortSignal\n ): Promise<InvokeResult> {\n const openaiTool = zodToOpenAITool(tool.name, tool.description, tool.schema);\n\n return this.withRetry(async () => {\n if (abortSignal?.aborted) throw new Error('Aborted');\n\n const response = await this.client.chatCompletion(\n messages,\n [openaiTool],\n { toolChoice: { type: 'function', function: { name: tool.name } } }\n );\n\n // Extract tool call\n const toolCall = response.toolCalls?.[0];\n if (!toolCall) {\n // Try to extract from content (some models put JSON in content)\n if (response.content) {\n const extracted = extractJsonFromString(response.content);\n if (extracted) {\n const args = typeof extracted === 'string' ? JSON.parse(extracted) : extracted;\n const result = await tool.execute(args);\n return {\n toolCall: { name: tool.name, args },\n toolResult: result,\n usage: response.usage,\n };\n }\n }\n throw new InvokeError(InvokeErrorType.NO_TOOL_CALL, 'No tool call in response');\n }\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch {\n // Try double-parse (some models double-stringify)\n try {\n args = JSON.parse(JSON.parse(toolCall.function.arguments));\n } catch {\n throw new InvokeError(InvokeErrorType.INVALID_TOOL_ARGS, `Invalid JSON in tool args: ${toolCall.function.arguments}`);\n }\n }\n\n let result: string;\n try {\n result = await tool.execute(args);\n } catch (err) {\n throw new InvokeError(InvokeErrorType.TOOL_EXECUTION_ERROR, `Tool execution failed: ${err}`, { rawError: err });\n }\n\n return {\n toolCall: { name: tool.name, args },\n toolResult: result,\n usage: response.usage,\n };\n });\n }\n\n private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n const maxRetries = this.config.maxRetries ?? 3;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (err instanceof InvokeError && !err.retryable) throw err;\n if (err instanceof Error && err.name === 'AbortError') throw err;\n if (attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));\n }\n }\n }\n\n throw lastError;\n }\n}\n\nfunction extractJsonFromString(str: string): unknown | null {\n const start = str.indexOf('{');\n const end = str.lastIndexOf('}');\n if (start === -1 || end === -1 || end <= start) return null;\n try {\n return JSON.parse(str.slice(start, end + 1));\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["args","result"]}