@cosmicstack/mercury-agent 1.0.6 → 1.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.
package/dist/index.js CHANGED
@@ -1535,9 +1535,9 @@ var OpenAICompatProvider = class extends BaseProvider {
1535
1535
  });
1536
1536
  return {
1537
1537
  text: result.text,
1538
- inputTokens: result.usage?.promptTokens ?? 0,
1539
- outputTokens: result.usage?.completionTokens ?? 0,
1540
- totalTokens: (result.usage?.promptTokens ?? 0) + (result.usage?.completionTokens ?? 0),
1538
+ inputTokens: result.usage?.inputTokens ?? 0,
1539
+ outputTokens: result.usage?.outputTokens ?? 0,
1540
+ totalTokens: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0),
1541
1541
  model: this.model,
1542
1542
  provider: this.name
1543
1543
  };
@@ -1585,9 +1585,9 @@ var AnthropicProvider = class extends BaseProvider {
1585
1585
  });
1586
1586
  return {
1587
1587
  text: result.text,
1588
- inputTokens: result.usage?.promptTokens ?? 0,
1589
- outputTokens: result.usage?.completionTokens ?? 0,
1590
- totalTokens: (result.usage?.promptTokens ?? 0) + (result.usage?.completionTokens ?? 0),
1588
+ inputTokens: result.usage?.inputTokens ?? 0,
1589
+ outputTokens: result.usage?.outputTokens ?? 0,
1590
+ totalTokens: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0),
1591
1591
  model: this.model,
1592
1592
  provider: this.name
1593
1593
  };
@@ -1611,6 +1611,38 @@ var AnthropicProvider = class extends BaseProvider {
1611
1611
  }
1612
1612
  };
1613
1613
 
1614
+ // src/providers/deepseek.ts
1615
+ import { createDeepSeek } from "@ai-sdk/deepseek";
1616
+ var DeepSeekProvider = class extends BaseProvider {
1617
+ name;
1618
+ model;
1619
+ modelInstance;
1620
+ isReasoner;
1621
+ constructor(config) {
1622
+ super(config);
1623
+ this.name = config.name;
1624
+ this.model = config.model;
1625
+ this.isReasoner = config.model === "deepseek-reasoner";
1626
+ const client = createDeepSeek({
1627
+ apiKey: config.apiKey,
1628
+ baseURL: config.baseUrl
1629
+ });
1630
+ this.modelInstance = client(config.model);
1631
+ }
1632
+ async generateText(_prompt, _systemPrompt) {
1633
+ throw new Error("Use getModelInstance() with the AI SDK agent loop");
1634
+ }
1635
+ async *streamText(_prompt, _systemPrompt) {
1636
+ throw new Error("Use getModelInstance() with the AI SDK agent loop");
1637
+ }
1638
+ isAvailable() {
1639
+ return this.config.apiKey.length > 0;
1640
+ }
1641
+ getModelInstance() {
1642
+ return this.modelInstance;
1643
+ }
1644
+ };
1645
+
1614
1646
  // src/providers/ollama.ts
1615
1647
  import { createOllama } from "ollama-ai-provider";
