@cosmicstack/mercury-agent 0.2.4 → 0.2.6
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 +168 -115
- package/dist/index.js.map +1 -1
- package/package.json +3 -6
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((
|
|
1710
|
-
this.rl?.question(question, (answer) =>
|
|
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((
|
|
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
|
-
|
|
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((
|
|
1982
|
-
this.pendingApprovals.set(`${id}:yes`, () =>
|
|
1983
|
-
this.pendingApprovals.set(`${id}:always`, () =>
|
|
1984
|
-
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"));
|
|
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
|
-
|
|
1989
|
+
resolve10("no");
|
|
1990
1990
|
}, 12e4);
|
|
1991
1991
|
});
|
|
1992
1992
|
}
|
|
@@ -2304,6 +2304,7 @@ var PermissionManager = class {
|
|
|
2304
2304
|
elevatedCommands = /* @__PURE__ */ new Set();
|
|
2305
2305
|
pendingApprovals = /* @__PURE__ */ new Set();
|
|
2306
2306
|
currentChannelType = "cli";
|
|
2307
|
+
tempScopes = [];
|
|
2307
2308
|
constructor() {
|
|
2308
2309
|
this.cwd = process.cwd();
|
|
2309
2310
|
this.manifest = this.load();
|
|
@@ -2334,8 +2335,8 @@ var PermissionManager = class {
|
|
|
2334
2335
|
clearElevation() {
|
|
2335
2336
|
this.elevatedCommands.clear();
|
|
2336
2337
|
}
|
|
2337
|
-
isElevated(
|
|
2338
|
-
if (this.elevatedCommands.has(
|
|
2338
|
+
isElevated(tool25) {
|
|
2339
|
+
if (this.elevatedCommands.has(tool25)) return true;
|
|
2339
2340
|
return false;
|
|
2340
2341
|
}
|
|
2341
2342
|
isShellElevated() {
|
|
@@ -2394,12 +2395,18 @@ var PermissionManager = class {
|
|
|
2394
2395
|
}
|
|
2395
2396
|
const resolved = resolve(path3);
|
|
2396
2397
|
const scope = this.findScope(resolved);
|
|
2398
|
+
const tempScope = this.findTempScope(resolved);
|
|
2397
2399
|
if (scope) {
|
|
2398
2400
|
if (mode === "read" && scope.read) return { allowed: true };
|
|
2399
2401
|
if (mode === "write" && scope.write) return { allowed: true };
|
|
2400
2402
|
return { allowed: false, reason: `Permission denied: ${mode} access to ${path3} (scope has ${mode}=false)` };
|
|
2401
2403
|
}
|
|
2402
|
-
|
|
2404
|
+
if (tempScope) {
|
|
2405
|
+
if (mode === "read" && tempScope.read) return { allowed: true };
|
|
2406
|
+
if (mode === "write" && tempScope.write) return { allowed: true };
|
|
2407
|
+
return { allowed: false, reason: `Permission denied: ${mode} access to ${path3}` };
|
|
2408
|
+
}
|
|
2409
|
+
return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
|
|
2403
2410
|
}
|
|
2404
2411
|
async checkShellCommand(command) {
|
|
2405
2412
|
if (this.autoApproveAll) {
|
|
@@ -2430,7 +2437,7 @@ var PermissionManager = class {
|
|
|
2430
2437
|
if (hasPathTraversal) {
|
|
2431
2438
|
const scopeCheck = await this.checkFsAccess(hasPathTraversal, "write");
|
|
2432
2439
|
if (!scopeCheck.allowed) {
|
|
2433
|
-
return { allowed: false, reason:
|
|
2440
|
+
return { allowed: false, reason: `No permission to access ${hasPathTraversal}. Use approve_scope tool with path="${hasPathTraversal}" and mode="write" to request access.`, needsApproval: false };
|
|
2434
2441
|
}
|
|
2435
2442
|
}
|
|
2436
2443
|
}
|
|
@@ -2501,22 +2508,39 @@ var PermissionManager = class {
|
|
|
2501
2508
|
}
|
|
2502
2509
|
return void 0;
|
|
2503
2510
|
}
|
|
2504
|
-
async
|
|
2511
|
+
async requestScopeExternal(path3, mode) {
|
|
2505
2512
|
if (!this.askHandler) {
|
|
2506
|
-
return { allowed: false, reason: `
|
|
2513
|
+
return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
|
|
2507
2514
|
}
|
|
2508
|
-
const
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2515
|
+
const prompt = `Mercury needs ${mode} access to:
|
|
2516
|
+
${path3}
|
|
2517
|
+
|
|
2518
|
+
Allow access?`;
|
|
2519
|
+
const response = await this.askHandler(prompt);
|
|
2520
|
+
if (response === "always") {
|
|
2512
2521
|
this.addScope(path3, mode === "read", mode === "write");
|
|
2513
2522
|
return { allowed: true };
|
|
2514
2523
|
}
|
|
2515
|
-
if (response
|
|
2524
|
+
if (response === "yes") {
|
|
2525
|
+
this.addTempScope(path3, mode === "read", mode === "write");
|
|
2516
2526
|
return { allowed: true };
|
|
2517
2527
|
}
|
|
2518
2528
|
return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
|
|
2519
2529
|
}
|
|
2530
|
+
addTempScope(path3, read, write) {
|
|
2531
|
+
const resolved = resolve(path3);
|
|
2532
|
+
this.tempScopes.push({ path: resolved, read, write });
|
|
2533
|
+
logger.info({ path: resolved, read, write }, "Temp permission scope added (session only)");
|
|
2534
|
+
}
|
|
2535
|
+
findTempScope(resolvedPath) {
|
|
2536
|
+
for (const scope of this.tempScopes) {
|
|
2537
|
+
const scopeResolved = resolve(scope.path.replace(/^~/, homedir2()));
|
|
2538
|
+
if (resolvedPath === scopeResolved || resolvedPath.startsWith(scopeResolved + sep)) {
|
|
2539
|
+
return scope;
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
return void 0;
|
|
2543
|
+
}
|
|
2520
2544
|
matchPattern(command, pattern) {
|
|
2521
2545
|
const regexStr = "^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$";
|
|
2522
2546
|
try {
|
|
@@ -2583,7 +2607,8 @@ function createReadFileTool(permissions) {
|
|
|
2583
2607
|
const resolved = resolve2(path3);
|
|
2584
2608
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2585
2609
|
if (!check.allowed) {
|
|
2586
|
-
|
|
2610
|
+
const parentDir = resolve2(resolved, "..");
|
|
2611
|
+
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
2612
|
}
|
|
2588
2613
|
if (!existsSync7(resolved)) {
|
|
2589
2614
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2620,7 +2645,8 @@ function createWriteFileTool(permissions) {
|
|
|
2620
2645
|
const resolved = resolve3(path3);
|
|
2621
2646
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2622
2647
|
if (!check.allowed) {
|
|
2623
|
-
|
|
2648
|
+
const parentDir = resolve3(resolved, "..");
|
|
2649
|
+
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
2650
|
}
|
|
2625
2651
|
if (!existsSync8(resolved)) {
|
|
2626
2652
|
return `Error: File not found: ${resolved}. Use create_file to create new files.`;
|
|
@@ -2651,7 +2677,8 @@ function createCreateFileTool(permissions) {
|
|
|
2651
2677
|
const resolved = resolve4(path3);
|
|
2652
2678
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2653
2679
|
if (!check.allowed) {
|
|
2654
|
-
|
|
2680
|
+
const parentDir = resolve4(resolved, "..");
|
|
2681
|
+
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
2682
|
}
|
|
2656
2683
|
if (existsSync9(resolved)) {
|
|
2657
2684
|
return `Error: File already exists: ${resolved}. Use write_file to modify existing files.`;
|
|
@@ -2685,7 +2712,7 @@ function createListDirTool(permissions) {
|
|
|
2685
2712
|
const resolved = resolve5(path3);
|
|
2686
2713
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2687
2714
|
if (!check.allowed) {
|
|
2688
|
-
return `Error: ${
|
|
2715
|
+
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
2716
|
}
|
|
2690
2717
|
if (!existsSync10(resolved)) {
|
|
2691
2718
|
return `Error: Directory not found: ${resolved}`;
|
|
@@ -2743,7 +2770,8 @@ function createDeleteFileTool(permissions) {
|
|
|
2743
2770
|
const resolved = resolve6(path3);
|
|
2744
2771
|
const check = await permissions.checkFsAccess(resolved, "write");
|
|
2745
2772
|
if (!check.allowed) {
|
|
2746
|
-
|
|
2773
|
+
const parentDir = resolve6(resolved, "..");
|
|
2774
|
+
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
2775
|
}
|
|
2748
2776
|
if (!existsSync11(resolved)) {
|
|
2749
2777
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2779,7 +2807,8 @@ function createEditFileTool(permissions) {
|
|
|
2779
2807
|
const resolved = resolve7(path3);
|
|
2780
2808
|
const fsCheck = await permissions.checkFsAccess(resolved, "write");
|
|
2781
2809
|
if (!fsCheck.allowed) {
|
|
2782
|
-
|
|
2810
|
+
const parentDir = resolve7(resolved, "..");
|
|
2811
|
+
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
2812
|
}
|
|
2784
2813
|
try {
|
|
2785
2814
|
const content = readFileSync9(resolved, "utf-8");
|
|
@@ -2820,7 +2849,8 @@ function createSendFileTool(permissions, sendFile) {
|
|
|
2820
2849
|
const resolved = resolve8(path3);
|
|
2821
2850
|
const check = await permissions.checkFsAccess(resolved, "read");
|
|
2822
2851
|
if (!check.allowed) {
|
|
2823
|
-
|
|
2852
|
+
const parentDir = resolve8(resolved, "..");
|
|
2853
|
+
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
2854
|
}
|
|
2825
2855
|
if (!existsSync12(resolved)) {
|
|
2826
2856
|
return `Error: File not found: ${resolved}`;
|
|
@@ -2844,18 +2874,40 @@ function createSendFileTool(permissions, sendFile) {
|
|
|
2844
2874
|
});
|
|
2845
2875
|
}
|
|
2846
2876
|
|
|
2847
|
-
// src/capabilities/
|
|
2877
|
+
// src/capabilities/filesystem/approve-scope.ts
|
|
2848
2878
|
import { tool as tool8 } from "ai";
|
|
2849
2879
|
import { z as z8 } from "zod";
|
|
2880
|
+
import { resolve as resolve9 } from "path";
|
|
2881
|
+
function createApproveScopeTool(permissions) {
|
|
2882
|
+
return tool8({
|
|
2883
|
+
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.',
|
|
2884
|
+
parameters: z8.object({
|
|
2885
|
+
path: z8.string().describe("The directory path to request access to"),
|
|
2886
|
+
mode: z8.enum(["read", "write"]).describe("The access mode needed")
|
|
2887
|
+
}),
|
|
2888
|
+
execute: async ({ path: path3, mode }) => {
|
|
2889
|
+
const resolved = resolve9(path3);
|
|
2890
|
+
const result = await permissions.requestScopeExternal(resolved, mode);
|
|
2891
|
+
if (result.allowed) {
|
|
2892
|
+
return `Access approved for ${mode} access to ${resolved}. You can now retry the file operation.`;
|
|
2893
|
+
}
|
|
2894
|
+
return `Access denied for ${mode} access to ${resolved}. The user did not approve scope access.`;
|
|
2895
|
+
}
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// src/capabilities/shell/run-command.ts
|
|
2900
|
+
import { tool as tool9 } from "ai";
|
|
2901
|
+
import { z as z9 } from "zod";
|
|
2850
2902
|
import { execSync } from "child_process";
|
|
2851
2903
|
function createRunCommandTool(permissions) {
|
|
2852
|
-
return
|
|
2904
|
+
return tool9({
|
|
2853
2905
|
description: `Run a shell command. Commands run in the current working directory unless an absolute path is given.
|
|
2854
2906
|
Blocked commands (sudo, rm -rf /, etc.) are never executed.
|
|
2855
2907
|
Auto-approved commands (ls, cat, git status, curl, etc.) run without asking.
|
|
2856
2908
|
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:
|
|
2858
|
-
command:
|
|
2909
|
+
parameters: z9.object({
|
|
2910
|
+
command: z9.string().describe("The shell command to execute")
|
|
2859
2911
|
}),
|
|
2860
2912
|
execute: async ({ command }) => {
|
|
2861
2913
|
const check = await permissions.checkShellCommand(command);
|
|
@@ -2895,13 +2947,13 @@ Error: ${stderr}`;
|
|
|
2895
2947
|
}
|
|
2896
2948
|
|
|
2897
2949
|
// src/capabilities/shell/approve-command.ts
|
|
2898
|
-
import { tool as
|
|
2899
|
-
import { z as
|
|
2950
|
+
import { tool as tool10 } from "ai";
|
|
2951
|
+
import { z as z10 } from "zod";
|
|
2900
2952
|
function createApproveCommandTool(permissions) {
|
|
2901
|
-
return
|
|
2953
|
+
return tool10({
|
|
2902
2954
|
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:
|
|
2904
|
-
command:
|
|
2955
|
+
parameters: z10.object({
|
|
2956
|
+
command: z10.string().describe('The base command to permanently approve (e.g. "curl", "docker", "npm")')
|
|
2905
2957
|
}),
|
|
2906
2958
|
execute: async ({ command }) => {
|
|
2907
2959
|
const baseCmd = command.trim().split(/\s+/)[0];
|
|
@@ -2912,15 +2964,15 @@ function createApproveCommandTool(permissions) {
|
|
|
2912
2964
|
}
|
|
2913
2965
|
|
|
2914
2966
|
// src/capabilities/skills/install-skill.ts
|
|
2915
|
-
import { tool as
|
|
2916
|
-
import { z as
|
|
2967
|
+
import { tool as tool11 } from "ai";
|
|
2968
|
+
import { z as z11 } from "zod";
|
|
2917
2969
|
import { parse as parseYaml4 } from "yaml";
|
|
2918
2970
|
function createInstallSkillTool(skillLoader) {
|
|
2919
|
-
return
|
|
2971
|
+
return tool11({
|
|
2920
2972
|
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:
|
|
2922
|
-
content:
|
|
2923
|
-
url:
|
|
2973
|
+
parameters: z11.object({
|
|
2974
|
+
content: z11.string().optional().describe("Raw SKILL.md markdown content with YAML frontmatter"),
|
|
2975
|
+
url: z11.string().optional().describe("URL to fetch a SKILL.md from")
|
|
2924
2976
|
}),
|
|
2925
2977
|
execute: async ({ content, url }) => {
|
|
2926
2978
|
let skillContent;
|
|
@@ -2960,12 +3012,12 @@ function createInstallSkillTool(skillLoader) {
|
|
|
2960
3012
|
}
|
|
2961
3013
|
|
|
2962
3014
|
// src/capabilities/skills/list-skills.ts
|
|
2963
|
-
import { tool as
|
|
2964
|
-
import { z as
|
|
3015
|
+
import { tool as tool12 } from "ai";
|
|
3016
|
+
import { z as z12 } from "zod";
|
|
2965
3017
|
function createListSkillsTool(skillLoader) {
|
|
2966
|
-
return
|
|
3018
|
+
return tool12({
|
|
2967
3019
|
description: "List all installed skills with their names and descriptions.",
|
|
2968
|
-
parameters:
|
|
3020
|
+
parameters: z12.object({}),
|
|
2969
3021
|
execute: async () => {
|
|
2970
3022
|
const skills = skillLoader.getDiscovered();
|
|
2971
3023
|
if (skills.length === 0) {
|
|
@@ -2977,13 +3029,13 @@ function createListSkillsTool(skillLoader) {
|
|
|
2977
3029
|
}
|
|
2978
3030
|
|
|
2979
3031
|
// src/capabilities/skills/use-skill.ts
|
|
2980
|
-
import { tool as
|
|
2981
|
-
import { z as
|
|
3032
|
+
import { tool as tool13 } from "ai";
|
|
3033
|
+
import { z as z13 } from "zod";
|
|
2982
3034
|
function createUseSkillTool(skillLoader, permissions) {
|
|
2983
|
-
return
|
|
3035
|
+
return tool13({
|
|
2984
3036
|
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:
|
|
2986
|
-
name:
|
|
3037
|
+
parameters: z13.object({
|
|
3038
|
+
name: z13.string().describe("Name of the skill to invoke")
|
|
2987
3039
|
}),
|
|
2988
3040
|
execute: async ({ name }) => {
|
|
2989
3041
|
const skill = skillLoader.load(name);
|
|
@@ -3010,18 +3062,18 @@ Allowed tools: ${skill["allowed-tools"].join(", ")}`;
|
|
|
3010
3062
|
}
|
|
3011
3063
|
|
|
3012
3064
|
// src/capabilities/scheduler/schedule-task.ts
|
|
3013
|
-
import { tool as
|
|
3014
|
-
import { z as
|
|
3065
|
+
import { tool as tool14 } from "ai";
|
|
3066
|
+
import { z as z14 } from "zod";
|
|
3015
3067
|
import cron2 from "node-cron";
|
|
3016
3068
|
function createScheduleTaskTool(scheduler, getContext) {
|
|
3017
|
-
return
|
|
3069
|
+
return tool14({
|
|
3018
3070
|
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:
|
|
3020
|
-
cron:
|
|
3021
|
-
delay_seconds:
|
|
3022
|
-
description:
|
|
3023
|
-
prompt:
|
|
3024
|
-
skill_name:
|
|
3071
|
+
parameters: z14.object({
|
|
3072
|
+
cron: z14.string().optional().describe('Cron expression for recurring tasks (e.g. "0 9 * * *" for daily at 9am)'),
|
|
3073
|
+
delay_seconds: z14.number().optional().describe('Delay in seconds for one-shot tasks (e.g. 15 for "remind me in 15 seconds")'),
|
|
3074
|
+
description: z14.string().describe("Human-readable description of what this task does"),
|
|
3075
|
+
prompt: z14.string().optional().describe("Prompt to send to the agent when the task fires"),
|
|
3076
|
+
skill_name: z14.string().optional().describe("Name of a skill to invoke when the task fires")
|
|
3025
3077
|
}),
|
|
3026
3078
|
execute: async ({ cron: cronExpr, delay_seconds, description, prompt, skill_name }) => {
|
|
3027
3079
|
if (!cronExpr && !delay_seconds) {
|
|
@@ -3074,12 +3126,12 @@ function createScheduleTaskTool(scheduler, getContext) {
|
|
|
3074
3126
|
}
|
|
3075
3127
|
|
|
3076
3128
|
// src/capabilities/scheduler/list-tasks.ts
|
|
3077
|
-
import { tool as
|
|
3078
|
-
import { z as
|
|
3129
|
+
import { tool as tool15 } from "ai";
|
|
3130
|
+
import { z as z15 } from "zod";
|
|
3079
3131
|
function createListTasksTool(scheduler) {
|
|
3080
|
-
return
|
|
3132
|
+
return tool15({
|
|
3081
3133
|
description: "List all scheduled tasks with their cron expressions and descriptions.",
|
|
3082
|
-
parameters:
|
|
3134
|
+
parameters: z15.object({}),
|
|
3083
3135
|
execute: async () => {
|
|
3084
3136
|
const manifests = scheduler.getManifests();
|
|
3085
3137
|
if (manifests.length === 0) {
|
|
@@ -3094,13 +3146,13 @@ function createListTasksTool(scheduler) {
|
|
|
3094
3146
|
}
|
|
3095
3147
|
|
|
3096
3148
|
// src/capabilities/scheduler/cancel-task.ts
|
|
3097
|
-
import { tool as
|
|
3098
|
-
import { z as
|
|
3149
|
+
import { tool as tool16 } from "ai";
|
|
3150
|
+
import { z as z16 } from "zod";
|
|
3099
3151
|
function createCancelTaskTool(scheduler) {
|
|
3100
|
-
return
|
|
3152
|
+
return tool16({
|
|
3101
3153
|
description: "Cancel and remove a scheduled task by its ID.",
|
|
3102
|
-
parameters:
|
|
3103
|
-
id:
|
|
3154
|
+
parameters: z16.object({
|
|
3155
|
+
id: z16.string().describe("ID of the scheduled task to cancel")
|
|
3104
3156
|
}),
|
|
3105
3157
|
execute: async ({ id }) => {
|
|
3106
3158
|
const manifests = scheduler.getManifests();
|
|
@@ -3116,12 +3168,12 @@ function createCancelTaskTool(scheduler) {
|
|
|
3116
3168
|
}
|
|
3117
3169
|
|
|
3118
3170
|
// src/capabilities/system/budget-status.ts
|
|
3119
|
-
import { tool as
|
|
3120
|
-
import { z as
|
|
3171
|
+
import { tool as tool17 } from "ai";
|
|
3172
|
+
import { z as z17 } from "zod";
|
|
3121
3173
|
function createBudgetStatusTool(tokenBudget) {
|
|
3122
|
-
return
|
|
3174
|
+
return tool17({
|
|
3123
3175
|
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:
|
|
3176
|
+
parameters: z17.object({}),
|
|
3125
3177
|
execute: async () => {
|
|
3126
3178
|
return tokenBudget.getStatusText();
|
|
3127
3179
|
}
|
|
@@ -3129,14 +3181,14 @@ function createBudgetStatusTool(tokenBudget) {
|
|
|
3129
3181
|
}
|
|
3130
3182
|
|
|
3131
3183
|
// src/capabilities/git/git-status.ts
|
|
3132
|
-
import { tool as
|
|
3133
|
-
import { z as
|
|
3184
|
+
import { tool as tool18 } from "ai";
|
|
3185
|
+
import { z as z18 } from "zod";
|
|
3134
3186
|
import { execSync as execSync2 } from "child_process";
|
|
3135
3187
|
function createGitStatusTool() {
|
|
3136
|
-
return
|
|
3188
|
+
return tool18({
|
|
3137
3189
|
description: "Show the working tree status. Returns staged, unstaged, and untracked files.",
|
|
3138
|
-
parameters:
|
|
3139
|
-
path:
|
|
3190
|
+
parameters: z18.object({
|
|
3191
|
+
path: z18.string().optional().describe("Path to check (defaults to current directory)")
|
|
3140
3192
|
}),
|
|
3141
3193
|
execute: async ({ path: path3 }) => {
|
|
3142
3194
|
try {
|
|
@@ -3152,15 +3204,15 @@ function createGitStatusTool() {
|
|
|
3152
3204
|
}
|
|
3153
3205
|
|
|
3154
3206
|
// src/capabilities/git/git-diff.ts
|
|
3155
|
-
import { tool as
|
|
3156
|
-
import { z as
|
|
3207
|
+
import { tool as tool19 } from "ai";
|
|
3208
|
+
import { z as z19 } from "zod";
|
|
3157
3209
|
import { execSync as execSync3 } from "child_process";
|
|
3158
3210
|
function createGitDiffTool() {
|
|
3159
|
-
return
|
|
3211
|
+
return tool19({
|
|
3160
3212
|
description: "Show changes between commits, commit and working tree, etc. Shows what has been modified.",
|
|
3161
|
-
parameters:
|
|
3162
|
-
path:
|
|
3163
|
-
staged:
|
|
3213
|
+
parameters: z19.object({
|
|
3214
|
+
path: z19.string().optional().describe("File or directory to diff"),
|
|
3215
|
+
staged: z19.boolean().optional().describe("Show staged changes (cached) instead of unstaged")
|
|
3164
3216
|
}),
|
|
3165
3217
|
execute: async ({ path: path3, staged }) => {
|
|
3166
3218
|
try {
|
|
@@ -3179,15 +3231,15 @@ function createGitDiffTool() {
|
|
|
3179
3231
|
}
|
|
3180
3232
|
|
|
3181
3233
|
// src/capabilities/git/git-log.ts
|
|
3182
|
-
import { tool as
|
|
3183
|
-
import { z as
|
|
3234
|
+
import { tool as tool20 } from "ai";
|
|
3235
|
+
import { z as z20 } from "zod";
|
|
3184
3236
|
import { execSync as execSync4 } from "child_process";
|
|
3185
3237
|
function createGitLogTool() {
|
|
3186
|
-
return
|
|
3238
|
+
return tool20({
|
|
3187
3239
|
description: "Show commit logs. Returns recent commit history with hash, author, date, and message.",
|
|
3188
|
-
parameters:
|
|
3189
|
-
count:
|
|
3190
|
-
path:
|
|
3240
|
+
parameters: z20.object({
|
|
3241
|
+
count: z20.number().optional().describe("Number of commits to show (default 10)"),
|
|
3242
|
+
path: z20.string().optional().describe("File or directory to show log for")
|
|
3191
3243
|
}),
|
|
3192
3244
|
execute: async ({ count, path: path3 }) => {
|
|
3193
3245
|
try {
|
|
@@ -3205,14 +3257,14 @@ function createGitLogTool() {
|
|
|
3205
3257
|
}
|
|
3206
3258
|
|
|
3207
3259
|
// src/capabilities/git/git-add.ts
|
|
3208
|
-
import { tool as
|
|
3209
|
-
import { z as
|
|
3260
|
+
import { tool as tool21 } from "ai";
|
|
3261
|
+
import { z as z21 } from "zod";
|
|
3210
3262
|
import { execSync as execSync5 } from "child_process";
|
|
3211
3263
|
function createGitAddTool() {
|
|
3212
|
-
return
|
|
3264
|
+
return tool21({
|
|
3213
3265
|
description: "Add file contents to the index (staging area). Prepares files for commit.",
|
|
3214
|
-
parameters:
|
|
3215
|
-
paths:
|
|
3266
|
+
parameters: z21.object({
|
|
3267
|
+
paths: z21.array(z21.string()).describe("File paths to stage")
|
|
3216
3268
|
}),
|
|
3217
3269
|
execute: async ({ paths }) => {
|
|
3218
3270
|
try {
|
|
@@ -3227,14 +3279,14 @@ function createGitAddTool() {
|
|
|
3227
3279
|
}
|
|
3228
3280
|
|
|
3229
3281
|
// src/capabilities/git/git-commit.ts
|
|
3230
|
-
import { tool as
|
|
3231
|
-
import { z as
|
|
3282
|
+
import { tool as tool22 } from "ai";
|
|
3283
|
+
import { z as z22 } from "zod";
|
|
3232
3284
|
import { execSync as execSync6 } from "child_process";
|
|
3233
3285
|
function createGitCommitTool() {
|
|
3234
|
-
return
|
|
3286
|
+
return tool22({
|
|
3235
3287
|
description: "Record changes to the repository. Creates a new commit with staged changes.",
|
|
3236
|
-
parameters:
|
|
3237
|
-
message:
|
|
3288
|
+
parameters: z22.object({
|
|
3289
|
+
message: z22.string().describe("Commit message")
|
|
3238
3290
|
}),
|
|
3239
3291
|
execute: async ({ message }) => {
|
|
3240
3292
|
try {
|
|
@@ -3253,15 +3305,15 @@ function createGitCommitTool() {
|
|
|
3253
3305
|
}
|
|
3254
3306
|
|
|
3255
3307
|
// src/capabilities/git/git-push.ts
|
|
3256
|
-
import { tool as
|
|
3257
|
-
import { z as
|
|
3308
|
+
import { tool as tool23 } from "ai";
|
|
3309
|
+
import { z as z23 } from "zod";
|
|
3258
3310
|
import { execSync as execSync7 } from "child_process";
|
|
3259
3311
|
function createGitPushTool(permissions) {
|
|
3260
|
-
return
|
|
3312
|
+
return tool23({
|
|
3261
3313
|
description: "Push commits to a remote repository. This modifies a remote and requires approval.",
|
|
3262
|
-
parameters:
|
|
3263
|
-
remote:
|
|
3264
|
-
branch:
|
|
3314
|
+
parameters: z23.object({
|
|
3315
|
+
remote: z23.string().optional().describe("Remote name (default: origin)"),
|
|
3316
|
+
branch: z23.string().optional().describe("Branch name (default: current branch)")
|
|
3265
3317
|
}),
|
|
3266
3318
|
execute: async ({ remote, branch }) => {
|
|
3267
3319
|
const cmd = `git push ${remote || "origin"} ${branch || ""}`.trim();
|
|
@@ -3286,8 +3338,8 @@ Ask the user for permission. If they approve, try again. If they say "always", u
|
|
|
3286
3338
|
}
|
|
3287
3339
|
|
|
3288
3340
|
// src/capabilities/web/fetch-url.ts
|
|
3289
|
-
import { tool as
|
|
3290
|
-
import { z as
|
|
3341
|
+
import { tool as tool24 } from "ai";
|
|
3342
|
+
import { z as z24 } from "zod";
|
|
3291
3343
|
var MAX_CONTENT_LENGTH = 15e3;
|
|
3292
3344
|
function stripHtml(html) {
|
|
3293
3345
|
let text = html;
|
|
@@ -3320,11 +3372,11 @@ function stripHtml(html) {
|
|
|
3320
3372
|
return text;
|
|
3321
3373
|
}
|
|
3322
3374
|
function createFetchUrlTool() {
|
|
3323
|
-
return
|
|
3375
|
+
return tool24({
|
|
3324
3376
|
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:
|
|
3326
|
-
url:
|
|
3327
|
-
format:
|
|
3377
|
+
parameters: z24.object({
|
|
3378
|
+
url: z24.string().describe("The URL to fetch"),
|
|
3379
|
+
format: z24.enum(["text", "markdown"]).optional().describe("Output format (default: markdown)")
|
|
3328
3380
|
}),
|
|
3329
3381
|
execute: async ({ url, format }) => {
|
|
3330
3382
|
const outputFormat = format ?? "markdown";
|
|
@@ -3413,6 +3465,7 @@ var CapabilityRegistry = class {
|
|
|
3413
3465
|
if (this.sendFileHandler) {
|
|
3414
3466
|
this.tools.send_file = createSendFileTool(this.permissions, this.sendFileHandler);
|
|
3415
3467
|
}
|
|
3468
|
+
this.tools.approve_scope = createApproveScopeTool(this.permissions);
|
|
3416
3469
|
logger.info("Filesystem tools registered");
|
|
3417
3470
|
}
|
|
3418
3471
|
if (manifest.capabilities.shell.enabled) {
|
|
@@ -4257,7 +4310,7 @@ async function runWithWatchdog(agentFn) {
|
|
|
4257
4310
|
await attempt();
|
|
4258
4311
|
}
|
|
4259
4312
|
function sleep(ms) {
|
|
4260
|
-
return new Promise((
|
|
4313
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
4261
4314
|
}
|
|
4262
4315
|
|
|
4263
4316
|
// src/index.ts
|
|
@@ -4291,10 +4344,10 @@ function splashScreen() {
|
|
|
4291
4344
|
}
|
|
4292
4345
|
async function ask(prompt) {
|
|
4293
4346
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
4294
|
-
return new Promise((
|
|
4347
|
+
return new Promise((resolve10) => {
|
|
4295
4348
|
rl.question(prompt, (answer) => {
|
|
4296
4349
|
rl.close();
|
|
4297
|
-
|
|
4350
|
+
resolve10(answer.trim());
|
|
4298
4351
|
});
|
|
4299
4352
|
});
|
|
4300
4353
|
}
|