@cosmicstack/mercury-agent 0.2.5 → 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 CHANGED
@@ -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();
@@ -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
- return await this.requestScope(resolved, mode);
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: scopeCheck.reason, needsApproval: true };
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
  }
@@ -2502,9 +2509,6 @@ var PermissionManager = class {
2502
2509
  return void 0;
2503
2510
  }
2504
2511
  async requestScopeExternal(path3, mode) {
2505
- return this.requestScope(path3, mode);
2506
- }
2507
- async requestScope(path3, mode) {
2508
2512
  if (!this.askHandler) {
2509
2513
  return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
2510
2514
  }
@@ -2517,11 +2521,26 @@ Allow access?`;
2517
2521
  this.addScope(path3, mode === "read", mode === "write");
2518
2522
  return { allowed: true };
2519
2523
  }
2520
- if (response === "yes" || response === "y") {
2524
+ if (response === "yes") {
2525
+ this.addTempScope(path3, mode === "read", mode === "write");
2521
2526
  return { allowed: true };
2522
2527
  }
2523
2528
  return { allowed: false, reason: `Permission denied for ${mode} access to ${path3}` };
2524
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
+ }
2525
2544
  matchPattern(command, pattern) {
2526
2545
  const regexStr = "^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$";
2527
2546
  try {
@@ -2861,18 +2880,18 @@ import { z as z8 } from "zod";
2861
2880
  import { resolve as resolve9 } from "path";
2862
2881
  function createApproveScopeTool(permissions) {
2863
2882
  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.",
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.',
2865
2884
  parameters: z8.object({
2866
- path: z8.string().describe("The directory path to add to allowed scopes"),
2885
+ path: z8.string().describe("The directory path to request access to"),
2867
2886
  mode: z8.enum(["read", "write"]).describe("The access mode needed")
2868
2887
  }),
2869
2888
  execute: async ({ path: path3, mode }) => {
2870
2889
  const resolved = resolve9(path3);
2871
2890
  const result = await permissions.requestScopeExternal(resolved, mode);
2872
2891
  if (result.allowed) {
2873
- return `Access approved for ${mode} access to ${resolved}`;
2892
+ return `Access approved for ${mode} access to ${resolved}. You can now retry the file operation.`;
2874
2893
  }
2875
- return `Access denied for ${mode} access to ${resolved}`;
2894
+ return `Access denied for ${mode} access to ${resolved}. The user did not approve scope access.`;
2876
2895
  }
2877
2896
  });
2878
2897
  }