@cosmicstack/mercury-agent 0.2.4 → 0.2.5

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
@@ -1706,16 +1706,16 @@ var CLIChannel = class extends BaseChannel {
1706
1706
  }
1707
1707
  }
1708
1708
  async prompt(question) {
1709
- return new Promise((resolve9) => {
1710
- this.rl?.question(question, (answer) => resolve9(answer.trim()));
1709
+ return new Promise((resolve10) => {
1710
+ this.rl?.question(question, (answer) => resolve10(answer.trim()));
1711
1711
  });
1712
1712
  }
1713
1713
  async askPermission(prompt) {
1714
- return new Promise((resolve9) => {
1714
+ return new Promise((resolve10) => {
1715
1715
  console.log("");
1716
1716
  console.log(chalk2.yellow(` \u26A0 ${prompt}`));
1717
1717
  this.rl?.question(chalk2.yellow(" > "), (answer) => {
1718
- resolve9(answer.trim());
1718
+ resolve10(answer.trim());
1719
1719
  });
1720
1720
  });
1721
1721
  }
@@ -1978,15 +1978,15 @@ var TelegramChannel = class extends BaseChannel {
1978
1978
  reply_markup: keyboard
1979
1979
  });
1980
1980
  }
1981
- return new Promise((resolve9) => {
1982
- this.pendingApprovals.set(`${id}:yes`, () => resolve9("yes"));
1983
- this.pendingApprovals.set(`${id}:always`, () => resolve9("always"));
1984
- this.pendingApprovals.set(`${id}:no`, () => resolve9("no"));
1981
+ return new Promise((resolve10) => {
1982
+ this.pendingApprovals.set(`${id}:yes`, () => resolve10("yes"));
1983
+ this.pendingApprovals.set(`${id}:always`, () => resolve10("always"));
1984
+ this.pendingApprovals.set(`${id}:no`, () => resolve10("no"));
1985
1985
  setTimeout(() => {
1986
1986
  this.pendingApprovals.delete(`${id}:yes`);
1987
1987
  this.pendingApprovals.delete(`${id}:always`);
1988
1988
  this.pendingApprovals.delete(`${id}:no`);
1989
- resolve9("no");
1989
+ resolve10("no");
1990
1990
  }, 12e4);
1991
1991
  });
1992
1992
  }
@@ -2334,8 +2334,8 @@ var PermissionManager = class {
2334
2334
  clearElevation() {
2335
2335
  this.elevatedCommands.clear();
2336
2336
  }
2337
- isElevated(tool24) {
2338
- if (this.elevatedCommands.has(tool24)) return true;
2337
+ isElevated(tool25) {
2338
+ if (this.elevatedCommands.has(tool25)) return true;
2339
2339
  return false;
2340
2340
  }
2341
2341
  isShellElevated() {
@@ -2501,18 +2501,23 @@ var PermissionManager = class {
2501
2501
  }
2502
2502
  return void 0;
2503
2503
  }
2504
+ async requestScopeExternal(path3, mode) {
2505
+ return this.requestScope(path3, mode);
2506
+ }
2504
2507
  async requestScope(path3, mode) {
2505
2508
  if (!this.askHandler) {
2506
- return { allowed: false, reason: `No permission to ${mode} ${path3}. Add scope to ~/.mercury/permissions.yaml` };
2509
+ return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
2507
2510
  }
2508
- const response = await this.askHandler(
2509
- `Mercury needs ${mode} access to ${path3}. Allow? (y/n/always): `
2510
- );
2511
- if (response.toLowerCase() === "always") {
2511
+ const prompt = `Mercury needs ${mode} access to:
2512
+ ${path3}
2513
+
2514
+ Allow access?`;
2515
+ const response = await this.askHandler(prompt);
2516
+ if (response === "always") {
2512
2517
  this.addScope(path3, mode === "read", mode === "write");
2513
2518
  return { allowed: true };
2514
2519
  }
2515
- if (response.toLowerCase() === "y" || response.toLowerCase() === "yes") {
2520
+ if (response === "yes" || response === "y") {
2516
2521
  return { allowed: true };
2517
2522
  }
2518
2523
  return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
@@ -2583,7 +2588,8 @@ function createReadFileTool(permissions) {
2583
2588
  const resolved = resolve2(path3);
2584
2589
  const check = await permissions.checkFsAccess(resolved, "read");
2585
2590
  if (!check.allowed) {
2586
- return `Error: ${check.reason}`;
2591
+ const parentDir = resolve2(resolved, "..");
2592
+ return `Error: Permission denied for read access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="read" to request access from the user.`;
2587
2593
  }
2588
2594
  if (!existsSync7(resolved)) {
2589
2595
  return `Error: File not found: ${resolved}`;
@@ -2620,7 +2626,8 @@ function createWriteFileTool(permissions) {
2620
2626
  const resolved = resolve3(path3);
2621
2627
  const check = await permissions.checkFsAccess(resolved, "write");
2622
2628
  if (!check.allowed) {
2623
- return `Error: ${check.reason}`;
2629
+ const parentDir = resolve3(resolved, "..");
2630
+ return `Error: Permission denied for write access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="write" to request access from the user.`;
2624
2631
  }
2625
2632
  if (!existsSync8(resolved)) {
2626
2633
  return `Error: File not found: ${resolved}. Use create_file to create new files.`;
@@ -2651,7 +2658,8 @@ function createCreateFileTool(permissions) {
2651
2658
  const resolved = resolve4(path3);
2652
2659
  const check = await permissions.checkFsAccess(resolved, "write");
2653
2660
  if (!check.allowed) {
2654
- return `Error: ${check.reason}`;
2661
+ const parentDir = resolve4(resolved, "..");
2662
+ return `Error: Permission denied for write access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="write" to request access from the user.`;
2655
2663
  }
2656
2664
  if (existsSync9(resolved)) {
2657
2665
  return `Error: File already exists: ${resolved}. Use write_file to modify existing files.`;
@@ -2685,7 +2693,7 @@ function createListDirTool(permissions) {
2685
2693
  const resolved = resolve5(path3);
2686
2694
  const check = await permissions.checkFsAccess(resolved, "read");
2687
2695
  if (!check.allowed) {
2688
- return `Error: ${check.reason}`;
2696
+ return `Error: Permission denied for read access to ${resolved}. Use the approve_scope tool with path="${resolved}" and mode="read" to request access from the user.`;
2689
2697
  }
2690
2698
  if (!existsSync10(resolved)) {
2691
2699
  return `Error: Directory not found: ${resolved}`;
@@ -2743,7 +2751,8 @@ function createDeleteFileTool(permissions) {
2743
2751
  const resolved = resolve6(path3);
2744
2752
  const check = await permissions.checkFsAccess(resolved, "write");
2745
2753
  if (!check.allowed) {
2746
- return `Error: ${check.reason}`;
2754
+ const parentDir = resolve6(resolved, "..");
2755
+ return `Error: Permission denied for write access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="write" to request access from the user.`;
2747
2756
  }
2748
2757
  if (!existsSync11(resolved)) {
2749
2758
  return `Error: File not found: ${resolved}`;
@@ -2779,7 +2788,8 @@ function createEditFileTool(permissions) {
2779
2788
  const resolved = resolve7(path3);
2780
2789
  const fsCheck = await permissions.checkFsAccess(resolved, "write");
2781
2790
  if (!fsCheck.allowed) {
2782
- return `Error: ${fsCheck.reason}`;
2791
+ const parentDir = resolve7(resolved, "..");
2792
+ return `Error: Permission denied for write access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="write" to request access from the user.`;
2783
2793
  }
2784
2794
  try {
2785
2795
  const content = readFileSync9(resolved, "utf-8");
@@ -2820,7 +2830,8 @@ function createSendFileTool(permissions, sendFile) {
2820
2830
  const resolved = resolve8(path3);
2821
2831
  const check = await permissions.checkFsAccess(resolved, "read");
2822
2832
  if (!check.allowed) {
2823
- return `Error: ${check.reason}`;
2833
+ const parentDir = resolve8(resolved, "..");
2834
+ return `Error: Permission denied for read access to ${resolved}. Use the approve_scope tool with path="${parentDir}" and mode="read" to request access from the user.`;
2824
2835
  }
2825
2836
  if (!existsSync12(resolved)) {
2826
2837
  return `Error: File not found: ${resolved}`;
@@ -2844,18 +2855,40 @@ function createSendFileTool(permissions, sendFile) {
2844
2855
  });
2845
2856
  }
2846
2857
 
2847
- // src/capabilities/shell/run-command.ts
2858
+ // src/capabilities/filesystem/approve-scope.ts
2848
2859
  import { tool as tool8 } from "ai";
2849
2860
  import { z as z8 } from "zod";
2861
+ import { resolve as resolve9 } from "path";
2862
+ function createApproveScopeTool(permissions) {
2863
+ return tool8({
2864
+ description: "Request user approval to add a directory to the allowed filesystem scopes. Use this when a file operation fails due to scope permissions. The user will see an approval prompt (inline keyboard on Telegram, readline on CLI). If approved, the scope is added permanently.",
2865
+ parameters: z8.object({
2866
+ path: z8.string().describe("The directory path to add to allowed scopes"),
2867
+ mode: z8.enum(["read", "write"]).describe("The access mode needed")
2868
+ }),
2869
+ execute: async ({ path: path3, mode }) => {
2870
+ const resolved = resolve9(path3);
2871
+ const result = await permissions.requestScopeExternal(resolved, mode);
2872
+ if (result.allowed) {
2873
+ return `Access approved for ${mode} access to ${resolved}`;
2874
+ }
2875
+ return `Access denied for ${mode} access to ${resolved}`;
2876
+ }
2877
+ });
2878
+ }
2879
+
2880
+ // src/capabilities/shell/run-command.ts
2881
+ import { tool as tool9 } from "ai";
2882
+ import { z as z9 } from "zod";
2850
2883
  import { execSync } from "child_process";
2851
2884
  function createRunCommandTool(permissions) {
2852
- return tool8({
2885
+ return tool9({
2853
2886
  description: `Run a shell command. Commands run in the current working directory unless an absolute path is given.
2854
2887
  Blocked commands (sudo, rm -rf /, etc.) are never executed.
2855
2888
  Auto-approved commands (ls, cat, git status, curl, etc.) run without asking.
2856
2889
  Other commands require user approval \u2014 tell the user what command you want to run and ask for confirmation. If they say "yes", try again. If they say "always", use the approve_command tool.`,
2857
- parameters: z8.object({
2858
- command: z8.string().describe("The shell command to execute")
2890
+ parameters: z9.object({
2891
+ command: z9.string().describe("The shell command to execute")
2859
2892
  }),
2860
2893
  execute: async ({ command }) => {
2861
2894
  const check = await permissions.checkShellCommand(command);
@@ -2895,13 +2928,13 @@ Error: ${stderr}`;
2895
2928
  }
2896
2929
 
2897
2930
  // src/capabilities/shell/approve-command.ts
2898
- import { tool as tool9 } from "ai";
2899
- import { z as z9 } from "zod";
2931
+ import { tool as tool10 } from "ai";
2932
+ import { z as z10 } from "zod";
2900
2933
  function createApproveCommandTool(permissions) {
2901
- return tool9({
2934
+ return tool10({
2902
2935
  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".',
2903
- parameters: z9.object({
2904
- command: z9.string().describe('The base command to permanently approve (e.g. "curl", "docker", "npm")')
2936
+ parameters: z10.object({
2937
+ command: z10.string().describe('The base command to permanently approve (e.g. "curl", "docker", "npm")')
2905
2938
  }),
2906
2939
  execute: async ({ command }) => {
2907
2940
  const baseCmd = command.trim().split(/\s+/)[0];
@@ -2912,15 +2945,15 @@ function createApproveCommandTool(permissions) {
2912
2945
  }
2913
2946
 
2914
2947
  // src/capabilities/skills/install-skill.ts
2915
- import { tool as tool10 } from "ai";
2916
- import { z as z10 } from "zod";
2948
+ import { tool as tool11 } from "ai";
2949
+ import { z as z11 } from "zod";
2917
2950
  import { parse as parseYaml4 } from "yaml";
2918
2951
  function createInstallSkillTool(skillLoader) {
2919
- return tool10({
2952
+ return tool11({
2920
2953
  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.",
2921
- parameters: z10.object({
2922
- content: z10.string().optional().describe("Raw SKILL.md markdown content with YAML frontmatter"),
2923
- url: z10.string().optional().describe("URL to fetch a SKILL.md from")
2954
+ parameters: z11.object({
2955
+ content: z11.string().optional().describe("Raw SKILL.md markdown content with YAML frontmatter"),
2956
+ url: z11.string().optional().describe("URL to fetch a SKILL.md from")
2924
2957
  }),
2925
2958
  execute: async ({ content, url }) => {
2926
2959
  let skillContent;
@@ -2960,12 +2993,12 @@ function createInstallSkillTool(skillLoader) {
2960
2993
  }
2961
2994
 
2962
2995
  // src/capabilities/skills/list-skills.ts
2963
- import { tool as tool11 } from "ai";
2964
- import { z as z11 } from "zod";
2996
+ import { tool as tool12 } from "ai";
2997
+ import { z as z12 } from "zod";
2965
2998
  function createListSkillsTool(skillLoader) {
2966
- return tool11({
2999
+ return tool12({
2967
3000
  description: "List all installed skills with their names and descriptions.",
2968
- parameters: z11.object({}),
3001
+ parameters: z12.object({}),
2969
3002
  execute: async () => {
2970
3003
  const skills = skillLoader.getDiscovered();
2971
3004
  if (skills.length === 0) {
@@ -2977,13 +3010,13 @@ function createListSkillsTool(skillLoader) {
2977
3010
  }
2978
3011
 
2979
3012
  // src/capabilities/skills/use-skill.ts
2980
- import { tool as tool12 } from "ai";
2981
- import { z as z12 } from "zod";
3013
+ import { tool as tool13 } from "ai";
3014
+ import { z as z13 } from "zod";
2982
3015
  function createUseSkillTool(skillLoader, permissions) {
2983
- return tool12({
3016
+ return tool13({
2984
3017
  description: "Load and invoke a skill by name. Returns the skill's full instructions which should be followed as guidance for the current task.",
2985
- parameters: z12.object({
2986
- name: z12.string().describe("Name of the skill to invoke")
3018
+ parameters: z13.object({
3019
+ name: z13.string().describe("Name of the skill to invoke")
2987
3020
  }),
2988
3021
  execute: async ({ name }) => {
2989
3022
  const skill = skillLoader.load(name);
@@ -3010,18 +3043,18 @@ Allowed tools: ${skill["allowed-tools"].join(", ")}`;
3010
3043
  }
3011
3044
 
3012
3045
  // src/capabilities/scheduler/schedule-task.ts
3013
- import { tool as tool13 } from "ai";
3014
- import { z as z13 } from "zod";
3046
+ import { tool as tool14 } from "ai";
3047
+ import { z as z14 } from "zod";
3015
3048
  import cron2 from "node-cron";
3016
3049
  function createScheduleTaskTool(scheduler, getContext) {
3017
- return tool13({
3050
+ return tool14({
3018
3051
  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.',
3019
- parameters: z13.object({
3020
- cron: z13.string().optional().describe('Cron expression for recurring tasks (e.g. "0 9 * * *" for daily at 9am)'),
3021
- delay_seconds: z13.number().optional().describe('Delay in seconds for one-shot tasks (e.g. 15 for "remind me in 15 seconds")'),
3022
- description: z13.string().describe("Human-readable description of what this task does"),
3023
- prompt: z13.string().optional().describe("Prompt to send to the agent when the task fires"),
3024
- skill_name: z13.string().optional().describe("Name of a skill to invoke when the task fires")
3052
+ parameters: z14.object({
3053
+ cron: z14.string().optional().describe('Cron expression for recurring tasks (e.g. "0 9 * * *" for daily at 9am)'),
3054
+ delay_seconds: z14.number().optional().describe('Delay in seconds for one-shot tasks (e.g. 15 for "remind me in 15 seconds")'),
3055
+ description: z14.string().describe("Human-readable description of what this task does"),
3056
+ prompt: z14.string().optional().describe("Prompt to send to the agent when the task fires"),
3057
+ skill_name: z14.string().optional().describe("Name of a skill to invoke when the task fires")
3025
3058
  }),
3026
3059
  execute: async ({ cron: cronExpr, delay_seconds, description, prompt, skill_name }) => {
3027
3060
  if (!cronExpr && !delay_seconds) {
@@ -3074,12 +3107,12 @@ function createScheduleTaskTool(scheduler, getContext) {
3074
3107
  }
3075
3108
 
3076
3109
  // src/capabilities/scheduler/list-tasks.ts
3077
- import { tool as tool14 } from "ai";
3078
- import { z as z14 } from "zod";
3110
+ import { tool as tool15 } from "ai";
3111
+ import { z as z15 } from "zod";
3079
3112
  function createListTasksTool(scheduler) {
3080
- return tool14({
3113
+ return tool15({
3081
3114
  description: "List all scheduled tasks with their cron expressions and descriptions.",
3082
- parameters: z14.object({}),
3115
+ parameters: z15.object({}),
3083
3116
  execute: async () => {
3084
3117
  const manifests = scheduler.getManifests();
3085
3118
  if (manifests.length === 0) {
@@ -3094,13 +3127,13 @@ function createListTasksTool(scheduler) {
3094
3127
  }
3095
3128
 
3096
3129
  // src/capabilities/scheduler/cancel-task.ts
3097
- import { tool as tool15 } from "ai";
3098
- import { z as z15 } from "zod";
3130
+ import { tool as tool16 } from "ai";
3131
+ import { z as z16 } from "zod";
3099
3132
  function createCancelTaskTool(scheduler) {
3100
- return tool15({
3133
+ return tool16({
3101
3134
  description: "Cancel and remove a scheduled task by its ID.",
3102
- parameters: z15.object({
3103
- id: z15.string().describe("ID of the scheduled task to cancel")
3135
+ parameters: z16.object({
3136
+ id: z16.string().describe("ID of the scheduled task to cancel")
3104
3137
  }),
3105
3138
  execute: async ({ id }) => {
3106
3139
  const manifests = scheduler.getManifests();
@@ -3116,12 +3149,12 @@ function createCancelTaskTool(scheduler) {
3116
3149
  }
3117
3150
 
3118
3151
  // src/capabilities/system/budget-status.ts
3119
- import { tool as tool16 } from "ai";
3120
- import { z as z16 } from "zod";
3152
+ import { tool as tool17 } from "ai";
3153
+ import { z as z17 } from "zod";
3121
3154
  function createBudgetStatusTool(tokenBudget) {
3122
- return tool16({
3155
+ return tool17({
3123
3156
  description: "Check the current token budget status \u2014 how many tokens have been used today, how many remain, and what percentage is consumed.",
3124
- parameters: z16.object({}),
3157
+ parameters: z17.object({}),
3125
3158
  execute: async () => {
3126
3159
  return tokenBudget.getStatusText();
3127
3160
  }
@@ -3129,14 +3162,14 @@ function createBudgetStatusTool(tokenBudget) {
3129
3162
  }
3130
3163
 
3131
3164
  // src/capabilities/git/git-status.ts
3132
- import { tool as tool17 } from "ai";
3133
- import { z as z17 } from "zod";
3165
+ import { tool as tool18 } from "ai";
3166
+ import { z as z18 } from "zod";
3134
3167
  import { execSync as execSync2 } from "child_process";
3135
3168
  function createGitStatusTool() {
3136
- return tool17({
3169
+ return tool18({
3137
3170
  description: "Show the working tree status. Returns staged, unstaged, and untracked files.",
3138
- parameters: z17.object({
3139
- path: z17.string().optional().describe("Path to check (defaults to current directory)")
3171
+ parameters: z18.object({
3172
+ path: z18.string().optional().describe("Path to check (defaults to current directory)")
3140
3173
  }),
3141
3174
  execute: async ({ path: path3 }) => {
3142
3175
  try {
@@ -3152,15 +3185,15 @@ function createGitStatusTool() {
3152
3185
  }
3153
3186
 
3154
3187
  // src/capabilities/git/git-diff.ts
3155
- import { tool as tool18 } from "ai";
3156
- import { z as z18 } from "zod";
3188
+ import { tool as tool19 } from "ai";
3189
+ import { z as z19 } from "zod";
3157
3190
  import { execSync as execSync3 } from "child_process";
3158
3191
  function createGitDiffTool() {
3159
- return tool18({
3192
+ return tool19({
3160
3193
  description: "Show changes between commits, commit and working tree, etc. Shows what has been modified.",
3161
- parameters: z18.object({
3162
- path: z18.string().optional().describe("File or directory to diff"),
3163
- staged: z18.boolean().optional().describe("Show staged changes (cached) instead of unstaged")
3194
+ parameters: z19.object({
3195
+ path: z19.string().optional().describe("File or directory to diff"),
3196
+ staged: z19.boolean().optional().describe("Show staged changes (cached) instead of unstaged")
3164
3197
  }),
3165
3198
  execute: async ({ path: path3, staged }) => {
3166
3199
  try {
@@ -3179,15 +3212,15 @@ function createGitDiffTool() {
3179
3212
  }
3180
3213
 
3181
3214
  // src/capabilities/git/git-log.ts
3182
- import { tool as tool19 } from "ai";
3183
- import { z as z19 } from "zod";
3215
+ import { tool as tool20 } from "ai";
3216
+ import { z as z20 } from "zod";
3184
3217
  import { execSync as execSync4 } from "child_process";
3185
3218
  function createGitLogTool() {
3186
- return tool19({
3219
+ return tool20({
3187
3220
  description: "Show commit logs. Returns recent commit history with hash, author, date, and message.",
3188
- parameters: z19.object({
3189
- count: z19.number().optional().describe("Number of commits to show (default 10)"),
3190
- path: z19.string().optional().describe("File or directory to show log for")
3221
+ parameters: z20.object({
3222
+ count: z20.number().optional().describe("Number of commits to show (default 10)"),
3223
+ path: z20.string().optional().describe("File or directory to show log for")
3191
3224
  }),
3192
3225
  execute: async ({ count, path: path3 }) => {
3193
3226
  try {
@@ -3205,14 +3238,14 @@ function createGitLogTool() {
3205
3238
  }
3206
3239
 
3207
3240
  // src/capabilities/git/git-add.ts
3208
- import { tool as tool20 } from "ai";
3209
- import { z as z20 } from "zod";
3241
+ import { tool as tool21 } from "ai";
3242
+ import { z as z21 } from "zod";
3210
3243
  import { execSync as execSync5 } from "child_process";
3211
3244
  function createGitAddTool() {
3212
- return tool20({
3245
+ return tool21({
3213
3246
  description: "Add file contents to the index (staging area). Prepares files for commit.",
3214
- parameters: z20.object({
3215
- paths: z20.array(z20.string()).describe("File paths to stage")
3247
+ parameters: z21.object({
3248
+ paths: z21.array(z21.string()).describe("File paths to stage")
3216
3249
  }),
3217
3250
  execute: async ({ paths }) => {
3218
3251
  try {
@@ -3227,14 +3260,14 @@ function createGitAddTool() {
3227
3260
  }
3228
3261
 
3229
3262
  // src/capabilities/git/git-commit.ts
3230
- import { tool as tool21 } from "ai";
3231
- import { z as z21 } from "zod";
3263
+ import { tool as tool22 } from "ai";
3264
+ import { z as z22 } from "zod";
3232
3265
  import { execSync as execSync6 } from "child_process";
3233
3266
  function createGitCommitTool() {
3234
- return tool21({
3267
+ return tool22({
3235
3268
  description: "Record changes to the repository. Creates a new commit with staged changes.",
3236
- parameters: z21.object({
3237
- message: z21.string().describe("Commit message")
3269
+ parameters: z22.object({
3270
+ message: z22.string().describe("Commit message")
3238
3271
  }),
3239
3272
  execute: async ({ message }) => {
3240
3273
  try {
@@ -3253,15 +3286,15 @@ function createGitCommitTool() {
3253
3286
  }
3254
3287
 
3255
3288
  // src/capabilities/git/git-push.ts
3256
- import { tool as tool22 } from "ai";
3257
- import { z as z22 } from "zod";
3289
+ import { tool as tool23 } from "ai";
3290
+ import { z as z23 } from "zod";
3258
3291
  import { execSync as execSync7 } from "child_process";
3259
3292
  function createGitPushTool(permissions) {
3260
- return tool22({
3293
+ return tool23({
3261
3294
  description: "Push commits to a remote repository. This modifies a remote and requires approval.",
3262
- parameters: z22.object({
3263
- remote: z22.string().optional().describe("Remote name (default: origin)"),
3264
- branch: z22.string().optional().describe("Branch name (default: current branch)")
3295
+ parameters: z23.object({
3296
+ remote: z23.string().optional().describe("Remote name (default: origin)"),
3297
+ branch: z23.string().optional().describe("Branch name (default: current branch)")
3265
3298
  }),
3266
3299
  execute: async ({ remote, branch }) => {
3267
3300
  const cmd = `git push ${remote || "origin"} ${branch || ""}`.trim();
@@ -3286,8 +3319,8 @@ Ask the user for permission. If they approve, try again. If they say "always", u
3286
3319
  }
3287
3320
 
3288
3321
  // src/capabilities/web/fetch-url.ts
3289
- import { tool as tool23 } from "ai";
3290
- import { z as z23 } from "zod";
3322
+ import { tool as tool24 } from "ai";
3323
+ import { z as z24 } from "zod";
3291
3324
  var MAX_CONTENT_LENGTH = 15e3;
3292
3325
  function stripHtml(html) {
3293
3326
  let text = html;
@@ -3320,11 +3353,11 @@ function stripHtml(html) {
3320
3353
  return text;
3321
3354
  }
3322
3355
  function createFetchUrlTool() {
3323
- return tool23({
3356
+ return tool24({
3324
3357
  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.",
3325
- parameters: z23.object({
3326
- url: z23.string().describe("The URL to fetch"),
3327
- format: z23.enum(["text", "markdown"]).optional().describe("Output format (default: markdown)")
3358
+ parameters: z24.object({
3359
+ url: z24.string().describe("The URL to fetch"),
3360
+ format: z24.enum(["text", "markdown"]).optional().describe("Output format (default: markdown)")
3328
3361
  }),
3329
3362
  execute: async ({ url, format }) => {
3330
3363
  const outputFormat = format ?? "markdown";
@@ -3413,6 +3446,7 @@ var CapabilityRegistry = class {
3413
3446
  if (this.sendFileHandler) {
3414
3447
  this.tools.send_file = createSendFileTool(this.permissions, this.sendFileHandler);
3415
3448
  }
3449
+ this.tools.approve_scope = createApproveScopeTool(this.permissions);
3416
3450
  logger.info("Filesystem tools registered");
3417
3451
  }
3418
3452
  if (manifest.capabilities.shell.enabled) {
@@ -4257,7 +4291,7 @@ async function runWithWatchdog(agentFn) {
4257
4291
  await attempt();
4258
4292
  }
4259
4293
  function sleep(ms) {
4260
- return new Promise((resolve9) => setTimeout(resolve9, ms));
4294
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
4261
4295
  }
4262
4296
 
4263
4297
  // src/index.ts
@@ -4291,10 +4325,10 @@ function splashScreen() {
4291
4325
  }
4292
4326
  async function ask(prompt) {
4293
4327
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
4294
- return new Promise((resolve9) => {
4328
+ return new Promise((resolve10) => {
4295
4329
  rl.question(prompt, (answer) => {
4296
4330
  rl.close();
4297
- resolve9(answer.trim());
4331
+ resolve10(answer.trim());
4298
4332
  });
4299
4333
  });
4300
4334
  }