1616
1648
  var OllamaProvider = class extends BaseProvider {
@@ -1668,6 +1700,8 @@ var ProviderRegistry = class {
1668
1700
  let provider;
1669
1701
  if (pc.name === "anthropic") {
1670
1702
  provider = new AnthropicProvider(pc);
1703
+ } else if (pc.name === "deepseek") {
1704
+ provider = new DeepSeekProvider(pc);
1671
1705
  } else if (pc.name === "ollamaCloud" || pc.name === "ollamaLocal") {
1672
1706
  provider = new OllamaProvider(pc);
1673
1707
  } else {
@@ -1720,7 +1754,7 @@ var ProviderRegistry = class {
1720
1754
  };
1721
1755
 
1722
1756
  // src/core/agent.ts
1723
- import { generateText as generateText3, streamText as streamText3 } from "ai";
1757
+ import { generateText as generateText3, streamText as streamText3, stepCountIs } from "ai";
1724
1758
 
1725
1759
  // src/core/lifecycle.ts
1726
1760
  var VALID_TRANSITIONS = [
@@ -3885,6 +3919,7 @@ You can override this:
3885
3919
  }
3886
3920
  for (const provider of fallbackIterator) {
3887
3921
  try {
3922
+ const deepseekProviderOptions = provider instanceof DeepSeekProvider && provider.isReasoner ? { deepseek: { thinking: { type: "enabled" } } } : void 0;
3888
3923
  logger.info({ provider: provider.name, model: provider.getModel(), steps: MAX_STEPS, stream: canStream }, "Generating agentic response");
3889
3924
  if (canStream && channel) {
3890
3925
  const streamResult = streamText3({
@@ -3892,8 +3927,9 @@ You can override this:
3892
3927
  system: systemPrompt,
3893
3928
  messages,
3894
3929
  tools: this.capabilities.getTools(),
3895
- maxSteps: MAX_STEPS,
3930
+ stopWhen: stepCountIs(MAX_STEPS),
3896
3931
  abortSignal: loopAbortController.signal,
3932
+ ...deepseekProviderOptions ? { providerOptions: deepseekProviderOptions } : {},
3897
3933
  onStepFinish: async ({ toolCalls, toolResults }) => {
3898
3934
  if (toolCalls && toolResults && toolCalls.length > 0) {
3899
3935
  const names = toolCalls.map((tc) => tc.toolName).join(", ");
@@ -3903,7 +3939,7 @@ You can override this:
3903
3939
  const tr = toolResults[i];
3904
3940
  const resultStr = typeof tr?.result === "string" ? tr.result : JSON.stringify(tr?.result ?? "");
3905
3941
  const failed = resultStr.length < 5e3 && (resultStr.startsWith("Error:") || resultStr.startsWith("\u26A0") || resultStr.includes("exited with code") || resultStr.includes("Command failed") || resultStr.startsWith("Command exited with code"));
3906
- loopDetector.record(tc.toolName, tc.args, failed);
3942
+ loopDetector.record(tc.toolName, tc.input, failed);
3907
3943
  }
3908
3944
  if (loopDetector.detectAbsoluteLimit()) {
3909
3945
  logger.warn("Absolute tool call limit reached \u2014 aborting");
@@ -3961,7 +3997,7 @@ You can override this:
3961
3997
  if (channel && msg.channelType !== "internal") {
3962
3998
  if (channel instanceof CLIChannel) {
3963
3999
  for (const tc of toolCalls) {
3964
- await channel.sendToolFeedback(tc.toolName, tc.args).catch(() => {
4000
+ await channel.sendToolFeedback(tc.toolName, tc.input).catch(() => {
3965
4001
  });
3966
4002
  }
3967
4003
  if (toolResults) {
@@ -3976,7 +4012,7 @@ You can override this:
3976
4012
  } else if (channel instanceof TelegramChannel) {
3977
4013
  const tgCh = channel;
3978
4014
  for (const tc of toolCalls) {
3979
- await tgCh.sendToolFeedback(tc.toolName, tc.args, msg.channelId).catch(() => {
4015
+ await tgCh.sendToolFeedback(tc.toolName, tc.input, msg.channelId).catch(() => {
3980
4016
  });
3981
4017
  }
3982
4018
  if (toolResults) {
@@ -4042,7 +4078,8 @@ You can override this:
4042
4078
  const [usage] = await Promise.all([
4043
4079
  streamResult.usage
4044
4080
  ]);
4045
- result = { text: fullText, usage };
4081
+ const streamReasoning = await streamResult.reasoning;
4082
+ result = { text: fullText, usage, reasoning: streamReasoning };
4046
4083
  streamedText = fullText;
4047
4084
  loopDetector.recordStepText(fullText);
4048
4085
  } else {
@@ -4051,8 +4088,9 @@ You can override this:
4051
4088
  system: systemPrompt,
4052
4089
  messages,
4053
4090
  tools: this.capabilities.getTools(),
4054
- maxSteps: MAX_STEPS,
4091
+ stopWhen: stepCountIs(MAX_STEPS),
4055
4092
  abortSignal: loopAbortController.signal,
4093
+ ...deepseekProviderOptions ? { providerOptions: deepseekProviderOptions } : {},
4056
4094
  onStepFinish: async ({ toolCalls, toolResults }) => {
4057
4095
  if (toolCalls && toolResults && toolCalls.length > 0) {
4058
4096
  const names = toolCalls.map((tc) => tc.toolName).join(", ");
@@ -4062,7 +4100,7 @@ You can override this:
4062
4100
  const tr = toolResults[i];
4063
4101
  const resultStr = typeof tr?.result === "string" ? tr.result : JSON.stringify(tr?.result ?? "");
4064
4102
  const failed = resultStr.length < 5e3 && (resultStr.startsWith("Error:") || resultStr.startsWith("\u26A0") || resultStr.includes("exited with code") || resultStr.includes("Command failed") || resultStr.startsWith("Command exited with code"));
4065
- loopDetector.record(tc.toolName, tc.args, failed);
4103
+ loopDetector.record(tc.toolName, tc.input, failed);
4066
4104
  }
4067
4105
  if (loopDetector.detectAbsoluteLimit()) {
4068
4106
  logger.warn("Absolute tool call limit reached \u2014 aborting");
@@ -4120,7 +4158,7 @@ You can override this:
4120
4158
  if (channel && msg.channelType !== "internal") {
4121
4159
  if (channel instanceof CLIChannel) {
4122
4160
  for (const tc of toolCalls) {
4123
- await channel.sendToolFeedback(tc.toolName, tc.args).catch(() => {
4161
+ await channel.sendToolFeedback(tc.toolName, tc.input).catch(() => {
4124
4162
  });
4125
4163
  }
4126
4164
  if (toolResults) {
@@ -4135,7 +4173,7 @@ You can override this:
4135
4173
  } else if (channel instanceof TelegramChannel) {
4136
4174
  const tgCh = channel;
4137
4175
  for (const tc of toolCalls) {
4138
- await tgCh.sendToolFeedback(tc.toolName, tc.args, msg.channelId).catch(() => {
4176
+ await tgCh.sendToolFeedback(tc.toolName, tc.input, msg.channelId).catch(() => {
4139
4177
  });
4140
4178
  }
4141
4179
  if (toolResults) {
@@ -4221,9 +4259,9 @@ You can override this:
4221
4259
  this.tokenBudget.recordUsage({
4222
4260
  provider: usedProvider.name,
4223
4261
  model: usedProvider.model,
4224
- inputTokens: result.usage?.promptTokens ?? 0,
4225
- outputTokens: result.usage?.completionTokens ?? 0,
4226
- totalTokens: (result.usage?.promptTokens ?? 0) + (result.usage?.completionTokens ?? 0),
4262
+ inputTokens: result.usage?.inputTokens ?? 0,
4263
+ outputTokens: result.usage?.outputTokens ?? 0,
4264
+ totalTokens: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0),
4227
4265
  channelType: msg.channelType
4228
4266
  });
4229
4267
  this.shortTerm.add(msg.channelId, {
@@ -4237,7 +4275,8 @@ You can override this:
4237
4275
  timestamp: Date.now(),
4238
4276
  role: "assistant",
4239
4277
  content: finalText,
4240
- tokenCount: (result.usage?.promptTokens ?? 0) + (result.usage?.completionTokens ?? 0)
4278
+ tokenCount: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0),
4279
+ reasoning: result.reasoning || void 0
4241
4280
  });
4242
4281
  this.episodic.record({
4243
4282
  type: "message",
@@ -4433,14 +4472,14 @@ All actions auto-approved for this run.`,
4433
4472
  { role: "user", content: `User: ${userMessage}
4434
4473
  Assistant: ${agentResponse}` }
4435
4474
  ],
4436
- maxTokens: 400
4475
+ maxOutputTokens: 400
4437
4476
  });
4438
4477
  this.tokenBudget.recordUsage({
4439
4478
  provider: provider.name,
4440
4479
  model: provider.getModel(),
4441
- inputTokens: result.usage?.promptTokens ?? 0,
4442
- outputTokens: result.usage?.completionTokens ?? 0,
4443
- totalTokens: (result.usage?.promptTokens ?? 0) + (result.usage?.completionTokens ?? 0),
4480
+ inputTokens: result.usage?.inputTokens ?? 0,
4481
+ outputTokens: result.usage?.outputTokens ?? 0,
4482
+ totalTokens: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0),
4444
4483
  channelType: "internal"
4445
4484
  });
4446
4485
  const text = result.text.trim();
@@ -4537,6 +4576,11 @@ Or use /budget override, /budget reset, /budget set <number> anytime.`,
4537
4576
  await channel.send(ctx.manual(), channelId);
4538
4577
  return true;
4539
4578
  }
4579
+ if (cmd === "/exit" || cmd === "/quit") {
4580
+ await channel.send("Goodbye! Shutting down Mercury...", channelId);
4581
+ this.shutdown();
4582
+ return true;
4583
+ }
4540
4584
  if (cmd === "/status") {
4541
4585
  const config = ctx.config();
4542
4586
  const budget = ctx.tokenBudget();
@@ -5842,16 +5886,16 @@ Allow access?`;
5842
5886
  };
5843
5887
 
5844
5888
  // src/capabilities/filesystem/read-file.ts
5845
- import { tool } from "ai";
5889
+ import { tool, zodSchema } from "ai";
5846
5890
  import { z } from "zod";
5847
5891
  import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
5848
5892
  import { resolve as resolve4, isAbsolute } from "path";
5849
5893
  function createReadFileTool(permissions, getCwd) {
5850
5894
  return tool({
5851
5895
  description: "Read the contents of a file. The path must be within an allowed scope.",
5852
- parameters: z.object({
5896
+ inputSchema: zodSchema(z.object({
5853
5897
  path: z.string().describe("Absolute or relative path to the file")
5854
- }),
5898
+ })),
5855
5899
  execute: async ({ path: path3 }) => {
5856
5900
  const resolved = isAbsolute(path3) ? resolve4(path3) : resolve4(getCwd(), path3);
5857
5901
  const check = await permissions.checkFsAccess(resolved, "read");
@@ -5879,17 +5923,17 @@ function createReadFileTool(permissions, getCwd) {
5879
5923
  }
5880
5924
 
5881
5925
  // src/capabilities/filesystem/write-file.ts
5882
- import { tool as tool2 } from "ai";
5926
+ import { tool as tool2, zodSchema as zodSchema2 } from "ai";
5883
5927
  import { z as z2 } from "zod";
5884
5928
  import { existsSync as existsSync9, writeFileSync as writeFileSync7 } from "fs";
5885
5929
  import { resolve as resolve5, isAbsolute as isAbsolute2 } from "path";
5886
5930
  function createWriteFileTool(permissions, getCwd) {
5887
5931
  return tool2({
5888
5932
  description: "Write content to an existing file. The path must be within a writable scope.",
5889
- parameters: z2.object({
5933
+ inputSchema: zodSchema2(z2.object({
5890
5934
  path: z2.string().describe("Absolute or relative path to the file"),
5891
5935
  content: z2.string().describe("The content to write to the file")
5892
- }),
5936
+ })),
5893
5937
  execute: async ({ path: path3, content }) => {
5894
5938
  const resolved = isAbsolute2(path3) ? resolve5(path3) : resolve5(getCwd(), path3);
5895
5939
  const check = await permissions.checkFsAccess(resolved, "write");
@@ -5911,17 +5955,17 @@ function createWriteFileTool(permissions, getCwd) {
5911
5955
  }
5912
5956
 
5913
5957
  // src/capabilities/filesystem/create-file.ts
5914
- import { tool as tool3 } from "ai";
5958
+ import { tool as tool3, zodSchema as zodSchema3 } from "ai";
5915
5959
  import { z as z3 } from "zod";
5916
5960
  import { existsSync as existsSync10, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
5917
5961
  import { resolve as resolve6, dirname as dirname3, isAbsolute as isAbsolute3 } from "path";
5918
5962
  function createCreateFileTool(permissions, getCwd) {
5919
5963
  return tool3({
5920
5964
  description: "Create a new file with the given content. Also creates parent directories if needed. The path must be within a writable scope.",
5921
- parameters: z3.object({
5965
+ inputSchema: zodSchema3(z3.object({
5922
5966
  path: z3.string().describe("Absolute or relative path for the new file"),
5923
5967
  content: z3.string().describe("The content of the new file")
5924
- }),
5968
+ })),
5925
5969
  execute: async ({ path: path3, content }) => {
5926
5970
  const resolved = isAbsolute3(path3) ? resolve6(path3) : resolve6(getCwd(), path3);
5927
5971
  const check = await permissions.checkFsAccess(resolved, "write");
@@ -5947,16 +5991,16 @@ function createCreateFileTool(permissions, getCwd) {
5947
5991
  }
5948
5992
 
5949
5993
  // src/capabilities/filesystem/list-dir.ts
5950
- import { tool as tool4 } from "ai";
5994
+ import { tool as tool4, zodSchema as zodSchema4 } from "ai";
5951
5995
  import { z as z4 } from "zod";
5952
5996
  import { existsSync as existsSync11, readdirSync as readdirSync2, statSync } from "fs";
5953
5997
  import { resolve as resolve7, isAbsolute as isAbsolute4, join as join9 } from "path";
5954
5998
  function createListDirTool(permissions, getCwd) {
5955
5999
  return tool4({
5956
6000
  description: "List the contents of a directory. Shows file names, types, and sizes.",
5957
- parameters: z4.object({
6001
+ inputSchema: zodSchema4(z4.object({
5958
6002
  path: z4.string().describe("Absolute or relative path to the directory")
5959
- }),
6003
+ })),
5960
6004
  execute: async ({ path: path3 }) => {
5961
6005
  const resolved = isAbsolute4(path3) ? resolve7(path3) : resolve7(getCwd(), path3);
5962
6006
  const check = await permissions.checkFsAccess(resolved, "read");
@@ -6002,16 +6046,16 @@ function formatSize(bytes) {
6002
6046
  }
6003
6047
 
6004
6048
  // src/capabilities/filesystem/delete-file.ts
6005
- import { tool as tool5 } from "ai";
6049
+ import { tool as tool5, zodSchema as zodSchema5 } from "ai";
6006
6050
  import { z as z5 } from "zod";
6007
6051
  import { existsSync as existsSync12, unlinkSync as unlinkSync2 } from "fs";
6008
6052
  import { resolve as resolve8, isAbsolute as isAbsolute5 } from "path";
6009
6053
  function createDeleteFileTool(permissions, getCwd) {
6010
6054
  return tool5({
6011
6055
  description: "Delete a file. This action cannot be undone. The path must be within a writable scope. Always asks for confirmation.",
6012
- parameters: z5.object({
6056
+ inputSchema: zodSchema5(z5.object({
6013
6057
  path: z5.string().describe("Absolute or relative path to the file to delete")
6014
- }),
6058
+ })),
6015
6059
  execute: async ({ path: path3 }) => {
6016
6060
  const resolved = isAbsolute5(path3) ? resolve8(path3) : resolve8(getCwd(), path3);
6017
6061
  const check = await permissions.checkFsAccess(resolved, "write");
@@ -6037,18 +6081,18 @@ function createDeleteFileTool(permissions, getCwd) {
6037
6081
  }
6038
6082
 
6039
6083
  // src/capabilities/filesystem/edit-file.ts
6040
- import { tool as tool6 } from "ai";
6084
+ import { tool as tool6, zodSchema as zodSchema6 } from "ai";
6041
6085
  import { z as z6 } from "zod";
6042
6086
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
6043
6087
  import { resolve as resolve9, isAbsolute as isAbsolute6 } from "path";
6044
6088
  function createEditFileTool(permissions, getCwd) {
6045
6089
  return tool6({
6046
6090
  description: "Edit a file by replacing an exact string match with new content. Use this instead of write_file when you only need to change part of a file. The old_string must match exactly (including whitespace and indentation). Fails if old_string is not found or found multiple times.",
6047
- parameters: z6.object({
6091
+ inputSchema: zodSchema6(z6.object({
6048
6092
  path: z6.string().describe("Absolute or relative path to the file"),
6049
6093
  old_string: z6.string().describe("The exact text to find in the file (must match exactly)"),
6050
6094
  new_string: z6.string().describe("The text to replace it with")
6051
- }),
6095
+ })),
6052
6096
  execute: async ({ path: path3, old_string, new_string }) => {
6053
6097
  const resolved = isAbsolute6(path3) ? resolve9(path3) : resolve9(getCwd(), path3);
6054
6098
  const fsCheck = await permissions.checkFsAccess(resolved, "write");
@@ -6081,16 +6125,16 @@ function createEditFileTool(permissions, getCwd) {
6081
6125
  }
6082
6126
 
6083
6127
  // src/capabilities/filesystem/send-file.ts
6084
- import { tool as tool7 } from "ai";
6128
+ import { tool as tool7, zodSchema as zodSchema7 } from "ai";
6085
6129
  import { z as z7 } from "zod";
6086
6130
  import { existsSync as existsSync13, statSync as statSync2 } from "fs";
6087
6131
  import { resolve as resolve10, basename as basename2, isAbsolute as isAbsolute7 } from "path";
6088
6132
  function createSendFileTool(permissions, getCwd, sendFile) {
6089
6133
  return tool7({
6090
6134
  description: "Send a file to the user. On Telegram the file is uploaded as an attachment to the relevant approved recipients. On CLI the file path and size are displayed. The path must be within an allowed read scope.",
6091
- parameters: z7.object({
6135
+ inputSchema: zodSchema7(z7.object({
6092
6136
  path: z7.string().describe("Absolute or relative path to the file to send")
6093
- }),
6137
+ })),
6094
6138
  execute: async ({ path: path3 }) => {
6095
6139
  const resolved = isAbsolute7(path3) ? resolve10(path3) : resolve10(getCwd(), path3);
6096
6140
  const check = await permissions.checkFsAccess(resolved, "read");
@@ -6121,14 +6165,14 @@ function createSendFileTool(permissions, getCwd, sendFile) {
6121
6165
  }
6122
6166
 
6123
6167
  // src/capabilities/messaging/send-message.ts
6124
- import { tool as tool8 } from "ai";
6168
+ import { tool as tool8, zodSchema as zodSchema8 } from "ai";
6125
6169
  import { z as z8 } from "zod";
6126
6170
  function createSendMessageTool(sendMessage) {
6127
6171
  return tool8({
6128
6172
  description: "Send a message through the configured outbound channel. For Telegram this sends to the approved Telegram recipients. Use this only when the user explicitly asks you to send something to Telegram or asks for scheduled results to be sent there.",
6129
- parameters: z8.object({
6173
+ inputSchema: zodSchema8(z8.object({
6130
6174
  content: z8.string().describe("The message content to send to the approved Telegram recipients")
6131
- }),
6175
+ })),
6132
6176
  execute: async ({ content }) => {
6133
6177
  const trimmed = content.trim();
6134
6178
  if (!trimmed) {
@@ -6145,16 +6189,16 @@ function createSendMessageTool(sendMessage) {
6145
6189
  }
6146
6190
 
6147
6191
  // src/capabilities/filesystem/approve-scope.ts
6148
- import { tool as tool9 } from "ai";
6192
+ import { tool as tool9, zodSchema as zodSchema9 } from "ai";
6149
6193
  import { z as z9 } from "zod";
6150
6194
  import { resolve as resolve11, isAbsolute as isAbsolute8 } from "path";
6151
6195
  function createApproveScopeTool(permissions, getCwd) {
6152
6196
  return tool9({
6153
6197
  description: 'Request user approval to access a directory outside current scopes. Use this when a file tool returns a permission denied error. The user gets an approval prompt (Allow/Always/Deny buttons on Telegram, yes/always/no on CLI). "Allow" grants session-only access. "Always" persists to disk. After approval, retry the original file operation.',
6154
- parameters: z9.object({
6198
+ inputSchema: zodSchema9(z9.object({
6155
6199
  path: z9.string().describe("The directory path to request access to"),
6156
6200
  mode: z9.enum(["read", "write"]).describe("The access mode needed")
6157
- }),
6201
+ })),
6158
6202
  execute: async ({ path: path3, mode }) => {
6159
6203
  const resolved = isAbsolute8(path3) ? resolve11(path3) : resolve11(getCwd(), path3);
6160
6204
  const result = await permissions.requestScopeExternal(resolved, mode);
@@ -6167,7 +6211,7 @@ function createApproveScopeTool(permissions, getCwd) {
6167
6211
  }
6168
6212
 
6169
6213
  // src/capabilities/shell/run-command.ts
6170
- import { tool as tool10 } from "ai";
6214
+ import { tool as tool10, zodSchema as zodSchema10 } from "ai";
6171
6215
  import { z as z10 } from "zod";
6172
6216
  import { execSync } from "child_process";
6173
6217
  import { resolve as resolve12, isAbsolute as isAbsolute9 } from "path";
@@ -6179,9 +6223,9 @@ function createRunCommandTool(permissions, getCwd, setCwd) {
6179
6223
  Blocked commands (sudo, rm -rf /, etc.) are never executed.
6180
6224
  Auto-approved commands (ls, cat, git status, curl, etc.) run without asking.
6181
6225
  Other commands require user approval.`,
6182
- parameters: z10.object({
6226
+ inputSchema: zodSchema10(z10.object({
6183
6227
  command: z10.string().describe("The shell command to execute")
6184
- }),
6228
+ })),
6185
6229
  execute: async ({ command }) => {
6186
6230
  const check = await permissions.checkShellCommand(command);
6187
6231
  if (!check.allowed) {
@@ -6245,16 +6289,16 @@ function detectCd(command, currentCwd, setCwd) {
6245
6289
  }
6246
6290
 
6247
6291
  // src/capabilities/shell/cd.ts
6248
- import { tool as tool11 } from "ai";
6292
+ import { tool as tool11, zodSchema as zodSchema11 } from "ai";
6249
6293
  import { z as z11 } from "zod";
6250
6294
  import { resolve as resolve13, isAbsolute as isAbsolute10 } from "path";
6251
6295
  import { existsSync as existsSync15, statSync as statSync3 } from "fs";
6252
6296
  function createCdTool(getCwd, setCwd) {
6253
6297
  return tool11({
6254
6298
  description: "Change the current working directory. All subsequent file operations, shell commands, and git operations will use this directory. Use this before running commands in a specific project folder.",
6255
- parameters: z11.object({
6299
+ inputSchema: zodSchema11(z11.object({
6256
6300
  path: z11.string().describe("The directory to change to. Can be absolute or relative to the current directory.")
6257
- }),
6301
+ })),
6258
6302
  execute: async ({ path: path3 }) => {
6259
6303
  const cwd = getCwd();
6260
6304
  const resolved = isAbsolute10(path3) ? resolve13(path3) : resolve13(cwd, path3);
@@ -6276,14 +6320,14 @@ function createCdTool(getCwd, setCwd) {
6276
6320
  }
6277
6321
 
6278
6322
  // src/capabilities/shell/approve-command.ts
6279
- import { tool as tool12 } from "ai";
6323
+ import { tool as tool12, zodSchema as zodSchema12 } from "ai";
6280
6324
  import { z as z12 } from "zod";
6281
6325
  function createApproveCommandTool(permissions) {
6282
6326
  return tool12({
6283
6327
  description: 'Permanently approve a command type so it runs without asking in the future. Use this when the user says "always" or "always approve" for a command. For example, if the user says "always approve curl", call this with command="curl".',
6284
- parameters: z12.object({
6328
+ inputSchema: zodSchema12(z12.object({
6285
6329
  command: z12.string().describe('The base command to permanently approve (e.g. "curl", "docker", "npm")')
6286
- }),
6330
+ })),
6287
6331
  execute: async ({ command }) => {
6288
6332
  const baseCmd = command.trim().split(/\s+/)[0];
6289
6333
  permissions.addApprovedCommand(baseCmd);
@@ -6293,16 +6337,16 @@ function createApproveCommandTool(permissions) {
6293
6337
  }
6294
6338
 
6295
6339
  // src/capabilities/skills/install-skill.ts
6296
- import { tool as tool13 } from "ai";
6340
+ import { tool as tool13, zodSchema as zodSchema13 } from "ai";
6297
6341
  import { z as z13 } from "zod";
6298
6342
  import { parse as parseYaml4 } from "yaml";
6299
6343
  function createInstallSkillTool(skillLoader) {
6300
6344
  return tool13({
6301
6345
  description: "Install a new skill by providing SKILL.md markdown content or a URL. The content must have YAML frontmatter (---) with at least name and description fields.",
6302
- parameters: z13.object({
6346
+ inputSchema: zodSchema13(z13.object({
6303
6347
  content: z13.string().optional().describe("Raw SKILL.md markdown content with YAML frontmatter"),
6304
6348
  url: z13.string().optional().describe("URL to fetch a SKILL.md from")
6305
- }),
6349
+ })),
6306
6350
  execute: async ({ content, url }) => {
6307
6351
  let skillContent;
6308
6352
  if (url && !content) {
@@ -6341,12 +6385,12 @@ function createInstallSkillTool(skillLoader) {
6341
6385
  }
6342
6386
 
6343
6387
  // src/capabilities/skills/list-skills.ts
6344
- import { tool as tool14 } from "ai";
6388
+ import { tool as tool14, zodSchema as zodSchema14 } from "ai";
6345
6389
  import { z as z14 } from "zod";
6346
6390
  function createListSkillsTool(skillLoader) {
6347
6391
  return tool14({
6348
6392
  description: "List all installed skills with their names and descriptions.",
6349
- parameters: z14.object({}),
6393
+ inputSchema: zodSchema14(z14.object({})),
6350
6394
  execute: async () => {
6351
6395
  const skills = skillLoader.getDiscovered();
6352
6396
  if (skills.length === 0) {
@@ -6358,14 +6402,14 @@ function createListSkillsTool(skillLoader) {
6358
6402
  }
6359
6403
 
6360
6404
  // src/capabilities/skills/use-skill.ts
6361
- import { tool as tool15 } from "ai";
6405
+ import { tool as tool15, zodSchema as zodSchema15 } from "ai";
6362
6406
  import { z as z15 } from "zod";
6363
6407
  function createUseSkillTool(skillLoader, permissions) {
6364
6408
  return tool15({
6365
6409
  description: "Load and invoke a skill by name. Returns the skill's full instructions which should be followed as guidance for the current task.",
6366
- parameters: z15.object({
6410
+ inputSchema: zodSchema15(z15.object({
6367
6411
  name: z15.string().describe("Name of the skill to invoke")
6368
- }),
6412
+ })),
6369
6413
  execute: async ({ name }) => {
6370
6414
  const skill = skillLoader.load(name);
6371
6415
  if (!skill) {
@@ -6391,19 +6435,19 @@ Allowed tools: ${skill["allowed-tools"].join(", ")}`;
6391
6435
  }
6392
6436
 
6393
6437
  // src/capabilities/scheduler/schedule-task.ts
6394
- import { tool as tool16 } from "ai";
6438
+ import { tool as tool16, zodSchema as zodSchema16 } from "ai";
6395
6439
  import { z as z16 } from "zod";
6396
6440
  import cron2 from "node-cron";
6397
6441
  function createScheduleTaskTool(scheduler, getContext) {
6398
6442
  return tool16({
6399
6443
  description: 'Schedule a task. Use "cron" for recurring tasks (e.g. "0 9 * * *" for daily at 9am) or "delay_seconds" for one-shot delayed tasks (e.g. 15 for "remind me in 15 seconds"). Provide exactly one of cron or delay_seconds.',
6400
- parameters: z16.object({
6444
+ inputSchema: zodSchema16(z16.object({
6401
6445
  cron: z16.string().optional().describe('Cron expression for recurring tasks (e.g. "0 9 * * *" for daily at 9am)'),
6402
6446
  delay_seconds: z16.number().optional().describe('Delay in seconds for one-shot tasks (e.g. 15 for "remind me in 15 seconds")'),
6403
6447
  description: z16.string().describe("Human-readable description of what this task does"),
6404
6448
  prompt: z16.string().optional().describe("Prompt to send to the agent when the task fires"),
6405
6449
  skill_name: z16.string().optional().describe("Name of a skill to invoke when the task fires")
6406
- }),
6450
+ })),
6407
6451
  execute: async ({ cron: cronExpr, delay_seconds, description, prompt, skill_name }) => {
6408
6452
  if (!cronExpr && !delay_seconds) {
6409
6453
  return "Either cron or delay_seconds must be provided.";
@@ -6455,12 +6499,12 @@ function createScheduleTaskTool(scheduler, getContext) {
6455
6499
  }
6456
6500
 
6457
6501
  // src/capabilities/scheduler/list-tasks.ts
6458
- import { tool as tool17 } from "ai";
6502
+ import { tool as tool17, zodSchema as zodSchema17 } from "ai";
6459
6503
  import { z as z17 } from "zod";
6460
6504
  function createListTasksTool(scheduler) {
6461
6505
  return tool17({
6462
6506
  description: "List all scheduled tasks with their cron expressions and descriptions.",
6463
- parameters: z17.object({}),
6507
+ inputSchema: zodSchema17(z17.object({})),
6464
6508
  execute: async () => {
6465
6509
  const manifests = scheduler.getManifests();
6466
6510
  if (manifests.length === 0) {
@@ -6475,14 +6519,14 @@ function createListTasksTool(scheduler) {
6475
6519
  }
6476
6520
 
6477
6521
  // src/capabilities/scheduler/cancel-task.ts
6478
- import { tool as tool18 } from "ai";
6522
+ import { tool as tool18, zodSchema as zodSchema18 } from "ai";
6479
6523
  import { z as z18 } from "zod";
6480
6524
  function createCancelTaskTool(scheduler) {
6481
6525
  return tool18({
6482
6526
  description: "Cancel and remove a scheduled task by its ID.",
6483
- parameters: z18.object({
6527
+ inputSchema: zodSchema18(z18.object({
6484
6528
  id: z18.string().describe("ID of the scheduled task to cancel")
6485
- }),
6529
+ })),
6486
6530
  execute: async ({ id }) => {
6487
6531
  const manifests = scheduler.getManifests();
6488
6532
  const exists = manifests.some((m) => m.id === id);
@@ -6497,12 +6541,12 @@ function createCancelTaskTool(scheduler) {
6497
6541
  }
6498
6542
 
6499
6543
  // src/capabilities/system/budget-status.ts
6500
- import { tool as tool19 } from "ai";
6544
+ import { tool as tool19, zodSchema as zodSchema19 } from "ai";
6501
6545
  import { z as z19 } from "zod";
6502
6546
  function createBudgetStatusTool(tokenBudget) {
6503
6547
  return tool19({
6504
6548
  description: "Check the current token budget status \u2014 how many tokens have been used today, how many remain, and what percentage is consumed.",
6505
- parameters: z19.object({}),
6549
+ inputSchema: zodSchema19(z19.object({})),
6506
6550
  execute: async () => {
6507
6551
  return tokenBudget.getStatusText();
6508
6552
  }
@@ -6510,15 +6554,15 @@ function createBudgetStatusTool(tokenBudget) {
6510
6554
  }
6511
6555
 
6512
6556
  // src/capabilities/git/git-status.ts
6513
- import { tool as tool20 } from "ai";
6557
+ import { tool as tool20, zodSchema as zodSchema20 } from "ai";
6514
6558
  import { z as z20 } from "zod";
6515
6559
  import { execSync as execSync2 } from "child_process";
6516
6560
  function createGitStatusTool(getCwd) {
6517
6561
  return tool20({
6518
6562
  description: "Show the working tree status. Returns staged, unstaged, and untracked files.",
6519
- parameters: z20.object({
6563
+ inputSchema: zodSchema20(z20.object({
6520
6564
  path: z20.string().optional().describe("Path to check (defaults to current directory)")
6521
- }),
6565
+ })),
6522
6566
  execute: async ({ path: path3 }) => {
6523
6567
  try {
6524
6568
  const cmd = path3 ? `git -C "${path3}" status --porcelain` : "git status --porcelain";
@@ -6533,16 +6577,16 @@ function createGitStatusTool(getCwd) {
6533
6577
  }
6534
6578
 
6535
6579
  // src/capabilities/git/git-diff.ts
6536
- import { tool as tool21 } from "ai";
6580
+ import { tool as tool21, zodSchema as zodSchema21 } from "ai";
6537
6581
  import { z as z21 } from "zod";
6538
6582
  import { execSync as execSync3 } from "child_process";
6539
6583
  function createGitDiffTool(getCwd) {
6540
6584
  return tool21({
6541
6585
  description: "Show changes between commits, commit and working tree, etc. Shows what has been modified.",
6542
- parameters: z21.object({
6586
+ inputSchema: zodSchema21(z21.object({
6543
6587
  path: z21.string().optional().describe("File or directory to diff"),
6544
6588
  staged: z21.boolean().optional().describe("Show staged changes (cached) instead of unstaged")
6545
- }),
6589
+ })),
6546
6590
  execute: async ({ path: path3, staged }) => {
6547
6591
  try {
6548
6592
  let cmd = "git diff";
@@ -6560,16 +6604,16 @@ function createGitDiffTool(getCwd) {
6560
6604
  }
6561
6605
 
6562
6606
  // src/capabilities/git/git-log.ts
6563
- import { tool as tool22 } from "ai";
6607
+ import { tool as tool22, zodSchema as zodSchema22 } from "ai";
6564
6608
  import { z as z22 } from "zod";
6565
6609
  import { execSync as execSync4 } from "child_process";
6566
6610
  function createGitLogTool(getCwd) {
6567
6611
  return tool22({
6568
6612
  description: "Show commit logs. Returns recent commit history with hash, author, date, and message.",
6569
- parameters: z22.object({
6613
+ inputSchema: zodSchema22(z22.object({
6570
6614
  count: z22.number().optional().describe("Number of commits to show (default 10)"),
6571
6615
  path: z22.string().optional().describe("File or directory to show log for")
6572
- }),
6616
+ })),
6573
6617
  execute: async ({ count, path: path3 }) => {
6574
6618
  try {
6575
6619
  const n = count ?? 10;
@@ -6586,15 +6630,15 @@ function createGitLogTool(getCwd) {
6586
6630
  }
6587
6631
 
6588
6632
  // src/capabilities/git/git-add.ts
6589
- import { tool as tool23 } from "ai";
6633
+ import { tool as tool23, zodSchema as zodSchema23 } from "ai";
6590
6634
  import { z as z23 } from "zod";
6591
6635
  import { execSync as execSync5 } from "child_process";
6592
6636
  function createGitAddTool(getCwd) {
6593
6637
  return tool23({
6594
6638
  description: "Add file contents to the index (staging area). Prepares files for commit.",
6595
- parameters: z23.object({
6639
+ inputSchema: zodSchema23(z23.object({
6596
6640
  paths: z23.array(z23.string()).describe("File paths to stage")
6597
- }),
6641
+ })),
6598
6642
  execute: async ({ paths }) => {
6599
6643
  try {
6600
6644
  const fileArgs = paths.map((p) => `"${p}"`).join(" ");
@@ -6608,7 +6652,7 @@ function createGitAddTool(getCwd) {
6608
6652
  }
6609
6653
 
6610
6654
  // src/capabilities/git/git-commit.ts
6611
- import { tool as tool24 } from "ai";
6655
+ import { tool as tool24, zodSchema as zodSchema24 } from "ai";
6612
6656
  import { z as z24 } from "zod";
6613
6657
  import { execSync as execSync6 } from "child_process";
6614
6658
  import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync3 } from "fs";
@@ -6617,9 +6661,9 @@ var CO_AUTHOR = "Mercury <mercury@cosmicstack.org>";
6617
6661
  function createGitCommitTool(getCwd) {
6618
6662
  return tool24({
6619
6663
  description: "Record changes to the repository. Creates a new commit with staged changes. Automatically includes a Co-authored-by trailer for attribution.",
6620
- parameters: z24.object({
6664
+ inputSchema: zodSchema24(z24.object({
6621
6665
  message: z24.string().describe("Commit message")
6622
- }),
6666
+ })),
6623
6667
  execute: async ({ message }) => {
6624
6668
  try {
6625
6669
  const fullMessage = `${message}
@@ -6654,16 +6698,16 @@ Co-authored-by: ${CO_AUTHOR}`;
6654
6698
  }
6655
6699
 
6656
6700
  // src/capabilities/git/git-push.ts
6657
- import { tool as tool25 } from "ai";
6701
+ import { tool as tool25, zodSchema as zodSchema25 } from "ai";
6658
6702
  import { z as z25 } from "zod";
6659
6703
  import { execSync as execSync7 } from "child_process";
6660
6704
  function createGitPushTool(permissions, getCwd) {
6661
6705
  return tool25({
6662
6706
  description: "Push commits to a remote repository. This modifies a remote and requires approval.",
6663
- parameters: z25.object({
6707
+ inputSchema: zodSchema25(z25.object({
6664
6708
  remote: z25.string().optional().describe("Remote name (default: origin)"),
6665
6709
  branch: z25.string().optional().describe("Branch name (default: current branch)")
6666
- }),
6710
+ })),
6667
6711
  execute: async ({ remote, branch }) => {
6668
6712
  const cmd = `git push ${remote || "origin"} ${branch || ""}`.trim();
6669
6713
  const check = await permissions.checkShellCommand(cmd);
@@ -6687,7 +6731,7 @@ Ask the user for permission. If they approve, try again. If they say "always", u
6687
6731
  }
6688
6732
 
6689
6733
  // src/capabilities/github/create-pr.ts
6690
- import { tool as tool26 } from "ai";
6734
+ import { tool as tool26, zodSchema as zodSchema26 } from "ai";
6691
6735
  import { z as z26 } from "zod";
6692
6736
 
6693
6737
  // src/utils/github.ts
@@ -6745,7 +6789,7 @@ async function githubRequest(path3, options = {}) {
6745
6789
  function createCreatePrTool() {
6746
6790
  return tool26({
6747
6791
  description: "Create a pull request on GitHub. Requires GITHUB_TOKEN to be configured.",
6748
- parameters: z26.object({
6792
+ inputSchema: zodSchema26(z26.object({
6749
6793
  owner: z26.string().describe("Repository owner (username or org)"),
6750
6794
  repo: z26.string().describe("Repository name"),
6751
6795
  title: z26.string().describe("PR title"),
@@ -6753,7 +6797,7 @@ function createCreatePrTool() {
6753
6797
  head: z26.string().describe("The branch containing the changes"),
6754
6798
  base: z26.string().describe("The branch to merge into").default("main"),
6755
6799
  draft: z26.boolean().describe("Create as draft PR").default(false)
6756
- }),
6800
+ })),
6757
6801
  execute: async ({ owner, repo, title, body, head, base, draft }) => {
6758
6802
  try {
6759
6803
  const result = await githubRequest(`/repos/${owner}/${repo}/pulls`, {
@@ -6771,17 +6815,17 @@ ${draft ? "(draft)" : ""} ${result.state}`;
6771
6815
  }
6772
6816
 
6773
6817
  // src/capabilities/github/review-pr.ts
6774
- import { tool as tool27 } from "ai";
6818
+ import { tool as tool27, zodSchema as zodSchema27 } from "ai";
6775
6819
  import { z as z27 } from "zod";
6776
6820
  function createReviewPrTool() {
6777
6821
  return tool27({
6778
6822
  description: "Get details of a pull request including the diff. Reviews the PR and returns the title, body, changed files, and diff. Optionally post a review comment.",
6779
- parameters: z27.object({
6823
+ inputSchema: zodSchema27(z27.object({
6780
6824
  owner: z27.string().describe("Repository owner (username or org)"),
6781
6825
  repo: z27.string().describe("Repository name"),
6782
6826
  number: z27.number().describe("PR number"),
6783
6827
  comment: z27.string().describe("Review comment to post on the PR (optional)").optional()
6784
- }),
6828
+ })),
6785
6829
  execute: async ({ owner, repo, number, comment }) => {
6786
6830
  try {
6787
6831
  const pr = await githubRequest(`/repos/${owner}/${repo}/pulls/${number}`);
@@ -6846,18 +6890,18 @@ Failed to post review comment: ${err.message}`;
6846
6890
  }
6847
6891
 
6848
6892
  // src/capabilities/github/list-issues.ts
6849
- import { tool as tool28 } from "ai";
6893
+ import { tool as tool28, zodSchema as zodSchema28 } from "ai";
6850
6894
  import { z as z28 } from "zod";
6851
6895
  function createListIssuesTool() {
6852
6896
  return tool28({
6853
6897
  description: "List GitHub issues for a repository. Requires GITHUB_TOKEN.",
6854
- parameters: z28.object({
6898
+ inputSchema: zodSchema28(z28.object({
6855
6899
  owner: z28.string().describe("Repository owner (username or org)"),
6856
6900
  repo: z28.string().describe("Repository name"),
6857
6901
  state: z28.enum(["open", "closed", "all"]).describe("Filter by issue state").default("open"),
6858
6902
  labels: z28.string().describe("Comma-separated label names to filter by (optional)").optional(),
6859
6903
  limit: z28.number().describe("Maximum number of issues to return").default(10)
6860
- }),
6904
+ })),
6861
6905
  execute: async ({ owner, repo, state, labels, limit }) => {
6862
6906
  try {
6863
6907
  const params = new URLSearchParams();
@@ -6884,18 +6928,18 @@ ${lines.join("\n")}`;
6884
6928
  }
6885
6929
 
6886
6930
  // src/capabilities/github/create-issue.ts
6887
- import { tool as tool29 } from "ai";
6931
+ import { tool as tool29, zodSchema as zodSchema29 } from "ai";
6888
6932
  import { z as z29 } from "zod";
6889
6933
  function createCreateIssueTool() {
6890
6934
  return tool29({
6891
6935
  description: "Create a new GitHub issue in a repository. Requires GITHUB_TOKEN.",
6892
- parameters: z29.object({
6936
+ inputSchema: zodSchema29(z29.object({
6893
6937
  owner: z29.string().describe("Repository owner (username or org)"),
6894
6938
  repo: z29.string().describe("Repository name"),
6895
6939
  title: z29.string().describe("Issue title"),
6896
6940
  body: z29.string().describe("Issue description (markdown supported)").default(""),
6897
6941
  labels: z29.array(z29.string()).describe("Label names to apply").optional()
6898
- }),
6942
+ })),
6899
6943
  execute: async ({ owner, repo, title, body, labels }) => {
6900
6944
  try {
6901
6945
  const payload = { title, body };
@@ -6914,7 +6958,7 @@ function createCreateIssueTool() {
6914
6958
  }
6915
6959
 
6916
6960
  // src/capabilities/github/github-api.ts
6917
- import { tool as tool30 } from "ai";
6961
+ import { tool as tool30, zodSchema as zodSchema30 } from "ai";
6918
6962
  import { z as z30 } from "zod";
6919
6963
  var CO_AUTHOR_NAME = "Mercury";
6920
6964
  var CO_AUTHOR_EMAIL = "mercury@cosmicstack.org";
@@ -6950,11 +6994,11 @@ Common operations you can perform:
6950
6994
  - Any other GitHub API v3 endpoint.
6951
6995
 
6952
6996
  IMPORTANT: When the user wants to push code or files to GitHub and git push fails (auth issues, no SSH key, etc.), use PUT /repos/{owner}/{repo}/contents/{path} to create or update files directly through the API. This bypasses local git and creates a commit with Mercury as co-author.`,
6953
- parameters: z30.object({
6997
+ inputSchema: zodSchema30(z30.object({
6954
6998
  path: z30.string().describe("Full API path (e.g., /repos/owner/repo/issues or /repos/owner/repo/contents/path/to/file)"),
6955
6999
  method: z30.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method").default("GET"),
6956
7000
  body: z30.string().describe("JSON body for write requests (as a JSON string)").optional()
6957
- }),
7001
+ })),
6958
7002
  execute: async ({ path: path3, method, body }) => {
6959
7003
  try {
6960
7004
  let parsedBody;
@@ -6983,7 +7027,7 @@ IMPORTANT: When the user wants to push code or files to GitHub and git push fail
6983
7027
  }
6984
7028
 
6985
7029
  // src/capabilities/web/fetch-url.ts
6986
- import { tool as tool31 } from "ai";
7030
+ import { tool as tool31, zodSchema as zodSchema31 } from "ai";
6987
7031
  import { z as z31 } from "zod";
6988
7032
  var MAX_CONTENT_LENGTH = 15e3;
6989
7033
  function stripHtml(html) {
@@ -7019,10 +7063,10 @@ function stripHtml(html) {
7019
7063
  function createFetchUrlTool() {
7020
7064
  return tool31({
7021
7065
  description: "Fetch a URL and return its content as text. Strips HTML to readable markdown-like format. Useful for reading documentation, APIs, or web pages.",
7022
- parameters: z31.object({
7066
+ inputSchema: zodSchema31(z31.object({
7023
7067
  url: z31.string().describe("The URL to fetch"),
7024
7068
  format: z31.enum(["text", "markdown"]).optional().describe("Output format (default: markdown)")
7025
- }),
7069
+ })),
7026
7070
  execute: async ({ url, format }) => {
7027
7071
  const outputFormat = format ?? "markdown";
7028
7072
  try {