@cosmicstack/mercury-agent 0.2.3 → 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 +153 -114
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
4
7
|
import { Command } from "commander";
|
|
5
8
|
import readline2 from "readline";
|
|
6
9
|
import chalk6 from "chalk";
|
|
@@ -1703,16 +1706,16 @@ var CLIChannel = class extends BaseChannel {
|
|
|
1703
1706
|
}
|
|
1704
1707
|
}
|
|
1705
1708
|
async prompt(question) {
|
|
1706
|
-
return new Promise((
|
|
1707
|
-
this.rl?.question(question, (answer) =>
|
|
1709
|
+
return new Promise((resolve10) => {
|
|
1710
|
+
this.rl?.question(question, (answer) => resolve10(answer.trim()));
|
|
1708
1711
|
});
|
|
1709
1712
|
}
|
|
1710
1713
|
async askPermission(prompt) {
|
|
1711
|
-
return new Promise((
|
|
1714
|
+
return new Promise((resolve10) => {
|
|
1712
1715
|
console.log("");
|
|
1713
1716
|
console.log(chalk2.yellow(` \u26A0 ${prompt}`));
|
|
1714
1717
|
this.rl?.question(chalk2.yellow(" > "), (answer) => {
|
|
1715
|
-
|
|
1718
|
+
resolve10(answer.trim());
|
|
1716
1719
|
});
|
|
1717
1720
|
});
|
|
1718
1721
|
}
|
|
@@ -1975,15 +1978,15 @@ var TelegramChannel = class extends BaseChannel {
|
|
|
1975
1978
|
reply_markup: keyboard
|
|
1976
1979
|
});
|
|
1977
1980
|
}
|
|
1978
|
-
return new Promise((
|
|
1979
|
-
this.pendingApprovals.set(`${id}:yes`, () =>
|
|
1980
|
-
this.pendingApprovals.set(`${id}:always`, () =>
|
|
1981
|
-
this.pendingApprovals.set(`${id}: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"));
|
|
1982
1985
|
setTimeout(() => {
|
|
1983
1986
|
this.pendingApprovals.delete(`${id}:yes`);
|
|
1984
1987
|
this.pendingApprovals.delete(`${id}:always`);
|
|
1985
1988
|
this.pendingApprovals.delete(`${id}:no`);
|
|
1986
|
-
|
|
1989
|
+
resolve10("no");
|
|
1987
1990
|
}, 12e4);
|
|
1988
1991
|
});
|
|
1989
1992
|
}
|
|
@@ -2331,8 +2334,8 @@ var PermissionManager = class {
|
|
|
2331
2334
|
clearElevation() {
|
|
2332
2335
|
this.elevatedCommands.clear();
|
|
2333
2336
|
}
|
|
2334
|
-
isElevated(
|
|
2335
|
-
if (this.elevatedCommands.has(
|
|
2337
|
+
isElevated(tool25) {
|
|
2338
|
+
if (this.elevatedCommands.has(tool25)) return true;
|
|
2336
2339
|
return false;
|
|
2337
2340
|
}
|
|
2338
2341
|
isShellElevated() {
|
|
@@ -2498,18 +2501,23 @@ var PermissionManager = class {
|
|
|
2498
2501
|
}
|
|
2499
2502
|
return void 0;
|
|
2500
2503
|
}
|
|
2504
|
+
async requestScopeExternal(path3, mode) {
|
|
2505
|
+
return this.requestScope(path3, mode);
|
|
2506
|
+
}
|
|
2501
2507
|
async requestScope(path3, mode) {
|
|
2502
2508
|
if (!this.askHandler) {
|
|
2503
|
-
return { allowed: false, reason: `
|
|
2509
|
+
return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
|
|
2504
2510
|
}
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
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") {
|
|
2509
2517
|
this.addScope(path3, mode === "read", mode === "write");
|
|
2510
2518
|
return { allowed: true };
|
|
2511
2519
|
}
|
|
2512
|
-
if (response
|
|
2520
|
+
if (response === "yes" || response === "y") {
|
|
2513
2521
|
return { allowed: true };
|
|
2514
2522
|
}
|
|
2515
2523
|
return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
|
|
@@ -2580,7 +2588,8 @@ function createReadFileTool(permissions) {
|
|
|
2580
2588
|
const resolved = resolve2(path3);
|
|
2581
2589
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2582
2590
|
if (!check.allowed) {
|
|
2583
|
-
|
|
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.`;
|
|
2584
2593
|
}
|
|
2585
2594
|
if (!existsSync7(resolved)) {
|
|
2586
2595
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2617,7 +2626,8 @@ function createWriteFileTool(permissions) {
|
|
|
2617
2626
|
const resolved = resolve3(path3);
|
|
2618
2627
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2619
2628
|
if (!check.allowed) {
|
|
2620
|
-
|
|
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.`;
|
|
2621
2631
|
}
|
|
2622
2632
|
if (!existsSync8(resolved)) {
|
|
2623
2633
|
return `Error: File not found: ${resolved}. Use create_file to create new files.`;
|
|
@@ -2648,7 +2658,8 @@ function createCreateFileTool(permissions) {
|
|
|
2648
2658
|
const resolved = resolve4(path3);
|
|
2649
2659
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2650
2660
|
if (!check.allowed) {
|
|
2651
|
-
|
|
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.`;
|
|
2652
2663
|
}
|
|
2653
2664
|
if (existsSync9(resolved)) {
|
|
2654
2665
|
return `Error: File already exists: ${resolved}. Use write_file to modify existing files.`;
|
|
@@ -2682,7 +2693,7 @@ function createListDirTool(permissions) {
|
|
|
2682
2693
|
const resolved = resolve5(path3);
|
|
2683
2694
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2684
2695
|
if (!check.allowed) {
|
|
2685
|
-
return `Error: ${
|
|
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.`;
|
|
2686
2697
|
}
|
|
2687
2698
|
if (!existsSync10(resolved)) {
|
|
2688
2699
|
return `Error: Directory not found: ${resolved}`;
|
|
@@ -2740,7 +2751,8 @@ function createDeleteFileTool(permissions) {
|
|
|
2740
2751
|
const resolved = resolve6(path3);
|
|
2741
2752
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2742
2753
|
if (!check.allowed) {
|
|
2743
|
-
|
|
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.`;
|
|
2744
2756
|
}
|
|
2745
2757
|
if (!existsSync11(resolved)) {
|
|
2746
2758
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2776,7 +2788,8 @@ function createEditFileTool(permissions) {
|
|
|
2776
2788
|
const resolved = resolve7(path3);
|
|
2777
2789
|
const fsCheck = await permissions.checkFsAccess(resolved, "write");
|
|
2778
2790
|
if (!fsCheck.allowed) {
|
|
2779
|
-
|
|
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.`;
|
|
2780
2793
|
}
|
|
2781
2794
|
try {
|
|
2782
2795
|
const content = readFileSync9(resolved, "utf-8");
|
|
@@ -2817,7 +2830,8 @@ function createSendFileTool(permissions, sendFile) {
|
|
|
2817
2830
|
const resolved = resolve8(path3);
|
|
2818
2831
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2819
2832
|
if (!check.allowed) {
|
|
2820
|
-
|
|
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.`;
|
|
2821
2835
|
}
|
|
2822
2836
|
if (!existsSync12(resolved)) {
|
|
2823
2837
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2841,18 +2855,40 @@ function createSendFileTool(permissions, sendFile) {
|
|
|
2841
2855
|
});
|
|
2842
2856
|
}
|
|
2843
2857
|
|
|
2844
|
-
// src/capabilities/
|
|
2858
|
+
// src/capabilities/filesystem/approve-scope.ts
|
|
2845
2859
|
import { tool as tool8 } from "ai";
|
|
2846
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";
|
|
2847
2883
|
import { execSync } from "child_process";
|
|
2848
2884
|
function createRunCommandTool(permissions) {
|
|
2849
|
-
return
|
|
2885
|
+
return tool9({
|
|
2850
2886
|
description: `Run a shell command. Commands run in the current working directory unless an absolute path is given.
|
|
2851
2887
|
Blocked commands (sudo, rm -rf /, etc.) are never executed.
|
|
2852
2888
|
Auto-approved commands (ls, cat, git status, curl, etc.) run without asking.
|
|
2853
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.`,
|
|
2854
|
-
parameters:
|
|
2855
|
-
command:
|
|
2890
|
+
parameters: z9.object({
|
|
2891
|
+
command: z9.string().describe("The shell command to execute")
|
|
2856
2892
|
}),
|
|
2857
2893
|
execute: async ({ command }) => {
|
|
2858
2894
|
const check = await permissions.checkShellCommand(command);
|
|
@@ -2892,13 +2928,13 @@ Error: ${stderr}`;
|
|
|
2892
2928
|
}
|
|
2893
2929
|
|
|
2894
2930
|
// src/capabilities/shell/approve-command.ts
|
|
2895
|
-
import { tool as
|
|
2896
|
-
import { z as
|
|
2931
|
+
import { tool as tool10 } from "ai";
|
|
2932
|
+
import { z as z10 } from "zod";
|
|
2897
2933
|
function createApproveCommandTool(permissions) {
|
|
2898
|
-
return
|
|
2934
|
+
return tool10({
|
|
2899
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".',
|
|
2900
|
-
parameters:
|
|
2901
|
-
command:
|
|
2936
|
+
parameters: z10.object({
|
|
2937
|
+
command: z10.string().describe('The base command to permanently approve (e.g. "curl", "docker", "npm")')
|
|
2902
2938
|
}),
|
|
2903
2939
|
execute: async ({ command }) => {
|
|
2904
2940
|
const baseCmd = command.trim().split(/\s+/)[0];
|
|
@@ -2909,15 +2945,15 @@ function createApproveCommandTool(permissions) {
|
|
|
2909
2945
|
}
|
|
2910
2946
|
|
|
2911
2947
|
// src/capabilities/skills/install-skill.ts
|
|
2912
|
-
import { tool as
|
|
2913
|
-
import { z as
|
|
2948
|
+
import { tool as tool11 } from "ai";
|
|
2949
|
+
import { z as z11 } from "zod";
|
|
2914
2950
|
import { parse as parseYaml4 } from "yaml";
|
|
2915
2951
|
function createInstallSkillTool(skillLoader) {
|
|
2916
|
-
return
|
|
2952
|
+
return tool11({
|
|
2917
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.",
|
|
2918
|
-
parameters:
|
|
2919
|
-
content:
|
|
2920
|
-
url:
|
|
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")
|
|
2921
2957
|
}),
|
|
2922
2958
|
execute: async ({ content, url }) => {
|
|
2923
2959
|
let skillContent;
|
|
@@ -2957,12 +2993,12 @@ function createInstallSkillTool(skillLoader) {
|
|
|
2957
2993
|
}
|
|
2958
2994
|
|
|
2959
2995
|
// src/capabilities/skills/list-skills.ts
|
|
2960
|
-
import { tool as
|
|
2961
|
-
import { z as
|
|
2996
|
+
import { tool as tool12 } from "ai";
|
|
2997
|
+
import { z as z12 } from "zod";
|
|
2962
2998
|
function createListSkillsTool(skillLoader) {
|
|
2963
|
-
return
|
|
2999
|
+
return tool12({
|
|
2964
3000
|
description: "List all installed skills with their names and descriptions.",
|
|
2965
|
-
parameters:
|
|
3001
|
+
parameters: z12.object({}),
|
|
2966
3002
|
execute: async () => {
|
|
2967
3003
|
const skills = skillLoader.getDiscovered();
|
|
2968
3004
|
if (skills.length === 0) {
|
|
@@ -2974,13 +3010,13 @@ function createListSkillsTool(skillLoader) {
|
|
|
2974
3010
|
}
|
|
2975
3011
|
|
|
2976
3012
|
// src/capabilities/skills/use-skill.ts
|
|
2977
|
-
import { tool as
|
|
2978
|
-
import { z as
|
|
3013
|
+
import { tool as tool13 } from "ai";
|
|
3014
|
+
import { z as z13 } from "zod";
|
|
2979
3015
|
function createUseSkillTool(skillLoader, permissions) {
|
|
2980
|
-
return
|
|
3016
|
+
return tool13({
|
|
2981
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.",
|
|
2982
|
-
parameters:
|
|
2983
|
-
name:
|
|
3018
|
+
parameters: z13.object({
|
|
3019
|
+
name: z13.string().describe("Name of the skill to invoke")
|
|
2984
3020
|
}),
|
|
2985
3021
|
execute: async ({ name }) => {
|
|
2986
3022
|
const skill = skillLoader.load(name);
|
|
@@ -3007,18 +3043,18 @@ Allowed tools: ${skill["allowed-tools"].join(", ")}`;
|
|
|
3007
3043
|
}
|
|
3008
3044
|
|
|
3009
3045
|
// src/capabilities/scheduler/schedule-task.ts
|
|
3010
|
-
import { tool as
|
|
3011
|
-
import { z as
|
|
3046
|
+
import { tool as tool14 } from "ai";
|
|
3047
|
+
import { z as z14 } from "zod";
|
|
3012
3048
|
import cron2 from "node-cron";
|
|
3013
3049
|
function createScheduleTaskTool(scheduler, getContext) {
|
|
3014
|
-
return
|
|
3050
|
+
return tool14({
|
|
3015
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.',
|
|
3016
|
-
parameters:
|
|
3017
|
-
cron:
|
|
3018
|
-
delay_seconds:
|
|
3019
|
-
description:
|
|
3020
|
-
prompt:
|
|
3021
|
-
skill_name:
|
|
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")
|
|
3022
3058
|
}),
|
|
3023
3059
|
execute: async ({ cron: cronExpr, delay_seconds, description, prompt, skill_name }) => {
|
|
3024
3060
|
if (!cronExpr && !delay_seconds) {
|
|
@@ -3071,12 +3107,12 @@ function createScheduleTaskTool(scheduler, getContext) {
|
|
|
3071
3107
|
}
|
|
3072
3108
|
|
|
3073
3109
|
// src/capabilities/scheduler/list-tasks.ts
|
|
3074
|
-
import { tool as
|
|
3075
|
-
import { z as
|
|
3110
|
+
import { tool as tool15 } from "ai";
|
|
3111
|
+
import { z as z15 } from "zod";
|
|
3076
3112
|
function createListTasksTool(scheduler) {
|
|
3077
|
-
return
|
|
3113
|
+
return tool15({
|
|
3078
3114
|
description: "List all scheduled tasks with their cron expressions and descriptions.",
|
|
3079
|
-
parameters:
|
|
3115
|
+
parameters: z15.object({}),
|
|
3080
3116
|
execute: async () => {
|
|
3081
3117
|
const manifests = scheduler.getManifests();
|
|
3082
3118
|
if (manifests.length === 0) {
|
|
@@ -3091,13 +3127,13 @@ function createListTasksTool(scheduler) {
|
|
|
3091
3127
|
}
|
|
3092
3128
|
|
|
3093
3129
|
// src/capabilities/scheduler/cancel-task.ts
|
|
3094
|
-
import { tool as
|
|
3095
|
-
import { z as
|
|
3130
|
+
import { tool as tool16 } from "ai";
|
|
3131
|
+
import { z as z16 } from "zod";
|
|
3096
3132
|
function createCancelTaskTool(scheduler) {
|
|
3097
|
-
return
|
|
3133
|
+
return tool16({
|
|
3098
3134
|
description: "Cancel and remove a scheduled task by its ID.",
|
|
3099
|
-
parameters:
|
|
3100
|
-
id:
|
|
3135
|
+
parameters: z16.object({
|
|
3136
|
+
id: z16.string().describe("ID of the scheduled task to cancel")
|
|
3101
3137
|
}),
|
|
3102
3138
|
execute: async ({ id }) => {
|
|
3103
3139
|
const manifests = scheduler.getManifests();
|
|
@@ -3113,12 +3149,12 @@ function createCancelTaskTool(scheduler) {
|
|
|
3113
3149
|
}
|
|
3114
3150
|
|
|
3115
3151
|
// src/capabilities/system/budget-status.ts
|
|
3116
|
-
import { tool as
|
|
3117
|
-
import { z as
|
|
3152
|
+
import { tool as tool17 } from "ai";
|
|
3153
|
+
import { z as z17 } from "zod";
|
|
3118
3154
|
function createBudgetStatusTool(tokenBudget) {
|
|
3119
|
-
return
|
|
3155
|
+
return tool17({
|
|
3120
3156
|
description: "Check the current token budget status \u2014 how many tokens have been used today, how many remain, and what percentage is consumed.",
|
|
3121
|
-
parameters:
|
|
3157
|
+
parameters: z17.object({}),
|
|
3122
3158
|
execute: async () => {
|
|
3123
3159
|
return tokenBudget.getStatusText();
|
|
3124
3160
|
}
|
|
@@ -3126,14 +3162,14 @@ function createBudgetStatusTool(tokenBudget) {
|
|
|
3126
3162
|
}
|
|
3127
3163
|
|
|
3128
3164
|
// src/capabilities/git/git-status.ts
|
|
3129
|
-
import { tool as
|
|
3130
|
-
import { z as
|
|
3165
|
+
import { tool as tool18 } from "ai";
|
|
3166
|
+
import { z as z18 } from "zod";
|
|
3131
3167
|
import { execSync as execSync2 } from "child_process";
|
|
3132
3168
|
function createGitStatusTool() {
|
|
3133
|
-
return
|
|
3169
|
+
return tool18({
|
|
3134
3170
|
description: "Show the working tree status. Returns staged, unstaged, and untracked files.",
|
|
3135
|
-
parameters:
|
|
3136
|
-
path:
|
|
3171
|
+
parameters: z18.object({
|
|
3172
|
+
path: z18.string().optional().describe("Path to check (defaults to current directory)")
|
|
3137
3173
|
}),
|
|
3138
3174
|
execute: async ({ path: path3 }) => {
|
|
3139
3175
|
try {
|
|
@@ -3149,15 +3185,15 @@ function createGitStatusTool() {
|
|
|
3149
3185
|
}
|
|
3150
3186
|
|
|
3151
3187
|
// src/capabilities/git/git-diff.ts
|
|
3152
|
-
import { tool as
|
|
3153
|
-
import { z as
|
|
3188
|
+
import { tool as tool19 } from "ai";
|
|
3189
|
+
import { z as z19 } from "zod";
|
|
3154
3190
|
import { execSync as execSync3 } from "child_process";
|
|
3155
3191
|
function createGitDiffTool() {
|
|
3156
|
-
return
|
|
3192
|
+
return tool19({
|
|
3157
3193
|
description: "Show changes between commits, commit and working tree, etc. Shows what has been modified.",
|
|
3158
|
-
parameters:
|
|
3159
|
-
path:
|
|
3160
|
-
staged:
|
|
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")
|
|
3161
3197
|
}),
|
|
3162
3198
|
execute: async ({ path: path3, staged }) => {
|
|
3163
3199
|
try {
|
|
@@ -3176,15 +3212,15 @@ function createGitDiffTool() {
|
|
|
3176
3212
|
}
|
|
3177
3213
|
|
|
3178
3214
|
// src/capabilities/git/git-log.ts
|
|
3179
|
-
import { tool as
|
|
3180
|
-
import { z as
|
|
3215
|
+
import { tool as tool20 } from "ai";
|
|
3216
|
+
import { z as z20 } from "zod";
|
|
3181
3217
|
import { execSync as execSync4 } from "child_process";
|
|
3182
3218
|
function createGitLogTool() {
|
|
3183
|
-
return
|
|
3219
|
+
return tool20({
|
|
3184
3220
|
description: "Show commit logs. Returns recent commit history with hash, author, date, and message.",
|
|
3185
|
-
parameters:
|
|
3186
|
-
count:
|
|
3187
|
-
path:
|
|
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")
|
|
3188
3224
|
}),
|
|
3189
3225
|
execute: async ({ count, path: path3 }) => {
|
|
3190
3226
|
try {
|
|
@@ -3202,14 +3238,14 @@ function createGitLogTool() {
|
|
|
3202
3238
|
}
|
|
3203
3239
|
|
|
3204
3240
|
// src/capabilities/git/git-add.ts
|
|
3205
|
-
import { tool as
|
|
3206
|
-
import { z as
|
|
3241
|
+
import { tool as tool21 } from "ai";
|
|
3242
|
+
import { z as z21 } from "zod";
|
|
3207
3243
|
import { execSync as execSync5 } from "child_process";
|
|
3208
3244
|
function createGitAddTool() {
|
|
3209
|
-
return
|
|
3245
|
+
return tool21({
|
|
3210
3246
|
description: "Add file contents to the index (staging area). Prepares files for commit.",
|
|
3211
|
-
parameters:
|
|
3212
|
-
paths:
|
|
3247
|
+
parameters: z21.object({
|
|
3248
|
+
paths: z21.array(z21.string()).describe("File paths to stage")
|
|
3213
3249
|
}),
|
|
3214
3250
|
execute: async ({ paths }) => {
|
|
3215
3251
|
try {
|
|
@@ -3224,14 +3260,14 @@ function createGitAddTool() {
|
|
|
3224
3260
|
}
|
|
3225
3261
|
|
|
3226
3262
|
// src/capabilities/git/git-commit.ts
|
|
3227
|
-
import { tool as
|
|
3228
|
-
import { z as
|
|
3263
|
+
import { tool as tool22 } from "ai";
|
|
3264
|
+
import { z as z22 } from "zod";
|
|
3229
3265
|
import { execSync as execSync6 } from "child_process";
|
|
3230
3266
|
function createGitCommitTool() {
|
|
3231
|
-
return
|
|
3267
|
+
return tool22({
|
|
3232
3268
|
description: "Record changes to the repository. Creates a new commit with staged changes.",
|
|
3233
|
-
parameters:
|
|
3234
|
-
message:
|
|
3269
|
+
parameters: z22.object({
|
|
3270
|
+
message: z22.string().describe("Commit message")
|
|
3235
3271
|
}),
|
|
3236
3272
|
execute: async ({ message }) => {
|
|
3237
3273
|
try {
|
|
@@ -3250,15 +3286,15 @@ function createGitCommitTool() {
|
|
|
3250
3286
|
}
|
|
3251
3287
|
|
|
3252
3288
|
// src/capabilities/git/git-push.ts
|
|
3253
|
-
import { tool as
|
|
3254
|
-
import { z as
|
|
3289
|
+
import { tool as tool23 } from "ai";
|
|
3290
|
+
import { z as z23 } from "zod";
|
|
3255
3291
|
import { execSync as execSync7 } from "child_process";
|
|
3256
3292
|
function createGitPushTool(permissions) {
|
|
3257
|
-
return
|
|
3293
|
+
return tool23({
|
|
3258
3294
|
description: "Push commits to a remote repository. This modifies a remote and requires approval.",
|
|
3259
|
-
parameters:
|
|
3260
|
-
remote:
|
|
3261
|
-
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)")
|
|
3262
3298
|
}),
|
|
3263
3299
|
execute: async ({ remote, branch }) => {
|
|
3264
3300
|
const cmd = `git push ${remote || "origin"} ${branch || ""}`.trim();
|
|
@@ -3283,8 +3319,8 @@ Ask the user for permission. If they approve, try again. If they say "always", u
|
|
|
3283
3319
|
}
|
|
3284
3320
|
|
|
3285
3321
|
// src/capabilities/web/fetch-url.ts
|
|
3286
|
-
import { tool as
|
|
3287
|
-
import { z as
|
|
3322
|
+
import { tool as tool24 } from "ai";
|
|
3323
|
+
import { z as z24 } from "zod";
|
|
3288
3324
|
var MAX_CONTENT_LENGTH = 15e3;
|
|
3289
3325
|
function stripHtml(html) {
|
|
3290
3326
|
let text = html;
|
|
@@ -3317,11 +3353,11 @@ function stripHtml(html) {
|
|
|
3317
3353
|
return text;
|
|
3318
3354
|
}
|
|
3319
3355
|
function createFetchUrlTool() {
|
|
3320
|
-
return
|
|
3356
|
+
return tool24({
|
|
3321
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.",
|
|
3322
|
-
parameters:
|
|
3323
|
-
url:
|
|
3324
|
-
format:
|
|
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)")
|
|
3325
3361
|
}),
|
|
3326
3362
|
execute: async ({ url, format }) => {
|
|
3327
3363
|
const outputFormat = format ?? "markdown";
|
|
@@ -3410,6 +3446,7 @@ var CapabilityRegistry = class {
|
|
|
3410
3446
|
if (this.sendFileHandler) {
|
|
3411
3447
|
this.tools.send_file = createSendFileTool(this.permissions, this.sendFileHandler);
|
|
3412
3448
|
}
|
|
3449
|
+
this.tools.approve_scope = createApproveScopeTool(this.permissions);
|
|
3413
3450
|
logger.info("Filesystem tools registered");
|
|
3414
3451
|
}
|
|
3415
3452
|
if (manifest.capabilities.shell.enabled) {
|
|
@@ -4254,10 +4291,12 @@ async function runWithWatchdog(agentFn) {
|
|
|
4254
4291
|
await attempt();
|
|
4255
4292
|
}
|
|
4256
4293
|
function sleep(ms) {
|
|
4257
|
-
return new Promise((
|
|
4294
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
4258
4295
|
}
|
|
4259
4296
|
|
|
4260
4297
|
// src/index.ts
|
|
4298
|
+
var __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
4299
|
+
var pkgVersion = JSON.parse(readFileSync12(join11(__dirname, "..", "package.json"), "utf8")).version;
|
|
4261
4300
|
function hr() {
|
|
4262
4301
|
console.log(chalk6.dim("\u2500".repeat(50)));
|
|
4263
4302
|
}
|
|
@@ -4269,7 +4308,7 @@ function banner() {
|
|
|
4269
4308
|
}
|
|
4270
4309
|
console.log("");
|
|
4271
4310
|
console.log(chalk6.white(" an AI agent for personal tasks"));
|
|
4272
|
-
console.log(chalk6.dim(
|
|
4311
|
+
console.log(chalk6.dim(` v${pkgVersion} \xB7 by Cosmic Stack \xB7 mercury.cosmicstack.org`));
|
|
4273
4312
|
console.log("");
|
|
4274
4313
|
}
|
|
4275
4314
|
function splashScreen() {
|
|
@@ -4286,10 +4325,10 @@ function splashScreen() {
|
|
|
4286
4325
|
}
|
|
4287
4326
|
async function ask(prompt) {
|
|
4288
4327
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
4289
|
-
return new Promise((
|
|
4328
|
+
return new Promise((resolve10) => {
|
|
4290
4329
|
rl.question(prompt, (answer) => {
|
|
4291
4330
|
rl.close();
|
|
4292
|
-
|
|
4331
|
+
resolve10(answer.trim());
|
|
4293
4332
|
});
|
|
4294
4333
|
});
|
|
4295
4334
|
}
|
|
@@ -4555,7 +4594,7 @@ async function runAgent(isDaemon = false) {
|
|
|
4555
4594
|
process.on("SIGTERM", shutdown);
|
|
4556
4595
|
}
|
|
4557
4596
|
var program = new Command();
|
|
4558
|
-
program.name("mercury").description("Mercury \u2014 Soul-driven AI agent with permission-hardened tools, token budgets, and multi-channel access.").version(
|
|
4597
|
+
program.name("mercury").description("Mercury \u2014 Soul-driven AI agent with permission-hardened tools, token budgets, and multi-channel access.").version(pkgVersion).option("-v, --verbose", "Show debug logs").action(async () => {
|
|
4559
4598
|
if (!isSetupComplete()) {
|
|
4560
4599
|
await configure();
|
|
4561
4600
|
autoDaemonize();
|